diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-08-28 02:28:15 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-08-28 02:28:15 +0000 |
commit | 87b5aa08ee93b317c4d88805ce8e361853411027 (patch) | |
tree | 7be2d51c02f47e64ee8dc4e4ec29bd1716dd3c70 | |
parent | f2ccfe95252579f4a77ff68a316f2f07850f0277 (diff) | |
download | FreeBSD-src-87b5aa08ee93b317c4d88805ce8e361853411027.zip FreeBSD-src-87b5aa08ee93b317c4d88805ce8e361853411027.tar.gz |
Implement casuword32, compare and set user integer, thank Marcel Moolenarr
who wrote the IA64 version of casuword32.
-rw-r--r-- | sys/amd64/amd64/support.S | 28 | ||||
-rw-r--r-- | sys/arm/arm/fusu.S | 1 | ||||
-rw-r--r-- | sys/i386/i386/support.s | 2 | ||||
-rw-r--r-- | sys/ia64/ia64/support.S | 50 | ||||
-rw-r--r-- | sys/powerpc/aim/copyinout.c | 6 | ||||
-rw-r--r-- | sys/powerpc/powerpc/copyinout.c | 6 | ||||
-rw-r--r-- | sys/sparc64/sparc64/support.S | 2 | ||||
-rw-r--r-- | sys/sys/systm.h | 3 |
8 files changed, 96 insertions, 2 deletions
diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index ea547f9..4e8efdf 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -314,6 +314,34 @@ copyin_fault: ret /* + * casuword32. Compare and set user integer. Returns -1 or the current value. + * dst = %rdi, old = %rsi, new = %rdx + */ +ENTRY(casuword32) + movq PCPU(CURPCB),%rcx + movq $fusufault,PCB_ONFAULT(%rcx) + + movq $VM_MAXUSER_ADDRESS-4,%rax + cmpq %rax,%rdi /* verify address is valid */ + ja fusufault + + movl %esi,%eax /* old */ +#ifdef SMP + lock +#endif + cmpxchgl %edx,(%rdi) /* new = %edx */ + + /* + * The old value is in %eax. If the store succeeded it will be the + * value we expected (old) from before the store, otherwise it will + * be the current value. + */ + + movq PCPU(CURPCB),%rcx + movq $0,PCB_ONFAULT(%rcx) + ret + +/* * casuptr. Compare and set user pointer. Returns -1 or the current value. * dst = %rdi, old = %rsi, new = %rdx */ diff --git a/sys/arm/arm/fusu.S b/sys/arm/arm/fusu.S index 095491a..f0d3688 100644 --- a/sys/arm/arm/fusu.S +++ b/sys/arm/arm/fusu.S @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); * Fetch an int from the user's address space. */ +ALTENTRY(casuword32) ENTRY(casuptr) #ifdef MULTIPROCESSOR /* XXX Probably not appropriate for non-Hydra SMPs */ diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index c3ac173..aee43a4 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -1142,6 +1142,8 @@ fastmove_tail_fault: /* * casuptr. Compare and set user pointer. Returns -1 or the current value. */ + +ALTENTRY(casuword32) ENTRY(casuptr) movl PCPU(CURPCB),%ecx movl $fusufault,PCB_ONFAULT(%ecx) diff --git a/sys/ia64/ia64/support.S b/sys/ia64/ia64/support.S index 95686b3..4a21274 100644 --- a/sys/ia64/ia64/support.S +++ b/sys/ia64/ia64/support.S @@ -242,6 +242,56 @@ ENTRY(casuptr, 3) END(casuptr) /* + * casuword32(int32_t *p, int32_t old, int32_t new) + * Perform a 32-bit compare-exchange in user space. + */ +ENTRY(casuword32, 3) +{ .mlx + add r15=PC_CURTHREAD,r13 + movl r14=VM_MAX_ADDRESS + ;; +} +{ .mib + ld8 r15=[r15] // r15 = curthread + cmp.geu p6,p0=in0,r14 +(p6) br.dpnt.few 1f + ;; +} +{ .mlx + add r15=TD_PCB,r15 + movl r14=fusufault + ;; +} +{ .mmi + ld8 r15=[r15] // r15 = PCB + ;; + mov ar.ccv=in1 + add r15=PCB_ONFAULT,r15 + ;; +} +{ .mmi + st8 [r15]=r14 // Set onfault + ;; + cmpxchg4.rel ret0=[in0],in2,ar.ccv + nop 0 + ;; +} +{ .mfb + st8.rel [r15]=r0 // Clear onfault + nop 0 + br.ret.sptk rp + ;; +} +1: +{ .mfb + add ret0=-1,r0 + nop 0 + br.ret.sptk rp + ;; +} +END(casuword32) + +/* * subyte(void *addr, int byte) * suword16(void *addr, int word) * suword32(void *addr, int word) diff --git a/sys/powerpc/aim/copyinout.c b/sys/powerpc/aim/copyinout.c index 7fa91ce..4c19cbf 100644 --- a/sys/powerpc/aim/copyinout.c +++ b/sys/powerpc/aim/copyinout.c @@ -322,6 +322,12 @@ fuword32(const void *addr) return ((int32_t)fuword(addr)); } +int32_t +casuword32(int32_t *base, int32_t oldval, int32_t newval) +{ + return (casuptr(base, oldval, newval)); +} + intptr_t casuptr(intptr_t *addr, intptr_t old, intptr_t new) { diff --git a/sys/powerpc/powerpc/copyinout.c b/sys/powerpc/powerpc/copyinout.c index 7fa91ce..4c19cbf 100644 --- a/sys/powerpc/powerpc/copyinout.c +++ b/sys/powerpc/powerpc/copyinout.c @@ -322,6 +322,12 @@ fuword32(const void *addr) return ((int32_t)fuword(addr)); } +int32_t +casuword32(int32_t *base, int32_t oldval, int32_t newval) +{ + return (casuptr(base, oldval, newval)); +} + intptr_t casuptr(intptr_t *addr, intptr_t old, intptr_t new) { diff --git a/sys/sparc64/sparc64/support.S b/sys/sparc64/sparc64/support.S index 57ca637..d554f63 100644 --- a/sys/sparc64/sparc64/support.S +++ b/sys/sparc64/sparc64/support.S @@ -402,7 +402,7 @@ fs_nofault_begin: .set susword, suword16 .set suword, suword64 - .globl casuptr, fuptr, suptr + .globl casuword32, casuptr, fuptr, suptr .set casuptr, casuword64 .set fuptr, fuword64 .set suptr, suword64 diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 35872f4..bc2c65d 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -203,7 +203,8 @@ int suword(void *base, long word); int suword16(void *base, int word); int suword32(void *base, int32_t word); int suword64(void *base, int64_t word); -intptr_t casuptr(intptr_t *p, intptr_t old, intptr_t new); +int32_t casuword32(int32_t *base, int32_t oldval, int32_t newval); +intptr_t casuptr(intptr_t *p, intptr_t oldval, intptr_t newval); void realitexpire(void *); |