2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-4-Clause
4 * Copyright (C) 2002 Benno Rice
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Copyright (C) 1993 Wolfgang Solfrank.
29 * Copyright (C) 1993 TooLs GmbH.
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by TooLs GmbH.
43 * 4. The name of TooLs GmbH may not be used to endorse or promote products
44 * derived from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
61 #include <sys/param.h>
63 #include <sys/mutex.h>
64 #include <sys/systm.h>
69 #include <vm/vm_map.h>
71 #include <machine/pcb.h>
72 #include <machine/vmparam.h>
75 copyout(const void *kaddr, void *udaddr, size_t len)
85 pm = &td->td_proc->p_vmspace->vm_pmap;
87 td->td_pcb->pcb_onfault = &env;
89 td->td_pcb->pcb_onfault = NULL;
97 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
98 td->td_pcb->pcb_onfault = NULL;
109 td->td_pcb->pcb_onfault = NULL;
114 copyin(const void *udaddr, void *kaddr, size_t len)
124 pm = &td->td_proc->p_vmspace->vm_pmap;
126 td->td_pcb->pcb_onfault = &env;
128 td->td_pcb->pcb_onfault = NULL;
136 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
137 td->td_pcb->pcb_onfault = NULL;
148 td->td_pcb->pcb_onfault = NULL;
153 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
165 for (l = 0; len-- > 0; l++) {
166 if ((c = fubyte(up++)) < 0) {
186 subyte(volatile void *addr, int byte)
194 pm = &td->td_proc->p_vmspace->vm_pmap;
196 td->td_pcb->pcb_onfault = &env;
198 td->td_pcb->pcb_onfault = NULL;
202 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
203 td->td_pcb->pcb_onfault = NULL;
209 td->td_pcb->pcb_onfault = NULL;
215 suword32(volatile void *addr, int word)
223 pm = &td->td_proc->p_vmspace->vm_pmap;
225 td->td_pcb->pcb_onfault = &env;
227 td->td_pcb->pcb_onfault = NULL;
231 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
232 td->td_pcb->pcb_onfault = NULL;
238 td->td_pcb->pcb_onfault = NULL;
244 suword(volatile void *addr, long word)
252 pm = &td->td_proc->p_vmspace->vm_pmap;
254 td->td_pcb->pcb_onfault = &env;
256 td->td_pcb->pcb_onfault = NULL;
260 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
261 td->td_pcb->pcb_onfault = NULL;
267 td->td_pcb->pcb_onfault = NULL;
273 suword64(volatile void *addr, int64_t word)
275 return (suword(addr, (long)word));
279 suword32(volatile void *addr, int32_t word)
281 return (suword(addr, (long)word));
286 fubyte(volatile const void *addr)
295 pm = &td->td_proc->p_vmspace->vm_pmap;
297 td->td_pcb->pcb_onfault = &env;
299 td->td_pcb->pcb_onfault = NULL;
303 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
304 td->td_pcb->pcb_onfault = NULL;
310 td->td_pcb->pcb_onfault = NULL;
315 fuword16(volatile const void *addr)
323 pm = &td->td_proc->p_vmspace->vm_pmap;
325 td->td_pcb->pcb_onfault = &env;
327 td->td_pcb->pcb_onfault = NULL;
331 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
332 td->td_pcb->pcb_onfault = NULL;
338 td->td_pcb->pcb_onfault = NULL;
343 fueword32(volatile const void *addr, int32_t *val)
351 pm = &td->td_proc->p_vmspace->vm_pmap;
353 td->td_pcb->pcb_onfault = &env;
355 td->td_pcb->pcb_onfault = NULL;
359 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
360 td->td_pcb->pcb_onfault = NULL;
366 td->td_pcb->pcb_onfault = NULL;
372 fueword64(volatile const void *addr, int64_t *val)
380 pm = &td->td_proc->p_vmspace->vm_pmap;
382 td->td_pcb->pcb_onfault = &env;
384 td->td_pcb->pcb_onfault = NULL;
388 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
389 td->td_pcb->pcb_onfault = NULL;
395 td->td_pcb->pcb_onfault = NULL;
401 fueword(volatile const void *addr, long *val)
409 pm = &td->td_proc->p_vmspace->vm_pmap;
411 td->td_pcb->pcb_onfault = &env;
413 td->td_pcb->pcb_onfault = NULL;
417 if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
418 td->td_pcb->pcb_onfault = NULL;
424 td->td_pcb->pcb_onfault = NULL;
429 casueword32(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
438 pm = &td->td_proc->p_vmspace->vm_pmap;
440 td->td_pcb->pcb_onfault = &env;
442 td->td_pcb->pcb_onfault = NULL;
446 if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p,
448 td->td_pcb->pcb_onfault = NULL;
453 "1:\tlwarx %0, 0, %2\n\t" /* load old value */
454 "cmplw %3, %0\n\t" /* compare */
455 "bne 2f\n\t" /* exit if not equal */
456 "stwcx. %4, 0, %2\n\t" /* attempt to store */
457 "bne- 1b\n\t" /* spin if failed */
458 "b 3f\n\t" /* we've succeeded */
460 "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */
462 : "=&r" (val), "=m" (*p)
463 : "r" (p), "r" (old), "r" (new), "m" (*p)
466 td->td_pcb->pcb_onfault = NULL;
472 #ifndef __powerpc64__
474 casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
477 return (casueword32((volatile uint32_t *)addr, old,
478 (uint32_t *)oldvalp, new));
482 casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
490 pm = &td->td_proc->p_vmspace->vm_pmap;
492 td->td_pcb->pcb_onfault = &env;
494 td->td_pcb->pcb_onfault = NULL;
498 if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p,
500 td->td_pcb->pcb_onfault = NULL;
505 "1:\tldarx %0, 0, %2\n\t" /* load old value */
506 "cmpld %3, %0\n\t" /* compare */
507 "bne 2f\n\t" /* exit if not equal */
508 "stdcx. %4, 0, %2\n\t" /* attempt to store */
509 "bne- 1b\n\t" /* spin if failed */
510 "b 3f\n\t" /* we've succeeded */
512 "stdcx. %0, 0, %2\n\t" /* clear reservation (74xx) */
514 : "=&r" (val), "=m" (*p)
515 : "r" (p), "r" (old), "r" (new), "m" (*p)
518 td->td_pcb->pcb_onfault = NULL;