Page MenuHomeFreeBSD

D39837.id121107.diff
No OneTemporary

D39837.id121107.diff

diff --git a/sys/arm64/arm64/support.S b/sys/arm64/arm64/support.S
--- a/sys/arm64/arm64/support.S
+++ b/sys/arm64/arm64/support.S
@@ -32,6 +32,8 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
+#include <sys/errno.h>
+
#include <machine/setjmp.h>
#include <machine/param.h>
#include <machine/vmparam.h>
@@ -55,6 +57,123 @@
ret
END(fsu_fault)
+ENTRY(swapuword8_llsc)
+ check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
+ adr x6, fsu_fault /* Load the fault handler */
+ mov w5, #1
+ SET_FAULT_HANDLER(x6, x4) /* And set it */
+ ENTER_USER_ACCESS(w6, x4)
+
+ /*
+ * x1 holds the address of our swap value; we pull the new value from it
+ * and stash the old value there since the caller will need it. The
+ * return value of swp_emulate_atomic() matches store(9)/fetch(9)
+ * semantics so that we can just re-use the existing fault handler.
+ */
+ ldr w7, [x1]
+
+ ldxrb w2, [x0]
+ stxrb w3, w7, [x0]
+ cbnz w3, 1f /* Don't clobber return on failure */
+
+ mov w5, #0 /* Return success */
+
+ str x2, [x1] /* Stash old value in *val */
+
+1: EXIT_USER_ACCESS(w6)
+ SET_FAULT_HANDLER(xzr, x6)
+ mov w0, w5
+ ret
+END(swapuword8_llsc)
+
+ENTRY(swapuword8_lse)
+ check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
+ adr x6, fsu_fault /* Load the fault handler */
+ mov w5, #1
+ SET_FAULT_HANDLER(x6, x4) /* And set it */
+ ENTER_USER_ACCESS(w6, x4)
+
+ /*
+ * x1 holds the address of our swap value; we pull the new value from it
+ * and stash the old value there since the caller will need it. The
+ * return value of swp_emulate_atomic() matches store(9)/fetch(9)
+ * semantics so that we can just re-use the existing fault handler.
+ */
+ ldr w7, [x1]
+
+ .arch_extension lse
+ swpb w7, w2, [x0]
+ .arch_extension nolse
+
+ mov w5, #0 /* Return success */
+
+ str x2, [x1] /* Stash old value in *val */
+
+ EXIT_USER_ACCESS(w6)
+ SET_FAULT_HANDLER(xzr, x6)
+ mov w0, w5
+ ret
+END(swapuword8_lse)
+
+ENTRY(swapuword32_llsc)
+ check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
+ adr x6, fsu_fault /* Load the fault handler */
+ mov w5, #1
+ SET_FAULT_HANDLER(x6, x4) /* And set it */
+ ENTER_USER_ACCESS(w6, x4)
+
+ /*
+ * x1 holds the address of our swap value; we pull the new value from it
+ * and stash the old value there since the caller will need it. The
+ * return value of swp_emulate_atomic() matches store(9)/fetch(9)
+ * semantics so that we can just re-use the existing fault handler.
+ */
+ ldr w7, [x1]
+
+ ldxr w2, [x0] /* Stash the old value in w2 */
+ stxr w3, w7, [x0] /* Store new value */
+ cbnz w3, 1f /* Don't clobber return on failure */
+
+ mov w5, #0 /* Return success */
+
+ str x2, [x1] /* Stash old value in *val */
+
+1: EXIT_USER_ACCESS(w6)
+ SET_FAULT_HANDLER(xzr, x6)
+ mov w0, w5
+ ret
+END(swapuword32_llsc)
+
+ENTRY(swapuword32_lse)
+ check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
+ adr x6, fsu_fault /* Load the fault handler */
+ mov w5, #1
+ SET_FAULT_HANDLER(x6, x4) /* And set it */
+ ENTER_USER_ACCESS(w6, x4)
+
+ /*
+ * x1 holds the address of our swap value; we pull the new value from it
+ * and stash the old value there since the caller will need it. The
+ * return value of swp_emulate_atomic() matches store(9)/fetch(9)
+ * semantics so that we can just re-use the existing fault handler.
+ */
+ ldr w7, [x1]
+
+ .arch_extension lse
+ swp w7, w2, [x0]
+ .arch_extension nolse
+
+ mov w5, #0 /* Return success */
+
+ str x2, [x1] /* Stash old value in *val */
+
+ EXIT_USER_ACCESS(w6)
+ SET_FAULT_HANDLER(xzr, x6)
+ mov w0, w5
+ ret
+END(swapuword32_llsc)
+
+
/*
* int casueword32_llsc(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
*/
diff --git a/sys/arm64/arm64/support_ifunc.c b/sys/arm64/arm64/support_ifunc.c
--- a/sys/arm64/arm64/support_ifunc.c
+++ b/sys/arm64/arm64/support_ifunc.c
@@ -39,6 +39,12 @@
int casueword_llsc(volatile u_long *, u_long, u_long *, u_long);
int casueword_lse(volatile u_long *, u_long, u_long *, u_long);
+int swapuword8_llsc(volatile uint8_t *, uint8_t *);
+int swapuword8_lse(volatile uint8_t *, uint8_t *);
+
+int swapuword32_llsc(volatile uint32_t *, uint32_t *);
+int swapuword32_lse(volatile uint32_t *, uint32_t *);
+
DEFINE_IFUNC(, int, casueword32, (volatile uint32_t *base, uint32_t oldval,
uint32_t *oldvalp, uint32_t newval))
{
@@ -56,3 +62,19 @@
return (casueword_llsc);
}
+
+DEFINE_IFUNC(, int, swapuword8, (volatile uint8_t *base, uint8_t *val))
+{
+ if (lse_supported)
+ return (swapuword8_lse);
+
+ return (swapuword8_llsc);
+}
+
+DEFINE_IFUNC(, int, swapuword32, (volatile uint32_t *base, uint32_t *val))
+{
+ if (lse_supported)
+ return (swapuword32_lse);
+
+ return (swapuword32_llsc);
+}
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -321,6 +321,10 @@
int suword16(volatile void *base, int word);
int suword32(volatile void *base, int32_t word);
int suword64(volatile void *base, int64_t word);
+#ifdef __aarch64__
+int swapuword8(volatile uint8_t *base, uint8_t *val);
+int swapuword32(volatile uint32_t *base, uint32_t *val);
+#endif
uint32_t casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval);
u_long casuword(volatile u_long *p, u_long oldval, u_long newval);
int casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 7, 1:48 PM (7 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36177460
Default Alt Text
D39837.id121107.diff (5 KB)

Event Timeline