2 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/types.h>
36 #include <sys/systm.h>
37 #include <cpu/lwbuf.h>
38 #include <vm/vm_page.h>
39 #include <vm/vm_extern.h>
46 casu64(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
48 struct vmspace *vm = curproc->p_vmspace;
51 volatile uint64_t *dest;
56 /* XXX No idea how to handle this case in a simple way, just abort */
57 if (PAGE_SIZE - ((vm_offset_t)p & PAGE_MASK) < sizeof(uint64_t))
60 m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)p),
61 VM_PROT_READ|VM_PROT_WRITE,
66 KKASSERT(m->busy == 0);
68 kva = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
69 dest = (uint64_t *)(kva + ((vm_offset_t)p & PAGE_MASK));
71 __asm __volatile(MPLOCKED "cmpxchgq %2,%1; " \
72 : "+a" (res), "=m" (*dest) \
73 : "r" (newval), "m" (*dest) \
85 casu32(volatile u_int *p, u_int oldval, u_int newval)
87 struct vmspace *vm = curproc->p_vmspace;
95 /* XXX No idea how to handle this case in a simple way, just abort */
96 if (PAGE_SIZE - ((vm_offset_t)p & PAGE_MASK) < sizeof(u_int))
99 m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)p),
100 VM_PROT_READ|VM_PROT_WRITE,
105 KKASSERT(m->busy == 0);
107 kva = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
108 dest = (u_int *)(kva + ((vm_offset_t)p & PAGE_MASK));
110 __asm __volatile(MPLOCKED "cmpxchgl %2,%1; " \
111 : "+a" (res), "=m" (*dest) \
112 : "r" (newval), "m" (*dest) \
124 swapu64(volatile uint64_t *p, uint64_t val)
126 struct vmspace *vm = curproc->p_vmspace;
133 /* XXX No idea how to handle this case in a simple way, just abort */
134 if (PAGE_SIZE - ((vm_offset_t)p & PAGE_MASK) < sizeof(uint64_t))
137 m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)p),
138 VM_PROT_READ|VM_PROT_WRITE,
143 KKASSERT(m->busy == 0);
145 kva = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
146 res = atomic_swap_long((uint64_t *)(kva + ((vm_offset_t)p & PAGE_MASK)),
157 swapu32(volatile uint32_t *p, uint32_t val)
159 struct vmspace *vm = curproc->p_vmspace;
166 /* XXX No idea how to handle this case in a simple way, just abort */
167 if (PAGE_SIZE - ((vm_offset_t)p & PAGE_MASK) < sizeof(uint64_t))
170 m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)p),
171 VM_PROT_READ|VM_PROT_WRITE,
176 KKASSERT(m->busy == 0);
178 kva = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
179 res = atomic_swap_int((u_int *)(kva + ((vm_offset_t)p & PAGE_MASK)),
190 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *lencopied)
194 for (i = 0; i < len; ++i) {
195 if ((((char *)kdaddr)[i] = ((const char *)kfaddr)[i]) == 0) {
201 return (ENAMETOOLONG);
205 * Copies a NUL-terminated string from user space to kernel space.
206 * The number of bytes copied, including the terminator, is returned in
209 * Returns 0 on success, EFAULT or ENAMETOOLONG on failure.
212 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *res)
216 const char *uptr = udaddr;
222 n = PAGE_SIZE - ((vm_offset_t)uptr & PAGE_MASK);
227 if ((error = copyin(uptr, kptr, n)) != 0)
241 return(ENAMETOOLONG);
245 * Copy a binary buffer from user space to kernel space.
247 * Returns 0 on success, EFAULT on failure.
250 copyin(const void *udaddr, void *kaddr, size_t len)
252 struct vmspace *vm = curproc->p_vmspace;
254 struct lwbuf lwb_cache;
261 m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)udaddr),
267 n = PAGE_SIZE - ((vm_offset_t)udaddr & PAGE_MASK);
270 lwb = lwbuf_alloc(m, &lwb_cache);
271 bcopy((char *)lwbuf_kva(lwb)+((vm_offset_t)udaddr & PAGE_MASK),
274 udaddr = (const char *)udaddr + n;
275 kaddr = (char *)kaddr + n;
285 * Copy a binary buffer from kernel space to user space.
287 * Returns 0 on success, EFAULT on failure.
290 copyout(const void *kaddr, void *udaddr, size_t len)
292 struct vmspace *vm = curproc->p_vmspace;
294 struct lwbuf lwb_cache;
302 m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)udaddr),
303 VM_PROT_READ|VM_PROT_WRITE,
308 KKASSERT(m->busy == 0);
309 n = PAGE_SIZE - ((vm_offset_t)udaddr & PAGE_MASK);
312 lwb = lwbuf_alloc(m, &lwb_cache);
313 bcopy(kaddr, (char *)lwbuf_kva(lwb) +
314 ((vm_offset_t)udaddr & PAGE_MASK), n);
316 udaddr = (char *)udaddr + n;
317 kaddr = (const char *)kaddr + n;
330 * Fetch the byte at the specified user address. Returns -1 on failure.
333 fubyte(const uint8_t *base)
337 if (copyin(base, &c, 1) == 0)
343 * Store a byte at the specified user address. Returns -1 on failure.
346 subyte(uint8_t *base, uint8_t byte)
350 if (copyout(&c, base, 1) == 0)
356 * Fetch a word (integer, 32 bits) from user space
359 fuword32(const uint32_t *base)
363 if (copyin(base, &v, sizeof(v)) == 0)
369 * Fetch a word (integer, 32 bits) from user space
372 fuword64(const uint64_t *base)
376 if (copyin(base, &v, sizeof(v)) == 0)
382 * Store a word (integer, 32 bits) to user space
385 suword64(uint64_t *base, uint64_t word)
387 if (copyout(&word, base, sizeof(word)) == 0)
393 suword32(uint32_t *base, int word)
395 if (copyout(&word, base, sizeof(word)) == 0)