1129198Scognet/* $NetBSD: bcopyinout.S,v 1.11 2003/10/13 21:22:40 scw Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 2002 Wasabi Systems, Inc. 5129198Scognet * All rights reserved. 6129198Scognet * 7129198Scognet * Written by Allen Briggs for Wasabi Systems, Inc. 8129198Scognet * 9129198Scognet * Redistribution and use in source and binary forms, with or without 10129198Scognet * modification, are permitted provided that the following conditions 11129198Scognet * are met: 12129198Scognet * 1. Redistributions of source code must retain the above copyright 13129198Scognet * notice, this list of conditions and the following disclaimer. 14129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 15129198Scognet * notice, this list of conditions and the following disclaimer in the 16129198Scognet * documentation and/or other materials provided with the distribution. 17129198Scognet * 3. All advertising materials mentioning features or use of this software 18129198Scognet * must display the following acknowledgement: 19129198Scognet * This product includes software developed for the NetBSD Project by 20129198Scognet * Wasabi Systems, Inc. 21129198Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22129198Scognet * or promote products derived from this software without specific prior 23129198Scognet * written permission. 24129198Scognet * 25129198Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26129198Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27129198Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28129198Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29129198Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30129198Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31129198Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32129198Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33129198Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34129198Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35129198Scognet * POSSIBILITY OF SUCH DAMAGE. 36129198Scognet */ 37129198Scognet 38129198Scognet 39129198Scognet#include "assym.s" 40129198Scognet 41129198Scognet#include <machine/asm.h> 42239033Sandrew#include <sys/errno.h> 43129198Scognet 44150864Scognet.L_arm_memcpy: 45150864Scognet .word _C_LABEL(_arm_memcpy) 46150864Scognet.L_min_memcpy_size: 47150864Scognet .word _C_LABEL(_min_memcpy_size) 48150864Scognet 49129198Scognet__FBSDID("$FreeBSD$"); 50172614Scognet#ifdef _ARM_ARCH_5E 51135643Scognet#include <arm/arm/bcopyinout_xscale.S> 52129198Scognet#else 53129198Scognet 54129198Scognet .text 55129198Scognet .align 0 56129198Scognet 57239268Sgonzo#ifdef _ARM_ARCH_6 58239268Sgonzo#define GET_PCB(tmp) \ 59239268Sgonzo mrc p15, 0, tmp, c13, c0, 4; \ 60266159Sian add tmp, tmp, #(TD_PCB) 61129198Scognet#else 62129198Scognet.Lcurpcb: 63239268Sgonzo .word _C_LABEL(__pcpu) + PC_CURPCB 64239268Sgonzo 65239268Sgonzo#define GET_PCB(tmp) \ 66239268Sgonzo ldr tmp, .Lcurpcb 67129198Scognet#endif 68129198Scognet 69239268Sgonzo 70129198Scognet#define SAVE_REGS stmfd sp!, {r4-r11} 71129198Scognet#define RESTORE_REGS ldmfd sp!, {r4-r11} 72129198Scognet 73172614Scognet#if defined(_ARM_ARCH_5E) 74129198Scognet#define HELLOCPP # 75129198Scognet#define PREFETCH(rx,o) pld [ rx , HELLOCPP (o) ] 76129198Scognet#else 77129198Scognet#define PREFETCH(rx,o) 78129198Scognet#endif 79129198Scognet 80129198Scognet/* 81129198Scognet * r0 = user space address 82129198Scognet * r1 = kernel space address 83129198Scognet * r2 = length 84129198Scognet * 85129198Scognet * Copies bytes from user space to kernel space 86129198Scognet * 87129198Scognet * We save/restore r4-r11: 88129198Scognet * r4-r11 are scratch 89129198Scognet */ 90129198ScognetENTRY(copyin) 91129198Scognet /* Quick exit if length is zero */ 92129198Scognet teq r2, #0 93129198Scognet moveq r0, #0 94138665Scognet RETeq 95129198Scognet 96150864Scognet ldr r3, .L_arm_memcpy 97150864Scognet ldr r3, [r3] 98150864Scognet cmp r3, #0 99150864Scognet beq .Lnormal 100150864Scognet ldr r3, .L_min_memcpy_size 101150864Scognet ldr r3, [r3] 102150864Scognet cmp r2, r3 103150864Scognet blt .Lnormal 104150864Scognet stmfd sp!, {r0-r2, r4, lr} 105150864Scognet mov r3, r0 106150864Scognet mov r0, r1 107150864Scognet mov r1, r3 108150864Scognet mov r3, #2 /* SRC_IS_USER */ 109150864Scognet ldr r4, .L_arm_memcpy 110150864Scognet mov lr, pc 111150864Scognet ldr pc, [r4] 112150864Scognet cmp r0, #0 113150864Scognet ldmfd sp!, {r0-r2, r4, lr} 114150864Scognet moveq r0, #0 115150864Scognet RETeq 116150864Scognet 117151596Scognet.Lnormal: 118129198Scognet SAVE_REGS 119239268Sgonzo GET_PCB(r4) 120129198Scognet ldr r4, [r4] 121129198Scognet 122239268Sgonzo 123129198Scognet ldr r5, [r4, #PCB_ONFAULT] 124129198Scognet adr r3, .Lcopyfault 125129198Scognet str r3, [r4, #PCB_ONFAULT] 126129198Scognet 127129198Scognet PREFETCH(r0, 0) 128129198Scognet PREFETCH(r1, 0) 129129198Scognet 130129198Scognet /* 131129198Scognet * If not too many bytes, take the slow path. 132129198Scognet */ 133129198Scognet cmp r2, #0x08 134129198Scognet blt .Licleanup 135129198Scognet 136129198Scognet /* 137129198Scognet * Align destination to word boundary. 138129198Scognet */ 139129198Scognet and r6, r1, #0x3 140129198Scognet ldr pc, [pc, r6, lsl #2] 141129198Scognet b .Lialend 142129198Scognet .word .Lialend 143129198Scognet .word .Lial3 144129198Scognet .word .Lial2 145129198Scognet .word .Lial1 146129198Scognet.Lial3: ldrbt r6, [r0], #1 147129198Scognet sub r2, r2, #1 148129198Scognet strb r6, [r1], #1 149129198Scognet.Lial2: ldrbt r7, [r0], #1 150129198Scognet sub r2, r2, #1 151129198Scognet strb r7, [r1], #1 152129198Scognet.Lial1: ldrbt r6, [r0], #1 153129198Scognet sub r2, r2, #1 154129198Scognet strb r6, [r1], #1 155129198Scognet.Lialend: 156129198Scognet 157129198Scognet /* 158129198Scognet * If few bytes left, finish slow. 159129198Scognet */ 160129198Scognet cmp r2, #0x08 161129198Scognet blt .Licleanup 162129198Scognet 163129198Scognet /* 164129198Scognet * If source is not aligned, finish slow. 165129198Scognet */ 166129198Scognet ands r3, r0, #0x03 167129198Scognet bne .Licleanup 168129198Scognet 169129198Scognet cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */ 170129198Scognet blt .Licleanup8 171129198Scognet 172129198Scognet /* 173129198Scognet * Align destination to cacheline boundary. 174129198Scognet * If source and destination are nicely aligned, this can be a big 175129198Scognet * win. If not, it's still cheaper to copy in groups of 32 even if 176129198Scognet * we don't get the nice cacheline alignment. 177129198Scognet */ 178129198Scognet and r6, r1, #0x1f 179129198Scognet ldr pc, [pc, r6] 180129198Scognet b .Licaligned 181129198Scognet .word .Licaligned 182129198Scognet .word .Lical28 183129198Scognet .word .Lical24 184129198Scognet .word .Lical20 185129198Scognet .word .Lical16 186129198Scognet .word .Lical12 187129198Scognet .word .Lical8 188129198Scognet .word .Lical4 189129198Scognet.Lical28:ldrt r6, [r0], #4 190129198Scognet sub r2, r2, #4 191129198Scognet str r6, [r1], #4 192129198Scognet.Lical24:ldrt r7, [r0], #4 193129198Scognet sub r2, r2, #4 194129198Scognet str r7, [r1], #4 195129198Scognet.Lical20:ldrt r6, [r0], #4 196129198Scognet sub r2, r2, #4 197129198Scognet str r6, [r1], #4 198129198Scognet.Lical16:ldrt r7, [r0], #4 199129198Scognet sub r2, r2, #4 200129198Scognet str r7, [r1], #4 201129198Scognet.Lical12:ldrt r6, [r0], #4 202129198Scognet sub r2, r2, #4 203129198Scognet str r6, [r1], #4 204129198Scognet.Lical8:ldrt r7, [r0], #4 205129198Scognet sub r2, r2, #4 206129198Scognet str r7, [r1], #4 207129198Scognet.Lical4:ldrt r6, [r0], #4 208129198Scognet sub r2, r2, #4 209129198Scognet str r6, [r1], #4 210129198Scognet 211129198Scognet /* 212129198Scognet * We start with > 0x40 bytes to copy (>= 0x60 got us into this 213129198Scognet * part of the code, and we may have knocked that down by as much 214129198Scognet * as 0x1c getting aligned). 215129198Scognet * 216129198Scognet * This loop basically works out to: 217129198Scognet * do { 218129198Scognet * prefetch-next-cacheline(s) 219129198Scognet * bytes -= 0x20; 220129198Scognet * copy cacheline 221129198Scognet * } while (bytes >= 0x40); 222129198Scognet * bytes -= 0x20; 223129198Scognet * copy cacheline 224129198Scognet */ 225129198Scognet.Licaligned: 226129198Scognet PREFETCH(r0, 32) 227129198Scognet PREFETCH(r1, 32) 228129198Scognet 229129198Scognet sub r2, r2, #0x20 230129198Scognet 231129198Scognet /* Copy a cacheline */ 232129198Scognet ldrt r10, [r0], #4 233129198Scognet ldrt r11, [r0], #4 234129198Scognet ldrt r6, [r0], #4 235129198Scognet ldrt r7, [r0], #4 236129198Scognet ldrt r8, [r0], #4 237129198Scognet ldrt r9, [r0], #4 238129198Scognet stmia r1!, {r10-r11} 239129198Scognet ldrt r10, [r0], #4 240129198Scognet ldrt r11, [r0], #4 241129198Scognet stmia r1!, {r6-r11} 242129198Scognet 243129198Scognet cmp r2, #0x40 244129198Scognet bge .Licaligned 245129198Scognet 246129198Scognet sub r2, r2, #0x20 247129198Scognet 248129198Scognet /* Copy a cacheline */ 249129198Scognet ldrt r10, [r0], #4 250129198Scognet ldrt r11, [r0], #4 251129198Scognet ldrt r6, [r0], #4 252129198Scognet ldrt r7, [r0], #4 253129198Scognet ldrt r8, [r0], #4 254129198Scognet ldrt r9, [r0], #4 255129198Scognet stmia r1!, {r10-r11} 256129198Scognet ldrt r10, [r0], #4 257129198Scognet ldrt r11, [r0], #4 258129198Scognet stmia r1!, {r6-r11} 259129198Scognet 260129198Scognet cmp r2, #0x08 261129198Scognet blt .Liprecleanup 262129198Scognet 263129198Scognet.Licleanup8: 264129198Scognet ldrt r8, [r0], #4 265129198Scognet ldrt r9, [r0], #4 266129198Scognet sub r2, r2, #8 267129198Scognet stmia r1!, {r8, r9} 268129198Scognet cmp r2, #8 269129198Scognet bge .Licleanup8 270129198Scognet 271129198Scognet.Liprecleanup: 272129198Scognet /* 273129198Scognet * If we're done, bail. 274129198Scognet */ 275129198Scognet cmp r2, #0 276129198Scognet beq .Lout 277129198Scognet 278129198Scognet.Licleanup: 279129198Scognet and r6, r2, #0x3 280129198Scognet ldr pc, [pc, r6, lsl #2] 281129198Scognet b .Licend 282129198Scognet .word .Lic4 283129198Scognet .word .Lic1 284129198Scognet .word .Lic2 285129198Scognet .word .Lic3 286129198Scognet.Lic4: ldrbt r6, [r0], #1 287129198Scognet sub r2, r2, #1 288129198Scognet strb r6, [r1], #1 289129198Scognet.Lic3: ldrbt r7, [r0], #1 290129198Scognet sub r2, r2, #1 291129198Scognet strb r7, [r1], #1 292129198Scognet.Lic2: ldrbt r6, [r0], #1 293129198Scognet sub r2, r2, #1 294129198Scognet strb r6, [r1], #1 295129198Scognet.Lic1: ldrbt r7, [r0], #1 296129198Scognet subs r2, r2, #1 297129198Scognet strb r7, [r1], #1 298129198Scognet.Licend: 299129198Scognet bne .Licleanup 300129198Scognet 301129198Scognet.Liout: 302129198Scognet mov r0, #0 303129198Scognet 304129198Scognet str r5, [r4, #PCB_ONFAULT] 305129198Scognet RESTORE_REGS 306129198Scognet 307137463Scognet RET 308129198Scognet 309129198Scognet.Lcopyfault: 310239033Sandrew ldr r0, =EFAULT 311129198Scognet str r5, [r4, #PCB_ONFAULT] 312129198Scognet RESTORE_REGS 313129198Scognet 314137463Scognet RET 315248361SandrewEND(copyin) 316129198Scognet 317129198Scognet/* 318129198Scognet * r0 = kernel space address 319129198Scognet * r1 = user space address 320129198Scognet * r2 = length 321129198Scognet * 322129198Scognet * Copies bytes from kernel space to user space 323129198Scognet * 324129198Scognet * We save/restore r4-r11: 325129198Scognet * r4-r11 are scratch 326129198Scognet */ 327129198Scognet 328129198ScognetENTRY(copyout) 329129198Scognet /* Quick exit if length is zero */ 330129198Scognet teq r2, #0 331129198Scognet moveq r0, #0 332137463Scognet RETeq 333129198Scognet 334150864Scognet ldr r3, .L_arm_memcpy 335150864Scognet ldr r3, [r3] 336150864Scognet cmp r3, #0 337150864Scognet beq .Lnormale 338150864Scognet ldr r3, .L_min_memcpy_size 339150864Scognet ldr r3, [r3] 340150864Scognet cmp r2, r3 341150864Scognet blt .Lnormale 342150864Scognet stmfd sp!, {r0-r2, r4, lr} 343150864Scognet mov r3, r0 344150864Scognet mov r0, r1 345150864Scognet mov r1, r3 346150864Scognet mov r3, #1 /* DST_IS_USER */ 347150864Scognet ldr r4, .L_arm_memcpy 348150864Scognet mov lr, pc 349150864Scognet ldr pc, [r4] 350150864Scognet cmp r0, #0 351150864Scognet ldmfd sp!, {r0-r2, r4, lr} 352150864Scognet moveq r0, #0 353150864Scognet RETeq 354150864Scognet 355151596Scognet.Lnormale: 356129198Scognet SAVE_REGS 357239268Sgonzo GET_PCB(r4) 358129198Scognet ldr r4, [r4] 359129198Scognet 360129198Scognet ldr r5, [r4, #PCB_ONFAULT] 361129198Scognet adr r3, .Lcopyfault 362129198Scognet str r3, [r4, #PCB_ONFAULT] 363129198Scognet 364129198Scognet PREFETCH(r0, 0) 365129198Scognet PREFETCH(r1, 0) 366129198Scognet 367129198Scognet /* 368129198Scognet * If not too many bytes, take the slow path. 369129198Scognet */ 370129198Scognet cmp r2, #0x08 371129198Scognet blt .Lcleanup 372129198Scognet 373129198Scognet /* 374129198Scognet * Align destination to word boundary. 375129198Scognet */ 376129198Scognet and r6, r1, #0x3 377129198Scognet ldr pc, [pc, r6, lsl #2] 378129198Scognet b .Lalend 379129198Scognet .word .Lalend 380129198Scognet .word .Lal3 381129198Scognet .word .Lal2 382129198Scognet .word .Lal1 383129198Scognet.Lal3: ldrb r6, [r0], #1 384129198Scognet sub r2, r2, #1 385129198Scognet strbt r6, [r1], #1 386129198Scognet.Lal2: ldrb r7, [r0], #1 387129198Scognet sub r2, r2, #1 388129198Scognet strbt r7, [r1], #1 389129198Scognet.Lal1: ldrb r6, [r0], #1 390129198Scognet sub r2, r2, #1 391129198Scognet strbt r6, [r1], #1 392129198Scognet.Lalend: 393129198Scognet 394129198Scognet /* 395129198Scognet * If few bytes left, finish slow. 396129198Scognet */ 397129198Scognet cmp r2, #0x08 398129198Scognet blt .Lcleanup 399129198Scognet 400129198Scognet /* 401129198Scognet * If source is not aligned, finish slow. 402129198Scognet */ 403129198Scognet ands r3, r0, #0x03 404129198Scognet bne .Lcleanup 405129198Scognet 406129198Scognet cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */ 407129198Scognet blt .Lcleanup8 408129198Scognet 409129198Scognet /* 410129198Scognet * Align source & destination to cacheline boundary. 411129198Scognet */ 412129198Scognet and r6, r1, #0x1f 413129198Scognet ldr pc, [pc, r6] 414129198Scognet b .Lcaligned 415129198Scognet .word .Lcaligned 416129198Scognet .word .Lcal28 417129198Scognet .word .Lcal24 418129198Scognet .word .Lcal20 419129198Scognet .word .Lcal16 420129198Scognet .word .Lcal12 421129198Scognet .word .Lcal8 422129198Scognet .word .Lcal4 423129198Scognet.Lcal28:ldr r6, [r0], #4 424129198Scognet sub r2, r2, #4 425129198Scognet strt r6, [r1], #4 426129198Scognet.Lcal24:ldr r7, [r0], #4 427129198Scognet sub r2, r2, #4 428129198Scognet strt r7, [r1], #4 429129198Scognet.Lcal20:ldr r6, [r0], #4 430129198Scognet sub r2, r2, #4 431129198Scognet strt r6, [r1], #4 432129198Scognet.Lcal16:ldr r7, [r0], #4 433129198Scognet sub r2, r2, #4 434129198Scognet strt r7, [r1], #4 435129198Scognet.Lcal12:ldr r6, [r0], #4 436129198Scognet sub r2, r2, #4 437129198Scognet strt r6, [r1], #4 438129198Scognet.Lcal8: ldr r7, [r0], #4 439129198Scognet sub r2, r2, #4 440129198Scognet strt r7, [r1], #4 441129198Scognet.Lcal4: ldr r6, [r0], #4 442129198Scognet sub r2, r2, #4 443129198Scognet strt r6, [r1], #4 444129198Scognet 445129198Scognet /* 446129198Scognet * We start with > 0x40 bytes to copy (>= 0x60 got us into this 447129198Scognet * part of the code, and we may have knocked that down by as much 448129198Scognet * as 0x1c getting aligned). 449129198Scognet * 450129198Scognet * This loop basically works out to: 451129198Scognet * do { 452129198Scognet * prefetch-next-cacheline(s) 453129198Scognet * bytes -= 0x20; 454129198Scognet * copy cacheline 455129198Scognet * } while (bytes >= 0x40); 456129198Scognet * bytes -= 0x20; 457129198Scognet * copy cacheline 458129198Scognet */ 459129198Scognet.Lcaligned: 460129198Scognet PREFETCH(r0, 32) 461129198Scognet PREFETCH(r1, 32) 462129198Scognet 463129198Scognet sub r2, r2, #0x20 464129198Scognet 465129198Scognet /* Copy a cacheline */ 466129198Scognet ldmia r0!, {r6-r11} 467129198Scognet strt r6, [r1], #4 468129198Scognet strt r7, [r1], #4 469129198Scognet ldmia r0!, {r6-r7} 470129198Scognet strt r8, [r1], #4 471129198Scognet strt r9, [r1], #4 472129198Scognet strt r10, [r1], #4 473129198Scognet strt r11, [r1], #4 474129198Scognet strt r6, [r1], #4 475129198Scognet strt r7, [r1], #4 476129198Scognet 477129198Scognet cmp r2, #0x40 478129198Scognet bge .Lcaligned 479129198Scognet 480129198Scognet sub r2, r2, #0x20 481129198Scognet 482129198Scognet /* Copy a cacheline */ 483129198Scognet ldmia r0!, {r6-r11} 484129198Scognet strt r6, [r1], #4 485129198Scognet strt r7, [r1], #4 486129198Scognet ldmia r0!, {r6-r7} 487129198Scognet strt r8, [r1], #4 488129198Scognet strt r9, [r1], #4 489129198Scognet strt r10, [r1], #4 490129198Scognet strt r11, [r1], #4 491129198Scognet strt r6, [r1], #4 492129198Scognet strt r7, [r1], #4 493129198Scognet 494129198Scognet cmp r2, #0x08 495129198Scognet blt .Lprecleanup 496129198Scognet 497129198Scognet.Lcleanup8: 498129198Scognet ldmia r0!, {r8-r9} 499129198Scognet sub r2, r2, #8 500129198Scognet strt r8, [r1], #4 501129198Scognet strt r9, [r1], #4 502129198Scognet cmp r2, #8 503129198Scognet bge .Lcleanup8 504129198Scognet 505129198Scognet.Lprecleanup: 506129198Scognet /* 507129198Scognet * If we're done, bail. 508129198Scognet */ 509129198Scognet cmp r2, #0 510129198Scognet beq .Lout 511129198Scognet 512129198Scognet.Lcleanup: 513129198Scognet and r6, r2, #0x3 514129198Scognet ldr pc, [pc, r6, lsl #2] 515129198Scognet b .Lcend 516129198Scognet .word .Lc4 517129198Scognet .word .Lc1 518129198Scognet .word .Lc2 519129198Scognet .word .Lc3 520129198Scognet.Lc4: ldrb r6, [r0], #1 521129198Scognet sub r2, r2, #1 522129198Scognet strbt r6, [r1], #1 523129198Scognet.Lc3: ldrb r7, [r0], #1 524129198Scognet sub r2, r2, #1 525129198Scognet strbt r7, [r1], #1 526129198Scognet.Lc2: ldrb r6, [r0], #1 527129198Scognet sub r2, r2, #1 528129198Scognet strbt r6, [r1], #1 529129198Scognet.Lc1: ldrb r7, [r0], #1 530129198Scognet subs r2, r2, #1 531129198Scognet strbt r7, [r1], #1 532129198Scognet.Lcend: 533129198Scognet bne .Lcleanup 534129198Scognet 535129198Scognet.Lout: 536129198Scognet mov r0, #0 537129198Scognet 538129198Scognet str r5, [r4, #PCB_ONFAULT] 539129198Scognet RESTORE_REGS 540129198Scognet 541137463Scognet RET 542248361SandrewEND(copyout) 543129198Scognet#endif 544129198Scognet 545129198Scognet/* 546129198Scognet * int badaddr_read_1(const uint8_t *src, uint8_t *dest) 547129198Scognet * 548129198Scognet * Copies a single 8-bit value from src to dest, returning 0 on success, 549129198Scognet * else EFAULT if a page fault occurred. 550129198Scognet */ 551129198ScognetENTRY(badaddr_read_1) 552239268Sgonzo GET_PCB(r2) 553129198Scognet ldr r2, [r2] 554239268Sgonzo 555129198Scognet ldr ip, [r2, #PCB_ONFAULT] 556129198Scognet adr r3, 1f 557129198Scognet str r3, [r2, #PCB_ONFAULT] 558129198Scognet nop 559129198Scognet nop 560129198Scognet nop 561129198Scognet ldrb r3, [r0] 562129198Scognet nop 563129198Scognet nop 564129198Scognet nop 565129198Scognet strb r3, [r1] 566129198Scognet mov r0, #0 /* No fault */ 567129198Scognet1: str ip, [r2, #PCB_ONFAULT] 568137463Scognet RET 569248361SandrewEND(badaddr_read_1) 570129198Scognet 571129198Scognet/* 572129198Scognet * int badaddr_read_2(const uint16_t *src, uint16_t *dest) 573129198Scognet * 574129198Scognet * Copies a single 16-bit value from src to dest, returning 0 on success, 575129198Scognet * else EFAULT if a page fault occurred. 576129198Scognet */ 577129198ScognetENTRY(badaddr_read_2) 578239268Sgonzo GET_PCB(r2) 579129198Scognet ldr r2, [r2] 580239268Sgonzo 581129198Scognet ldr ip, [r2, #PCB_ONFAULT] 582129198Scognet adr r3, 1f 583129198Scognet str r3, [r2, #PCB_ONFAULT] 584129198Scognet nop 585129198Scognet nop 586129198Scognet nop 587129198Scognet ldrh r3, [r0] 588129198Scognet nop 589129198Scognet nop 590129198Scognet nop 591129198Scognet strh r3, [r1] 592129198Scognet mov r0, #0 /* No fault */ 593129198Scognet1: str ip, [r2, #PCB_ONFAULT] 594137463Scognet RET 595248361SandrewEND(badaddr_read_2) 596129198Scognet 597129198Scognet/* 598129198Scognet * int badaddr_read_4(const uint32_t *src, uint32_t *dest) 599129198Scognet * 600129198Scognet * Copies a single 32-bit value from src to dest, returning 0 on success, 601129198Scognet * else EFAULT if a page fault occurred. 602129198Scognet */ 603129198ScognetENTRY(badaddr_read_4) 604239268Sgonzo GET_PCB(r2) 605129198Scognet ldr r2, [r2] 606239268Sgonzo 607129198Scognet ldr ip, [r2, #PCB_ONFAULT] 608129198Scognet adr r3, 1f 609129198Scognet str r3, [r2, #PCB_ONFAULT] 610129198Scognet nop 611129198Scognet nop 612129198Scognet nop 613129198Scognet ldr r3, [r0] 614129198Scognet nop 615129198Scognet nop 616129198Scognet nop 617129198Scognet str r3, [r1] 618129198Scognet mov r0, #0 /* No fault */ 619129198Scognet1: str ip, [r2, #PCB_ONFAULT] 620137463Scognet RET 621248361SandrewEND(badaddr_read_4) 622129198Scognet 623