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>
76 #define ENTRY_DIRECT(x) ENTRY(x ## _direct)
77 #define END_DIRECT(x) END(x ## _direct)
79 #define ENTRY_DIRECT(x) ENTRY(x)
80 #define END_DIRECT(x) END(x)
94 #define VALIDATE_TRUNCATE_ADDR_COPY VALIDATE_ADDR_COPY
95 #define VALIDATE_ADDR_COPY(raddr, len) \
96 srdi %r0, raddr, 52 ;\
101 #define VALIDATE_ADDR_FUSU(raddr) ;\
102 srdi %r0, raddr, 52 ;\
118 /* %r0 is temporary */
120 * Validate address and length are valid.
121 * For VALIDATE_ADDR_COPY() have to account for wraparound.
123 #define VALIDATE_ADDR_COPY(raddr, len) \
124 lis %r0, VM_MAXUSER_ADDRESS@h ;\
125 ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
128 add %r0, raddr, len ;\
129 cmplw 7, %r0, raddr ;\
130 blt- 7, copy_fault ;\
135 #define VALIDATE_TRUNCATE_ADDR_COPY(raddr, len) \
136 lis %r0, VM_MAXUSER_ADDRESS@h ;\
137 ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
140 sub %r0, %r0, raddr ;\
142 isel len, len, %r0, 0 ;\
144 #define VALIDATE_ADDR_FUSU(raddr) \
145 lis %r0, VM_MAXUSER_ADDRESS@h ;\
146 ori %r0, %r0, VM_MAXUSER_ADDRESS@l ;\
152 #define PCPU(reg) mfsprg reg, 0
154 #define SET_COPYFAULT(raddr, rpcb, len) \
155 VALIDATE_ADDR_COPY(raddr, len) ;\
158 LOAD rpcb, PC_CURPCB(%r9) ;\
159 STORE %r0, PCB_ONFAULT(rpcb) ;\
161 #define SET_COPYFAULT_TRUNCATE(raddr, rpcb, len)\
162 VALIDATE_TRUNCATE_ADDR_COPY(raddr, len) ;\
165 LOAD rpcb, PC_CURPCB(%r9) ;\
166 STORE %r0, PCB_ONFAULT(rpcb)
168 #define SET_FUSUFAULT(raddr, rpcb) \
169 VALIDATE_ADDR_FUSU(raddr) ;\
172 LOAD rpcb, PC_CURPCB(%r9) ;\
173 STORE %r0, PCB_ONFAULT(rpcb)
175 #define CLEAR_FAULT_NO_CLOBBER(rpcb) \
177 LOAD rpcb, PC_CURPCB(%r9) ;\
179 STORE %r0, PCB_ONFAULT(rpcb)
181 #define CLEAR_FAULT(rpcb) \
182 CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
186 * bcopy(src, dst, len)
189 * %r7 is the pcb pointer
191 * %r0 and %r8-%r10 are volatile
192 * %r11 and %r12 are generally volatile, used in linking and exception
193 * handling. Can be clobbered here.
195 * Does not allocate or use stack space, but clobbers all volatile registers.
211 #define Thresh WORD * 8
215 #define WORDS(n) (32 - LOG_WORD - W##n)
227 .Lsmall: /* < 8 words remaining */
241 0: /* < 4 words remaining */
249 1: /* < 2 words remaining */
255 2: /* < 1 word remaining */
262 3: /* < 4 bytes remaining */
269 4: /* < 2 bytes remaining */
280 andi. t6, t3, WORD-1 /* Align rd to word size */
292 srwi. t2, rl, LOOP_LOG /* length >> log_2(loop_size) => 8W iterations */
328 * copyout(from_kernel, to_user, len)
331 ENTRY_DIRECT(copyout)
333 SET_COPYFAULT(%r4, %r7, %r5)
341 * copyin(from_user, to_kernel, len)
346 SET_COPYFAULT(%r3, %r7, %r5)
354 * copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
358 ENTRY_DIRECT(copyinstr)
360 SET_COPYFAULT_TRUNCATE(%r3, %r7, %r5)
372 // NULL byte reached ?
379 /* skip storing length if done is NULL */
386 CLEAR_FAULT_NO_CLOBBER(%r7)
388 END_DIRECT(copyinstr)
392 SET_FUSUFAULT(%r3, %r7)
398 #ifndef __powerpc64__
401 SET_FUSUFAULT(%r3, %r7)
408 ENTRY_DIRECT(suword32)
410 SET_FUSUFAULT(%r3, %r7)
417 ENTRY_DIRECT(suword64)
419 SET_FUSUFAULT(%r3, %r7)
427 SET_FUSUFAULT(%r3, %r7)
436 SET_FUSUFAULT(%r3, %r7)
438 CLEAR_FAULT_NO_CLOBBER(%r7)
442 ENTRY_DIRECT(fuword16)
444 SET_FUSUFAULT(%r3, %r7)
446 CLEAR_FAULT_NO_CLOBBER(%r7)
450 #ifndef __powerpc64__
451 ENTRY_DIRECT(fueword)
453 SET_FUSUFAULT(%r3, %r7)
460 ENTRY_DIRECT(fueword32)
462 SET_FUSUFAULT(%r3, %r7)
467 END_DIRECT(fueword32)
470 ENTRY_DIRECT(fueword)
472 SET_FUSUFAULT(%r3, %r7)
479 ENTRY_DIRECT(fueword64)
481 SET_FUSUFAULT(%r3, %r7)
486 END_DIRECT(fueword64)
490 * casueword(volatile u_long *base, u_long old, u_long *oldp, u_long new)
494 #define CASUEWORD32(raddr, rpcb) ;\
496 SET_FUSUFAULT(raddr, rpcb) ;\
502 stwcx. %r6, 0, %r3 ;\
506 stwcx. %r0, 0, %r3 /* clear reservation (74xx) */ ;\
511 CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
515 ENTRY_DIRECT(casueword32)
516 CASUEWORD32(%r3, %r7)
517 END_DIRECT(casueword32)
520 #define CASUEWORD64(raddr, rpcb) ;\
522 SET_FUSUFAULT(raddr, rpcb) ;\
528 stdcx. %r6, 0, %r3 ;\
532 stdcx. %r0, 0, %r3 /* clear reservation (74xx) */ ;\
537 CLEAR_FAULT_NO_CLOBBER(rpcb) ;\
541 ENTRY_DIRECT(casueword)
542 CASUEWORD64(%r3, %r7)
543 END_DIRECT(casueword)
545 ENTRY_DIRECT(casueword64)
546 CASUEWORD64(%r3, %r7)
547 END_DIRECT(casueword64)
549 ENTRY_DIRECT(casueword)
550 CASUEWORD32(%r3, %r7)
551 END_DIRECT(casueword)
554 _NAKED_ENTRY(fusufault)
555 CLEAR_FAULT_NO_CLOBBER(%r7)
560 _NAKED_ENTRY(copy_fault)
561 CLEAR_FAULT_NO_CLOBBER(%r7)