#include <sys/elf_common.h>
#include <machine/asm.h>
#include <machine/setjmp.h>
#include <machine/param.h>
#include <machine/vmparam.h>
#include "assym.inc"
.macro check_user_access user_arg, limit, bad_addr_func
and x6, x\user_arg, #(~TBI_ADDR_MASK)
ldr x7, =(\limit)
cmp x6, x7
b.cs \bad_addr_func
.endm
ENTRY(fsu_fault)
SET_FAULT_HANDLER(xzr, x1)
EXIT_USER_ACCESS_CHECK(w0, x1)
fsu_fault_nopcb:
mov x0, #-1
ret
END(fsu_fault)
ENTRY(swapueword8_llsc)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
ldrb w7, [x1]
ldxrb w2, [x0]
stxrb w3, w7, [x0]
cbnz w3, 1f
strb w2, [x1]
1: EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
mov w0, w3
ret
END(swapueword8_llsc)
ENTRY(swapueword8_lse)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
ldrb w7, [x1]
.arch_extension lse
swpb w7, w2, [x0]
.arch_extension nolse
strb w2, [x1]
EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
mov w0, #0
ret
END(swapueword8_lse)
ENTRY(swapueword32_llsc)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
ldr w7, [x1]
ldxr w2, [x0]
stxr w3, w7, [x0]
cbnz w3, 1f
str w2, [x1]
1: EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
mov w0, w3
ret
END(swapueword32_llsc)
ENTRY(swapueword32_lse)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
ldr w7, [x1]
.arch_extension lse
swp w7, w2, [x0]
.arch_extension nolse
str w2, [x1]
EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
mov w0, #0
ret
END(swapueword32_llsc)
ENTRY(casueword32_llsc)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
mov w5, #1
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
ldxr w4, [x0]
cmp w4, w1
b.ne 1f
stxr w5, w3, [x0]
1: EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
str w4, [x2]
mov w0, w5
ret
END(casueword32_llsc)
ENTRY(casueword32_lse)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
mov w7, w1
.arch_extension lse
cas w1, w3, [x0]
.arch_extension nolse
cmp w1, w7
cset w0, ne
EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
str w1, [x2]
ret
END(casueword32_lse)
ENTRY(casueword_llsc)
check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
adr x6, fsu_fault
mov w5, #1
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
ldxr x4, [x0]
cmp x4, x1
b.ne 1f
stxr w5, x3, [x0]
1: EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
str x4, [x2]
mov w0, w5
ret
END(casueword_llsc)
ENTRY(casueword_lse)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
adr x6, fsu_fault
SET_FAULT_HANDLER(x6, x4)
ENTER_USER_ACCESS(w6, x4)
mov x7, x1
.arch_extension lse
cas x1, x3, [x0]
.arch_extension nolse
cmp x1, x7
cset w0, ne
EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x6)
str x1, [x2]
ret
END(casueword_lse)
.macro fsudata insn, ret_reg, user_arg
adr x7, fsu_fault
SET_FAULT_HANDLER(x7, x6)
\insn \ret_reg, [x\user_arg]
SET_FAULT_HANDLER(xzr, x6)
.endm
ENTRY(fubyte)
check_user_access 0, (VM_MAXUSER_ADDRESS), fsu_fault_nopcb
fsudata ldtrb, w0, 0
ret
END(fubyte)
ENTRY(fuword16)
check_user_access 0, (VM_MAXUSER_ADDRESS-1), fsu_fault_nopcb
fsudata ldtrh, w0, 0
ret
END(fuword16)
ENTRY(fueword32)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
fsudata ldtr, w0, 0
str w0, [x1]
mov w0, #0
ret
END(fueword32)
EENTRY(fueword64)
ENTRY(fueword)
check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
fsudata ldtr, x0, 0
str x0, [x1]
mov x0, #0
ret
END(fueword)
EEND(fueword64)
ENTRY(subyte)
check_user_access 0, (VM_MAXUSER_ADDRESS), fsu_fault_nopcb
fsudata sttrb, w1, 0
mov x0, #0
ret
END(subyte)
ENTRY(suword16)
check_user_access 0, (VM_MAXUSER_ADDRESS-1), fsu_fault_nopcb
fsudata sttrh, w1, 0
mov x0, #0
ret
END(suword16)
ENTRY(suword32)
check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
fsudata sttr, w1, 0
mov x0, #0
ret
END(suword32)
EENTRY(suword64)
ENTRY(suword)
check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
fsudata sttr, x1, 0
mov x0, #0
ret
END(suword)
EEND(suword64)
ENTRY(setjmp)
mov x8, sp
str x8, [x0], #8
stp x19, x20, [x0], #16
stp x21, x22, [x0], #16
stp x23, x24, [x0], #16
stp x25, x26, [x0], #16
stp x27, x28, [x0], #16
stp x29, lr, [x0], #16
mov x0, #0
ret
END(setjmp)
ENTRY(longjmp)
ldr x8, [x0], #8
mov sp, x8
ldp x19, x20, [x0], #16
ldp x21, x22, [x0], #16
ldp x23, x24, [x0], #16
ldp x25, x26, [x0], #16
ldp x27, x28, [x0], #16
ldp x29, lr, [x0], #16
mov x0, x1
ret
END(longjmp)
ENTRY(pagezero_simple)
add x1, x0, #PAGE_SIZE
1:
stp xzr, xzr, [x0], #0x10
stp xzr, xzr, [x0], #0x10
stp xzr, xzr, [x0], #0x10
stp xzr, xzr, [x0], #0x10
cmp x0, x1
b.ne 1b
ret
END(pagezero_simple)
ENTRY(pagezero_cache)
add x1, x0, #PAGE_SIZE
adrp x2, dczva_line_size
ldr x2, [x2, :lo12:dczva_line_size]
1:
dc zva, x0
add x0, x0, x2
cmp x0, x1
b.ne 1b
ret
END(pagezero_cache)
ENTRY(pagezero_mops)
mov x1, #PAGE_SIZE
.inst 0x19df0420
.inst 0x19df4420
.inst 0x19df8420
ret
END(pagezero_mops)
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)