Changeset View
Changeset View
Standalone View
Standalone View
sys/powerpc/powerpc/copyinout.c
Show First 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <vm/vm_extern.h> | |||||
#include <vm/vm_map.h> | #include <vm/vm_map.h> | ||||
#include <machine/mmuvar.h> | |||||
#include <machine/pcb.h> | #include <machine/pcb.h> | ||||
#include <machine/vmparam.h> | #include <machine/vmparam.h> | ||||
#include <machine/ifunc.h> | |||||
/* | |||||
* On powerpc64 (AIM only) the copy functions are IFUNcs, selecting the best | |||||
bdragon: minor nit: s/IFUNcs/IFUNCs/ | |||||
* option based on the PMAP in use. | |||||
* | |||||
* There are two options for copy functions on powerpc64: | |||||
bdragonUnsubmitted Not Done Inline Actionss/powerpc64/AIM powerpc64/ as Book-E is described in the next paragraph bdragon: s/powerpc64/AIM powerpc64/ as Book-E is described in the next paragraph | |||||
* - 'remap' copies, which remap userspace segments into kernel space for | |||||
* copying. This is used by the 'oea64' pmap. | |||||
* - 'direct' copies, which copy directly from userspace. This does not require | |||||
* remapping user segments into kernel. This is used by the 'radix' pmap for | |||||
* performance. | |||||
* | |||||
* Book-E does not use the C functions, opting instead to use the 'direct' | |||||
* copies, directly, avoiding the IFUNC overhead. | |||||
* | |||||
* On 32-bit AIM these functions are direct, not IFUNCs, for performance. | |||||
bdragonUnsubmitted Not Done Inline ActionsThe last two paragraphs are overloading the term "direct" -- the rest of the code treat "direct" as in "doesn't map user pointers" instead of "direct" as in "bypasses ifunc" bdragon: The last two paragraphs are overloading the term "direct" -- the rest of the code treat… | |||||
*/ | |||||
#ifdef __powerpc64__ | |||||
int subyte_remap(volatile void *addr, int byte); | |||||
int subyte_direct(volatile void *addr, int byte); | |||||
int copyinstr_remap(const void *udaddr, void *kaddr, size_t len, size_t *done); | |||||
int copyinstr_direct(const void *udaddr, void *kaddr, size_t len, size_t *done); | |||||
int copyout_remap(const void *kaddr, void *udaddr, size_t len); | |||||
int copyout_direct(const void *kaddr, void *udaddr, size_t len); | |||||
int copyin_remap(const void *uaddr, void *kaddr, size_t len); | |||||
int copyin_direct(const void *uaddr, void *kaddr, size_t len); | |||||
int suword32_remap(volatile void *addr, int word); | |||||
int suword32_direct(volatile void *addr, int word); | |||||
int suword_remap(volatile void *addr, long word); | |||||
int suword_direct(volatile void *addr, long word); | |||||
int suword64_remap(volatile void *addr, int64_t word); | |||||
int suword64_direct(volatile void *addr, int64_t word); | |||||
int fubyte_remap(volatile const void *addr); | |||||
int fubyte_direct(volatile const void *addr); | |||||
int fuword16_remap(volatile const void *addr); | |||||
int fuword16_direct(volatile const void *addr); | |||||
int fueword32_remap(volatile const void *addr, int32_t *val); | |||||
int fueword32_direct(volatile const void *addr, int32_t *val); | |||||
int fueword64_remap(volatile const void *addr, int64_t *val); | |||||
int fueword64_direct(volatile const void *addr, int64_t *val); | |||||
int fueword_remap(volatile const void *addr, long *val); | |||||
int fueword_direct(volatile const void *addr, long *val); | |||||
int casueword32_remap(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp, | |||||
uint32_t new); | |||||
int casueword32_direct(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp, | |||||
uint32_t new); | |||||
int casueword_remap(volatile u_long *addr, u_long old, u_long *oldvalp, | |||||
u_long new); | |||||
int casueword_direct(volatile u_long *addr, u_long old, u_long *oldvalp, | |||||
u_long new); | |||||
/* | |||||
* The IFUNC resolver determines the copy based on if the PMAP implementation | |||||
bdragonUnsubmitted Not Done Inline Actionsenglish nit: s/if/whether/ might be easier to read bdragon: english nit: s/if/whether/ might be easier to read | |||||
* includes a pmap_map_user_ptr function. | |||||
*/ | |||||
#define DEFINE_COPY_FUNC(ret, func, args) \ | |||||
DEFINE_IFUNC(, ret, func, args) \ | |||||
{ \ | |||||
return (PMAP_RESOLVE_FUNC(map_user_ptr) ? \ | |||||
func##_remap : func##_direct); \ | |||||
} | |||||
DEFINE_COPY_FUNC(int, subyte, (volatile void *, int)) | |||||
DEFINE_COPY_FUNC(int, copyinstr, (const void *, void *, size_t, size_t *)) | |||||
DEFINE_COPY_FUNC(int, copyin, (const void *, void *, size_t)) | |||||
DEFINE_COPY_FUNC(int, copyout, (const void *, void *, size_t)) | |||||
DEFINE_COPY_FUNC(int, suword, (volatile void *, long)) | |||||
DEFINE_COPY_FUNC(int, suword32, (volatile void *, int)) | |||||
#ifdef __powerpc64__ | |||||
DEFINE_COPY_FUNC(int, suword64, (volatile void *, int64_t)) | |||||
#endif | |||||
DEFINE_COPY_FUNC(int, fubyte, (volatile const void *)) | |||||
DEFINE_COPY_FUNC(int, fuword16, (volatile const void *)) | |||||
DEFINE_COPY_FUNC(int, fueword32, (volatile const void *, int32_t *)) | |||||
#ifdef __powerpc64__ | |||||
DEFINE_COPY_FUNC(int, fueword64, (volatile const void *, int64_t *)) | |||||
#endif | |||||
DEFINE_COPY_FUNC(int, fueword, (volatile const void *, long *)) | |||||
DEFINE_COPY_FUNC(int, casueword32, | |||||
(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)) | |||||
DEFINE_COPY_FUNC(int, casueword, (volatile u_long *, u_long, u_long *, u_long)) | |||||
#define REMAP(x) x##_remap | |||||
#else | |||||
#define REMAP(x) x | |||||
#endif | |||||
int | int | ||||
copyout(const void *kaddr, void *udaddr, size_t len) | REMAP(copyout)(const void *kaddr, void *udaddr, size_t len) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
const char *kp; | const char *kp; | ||||
char *up, *p; | char *up, *p; | ||||
size_t l; | size_t l; | ||||
Show All 22 Lines | while (len > 0) { | ||||
len -= l; | len -= l; | ||||
} | } | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
copyin(const void *udaddr, void *kaddr, size_t len) | REMAP(copyin)(const void *udaddr, void *kaddr, size_t len) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
const char *up; | const char *up; | ||||
char *kp, *p; | char *kp, *p; | ||||
size_t l; | size_t l; | ||||
Show All 22 Lines | while (len > 0) { | ||||
len -= l; | len -= l; | ||||
} | } | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) | REMAP(copyinstr)(const void *udaddr, void *kaddr, size_t len, size_t *done) | ||||
{ | { | ||||
const char *up; | const char *up; | ||||
char *kp; | char *kp; | ||||
size_t l; | size_t l; | ||||
int rv, c; | int rv, c; | ||||
kp = kaddr; | kp = kaddr; | ||||
up = udaddr; | up = udaddr; | ||||
Show All 16 Lines | REMAP(copyinstr)(const void *udaddr, void *kaddr, size_t len, size_t *done) | ||||
if (done != NULL) { | if (done != NULL) { | ||||
*done = l; | *done = l; | ||||
} | } | ||||
return (rv); | return (rv); | ||||
} | } | ||||
int | int | ||||
subyte(volatile void *addr, int byte) | REMAP(subyte)(volatile void *addr, int byte) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
char *p; | char *p; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 12 Lines | REMAP(subyte)(volatile void *addr, int byte) | ||||
*p = (char)byte; | *p = (char)byte; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef __powerpc64__ | #ifdef __powerpc64__ | ||||
int | int | ||||
suword32(volatile void *addr, int word) | REMAP(suword32)(volatile void *addr, int word) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
int *p; | int *p; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 9 Lines | if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) { | ||||
return (-1); | return (-1); | ||||
} | } | ||||
*p = word; | *p = word; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
#else | |||||
int | |||||
REMAP(suword32)(volatile void *addr, int32_t word) | |||||
{ | |||||
REMAP( return (suword)(addr, (long)word)); | |||||
} | |||||
#endif | #endif | ||||
int | int | ||||
suword(volatile void *addr, long word) | REMAP(suword)(volatile void *addr, long word) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
long *p; | long *p; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 12 Lines | REMAP(suword)(volatile void *addr, long word) | ||||
*p = word; | *p = word; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef __powerpc64__ | #ifdef __powerpc64__ | ||||
int | int | ||||
suword64(volatile void *addr, int64_t word) | REMAP(suword64)(volatile void *addr, int64_t word) | ||||
{ | { | ||||
return (suword(addr, (long)word)); | return (REMAP(suword)(addr, (long)word)); | ||||
} | } | ||||
#else | |||||
int | |||||
suword32(volatile void *addr, int32_t word) | |||||
{ | |||||
return (suword(addr, (long)word)); | |||||
} | |||||
#endif | #endif | ||||
int | int | ||||
fubyte(volatile const void *addr) | REMAP(fubyte)(volatile const void *addr) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
u_char *p; | u_char *p; | ||||
int val; | int val; | ||||
td = curthread; | td = curthread; | ||||
Show All 12 Lines | REMAP(fubyte)(volatile const void *addr) | ||||
val = *p; | val = *p; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (val); | return (val); | ||||
} | } | ||||
int | int | ||||
fuword16(volatile const void *addr) | REMAP(fuword16)(volatile const void *addr) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
uint16_t *p, val; | uint16_t *p, val; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 11 Lines | REMAP(fuword16)(volatile const void *addr) | ||||
val = *p; | val = *p; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (val); | return (val); | ||||
} | } | ||||
int | int | ||||
fueword32(volatile const void *addr, int32_t *val) | REMAP(fueword32)(volatile const void *addr, int32_t *val) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
int32_t *p; | int32_t *p; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 12 Lines | REMAP(fueword32)(volatile const void *addr, int32_t *val) | ||||
*val = *p; | *val = *p; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef __powerpc64__ | #ifdef __powerpc64__ | ||||
int | int | ||||
fueword64(volatile const void *addr, int64_t *val) | REMAP(fueword64)(volatile const void *addr, int64_t *val) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
int64_t *p; | int64_t *p; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 12 Lines | REMAP(fueword64)(volatile const void *addr, int64_t *val) | ||||
*val = *p; | *val = *p; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
int | int | ||||
fueword(volatile const void *addr, long *val) | REMAP(fueword)(volatile const void *addr, long *val) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
long *p; | long *p; | ||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
Show All 11 Lines | REMAP(fueword)(volatile const void *addr, long *val) | ||||
*val = *p; | *val = *p; | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
casueword32(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp, | REMAP(casueword32)(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp, | ||||
uint32_t new) | uint32_t new) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
uint32_t *p, val; | uint32_t *p, val; | ||||
int res; | int res; | ||||
Show All 31 Lines | REMAP(casueword32)(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp, | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
*oldvalp = val; | *oldvalp = val; | ||||
return (res); | return (res); | ||||
} | } | ||||
#ifndef __powerpc64__ | #ifndef __powerpc64__ | ||||
int | int | ||||
casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new) | REMAP(casueword)(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new) | ||||
{ | { | ||||
return (casueword32((volatile uint32_t *)addr, old, | return (casueword32((volatile uint32_t *)addr, old, | ||||
(uint32_t *)oldvalp, new)); | (uint32_t *)oldvalp, new)); | ||||
} | } | ||||
#else | #else | ||||
int | int | ||||
casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new) | REMAP(casueword)(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
pmap_t pm; | pmap_t pm; | ||||
jmp_buf env; | jmp_buf env; | ||||
u_long *p, val; | u_long *p, val; | ||||
int res; | int res; | ||||
td = curthread; | td = curthread; | ||||
Show All 36 Lines |
minor nit: s/IFUNcs/IFUNCs/