#include "assym.inc"
#include "opt_kstack_pages.h"
#include <sys/elf_common.h>
#include <machine/asm.h>
#include <machine/armreg.h>
#include <machine/proc.h>
.macro clear_step_flag pcbflags, tmp
tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
mrs \tmp, mdscr_el1
bic \tmp, \tmp, #MDSCR_SS
msr mdscr_el1, \tmp
isb
999:
.endm
.macro set_step_flag pcbflags, tmp
tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
mrs \tmp, mdscr_el1
orr \tmp, \tmp, #MDSCR_SS
msr mdscr_el1, \tmp
isb
999:
.endm
.macro pid_in_context_idr
adrp x9, arm64_pid_in_contextidr
ldrb w10, [x9, :lo12:arm64_pid_in_contextidr]
cbz w10, 998f
ldr x9, [x1, #TD_PROC]
ldr w10, [x9, #P_PID]
msr contextidr_el1, x10
998:
.endm
ENTRY(cpu_throw)
cbz x0, 1f
ldr x4, [x0, #TD_PCB]
ldr w5, [x4, #PCB_FLAGS]
clear_step_flag w5, x6
1:
pid_in_context_idr
#ifdef VFP
mov x19, x1
bl vfp_discard
mov x0, x19
#else
mov x0, x1
#endif
bl ptrauth_switch
#ifdef PERTHREAD_SSP
mov x19, x0
#endif
bl pmap_switch
mov x4, x0
#ifdef PERTHREAD_SSP
add x19, x19, #(TD_MD_CANARY)
msr sp_el0, x19
#endif
ldr w5, [x4, #PCB_FLAGS]
set_step_flag w5, x6
ldp x5, x6, [x4, #PCB_SP]
mov sp, x5
msr tpidr_el0, x6
ldr x6, [x4, #PCB_TPIDRRO]
msr tpidrro_el0, x6
ldp x19, x20, [x4, #PCB_REGS + (PCB_X19 + 0) * 8]
ldp x21, x22, [x4, #PCB_REGS + (PCB_X19 + 2) * 8]
ldp x23, x24, [x4, #PCB_REGS + (PCB_X19 + 4) * 8]
ldp x25, x26, [x4, #PCB_REGS + (PCB_X19 + 6) * 8]
ldp x27, x28, [x4, #PCB_REGS + (PCB_X19 + 8) * 8]
ldp x29, lr, [x4, #PCB_REGS + (PCB_X19 + 10) * 8]
ret
END(cpu_throw)
ENTRY(cpu_switch)
ldr x4, [x0, #TD_PCB]
stp x19, x20, [x4, #PCB_REGS + (PCB_X19 + 0) * 8]
stp x21, x22, [x4, #PCB_REGS + (PCB_X19 + 2) * 8]
stp x23, x24, [x4, #PCB_REGS + (PCB_X19 + 4) * 8]
stp x25, x26, [x4, #PCB_REGS + (PCB_X19 + 6) * 8]
stp x27, x28, [x4, #PCB_REGS + (PCB_X19 + 8) * 8]
stp x29, lr, [x4, #PCB_REGS + (PCB_X19 + 10) * 8]
mov x5, sp
mrs x6, tpidrro_el0
str x6, [x4, #PCB_TPIDRRO]
mrs x6, tpidr_el0
stp x5, x6, [x4, #PCB_SP]
ldr w5, [x4, #PCB_FLAGS]
clear_step_flag w5, x6
mov x19, x0
mov x20, x1
mov x21, x2
pid_in_context_idr
#ifdef VFP
bl vfp_save_state_switch
mov x0, x20
#else
mov x0, x1
#endif
bl ptrauth_switch
bl pmap_switch
mov x4, x0
mov x2, x21
mov x1, x20
mov x0, x19
#ifdef PERTHREAD_SSP
add x20, x20, #(TD_MD_CANARY)
msr sp_el0, x20
#endif
stlr x2, [x0, #TD_LOCK]
#if defined(SMP)
ldr x2, =_C_LABEL(blocked_lock)
1:
ldar x3, [x1, #TD_LOCK]
cmp x3, x2
b.eq 1b
#endif
ldr w5, [x4, #PCB_FLAGS]
set_step_flag w5, x6
ldp x5, x6, [x4, #PCB_SP]
mov sp, x5
msr tpidr_el0, x6
ldr x6, [x4, #PCB_TPIDRRO]
msr tpidrro_el0, x6
ldp x19, x20, [x4, #PCB_REGS + (PCB_X19 + 0) * 8]
ldp x21, x22, [x4, #PCB_REGS + (PCB_X19 + 2) * 8]
ldp x23, x24, [x4, #PCB_REGS + (PCB_X19 + 4) * 8]
ldp x25, x26, [x4, #PCB_REGS + (PCB_X19 + 6) * 8]
ldp x27, x28, [x4, #PCB_REGS + (PCB_X19 + 8) * 8]
ldp x29, lr, [x4, #PCB_REGS + (PCB_X19 + 10) * 8]
ret
END(cpu_switch)
ENTRY(fork_trampoline)
mov x0, x19
mov x1, x20
mov x2, sp
mov fp, #0
bl _C_LABEL(fork_exit)
msr daifset, #(DAIF_D | DAIF_INTR)
ldr x0, [x18, #PC_CURTHREAD]
ldr x10, [x0, #TD_PROC]
ldr x10, [x10, #P_MD_TCR]
mrs x11, tcr_el1
and x11, x11, #(~MD_TCR_FIELDS)
orr x11, x11, x10
msr tcr_el1, x11
bl ptrauth_enter_el0
ldp x18, lr, [sp, #TF_SP]
ldp x10, x11, [sp, #TF_ELR]
msr sp_el0, x18
msr spsr_el1, x11
msr elr_el1, x10
ldp x0, x1, [sp, #TF_X + 0 * 8]
ldp x2, x3, [sp, #TF_X + 2 * 8]
ldp x4, x5, [sp, #TF_X + 4 * 8]
ldp x6, x7, [sp, #TF_X + 6 * 8]
ldp x8, x9, [sp, #TF_X + 8 * 8]
ldp x10, x11, [sp, #TF_X + 10 * 8]
ldp x12, x13, [sp, #TF_X + 12 * 8]
ldp x14, x15, [sp, #TF_X + 14 * 8]
ldp x16, x17, [sp, #TF_X + 16 * 8]
ldp x18, x19, [sp, #TF_X + 18 * 8]
ldp x20, x21, [sp, #TF_X + 20 * 8]
ldp x22, x23, [sp, #TF_X + 22 * 8]
ldp x24, x25, [sp, #TF_X + 24 * 8]
ldp x26, x27, [sp, #TF_X + 26 * 8]
ldp x28, x29, [sp, #TF_X + 28 * 8]
ERET
END(fork_trampoline)
ENTRY(savectx)
stp x19, x20, [x0, #PCB_REGS + (PCB_X19 + 0) * 8]
stp x21, x22, [x0, #PCB_REGS + (PCB_X19 + 2) * 8]
stp x23, x24, [x0, #PCB_REGS + (PCB_X19 + 4) * 8]
stp x25, x26, [x0, #PCB_REGS + (PCB_X19 + 6) * 8]
stp x27, x28, [x0, #PCB_REGS + (PCB_X19 + 8) * 8]
stp x29, lr, [x0, #PCB_REGS + (PCB_X19 + 10) * 8]
mov x5, sp
mrs x6, tpidrro_el0
str x6, [x0, #PCB_TPIDRRO]
mrs x6, tpidr_el0
stp x5, x6, [x0, #PCB_SP]
#ifdef VFP
b vfp_save_state_savectx
#else
ret
#endif
END(savectx)
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)