#include <aarch64/asm.h>
#include <aarch64/locore.h>
#include "assym.h"
#include "opt_cpuoptions.h"
#include "opt_ddb.h"
#include "opt_kasan.h"
RCSID("$NetBSD: cpuswitch.S,v 1.41 2023/03/01 08:17:24 riastradh Exp $")
ARMV8_DEFINE_OPTIONS
ENTRY_NP(cpu_switchto)
sub sp, sp, #TF_SIZE
stp x19, x20, [sp, #TF_X19]
stp x21, x22, [sp, #TF_X21]
stp x23, x24, [sp, #TF_X23]
stp x25, x26, [sp, #TF_X25]
stp x27, x28, [sp, #TF_X27]
stp x29, x30, [sp, #TF_X29]
#ifdef DDB
.if TF_SP + 8 == TF_PC
stp xzr, lr, [sp, #TF_SP]
.else
str xzr, [sp, #TF_SP]
str lr, [sp, #TF_PC]
.endif
#endif
mov x4, sp
mrs x5, cpacr_el1
str x5, [x0, #L_MD_CPACR]
ldr x6, [x0, #L_PCB]
str x4, [x6, #PCB_TF]
ldr x6, [x1, #L_PCB]
ldr x4, [x6, #PCB_TF]
#ifdef DDB
str xzr, [x6, #PCB_TF]
#endif
ldr x5, [x1, #L_MD_CPACR]
DISABLE_INTERRUPT
mov sp, x4
msr cpacr_el1, x5
isb
#ifdef ARMV83_PAC
adrl x4, _C_LABEL(aarch64_pac_enabled)
ldr w4, [x4]
cbz w4, 1f
ldp x5, x6, [x1, #L_MD_IA_KERN]
msr APIAKeyLo_EL1, x5
msr APIAKeyHi_EL1, x6
ldr w5, [x1, #L_FLAG]
and w5, w5, #LW_SYSTEM
cbnz w5, 1f
ldp x5, x6, [x1, #L_MD_IB_USER]
msr APIBKeyLo_EL1, x5
msr APIBKeyHi_EL1, x6
ldp x5, x6, [x1, #L_MD_DA_USER]
msr APDAKeyLo_EL1, x5
msr APDAKeyHi_EL1, x6
ldp x5, x6, [x1, #L_MD_DB_USER]
msr APDBKeyLo_EL1, x5
msr APDBKeyHi_EL1, x6
ldp x5, x6, [x1, #L_MD_GA_USER]
msr APGAKeyLo_EL1, x5
msr APGAKeyHi_EL1, x6
1:
isb
#endif
msr tpidr_el1, x1
ldr x3, [x1, #L_CPU]
dmb ishst
str x1, [x3, #CI_CURLWP]
dmb ish
ENABLE_INTERRUPT
ldp x19, x20, [sp, #TF_X19]
ldp x21, x22, [sp, #TF_X21]
ldp x23, x24, [sp, #TF_X23]
ldp x25, x26, [sp, #TF_X25]
ldp x27, x28, [sp, #TF_X27]
ldp x29, lr, [sp, #TF_X29]
add sp, sp, #TF_SIZE
ret
END(cpu_switchto)
ENTRY_NP(cpu_switchto_softint)
#ifdef DDB
mov x7, sp
#endif
stp x19, x20, [sp, #-16]!
sub sp, sp, #TF_SIZE
adr x2, softint_cleanup
mrs x19, daif
stp x19, lr, [sp, #TF_X19]
stp x21, x22, [sp, #TF_X21]
stp x23, x24, [sp, #TF_X23]
stp x25, x26, [sp, #TF_X25]
stp x27, x28, [sp, #TF_X27]
stp x29, x2, [sp, #TF_X29]
mrs x19, tpidr_el1
mov x4, sp
mrs x5, cpacr_el1
ldr x6, [x19, #L_PCB]
str x4, [x6, #PCB_TF]
str x5, [x19, #L_MD_CPACR]
#ifdef KASAN
stp x0, x1, [sp, #-16]!
#ifdef DDB
stp x7, lr, [sp, #-16]!
#endif
bl _C_LABEL(kasan_softint)
#ifdef DDB
ldp x7, lr, [sp], #16
#endif
ldp x0, x1, [sp], #16
#endif
ldr x4, [x0, #L_MD_UTF]
DISABLE_INTERRUPT
ldr x20, [x19, #L_CPU]
sub sp, x4, #TF_SIZE
msr tpidr_el1, x0
dmb ishst
str x0, [x20, #CI_CURLWP]
mov x5, #CPACR_FPEN_NONE
msr cpacr_el1, x5
isb
#ifdef ARMV83_PAC
adrl x4, _C_LABEL(aarch64_pac_enabled)
ldr w4, [x4]
cbz w4, 1f
ldp x5, x6, [x0, #L_MD_IA_KERN]
msr APIAKeyLo_EL1, x5
msr APIAKeyHi_EL1, x6
isb
1:
#endif
ENABLE_INTERRUPT
#ifdef DDB
stp x7, lr, [sp, #-16]!
#endif
mov x0, x19
bl _C_LABEL(softint_dispatch)
#ifdef DDB
add sp, sp, #16
#endif
ldr x6, [x19, #L_PCB]
ldr x4, [x6, #PCB_TF]
#ifdef DDB
str xzr, [x6, #PCB_TF]
#endif
ldr x5, [x19, #L_MD_CPACR]
DISABLE_INTERRUPT
msr tpidr_el1, x19
ldr x3, [x19, #L_CPU]
dmb ishst
str x19, [x3, #CI_CURLWP]
dmb ish
mov sp, x4
msr cpacr_el1, x5
isb
#ifdef ARMV83_PAC
adrl x4, _C_LABEL(aarch64_pac_enabled)
ldr w4, [x4]
cbz w4, 1f
ldp x5, x6, [x19, #L_MD_IA_KERN]
msr APIAKeyLo_EL1, x5
msr APIAKeyHi_EL1, x6
isb
1:
#endif
ldp x19, lr, [sp, #TF_X19]
msr daif, x19
add sp, sp, #TF_SIZE
ldp x19, x20, [sp], #16
ret
END(cpu_switchto_softint)
ENTRY_NP(softint_cleanup)
mov lr, x20
mrs x20, tpidr_el1
ldr x3, [x20, #L_CPU]
ldr w2, [x3, #CI_MTX_COUNT]
add w2, w2, #1
str w2, [x3, #CI_MTX_COUNT]
msr daif, x19
ldp x19, x20, [sp], #16
ret
END(softint_cleanup)
ENTRY_NP(lwp_trampoline)
stp x0, x1, [sp, #-16]!
bl _C_LABEL(lwp_startup)
ldp x0, x1, [sp], #16
#ifdef ARMV83_PAC
adrl x4, _C_LABEL(aarch64_pac_enabled)
ldr w4, [x4]
cbz w4, 1f
mov x26, x1
bl _C_LABEL(cprng_strong64)
mov x25, x0
bl _C_LABEL(cprng_strong64)
stp x25, x0, [x26, #L_MD_IA_KERN]
msr APIAKeyLo_EL1, x25
msr APIAKeyHi_EL1, x0
isb
1:
#endif
adr lr, el0_trap_exit
mov x0, x28
mov x16, x27
br x16
END(lwp_trampoline)
ENTRY_NP(cpu_set_onfault)
mrs x2, tpidr_el1
str x0, [x2, #L_MD_ONFAULT]
stp x19, x20, [x0, #(FB_X19 * 8)]
stp x21, x22, [x0, #(FB_X21 * 8)]
stp x23, x24, [x0, #(FB_X23 * 8)]
stp x25, x26, [x0, #(FB_X25 * 8)]
stp x27, x28, [x0, #(FB_X27 * 8)]
stp x29, x30, [x0, #(FB_X29 * 8)]
mov x1, sp
str x1, [x0, #(FB_SP * 8)]
mov x0, #0
ret
END(cpu_set_onfault)
ENTRY_NP(setjmp)
stp x19, x20, [x0, #(LBL_X19 * 8)]
stp x21, x22, [x0, #(LBL_X21 * 8)]
stp x23, x24, [x0, #(LBL_X23 * 8)]
stp x25, x26, [x0, #(LBL_X25 * 8)]
stp x27, x28, [x0, #(LBL_X27 * 8)]
stp x29, x30, [x0, #(LBL_X29 * 8)]
mov x1, sp
str x1, [x0, #(LBL_SP * 8)]
mov x0, #0
ret
END(setjmp)
ENTRY_NP(longjmp)
ldp x19, x20, [x0, #(LBL_X19 * 8)]
ldp x21, x22, [x0, #(LBL_X21 * 8)]
ldp x23, x24, [x0, #(LBL_X23 * 8)]
ldp x25, x26, [x0, #(LBL_X25 * 8)]
ldp x27, x28, [x0, #(LBL_X27 * 8)]
ldp x29, x30, [x0, #(LBL_X29 * 8)]
ldr x1, [x0, #(LBL_SP * 8)]
mov sp, x1
mov x0, #1
ret
END(longjmp)
ENTRY_NP(load_fpregs)
ldp q0, q1, [x0, #FPREG_Q0]
ldp q2, q3, [x0, #FPREG_Q2]
ldp q4, q5, [x0, #FPREG_Q4]
ldp q6, q7, [x0, #FPREG_Q6]
ldp q8, q9, [x0, #FPREG_Q8]
ldp q10, q11, [x0, #FPREG_Q10]
ldp q12, q13, [x0, #FPREG_Q12]
ldp q14, q15, [x0, #FPREG_Q14]
ldp q16, q17, [x0, #FPREG_Q16]
ldp q18, q19, [x0, #FPREG_Q18]
ldp q20, q21, [x0, #FPREG_Q20]
ldp q22, q23, [x0, #FPREG_Q22]
ldp q24, q25, [x0, #FPREG_Q24]
ldp q26, q27, [x0, #FPREG_Q26]
ldp q28, q29, [x0, #FPREG_Q28]
ldp q30, q31, [x0, #FPREG_Q30]
ldr w8, [x0, #FPREG_FPCR]
ldr w9, [x0, #FPREG_FPSR]
msr fpcr, x8
msr fpsr, x9
ret
END(load_fpregs)
ENTRY_NP(save_fpregs)
stp q0, q1, [x0, #FPREG_Q0]
stp q2, q3, [x0, #FPREG_Q2]
stp q4, q5, [x0, #FPREG_Q4]
stp q6, q7, [x0, #FPREG_Q6]
stp q8, q9, [x0, #FPREG_Q8]
stp q10, q11, [x0, #FPREG_Q10]
stp q12, q13, [x0, #FPREG_Q12]
stp q14, q15, [x0, #FPREG_Q14]
stp q16, q17, [x0, #FPREG_Q16]
stp q18, q19, [x0, #FPREG_Q18]
stp q20, q21, [x0, #FPREG_Q20]
stp q22, q23, [x0, #FPREG_Q22]
stp q24, q25, [x0, #FPREG_Q24]
stp q26, q27, [x0, #FPREG_Q26]
stp q28, q29, [x0, #FPREG_Q28]
stp q30, q31, [x0, #FPREG_Q30]
mrs x8, fpcr
mrs x9, fpsr
str w8, [x0, #FPREG_FPCR]
str w9, [x0, #FPREG_FPSR]
ret
END(save_fpregs)