Changeset View
Changeset View
Standalone View
Standalone View
sys/powerpc/powerpc/copyinout.c
Show First 20 Lines • Show All 427 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
casueword32(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp, | 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; | |||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
td->td_pcb->pcb_onfault = &env; | td->td_pcb->pcb_onfault = &env; | ||||
if (setjmp(env)) { | if (setjmp(env)) { | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, | if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, | ||||
sizeof(*p), NULL)) { | sizeof(*p), NULL)) { | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
res = 0; | |||||
__asm __volatile ( | __asm __volatile ( | ||||
"1:\tlwarx %0, 0, %2\n\t" /* load old value */ | "lwarx %0, 0, %3\n\t" /* load old value */ | ||||
"cmplw %3, %0\n\t" /* compare */ | "cmplw %4, %0\n\t" /* compare */ | ||||
"bne 2f\n\t" /* exit if not equal */ | "bne 1f\n\t" /* exit if not equal */ | ||||
"stwcx. %4, 0, %2\n\t" /* attempt to store */ | "stwcx. %5, 0, %3\n\t" /* attempt to store */ | ||||
"bne- 1b\n\t" /* spin if failed */ | "bne- 1f\n\t" /* if failed */ | ||||
"b 3f\n\t" /* we've succeeded */ | "b 2f\n\t" /* we've succeeded */ | ||||
"1:\n\t" | |||||
"stwcx. %0, 0, %4\n\t" /* clear reservation (74xx) */ | |||||
"li %2, 1\n\t" | |||||
"2:\n\t" | "2:\n\t" | ||||
"stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ | : "=&r" (val), "=m" (*p), "=&r" (res) | ||||
"3:\n\t" | |||||
: "=&r" (val), "=m" (*p) | |||||
: "r" (p), "r" (old), "r" (new), "m" (*p) | : "r" (p), "r" (old), "r" (new), "m" (*p) | ||||
: "cr0", "memory"); | : "cr0", "memory"); | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
*oldvalp = val; | *oldvalp = val; | ||||
return (0); | return (res); | ||||
} | } | ||||
#ifndef __powerpc64__ | #ifndef __powerpc64__ | ||||
int | int | ||||
casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new) | 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) | 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; | |||||
td = curthread; | td = curthread; | ||||
pm = &td->td_proc->p_vmspace->vm_pmap; | pm = &td->td_proc->p_vmspace->vm_pmap; | ||||
td->td_pcb->pcb_onfault = &env; | td->td_pcb->pcb_onfault = &env; | ||||
if (setjmp(env)) { | if (setjmp(env)) { | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, | if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, | ||||
sizeof(*p), NULL)) { | sizeof(*p), NULL)) { | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
res = 0; | |||||
__asm __volatile ( | __asm __volatile ( | ||||
"1:\tldarx %0, 0, %2\n\t" /* load old value */ | "ldarx %0, 0, %3\n\t" /* load old value */ | ||||
"cmpld %3, %0\n\t" /* compare */ | "cmpld %4, %0\n\t" /* compare */ | ||||
"bne 2f\n\t" /* exit if not equal */ | "bne 1f\n\t" /* exit if not equal */ | ||||
"stdcx. %4, 0, %2\n\t" /* attempt to store */ | "stdcx. %5, 0, %3\n\t" /* attempt to store */ | ||||
"bne- 1b\n\t" /* spin if failed */ | "bne- 1f\n\t" /* if failed */ | ||||
brooks: This comment is now out of date. | |||||
"b 3f\n\t" /* we've succeeded */ | "b 2f\n\t" /* we've succeeded */ | ||||
"1:\n\t" | |||||
"stdcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ | |||||
"li %2, 1\n\t" | |||||
"2:\n\t" | "2:\n\t" | ||||
"stdcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ | : "=&r" (val), "=m" (*p), "=&r" (res) | ||||
"3:\n\t" | |||||
: "=&r" (val), "=m" (*p) | |||||
: "r" (p), "r" (old), "r" (new), "m" (*p) | : "r" (p), "r" (old), "r" (new), "m" (*p) | ||||
: "cr0", "memory"); | : "cr0", "memory"); | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
*oldvalp = val; | *oldvalp = val; | ||||
return (0); | return (res); | ||||
} | } | ||||
#endif | #endif |
This comment is now out of date.