2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2018, Matthew Macy <mmacy@freebsd.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Assembly variants of various functions, for those that don't need generic C
32 * implementations. Currently this includes:
34 * - Direct-access versions of copyin/copyout methods.
35 * - These are used by Radix AIM pmap (ISA 3.0), and Book-E, to avoid
36 * unnecessary pmap_map_usr_ptr() calls.
40 #include "opt_sched.h"
42 #include <sys/syscall.h>
43 #include <sys/errno.h>
45 #include <machine/param.h>
46 #include <machine/asm.h>
47 #include <machine/spr.h>
48 #include <machine/trap.h>
49 #include <machine/vmparam.h>
64 #define CURTHREAD %r13
78 #define ENTRY_DIRECT(x) ENTRY(x ## _direct)
79 #define END_DIRECT(x) END(x ## _direct)
81 #define ENTRY_DIRECT(x) ENTRY(x)
82 #define END_DIRECT(x) END(x)
96 #define VALIDATE_TRUNCATE_ADDR_COPY VALIDATE_ADDR_COPY
97 #define VALIDATE_ADDR_COPY(raddr, len) \
98 srdi %r0, raddr, 52 ;\
103 #define VALIDATE_ADDR_FUSU(raddr) ;\
104 srdi %r0, raddr, 52 ;\
120 /* %r0 is temporary */
122 * Validate address and length are valid.
123 * For VALIDATE_ADDR_COPY() have to account for wraparound.
125 #define VALIDATE_ADDR_COPY(raddr, len) \
126 lis %r0, VM_MAXUSER_ADDRESS@h ;\
127 ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
130 add %r0, raddr, len ;\
131 cmplw 7, %r0, raddr ;\
132 blt- 7, copy_fault ;\
137 #define VALIDATE_TRUNCATE_ADDR_COPY(raddr, len) \
138 lis %r0, VM_MAXUSER_ADDRESS@h ;\
139 ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
142 sub %r0, %r0, raddr ;\
144 isel len, len, %r0, 0 ;\
146 #define VALIDATE_ADDR_FUSU(raddr) \
147 lis %r0, VM_MAXUSER_ADDRESS@h ;\
148 ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
154 #define SET_COPYFAULT(raddr, rpcb, len) \
155 VALIDATE_ADDR_COPY(raddr, len) ;\
157 LOAD rpcb, TD_PCB(CURTHREAD) ;\
158 STORE %r0, PCB_ONFAULT(rpcb) ;\
160 #define SET_COPYFAULT_TRUNCATE(raddr, rpcb, len)\
161 VALIDATE_TRUNCATE_ADDR_COPY(raddr, len) ;\
163 LOAD rpcb, TD_PCB(CURTHREAD) ;\
164 STORE %r0, PCB_ONFAULT(rpcb)
166 #define SET_FUSUFAULT(raddr, rpcb) \
167 VALIDATE_ADDR_FUSU(raddr) ;\
169 LOAD rpcb, TD_PCB(CURTHREAD) ;\
170 STORE %r0, PCB_ONFAULT(rpcb)
172 #define CLEAR_FAULT_NO_CLOBBER(rpcb) \
173 LOAD rpcb, TD_PCB(CURTHREAD) ;\
175 STORE %r0, PCB_ONFAULT(rpcb)
177 #define CLEAR_FAULT(rpcb) \
178 CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
182 * bcopy(src, dst, len)
185 * %r7 is the pcb pointer
187 * %r0 and %r8-%r10 are volatile
188 * %r11 and %r12 are generally volatile, used in linking and exception
189 * handling. Can be clobbered here.
191 * Does not allocate or use stack space, but clobbers all volatile registers.
207 #define Thresh WORD * 8
211 #define WORDS(n) (32 - LOG_WORD - W##n)
223 .Lsmall: /* < 8 words remaining */
237 0: /* < 4 words remaining */
245 1: /* < 2 words remaining */
251 2: /* < 1 word remaining */
258 3: /* < 4 bytes remaining */
265 4: /* < 2 bytes remaining */
276 andi. t6, t3, WORD-1 /* Align rd to word size */
288 srwi. t2, rl, LOOP_LOG /* length >> log_2(loop_size) => 8W iterations */
324 * copyout(from_kernel, to_user, len)
327 ENTRY_DIRECT(copyout)
329 SET_COPYFAULT(%r4, %r7, %r5)
337 * copyin(from_user, to_kernel, len)
342 SET_COPYFAULT(%r3, %r7, %r5)
350 * copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
354 ENTRY_DIRECT(copyinstr)
356 SET_COPYFAULT_TRUNCATE(%r3, %r7, %r5)
368 // NULL byte reached ?
375 /* skip storing length if done is NULL */
382 CLEAR_FAULT_NO_CLOBBER(%r7)
384 END_DIRECT(copyinstr)
388 SET_FUSUFAULT(%r3, %r7)
394 #ifndef __powerpc64__
397 SET_FUSUFAULT(%r3, %r7)
404 ENTRY_DIRECT(suword32)
406 SET_FUSUFAULT(%r3, %r7)
413 ENTRY_DIRECT(suword64)
415 SET_FUSUFAULT(%r3, %r7)
423 SET_FUSUFAULT(%r3, %r7)
432 SET_FUSUFAULT(%r3, %r7)
434 CLEAR_FAULT_NO_CLOBBER(%r7)
438 ENTRY_DIRECT(fuword16)
440 SET_FUSUFAULT(%r3, %r7)
442 CLEAR_FAULT_NO_CLOBBER(%r7)
446 #ifndef __powerpc64__
447 ENTRY_DIRECT(fueword)
449 SET_FUSUFAULT(%r3, %r7)
456 ENTRY_DIRECT(fueword32)
458 SET_FUSUFAULT(%r3, %r7)
463 END_DIRECT(fueword32)
466 ENTRY_DIRECT(fueword)
468 SET_FUSUFAULT(%r3, %r7)
475 ENTRY_DIRECT(fueword64)
477 SET_FUSUFAULT(%r3, %r7)
482 END_DIRECT(fueword64)
486 * casueword(volatile u_long *base, u_long old, u_long *oldp, u_long new)
490 #define CASUEWORD32(raddr, rpcb) ;\
492 SET_FUSUFAULT(raddr, rpcb) ;\
498 stwcx. %r6, 0, %r3 ;\
502 stwcx. %r0, 0, %r3 /* clear reservation (74xx) */ ;\
507 CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
511 ENTRY_DIRECT(casueword32)
512 CASUEWORD32(%r3, %r7)
513 END_DIRECT(casueword32)
516 #define CASUEWORD64(raddr, rpcb) ;\
518 SET_FUSUFAULT(raddr, rpcb) ;\
524 stdcx. %r6, 0, %r3 ;\
528 stdcx. %r0, 0, %r3 /* clear reservation (74xx) */ ;\
533 CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
537 ENTRY_DIRECT(casueword)
538 CASUEWORD64(%r3, %r7)
539 END_DIRECT(casueword)
541 ENTRY_DIRECT(casueword64)
542 CASUEWORD64(%r3, %r7)
543 END_DIRECT(casueword64)
545 ENTRY_DIRECT(casueword)
546 CASUEWORD32(%r3, %r7)
547 END_DIRECT(casueword)
550 _NAKED_ENTRY(fusufault)
551 CLEAR_FAULT_NO_CLOBBER(%r7)
556 _NAKED_ENTRY(copy_fault)
557 CLEAR_FAULT_NO_CLOBBER(%r7)