1/* $NetBSD: copy.S,v 1.10 2010/07/07 01:21:47 chs Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Digital Equipment Corporation and Ralph Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * Copyright (C) 1989 Digital Equipment Corporation. 35 * Permission to use, copy, modify, and distribute this software and 36 * its documentation for any purpose and without fee is hereby granted, 37 * provided that the above copyright notice appears in all copies. 38 * Digital Equipment Corporation makes no representations about the 39 * suitability of this software for any purpose. It is provided "as is" 40 * without express or implied warranty. 41 * 42 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 43 * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 44 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 45 * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 46 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 47 * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 48 * 49 * @(#)locore.s 8.5 (Berkeley) 1/4/94 50 */ 51 52/* 53 * copy(9) - kernel space to/from user space copy functions. 54 * fetch(9) - fetch data from user-space. 55 * store(9) - store data to user-space. 56 */ 57 58#include <sys/errno.h> 59#include <mips/asm.h> 60#include <mips/cpu.h> 61#include "assym.h" 62 63 .set noreorder 64/* 65 * int copystr(void *kfaddr, void *kdaddr, size_t maxlen, size_t *lencopied) 66 * Copy a NIL-terminated string, at most maxlen characters long. Return the 67 * number of characters copied (including the NIL) in *lencopied. If the 68 * string is too long, return ENAMETOOLONG; else return 0. 69 */ 70LEAF(copystr) 71 move t0, a2 72 beq a2, zero, 4f 73 nop 741: 75 lbu v0, 0(a0) 76 PTR_SUBU a2, a2, 1 77 beq v0, zero, 2f 78 sb v0, 0(a1) # each byte until NIL 79 PTR_ADDU a0, a0, 1 80 bne a2, zero, 1b # less than maxlen 81 PTR_ADDU a1, a1, 1 824: 83 li v0, ENAMETOOLONG # run out of space 842: 85 beq a3, zero, 3f # return num. of copied bytes 86 PTR_SUBU a2, t0, a2 # if the 4th arg was non-NULL 87 PTR_S a2, 0(a3) 883: 89 j ra # v0 is 0 or ENAMETOOLONG 90 nop 91END(copystr) 92 93/* 94 * int copyinstr(void *uaddr, void *kaddr, size_t maxlen, size_t *lencopied) 95 * Copy a NUL-terminated string, at most maxlen characters long, from the 96 * user's address space. Return the number of characters copied (including 97 * the NUL) in *lencopied. If the string is too long, return ENAMETOOLONG; 98 * else return 0 or EFAULT. 99 */ 100LEAF(copyinstr) 101 PTR_L v1, L_PCB(MIPS_CURLWP) 102 PTR_LA v0, _C_LABEL(copystrerr) 103 blt a0, zero, _C_LABEL(copystrefault) 104 PTR_S v0, PCB_ONFAULT(v1) 105 move t0, a2 106 beq a2, zero, 4f 107 nop 1081: 109 lbu v0, 0(a0) 110 PTR_SUBU a2, a2, 1 111 beq v0, zero, 2f 112 sb v0, 0(a1) # write trailing NUL 113 PTR_ADDU a0, a0, 1 114 bne a2, zero, 1b 115 PTR_ADDU a1, a1, 1 1164: 117 li v0, ENAMETOOLONG 1182: 119 beq a3, zero, 3f 120 PTR_SUBU a2, t0, a2 121 PTR_S a2, 0(a3) 1223: 123 j ra # v0 is 0 or ENAMETOOLONG 124 PTR_S zero, PCB_ONFAULT(v1) 125END(copyinstr) 126 127/* 128 * int copyoutstr(void *uaddr, void *kaddr, size_t maxlen, size_t *lencopied); 129 * Copy a NIL-terminated string, at most maxlen characters long, into the 130 * user's address space. Return the number of characters copied (including 131 * the NIL) in *lencopied. If the string is too long, return ENAMETOOLONG; 132 * else return 0 or EFAULT. 133 */ 134LEAF(copyoutstr) 135 PTR_L v1, L_PCB(MIPS_CURLWP) 136 PTR_LA v0, _C_LABEL(copystrerr) 137 blt a1, zero, _C_LABEL(copystrefault) 138 PTR_S v0, PCB_ONFAULT(v1) 139 move t0, a2 140 beq a2, zero, 4f 141 nop 1421: 143 lbu v0, 0(a0) 144 PTR_SUBU a2, a2, 1 145 beq v0, zero, 2f 146 sb v0, 0(a1) 147 PTR_ADDU a0, a0, 1 148 bne a2, zero, 1b 149 PTR_ADDU a1, a1, 1 1504: 151 li v0, ENAMETOOLONG 1522: 153 beq a3, zero, 3f 154 PTR_SUBU a2, t0, a2 155 PTR_S a2, 0(a3) 1563: 157 j ra # v0 is 0 or ENAMETOOLONG 158 PTR_S zero, PCB_ONFAULT(v1) 159END(copyoutstr) 160 161LEAF(copystrerr) 162 j ra 163 PTR_S zero, PCB_ONFAULT(v1) 164END(copystrerr) 165 166LEAF(copystrefault) 167 b copystrerr 168 li v0, EFAULT 169END(copystrefault) 170 171/* 172 * kcopy(const void *src, void *dst, size_t len); 173 * 174 * Copy len bytes from src to dst, aborting if we encounter a fatal 175 * page fault. 176 * 177 * kcopy() _must_ save and restore the old fault handler since it is 178 * called by uiomove(), which may be in the path of servicing a non-fatal 179 * page fault. 180 */ 181NESTED(kcopy, 2*CALLFRAME_SIZ, ra) 182 PTR_SUBU sp, sp, 2*CALLFRAME_SIZ # set up stack frame 183 /* Frame contains RA (31) and S0 (16). */ 184 .mask 0x80010000, -SZREG 185 REG_S ra, CALLFRAME_SIZ+CALLFRAME_RA(sp) # save ra 186 REG_S s0, CALLFRAME_SIZ+CALLFRAME_S0(sp) # save s0 187 move v0, a0 # swap a0, a1 for call to memcpy 188 move a0, a1 189 move a1, v0 190 PTR_L v1, L_PCB(MIPS_CURLWP) # set up fault handler 191 PTR_LA v0, _C_LABEL(kcopyerr) 192 PTR_L s0, PCB_ONFAULT(v1) # save old handler 193 jal memcpy 194 PTR_S v0, PCB_ONFAULT(v1) 195 196 PTR_L v1, L_PCB(MIPS_CURLWP) # restore the old handler 197 REG_L ra, CALLFRAME_SIZ+CALLFRAME_RA(sp) # restore ra 198 PTR_S s0, PCB_ONFAULT(v1) 199 REG_L s0, CALLFRAME_SIZ+CALLFRAME_S0(sp) # restore s0 200 PTR_ADDU sp, sp, 2*CALLFRAME_SIZ # kill stack frame 201 j ra 202 move v0, zero # success! 203END(kcopy) 204 205LEAF(kcopyerr) 206 PTR_L v1, L_PCB(MIPS_CURLWP) # restore the old handler 207 REG_L ra, CALLFRAME_SIZ+CALLFRAME_RA(sp) # restore ra 208 PTR_S s0, PCB_ONFAULT(v1) 209 REG_L s0, CALLFRAME_SIZ+CALLFRAME_S0(sp) # restore s0 210 j ra 211 PTR_ADDU sp, sp, 2*CALLFRAME_SIZ # kill stack frame 212END(kcopyerr) 213 214/* 215 * int copyin(void *uaddr, void *kaddr, size_t len) 216 * Copies len bytes of data from the user-space address uaddr to the 217 * kernel-space address kaddr. copyin returns 0 on success or EFAULT 218 * if a bad address is encountered. 219 */ 220NESTED(copyin, CALLFRAME_SIZ, ra) 221 PTR_SUBU sp, sp, CALLFRAME_SIZ 222 .mask 0x80000000, -4 223 REG_S ra, CALLFRAME_RA(sp) 224 blt a0, zero, _C_LABEL(copyefault) 225 move v0, a0 # swap a0, a1 for call to memcpy 226 move a0, a1 227 move a1, v0 228 PTR_L v1, L_PCB(MIPS_CURLWP) 229 PTR_LA v0, _C_LABEL(copyerr) 230 jal memcpy 231 PTR_S v0, PCB_ONFAULT(v1) 232 233 PTR_L v1, L_PCB(MIPS_CURLWP) 234 REG_L ra, CALLFRAME_RA(sp) 235 PTR_ADDU sp, sp, CALLFRAME_SIZ 236 PTR_S zero, PCB_ONFAULT(v1) 237 j ra 238 move v0, zero 239END(copyin) 240 241/* 242 * int copyout(void *kaddr, void *uaddr, size_t len) 243 * Copies len bytes of data from the kernel-space address kaddr to the 244 * user-space address uaddr. copyout returns 0 on success or EFAULT 245 * if a bad address is encountered. 246 */ 247NESTED(copyout, CALLFRAME_SIZ, ra) 248 PTR_SUBU sp, sp, CALLFRAME_SIZ 249 .mask 0x80000000, -4 250 REG_S ra, CALLFRAME_RA(sp) 251 blt a1, zero, _C_LABEL(copyefault) 252 move v0, a0 # swap a0, a1 for call to memcpy 253 move a0, a1 254 move a1, v0 255 PTR_L v1, L_PCB(MIPS_CURLWP) 256 PTR_LA v0, _C_LABEL(copyerr) 257 jal memcpy 258 PTR_S v0, PCB_ONFAULT(v1) 259 260 PTR_L v1, L_PCB(MIPS_CURLWP) 261 REG_L ra, CALLFRAME_RA(sp) 262 PTR_ADDU sp, sp, CALLFRAME_SIZ 263 PTR_S zero, PCB_ONFAULT(v1) 264 j ra 265 move v0, zero 266END(copyout) 267 268LEAF(copyerr) 269 PTR_L v1, L_PCB(MIPS_CURLWP) 270 REG_L ra, CALLFRAME_RA(sp) 271 PTR_ADDU sp, sp, CALLFRAME_SIZ 272 j ra 273 PTR_S zero, PCB_ONFAULT(v1) 274END(copyerr) 275 276LEAF(copyefault) 277 b copyerr 278 li v0, EFAULT 279END(copyefault) 280 281/* 282 * int fuswintr(void *) 283 * Fetches a short word of data from the user-space address. 284 * This function is safe to call during an interrupt context. 285 */ 286LEAF(fuswintr) 287 PTR_L v1, L_PCB(MIPS_CURLWP) 288 PTR_LA v0, _C_LABEL(fswintrberr) 289 PTR_L a2, PCB_ONFAULT(v1) 290 blt a0, zero, _C_LABEL(fswintrberr) 291 PTR_S v0, PCB_ONFAULT(v1) 292 lhu v0, 0(a0) # fetch short 293 j ra 294 PTR_S a2, PCB_ONFAULT(v1) 295END(fuswintr) 296 297/* 298 * int suswintr(void *, short); 299 * Stores a short word of data to the user-space address. 300 * This function is safe to call during an interrupt context. 301 */ 302LEAF(suswintr) 303 PTR_L v1, L_PCB(MIPS_CURLWP) 304 PTR_LA v0, _C_LABEL(fswintrberr) 305 PTR_L a2, PCB_ONFAULT(v1) 306 blt a0, zero, _C_LABEL(fswintrberr) 307 PTR_S v0, PCB_ONFAULT(v1) 308 sh a1, 0(a0) # store short 309 PTR_S a2, PCB_ONFAULT(v1) 310 j ra 311 move v0, zero 312END(suswintr) 313 314/* 315 * uint32_t ufetch_uint32(void *) 316 * Fetches a 32-bit datum from the user-space address. 317 */ 318LEAF(ufetch_uint32) 319 PTR_L v1, L_PCB(MIPS_CURLWP) 320 PTR_LA v0, _C_LABEL(fswberr) 321 blt a0, zero, _C_LABEL(fswberr) 322 PTR_S v0, PCB_ONFAULT(v1) 323 INT_L v0, 0(a0) # fetch int 324 j ra 325 PTR_S zero, PCB_ONFAULT(v1) 326END(ufetch_uint32) 327STRONG_ALIAS(ufetch_int32, ufetch_uint32) 328STRONG_ALIAS(ufetch_int, ufetch_uint32) 329STRONG_ALIAS(ufetch_uint, ufetch_uint32) 330STRONG_ALIAS(ufetch_uint32_intrsafe, ufetch_uint32) 331STRONG_ALIAS(ufetch_int32_intrsafe, ufetch_uint32) 332STRONG_ALIAS(ufetch_int_intrsafe, ufetch_uint32) 333STRONG_ALIAS(ufetch_uint_intrsafe, ufetch_uint32) 334#ifndef _LP64 335STRONG_ALIAS(ufetch_ptr, ufetch_uint32) 336STRONG_ALIAS(ufetch_long, ufetch_uint32) 337STRONG_ALIAS(ufetch_ulong, ufetch_uint32) 338STRONG_ALIAS(ufetch_ptr_intrsafe, ufetch_uint32) 339STRONG_ALIAS(ufetch_long_intrsafe, ufetch_uint32) 340STRONG_ALIAS(ufetch_ulong_intrsafe, ufetch_uint32) 341STRONG_ALIAS(fuword, ufetch_uint32) 342STRONG_ALIAS(fuiword, ufetch_uint32) 343#endif 344 345#ifdef _LP64 346/* 347 * uint64_t ufetch_uint64(void *) 348 * Fetches a 64-bit datum from the user-space address. 349 */ 350LEAF(ufetch_uint64) 351 PTR_L v1, L_PCB(MIPS_CURLWP) 352 PTR_LA v0, _C_LABEL(fswberr) 353 blt a0, zero, _C_LABEL(fswberr) 354 PTR_S v0, PCB_ONFAULT(v1) 355 LONG_L v0, 0(a0) # fetch 64-bit datum 356 j ra 357 PTR_S zero, PCB_ONFAULT(v1) 358END(ufetch_uint64) 359STRONG_ALIAS(ufetch_int64, ufetch_uint64) 360STRONG_ALIAS(ufetch_ptr, ufetch_uint64) 361STRONG_ALIAS(ufetch_long, ufetch_uint64) 362STRONG_ALIAS(ufetch_ulong, ufetch_uint64) 363STRONG_ALIAS(ufetch_int64_intrsafe, ufetch_uint64) 364STRONG_ALIAS(ufetch_ptr_intrsafe, ufetch_uint64) 365STRONG_ALIAS(ufetch_long_intrsafe, ufetch_uint64) 366STRONG_ALIAS(ufetch_ulong_intrsafe, ufetch_uint64) 367STRONG_ALIAS(fuword, ufetch_uint64) 368STRONG_ALIAS(fuiword, ufetch_uint64) 369#endif 370 371/* 372 * uint16_t ufetch_uint16(void *) 373 * Fetches an unsigned 16-bit datum from the user-space address. 374 */ 375LEAF(ufetch_uint16) 376 PTR_L v1, L_PCB(MIPS_CURLWP) 377 PTR_LA v0, _C_LABEL(fswberr) 378 blt a0, zero, _C_LABEL(fswberr) 379 PTR_S v0, PCB_ONFAULT(v1) 380 lhu v0, 0(a0) # fetch short 381 j ra 382 PTR_S zero, PCB_ONFAULT(v1) 383END(ufetch_uint16) 384STRONG_ALIAS(ufetch_ushort, ufetch_uint16) 385STRONG_ALIAS(ufetch_uint16_intrsafe, ufetch_uint16) 386STRONG_ALIAS(ufetch_ushort_intrsafe, ufetch_uint16) 387STRONG_ALIAS(fusword, ufetch_uint16) 388STRONG_ALIAS(fuisword, ufetch_uint16) 389 390/* 391 * uint16_t ufetch_int16(void *) 392 * Fetches a signed 16-bit datum from the user-space address. 393 */ 394LEAF(ufetch_int16) 395 PTR_L v1, L_PCB(MIPS_CURLWP) 396 PTR_LA v0, _C_LABEL(fswberr) 397 blt a0, zero, _C_LABEL(fswberr) 398 PTR_S v0, PCB_ONFAULT(v1) 399 lh v0, 0(a0) # fetch short 400 j ra 401 PTR_S zero, PCB_ONFAULT(v1) 402END(ufetch_int16) 403STRONG_ALIAS(ufetch_short, ufetch_int16) 404STRONG_ALIAS(ufetch_int16_intrsafe, ufetch_int16) 405STRONG_ALIAS(ufetch_short_intrsafe, ufetch_int16) 406 407/* 408 * uint8_t uftech_uint8(void *) 409 * Fetch a byte from the user's address space. 410 */ 411LEAF(ufetch_uint8) 412 PTR_L v1, L_PCB(MIPS_CURLWP) 413 PTR_LA v0, _C_LABEL(fswberr) 414 blt a0, zero, _C_LABEL(fswberr) 415 PTR_S v0, PCB_ONFAULT(v1) 416 lbu v0, 0(a0) # fetch byte 417 j ra 418 PTR_S zero, PCB_ONFAULT(v1) 419END(ufetch_uint8) 420STRONG_ALIAS(ufetch_uchar, ufetch_uint8) 421STRONG_ALIAS(ufetch_uint8_intrsafe, ufetch_uint8) 422STRONG_ALIAS(ufetch_uchar_intrsafe, ufetch_uint8) 423STRONG_ALIAS(fubyte, ufetch_uint8) 424STRONG_ALIAS(fuibyte, ufetch_uint8) 425 426/* 427 * int8_t uftech_int8(void *) 428 * Fetch a byte from the user's address space. 429 */ 430LEAF(ufetch_int8) 431 PTR_L v1, L_PCB(MIPS_CURLWP) 432 PTR_LA v0, _C_LABEL(fswberr) 433 blt a0, zero, _C_LABEL(fswberr) 434 PTR_S v0, PCB_ONFAULT(v1) 435 lb v0, 0(a0) # fetch byte 436 j ra 437 PTR_S zero, PCB_ONFAULT(v1) 438END(ufetch_int8) 439STRONG_ALIAS(ufetch_char, ufetch_int8) 440STRONG_ALIAS(ufetch_int8_intrsafe, ufetch_int8) 441STRONG_ALIAS(ufetch_char_intrsafe, ufetch_int8) 442 443/* 444 * int ustore_uint32(void *, uint32_t) 445 * Stores a 32-bit datum to the user-space address. 446 */ 447LEAF(ustore_uint32) 448 PTR_L v1, L_PCB(MIPS_CURLWP) 449 PTR_LA v0, _C_LABEL(fswberr) 450 blt a0, zero, _C_LABEL(fswberr) 451 PTR_S v0, PCB_ONFAULT(v1) 452 INT_S a1, 0(a0) # store word 453 PTR_S zero, PCB_ONFAULT(v1) 454 j ra 455 move v0, zero 456END(ustore_uint32) 457STRONG_ALIAS(ustore_int32, ustore_uint32) 458STRONG_ALIAS(ustore_int, ustore_uint32) 459STRONG_ALIAS(ustore_uint, ustore_uint32) 460STRONG_ALIAS(ustore_uint32_intrsafe, ustore_uint32) 461STRONG_ALIAS(ustore_int32_intrsafe, ustore_uint32) 462STRONG_ALIAS(ustore_int_intrsafe, ustore_uint32) 463STRONG_ALIAS(ustore_uint_intrsafe, ustore_uint32) 464#ifndef _LP64 465STRONG_ALIAS(ustore_ptr, ustore_uint32) 466STRONG_ALIAS(ustore_long, ustore_uint32) 467STRONG_ALIAS(ustore_ulong, ustore_uint32) 468STRONG_ALIAS(ustore_ptr_intrsafe, ustore_uint32) 469STRONG_ALIAS(ustore_long_intrsafe, ustore_uint32) 470STRONG_ALIAS(ustore_ulong_intrsafe, ustore_uint32) 471STRONG_ALIAS(suword, ustore_uint32) 472#endif 473 474/* 475 * int ustore_uint32_isync(void *, uint32_t) 476 * Have to flush instruction cache afterwards. 477 */ 478LEAF(ustore_uint32_isync) 479 PTR_L v1, L_PCB(MIPS_CURLWP) 480 PTR_LA v0, _C_LABEL(fswberr) 481 blt a0, zero, _C_LABEL(fswberr) 482 PTR_S v0, PCB_ONFAULT(v1) 483 INT_S a1, 0(a0) # store word 484 PTR_S zero, PCB_ONFAULT(v1) 485 move v0, zero 486 PTR_L v1, _C_LABEL(mips_cache_ops) + MIPSX_FLUSHICACHE 487 j v1 # NOTE: must not clobber v0! 488 li a1, 4 # size of word 489END(ustore_uint32_isync) 490 491#ifdef _LP64 492/* 493 * int ustore_uint64(void *, uint64_t) 494 * Stores a 64-bit datum to the user-space address. 495 */ 496LEAF(ustore_uint64) 497 PTR_L v1, L_PCB(MIPS_CURLWP) 498 PTR_LA v0, _C_LABEL(fswberr) 499 blt a0, zero, _C_LABEL(fswberr) 500 PTR_S v0, PCB_ONFAULT(v1) 501 LONG_S a1, 0(a0) # store word 502 PTR_S zero, PCB_ONFAULT(v1) 503 j ra 504 move v0, zero 505END(ustore_uint64) 506STRONG_ALIAS(ustore_int64, ustore_uint64) 507STRONG_ALIAS(ustore_int, ustore_uint64) 508STRONG_ALIAS(ustore_uint, ustore_uint64) 509STRONG_ALIAS(ustore_uint64_intrsafe, ustore_uint64) 510STRONG_ALIAS(ustore_int64_intrsafe, ustore_uint64) 511STRONG_ALIAS(ustore_int_intrsafe, ustore_uint64) 512STRONG_ALIAS(ustore_uint_intrsafe, ustore_uint64) 513STRONG_ALIAS(ustore_ptr, ustore_uint64) 514STRONG_ALIAS(ustore_long, ustore_uint64) 515STRONG_ALIAS(ustore_ulong, ustore_uint64) 516STRONG_ALIAS(ustore_long_intrsafe, ustore_uint64) 517STRONG_ALIAS(ustore_ulong_intrsafe, ustore_uint64) 518STRONG_ALIAS(suword, ustore_uint64) 519#endif 520 521/* 522 * int ustore_uint16(void *, uint16_t) 523 * Stores a short word of data to the user-space address. 524 */ 525LEAF(ustore_uint16) 526 PTR_L v1, L_PCB(MIPS_CURLWP) 527 PTR_LA v0, _C_LABEL(fswberr) 528 blt a0, zero, _C_LABEL(fswberr) 529 PTR_S v0, PCB_ONFAULT(v1) 530 sh a1, 0(a0) # store short 531 PTR_S zero, PCB_ONFAULT(v1) 532 j ra 533 move v0, zero 534END(ustore_uint16) 535STRONG_ALIAS(ustore_int16, ustore_uint16) 536STRONG_ALIAS(ustore_uint16_intrsafe, ustore_uint16) 537STRONG_ALIAS(ustore_int16_intrsafe, ustore_uint16) 538STRONG_ALIAS(susword, ustore_uint16) 539STRONG_ALIAS(suisword, ustore_uint16) 540 541/* 542 * int ustore_uint8(void *, uint8_t) 543 * Stores a byte of data to the user-space address. 544 */ 545LEAF(ustore_uint8) 546 PTR_L v1, L_PCB(MIPS_CURLWP) 547 PTR_LA v0, _C_LABEL(fswberr) 548 blt a0, zero, _C_LABEL(fswberr) 549 PTR_S v0, PCB_ONFAULT(v1) 550 sb a1, 0(a0) # store byte 551 PTR_S zero, PCB_ONFAULT(v1) 552 j ra 553 move v0, zero 554END(ustore_uint8) 555STRONG_ALIAS(ustore_int8, ustore_uint8) 556STRONG_ALIAS(ustore_uint8_intrsafe, ustore_uint8) 557STRONG_ALIAS(ustore_int8_intrsafe, ustore_uint8) 558STRONG_ALIAS(subyte, ustore_uint8) 559STRONG_ALIAS(suibyte, ustore_uint8) 560 561/* 562 * int badaddr(void addr, int len) 563 * See if access to addr with a len type instruction causes a machine check. 564 * len is length of access (1=byte, 2=short, 4=long) 565 */ 566LEAF(badaddr) 567 PTR_L v1, L_PCB(MIPS_CURLWP) 568 PTR_LA v0, _C_LABEL(baderr) 569 bne a1, 1, 2f 570 PTR_S v0, PCB_ONFAULT(v1) 571 b 5f 572 lbu v0, (a0) 5732: 574 bne a1, 2, 4f 575 nop 576 b 5f 577 lhu v0, (a0) 5784: 579 INT_L v0, (a0) 5805: 581 PTR_S zero, PCB_ONFAULT(v1) 582 j ra 583 move v0, zero # made it w/o errors 584END(badaddr) 585 586/* 587 * Error routine for {f,s}uswintr. The fault handler in trap.c 588 * checks for pcb_onfault set to this fault handler and 589 * "bails out" before calling the VM fault handler. 590 * (We can not call VM code from interrupt level.) 591 */ 592LEAF(fswintrberr) 593 nop 594 PTR_S a2, PCB_ONFAULT(v1) 595 j ra 596 li v0, -1 597END(fswintrberr) 598 599LEAF(fswberr) 600XLEAF(baderr) 601 PTR_S zero, PCB_ONFAULT(v1) 602 j ra 603 li v0, -1 604END(fswberr) 605