#include <sys/elf_common.h>
#include <machine/asm.h>
#include <machine/param.h>
#include <machine/vmparam.h>
#include <sys/errno.h>
#include "assym.inc"
.macro check_user_access user_arg, limit, bad_addr_func
ldr x7, =(\limit)
cmp x\user_arg, x7
b.cs \bad_addr_func
.endm
futex_fault:
SET_FAULT_HANDLER(xzr, x1)
EXIT_USER_ACCESS_CHECK(w0, x1)
futex_fault_nopcb:
mov x0, #EFAULT
ret
#define LINUX_FUTEX_MAX_LOOPS 128
ENTRY(futex_xchgl)
check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
adr x9, futex_fault
SET_FAULT_HANDLER(x9, x4)
ENTER_USER_ACCESS(w9, x4)
mov w5, #LINUX_FUTEX_MAX_LOOPS
prfm pstl1strm, [x1]
mov w6, w0
1: ldxr w4, [x1]
stlxr w0, w6, [x1]
cbz w0, 3f
sub w5, w5, w0
cbnz w5, 1b
mov x0, #EAGAIN
3: dmb ish
EXIT_USER_ACCESS(w9)
SET_FAULT_HANDLER(xzr, x9)
str w4, [x2]
ret
END(futex_xchgl)
ENTRY(futex_addl)
check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
adr x9, futex_fault
SET_FAULT_HANDLER(x9, x4)
ENTER_USER_ACCESS(w9, x4)
mov w5, #LINUX_FUTEX_MAX_LOOPS
prfm pstl1strm, [x1]
mov w6, w0
1: ldxr w4, [x1]
add w3, w4, w6
stlxr w0, w3, [x1]
cbz w0, 3f
sub w5, w5, w0
cbnz w5, 1b
mov x0, #EAGAIN
3: dmb ish
EXIT_USER_ACCESS(w9)
SET_FAULT_HANDLER(xzr, x9)
str w4, [x2]
ret
END(futex_addl)
ENTRY(futex_orl)
check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
adr x9, futex_fault
SET_FAULT_HANDLER(x9, x4)
ENTER_USER_ACCESS(w9, x4)
mov w5, #LINUX_FUTEX_MAX_LOOPS
prfm pstl1strm, [x1]
mov w6, w0
1: ldxr w4, [x1]
orr w3, w4, w6
stlxr w0, w3, [x1]
cbz w0, 3f
sub w5, w5, w0
cbnz w5, 1b
mov x0, #EAGAIN
3: dmb ish
EXIT_USER_ACCESS(w9)
SET_FAULT_HANDLER(xzr, x9)
str w4, [x2]
ret
END(futex_orl)
ENTRY(futex_andl)
check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
adr x9, futex_fault
SET_FAULT_HANDLER(x9, x4)
ENTER_USER_ACCESS(w9, x4)
mov w5, #LINUX_FUTEX_MAX_LOOPS
prfm pstl1strm, [x1]
mov w6, w0
1: ldxr w4, [x1]
and w3, w4, w6
stlxr w0, w3, [x1]
cbz w0, 3f
sub w5, w5, w0
cbnz w5, 1b
mov x0, #EAGAIN
3: dmb ish
EXIT_USER_ACCESS(w9)
SET_FAULT_HANDLER(xzr, x9)
str w4, [x2]
ret
END(futex_andl)
ENTRY(futex_xorl)
check_user_access 1, (VM_MAXUSER_ADDRESS-3), futex_fault_nopcb
adr x9, futex_fault
SET_FAULT_HANDLER(x9, x4)
ENTER_USER_ACCESS(w9, x4)
mov w5, #LINUX_FUTEX_MAX_LOOPS
prfm pstl1strm, [x1]
mov w6, w0
1: ldxr w4, [x1]
eor w3, w4, w6
stlxr w0, w3, [x1]
cbz w0, 3f
sub w5, w5, w0
cbnz w5, 1b
mov x0, #EAGAIN
3: dmb ish
EXIT_USER_ACCESS(w9)
SET_FAULT_HANDLER(xzr, x9)
str w4, [x2]
ret
END(futex_xorl)
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)
.section .note.GNU-stack,"",%progbits