11bb92983SJerome Forissier/* SPDX-License-Identifier: BSD-2-Clause */ 2e0cbf7deSJens Wiklander/* 393dc6b29SJens Wiklander * Copyright (c) 2015-2022, Linaro Limited 4e0cbf7deSJens Wiklander */ 5e0cbf7deSJens Wiklander 6e13d1040SJens Wiklander#include <arm64_macros.S> 77e399f9bSJens Wiklander#include <arm.h> 80e7659caSJens Wiklander#include <asm.S> 989fe7c3cSJerome Forissier#include <generated/asm-defines.h> 100e7659caSJens Wiklander#include <keep.h> 1114d6d42bSJens Wiklander#include <kernel/cache_helpers.h> 12891569afSJens Wiklander#include <kernel/thread.h> 137e399f9bSJens Wiklander#include <kernel/thread_private.h> 145b8a58b4SJens Wiklander#include <mm/core_mmu.h> 15e13d1040SJens Wiklander#include <smccc.h> 160e7659caSJens Wiklander 17e0cbf7deSJens Wiklander .macro get_thread_ctx core_local, res, tmp0, tmp1 18f86aa9e1SJerome Forissier ldrh w\tmp0, [\core_local, \ 19c02f9fb0SJens Wiklander #THREAD_CORE_LOCAL_CURR_THREAD] 2009608235SJerome Forissier adr_l x\res, threads 21*91d4649dSJens Wiklander ldr x\res, [x\res] 22f07647d4SJens Wiklander mov x\tmp1, #THREAD_CTX_SIZE 23f07647d4SJens Wiklander madd x\res, x\tmp0, x\tmp1, x\res 24e0cbf7deSJens Wiklander .endm 25e0cbf7deSJens Wiklander 26abfd092aSAnthony Steinhauser .macro return_from_exception 27abfd092aSAnthony Steinhauser eret 28abfd092aSAnthony Steinhauser /* Guard against speculation past ERET */ 29abfd092aSAnthony Steinhauser dsb nsh 30abfd092aSAnthony Steinhauser isb 31abfd092aSAnthony Steinhauser .endm 32abfd092aSAnthony Steinhauser 335b8a58b4SJens Wiklander .macro b_if_spsr_is_el0 reg, label 345b8a58b4SJens Wiklander tbnz \reg, #(SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT), \label 355b8a58b4SJens Wiklander tst \reg, #(SPSR_64_MODE_EL_MASK << SPSR_64_MODE_EL_SHIFT) 365b8a58b4SJens Wiklander b.eq \label 375b8a58b4SJens Wiklander .endm 385b8a58b4SJens Wiklander 3993dc6b29SJens Wiklander .macro pauth_el0_to_el1 reg 4093dc6b29SJens Wiklander /* 4193dc6b29SJens Wiklander * If pauth is only enabled in one of core or TA (xor) we 4293dc6b29SJens Wiklander * need to update sctlr. 4393dc6b29SJens Wiklander */ 4493dc6b29SJens Wiklander#if (defined(CFG_TA_PAUTH) && !defined(CFG_CORE_PAUTH)) || \ 4593dc6b29SJens Wiklander (!defined(CFG_TA_PAUTH) && defined(CFG_CORE_PAUTH)) 462b06f9deSRuchika Gupta mrs \reg, sctlr_el1 4793dc6b29SJens Wiklander /* Flip the SCTLR_ENIA bit */ 4893dc6b29SJens Wiklander eor \reg, \reg, #SCTLR_ENIA 492b06f9deSRuchika Gupta msr sctlr_el1, \reg 502b06f9deSRuchika Gupta#endif 512b06f9deSRuchika Gupta .endm 522b06f9deSRuchika Gupta 5393dc6b29SJens Wiklander .macro pauth_el1_to_el0 reg 5493dc6b29SJens Wiklander /* 5593dc6b29SJens Wiklander * If pauth is only enabled in one of core or TA (xor) we 5693dc6b29SJens Wiklander * need to update sctlr. 5793dc6b29SJens Wiklander */ 5893dc6b29SJens Wiklander#if (defined(CFG_TA_PAUTH) && !defined(CFG_CORE_PAUTH)) || \ 5993dc6b29SJens Wiklander (!defined(CFG_TA_PAUTH) && defined(CFG_CORE_PAUTH)) 602b06f9deSRuchika Gupta mrs \reg, sctlr_el1 6193dc6b29SJens Wiklander /* Flip the SCTLR_ENIA bit */ 6293dc6b29SJens Wiklander eor \reg, \reg, #SCTLR_ENIA 632b06f9deSRuchika Gupta msr sctlr_el1, \reg 642b06f9deSRuchika Gupta#endif 652b06f9deSRuchika Gupta .endm 662b06f9deSRuchika Gupta 67e0cbf7deSJens Wiklander/* void thread_resume(struct thread_ctx_regs *regs) */ 68e0cbf7deSJens WiklanderFUNC thread_resume , : 69c02f9fb0SJens Wiklander load_xregs x0, THREAD_CTX_REGS_SP, 1, 3 705b8a58b4SJens Wiklander load_xregs x0, THREAD_CTX_REGS_X4, 4, 30 71e0cbf7deSJens Wiklander mov sp, x1 72e0cbf7deSJens Wiklander msr elr_el1, x2 73e0cbf7deSJens Wiklander msr spsr_el1, x3 7404752110SJerome Forissier ldr x1, [x0, THREAD_CTX_REGS_TPIDR_EL0] 7504752110SJerome Forissier msr tpidr_el0, x1 765b8a58b4SJens Wiklander 7793dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 7893dc6b29SJens Wiklander load_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 7993dc6b29SJens Wiklander write_apiakeyhi x1 8093dc6b29SJens Wiklander write_apiakeylo x2 8193dc6b29SJens Wiklander#endif 825b8a58b4SJens Wiklander b_if_spsr_is_el0 w3, 1f 835b8a58b4SJens Wiklander 8493dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) 8593dc6b29SJens Wiklander /* SCTLR or the APIA key has changed */ 8693dc6b29SJens Wiklander isb 8793dc6b29SJens Wiklander#endif 885b8a58b4SJens Wiklander load_xregs x0, THREAD_CTX_REGS_X1, 1, 3 89c02f9fb0SJens Wiklander ldr x0, [x0, THREAD_CTX_REGS_X0] 90abfd092aSAnthony Steinhauser return_from_exception 915b8a58b4SJens Wiklander 922b06f9deSRuchika Gupta1: 932b06f9deSRuchika Gupta load_xregs x0, THREAD_CTX_REGS_X1, 1, 3 945b8a58b4SJens Wiklander ldr x0, [x0, THREAD_CTX_REGS_X0] 955b8a58b4SJens Wiklander 965b8a58b4SJens Wiklander msr spsel, #1 975b8a58b4SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 985b8a58b4SJens Wiklander b eret_to_el0 99e0cbf7deSJens WiklanderEND_FUNC thread_resume 100e0cbf7deSJens Wiklander 101bc09bb53SJens Wiklander#ifdef CFG_CORE_SEL2_SPMC 102bc09bb53SJens WiklanderFUNC thread_hvc , : 103bc09bb53SJens Wiklander hvc #0 104bc09bb53SJens Wiklander ret 105bc09bb53SJens WiklanderEND_FUNC thread_hvc 106bc09bb53SJens Wiklander#endif 107bc09bb53SJens Wiklander 108cd69dc9eSJens WiklanderFUNC thread_smc , : 109cd69dc9eSJens Wiklander smc #0 110cd69dc9eSJens Wiklander ret 111cd69dc9eSJens WiklanderEND_FUNC thread_smc 112cd69dc9eSJens Wiklander 11379454c60SJens Wiklander/* void thread_smccc(struct thread_smc_args *arg_res) */ 11479454c60SJens WiklanderFUNC thread_smccc , : 11579454c60SJens Wiklander push x0, xzr 11679454c60SJens Wiklander mov x8, x0 11779454c60SJens Wiklander load_xregs x8, 0, 0, 7 11879454c60SJens Wiklander#ifdef CFG_CORE_SEL2_SPMC 11979454c60SJens Wiklander hvc #0 12079454c60SJens Wiklander#else 12179454c60SJens Wiklander smc #0 12279454c60SJens Wiklander#endif 12379454c60SJens Wiklander pop x8, xzr 12479454c60SJens Wiklander store_xregs x8, 0, 0, 7 12579454c60SJens Wiklander ret 12679454c60SJens WiklanderEND_FUNC thread_smccc 12779454c60SJens Wiklander 128e0cbf7deSJens WiklanderFUNC thread_init_vbar , : 1293889635bSJens Wiklander msr vbar_el1, x0 130e0cbf7deSJens Wiklander ret 131e0cbf7deSJens WiklanderEND_FUNC thread_init_vbar 1323639b55fSJerome ForissierDECLARE_KEEP_PAGER thread_init_vbar 133e0cbf7deSJens Wiklander 134e0cbf7deSJens Wiklander/* 135e94702a4SJens Wiklander * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, 136e94702a4SJens Wiklander * uint32_t *exit_status0, 137e94702a4SJens Wiklander * uint32_t *exit_status1); 138a702f5e7SJens Wiklander * 139e94702a4SJens Wiklander * This function depends on being called with exceptions masked. 140e0cbf7deSJens Wiklander */ 141a702f5e7SJens WiklanderFUNC __thread_enter_user_mode , : 142e0cbf7deSJens Wiklander /* 143e0cbf7deSJens Wiklander * Create the and fill in the struct thread_user_mode_rec 144e0cbf7deSJens Wiklander */ 145e0cbf7deSJens Wiklander sub sp, sp, #THREAD_USER_MODE_REC_SIZE 146e94702a4SJens Wiklander store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 0, 2 147c02f9fb0SJens Wiklander store_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30 148e0cbf7deSJens Wiklander 149e0cbf7deSJens Wiklander /* 150e0cbf7deSJens Wiklander * Save kern sp in x19 151e94702a4SJens Wiklander * Switch to SP_EL1 152e0cbf7deSJens Wiklander */ 153e0cbf7deSJens Wiklander mov x19, sp 154e0cbf7deSJens Wiklander msr spsel, #1 155e0cbf7deSJens Wiklander 156e0cbf7deSJens Wiklander /* 157e0cbf7deSJens Wiklander * Save the kernel stack pointer in the thread context 158e0cbf7deSJens Wiklander */ 159e0cbf7deSJens Wiklander /* get pointer to current thread context */ 160f07647d4SJens Wiklander get_thread_ctx sp, 21, 20, 22 161bee02359SJens Wiklander /* 162bee02359SJens Wiklander * Save kernel stack pointer to ensure that el0_svc() uses 163bee02359SJens Wiklander * correct stack pointer 164bee02359SJens Wiklander */ 165c02f9fb0SJens Wiklander str x19, [x21, #THREAD_CTX_KERN_SP] 166e0cbf7deSJens Wiklander 167e0cbf7deSJens Wiklander /* 168e0cbf7deSJens Wiklander * Initialize SPSR, ELR_EL1, and SP_EL0 to enter user mode 169e0cbf7deSJens Wiklander */ 170e94702a4SJens Wiklander load_xregs x0, THREAD_CTX_REGS_SP, 1, 3 171e94702a4SJens Wiklander msr sp_el0, x1 172e94702a4SJens Wiklander msr elr_el1, x2 173e94702a4SJens Wiklander msr spsr_el1, x3 174e94702a4SJens Wiklander 1752b06f9deSRuchika Gupta#ifdef CFG_TA_PAUTH 1762b06f9deSRuchika Gupta /* Load APIAKEY */ 1772b06f9deSRuchika Gupta load_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 1782b06f9deSRuchika Gupta write_apiakeyhi x1 1792b06f9deSRuchika Gupta write_apiakeylo x2 1802b06f9deSRuchika Gupta#endif 1812b06f9deSRuchika Gupta 182e94702a4SJens Wiklander /* 183e94702a4SJens Wiklander * Save the values for x0 and x1 in struct thread_core_local to be 184e94702a4SJens Wiklander * restored later just before the eret. 185e94702a4SJens Wiklander */ 186e94702a4SJens Wiklander load_xregs x0, THREAD_CTX_REGS_X0, 1, 2 187e94702a4SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 1, 2 188e94702a4SJens Wiklander 189e94702a4SJens Wiklander /* Load the rest of the general purpose registers */ 190e94702a4SJens Wiklander load_xregs x0, THREAD_CTX_REGS_X2, 2, 30 191e0cbf7deSJens Wiklander 192e0cbf7deSJens Wiklander /* Jump into user mode */ 1935b8a58b4SJens Wiklander b eret_to_el0 194a702f5e7SJens WiklanderEND_FUNC __thread_enter_user_mode 1953639b55fSJerome ForissierDECLARE_KEEP_PAGER __thread_enter_user_mode 196e0cbf7deSJens Wiklander 197e0cbf7deSJens Wiklander/* 198e0cbf7deSJens Wiklander * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, 199e0cbf7deSJens Wiklander * uint32_t exit_status1); 200e0cbf7deSJens Wiklander * See description in thread.h 201e0cbf7deSJens Wiklander */ 202e0cbf7deSJens WiklanderFUNC thread_unwind_user_mode , : 203e0cbf7deSJens Wiklander /* Store the exit status */ 204e94702a4SJens Wiklander load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 3, 5 205e94702a4SJens Wiklander str w1, [x4] 206e94702a4SJens Wiklander str w2, [x5] 207e94702a4SJens Wiklander /* Save x19..x30 */ 208e94702a4SJens Wiklander store_xregs x3, THREAD_CTX_REGS_X19, 19, 30 209e0cbf7deSJens Wiklander /* Restore x19..x30 */ 210c02f9fb0SJens Wiklander load_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30 211e0cbf7deSJens Wiklander add sp, sp, #THREAD_USER_MODE_REC_SIZE 212e0cbf7deSJens Wiklander /* Return from the call of thread_enter_user_mode() */ 213e0cbf7deSJens Wiklander ret 214e0cbf7deSJens WiklanderEND_FUNC thread_unwind_user_mode 215e0cbf7deSJens Wiklander 216e0cbf7deSJens Wiklander /* 217e0cbf7deSJens Wiklander * This macro verifies that the a given vector doesn't exceed the 218e0cbf7deSJens Wiklander * architectural limit of 32 instructions. This is meant to be placed 219e0cbf7deSJens Wiklander * immedately after the last instruction in the vector. It takes the 220e0cbf7deSJens Wiklander * vector entry as the parameter 221e0cbf7deSJens Wiklander */ 222e0cbf7deSJens Wiklander .macro check_vector_size since 223e0cbf7deSJens Wiklander .if (. - \since) > (32 * 4) 224e0cbf7deSJens Wiklander .error "Vector exceeds 32 instructions" 225e0cbf7deSJens Wiklander .endif 226e0cbf7deSJens Wiklander .endm 227e0cbf7deSJens Wiklander 2285b8a58b4SJens Wiklander .macro restore_mapping 2295b8a58b4SJens Wiklander#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 230ab61a1dcSJens Wiklander /* Temporarily save x0, x1 */ 2315b8a58b4SJens Wiklander msr tpidr_el1, x0 232ab61a1dcSJens Wiklander msr tpidrro_el0, x1 2335b8a58b4SJens Wiklander 2345b8a58b4SJens Wiklander /* Update the mapping to use the full kernel mapping */ 2355b8a58b4SJens Wiklander mrs x0, ttbr0_el1 236f9f2a146SJens Wiklander sub_imm x0, __CORE_MMU_BASE_TABLE_OFFSET 2375b8a58b4SJens Wiklander /* switch to kernel mode ASID */ 2385b8a58b4SJens Wiklander bic x0, x0, #BIT(TTBR_ASID_SHIFT) 2395b8a58b4SJens Wiklander msr ttbr0_el1, x0 2405b8a58b4SJens Wiklander isb 2415b8a58b4SJens Wiklander 2425b8a58b4SJens Wiklander /* Jump into the full mapping and continue execution */ 24328f6da21SJerome Forissier adr x0, 1f 24428f6da21SJerome Forissier ldr x1, [sp, #THREAD_CORE_LOCAL_KCODE_OFFSET] 24528f6da21SJerome Forissier add x0, x0, x1 2465b8a58b4SJens Wiklander br x0 2475b8a58b4SJens Wiklander 1: 2487ad2713dSRuchika GuptaBTI( bti j) 2495b8a58b4SJens Wiklander /* Point to the vector into the full mapping */ 25015081979SIlias Apalodimas adr_l x0, thread_user_kcode_offset 251ab61a1dcSJens Wiklander ldr x0, [x0] 252ab61a1dcSJens Wiklander mrs x1, vbar_el1 253ab61a1dcSJens Wiklander add x1, x1, x0 254ab61a1dcSJens Wiklander msr vbar_el1, x1 2555b8a58b4SJens Wiklander isb 2565b8a58b4SJens Wiklander 257657d02f2SJens Wiklander#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC 258657d02f2SJens Wiklander /* 259657d02f2SJens Wiklander * Update the SP with thread_user_kdata_sp_offset as 260657d02f2SJens Wiklander * described in init_user_kcode(). 261657d02f2SJens Wiklander */ 26215081979SIlias Apalodimas adr_l x0, thread_user_kdata_sp_offset 263657d02f2SJens Wiklander ldr x0, [x0] 264657d02f2SJens Wiklander add sp, sp, x0 265657d02f2SJens Wiklander#endif 266657d02f2SJens Wiklander 267ab61a1dcSJens Wiklander /* Restore x0, x1 */ 2685b8a58b4SJens Wiklander mrs x0, tpidr_el1 269ab61a1dcSJens Wiklander mrs x1, tpidrro_el0 2705b8a58b4SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 2715b8a58b4SJens Wiklander#else 2725b8a58b4SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 2735b8a58b4SJens Wiklander mrs x0, ttbr0_el1 2745b8a58b4SJens Wiklander /* switch to kernel mode ASID */ 2755b8a58b4SJens Wiklander bic x0, x0, #BIT(TTBR_ASID_SHIFT) 2765b8a58b4SJens Wiklander msr ttbr0_el1, x0 2775b8a58b4SJens Wiklander isb 2785b8a58b4SJens Wiklander#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ 2795b8a58b4SJens Wiklander .endm 280e0cbf7deSJens Wiklander 281ed17deb1SJens Wiklander#define INV_INSN 0 28203bada66SRuchika GuptaFUNC thread_excp_vect , : , default, 2048, nobti 283e0cbf7deSJens Wiklander /* ----------------------------------------------------- 284e0cbf7deSJens Wiklander * EL1 with SP0 : 0x0 - 0x180 285e0cbf7deSJens Wiklander * ----------------------------------------------------- 286e0cbf7deSJens Wiklander */ 2870d57f57cSJens Wiklander .balign 128, INV_INSN 288d9477b97SJens Wiklanderel1_sync_sp0: 289c02f9fb0SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 290e0cbf7deSJens Wiklander b el1_sync_abort 291d9477b97SJens Wiklander check_vector_size el1_sync_sp0 292e0cbf7deSJens Wiklander 2930d57f57cSJens Wiklander .balign 128, INV_INSN 294d9477b97SJens Wiklanderel1_irq_sp0: 295c02f9fb0SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 296e0cbf7deSJens Wiklander b elx_irq 297d9477b97SJens Wiklander check_vector_size el1_irq_sp0 298e0cbf7deSJens Wiklander 2990d57f57cSJens Wiklander .balign 128, INV_INSN 300d9477b97SJens Wiklanderel1_fiq_sp0: 301c02f9fb0SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 302e0cbf7deSJens Wiklander b elx_fiq 303d9477b97SJens Wiklander check_vector_size el1_fiq_sp0 304e0cbf7deSJens Wiklander 3050d57f57cSJens Wiklander .balign 128, INV_INSN 306d9477b97SJens Wiklanderel1_serror_sp0: 307d9477b97SJens Wiklander b el1_serror_sp0 308d9477b97SJens Wiklander check_vector_size el1_serror_sp0 309e0cbf7deSJens Wiklander 310e0cbf7deSJens Wiklander /* ----------------------------------------------------- 311d9477b97SJens Wiklander * Current EL with SP1: 0x200 - 0x380 312e0cbf7deSJens Wiklander * ----------------------------------------------------- 313e0cbf7deSJens Wiklander */ 3140d57f57cSJens Wiklander .balign 128, INV_INSN 315d9477b97SJens Wiklanderel1_sync_sp1: 316d9477b97SJens Wiklander b el1_sync_sp1 317d9477b97SJens Wiklander check_vector_size el1_sync_sp1 318e0cbf7deSJens Wiklander 3190d57f57cSJens Wiklander .balign 128, INV_INSN 320d9477b97SJens Wiklanderel1_irq_sp1: 321d9477b97SJens Wiklander b el1_irq_sp1 322d9477b97SJens Wiklander check_vector_size el1_irq_sp1 323e0cbf7deSJens Wiklander 3240d57f57cSJens Wiklander .balign 128, INV_INSN 325d9477b97SJens Wiklanderel1_fiq_sp1: 326d9477b97SJens Wiklander b el1_fiq_sp1 327d9477b97SJens Wiklander check_vector_size el1_fiq_sp1 328e0cbf7deSJens Wiklander 3290d57f57cSJens Wiklander .balign 128, INV_INSN 330d9477b97SJens Wiklanderel1_serror_sp1: 331d9477b97SJens Wiklander b el1_serror_sp1 332d9477b97SJens Wiklander check_vector_size el1_serror_sp1 333e0cbf7deSJens Wiklander 334e0cbf7deSJens Wiklander /* ----------------------------------------------------- 335e0cbf7deSJens Wiklander * Lower EL using AArch64 : 0x400 - 0x580 336e0cbf7deSJens Wiklander * ----------------------------------------------------- 337e0cbf7deSJens Wiklander */ 3380d57f57cSJens Wiklander .balign 128, INV_INSN 339e0cbf7deSJens Wiklanderel0_sync_a64: 3405b8a58b4SJens Wiklander restore_mapping 3412b06f9deSRuchika Gupta /* PAuth will be disabled later else check_vector_size will fail */ 3425b8a58b4SJens Wiklander 34328f6da21SJerome Forissier b el0_sync_a64_finish 344e0cbf7deSJens Wiklander check_vector_size el0_sync_a64 345e0cbf7deSJens Wiklander 3460d57f57cSJens Wiklander .balign 128, INV_INSN 347bee02359SJens Wiklanderel0_irq_a64: 3485b8a58b4SJens Wiklander restore_mapping 34993dc6b29SJens Wiklander pauth_el0_to_el1 x1 3505b8a58b4SJens Wiklander 351bee02359SJens Wiklander b elx_irq 352bee02359SJens Wiklander check_vector_size el0_irq_a64 353e0cbf7deSJens Wiklander 3540d57f57cSJens Wiklander .balign 128, INV_INSN 355bee02359SJens Wiklanderel0_fiq_a64: 3565b8a58b4SJens Wiklander restore_mapping 35793dc6b29SJens Wiklander pauth_el0_to_el1 x1 3585b8a58b4SJens Wiklander 3592dac4a2dSJens Wiklander b elx_fiq 360bee02359SJens Wiklander check_vector_size el0_fiq_a64 361e0cbf7deSJens Wiklander 3620d57f57cSJens Wiklander .balign 128, INV_INSN 363d9477b97SJens Wiklanderel0_serror_a64: 364d9477b97SJens Wiklander b el0_serror_a64 365d9477b97SJens Wiklander check_vector_size el0_serror_a64 366e0cbf7deSJens Wiklander 367e0cbf7deSJens Wiklander /* ----------------------------------------------------- 368e0cbf7deSJens Wiklander * Lower EL using AArch32 : 0x0 - 0x180 369e0cbf7deSJens Wiklander * ----------------------------------------------------- 370e0cbf7deSJens Wiklander */ 3710d57f57cSJens Wiklander .balign 128, INV_INSN 372e0cbf7deSJens Wiklanderel0_sync_a32: 3735b8a58b4SJens Wiklander restore_mapping 3745b8a58b4SJens Wiklander 37528f6da21SJerome Forissier b el0_sync_a32_finish 376e0cbf7deSJens Wiklander check_vector_size el0_sync_a32 377e0cbf7deSJens Wiklander 3780d57f57cSJens Wiklander .balign 128, INV_INSN 379e0cbf7deSJens Wiklanderel0_irq_a32: 3805b8a58b4SJens Wiklander restore_mapping 3815b8a58b4SJens Wiklander 382e0cbf7deSJens Wiklander b elx_irq 383e0cbf7deSJens Wiklander check_vector_size el0_irq_a32 384e0cbf7deSJens Wiklander 3850d57f57cSJens Wiklander .balign 128, INV_INSN 386e0cbf7deSJens Wiklanderel0_fiq_a32: 3875b8a58b4SJens Wiklander restore_mapping 3885b8a58b4SJens Wiklander 389e0cbf7deSJens Wiklander b elx_fiq 390e0cbf7deSJens Wiklander check_vector_size el0_fiq_a32 391e0cbf7deSJens Wiklander 3920d57f57cSJens Wiklander .balign 128, INV_INSN 393d9477b97SJens Wiklanderel0_serror_a32: 394d9477b97SJens Wiklander b el0_serror_a32 395d9477b97SJens Wiklander check_vector_size el0_serror_a32 396e0cbf7deSJens Wiklander 397fecdfb75SJens Wiklander#if defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) 398fecdfb75SJens Wiklander .macro invalidate_branch_predictor 399e13d1040SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 400e13d1040SJens Wiklander mov_imm x0, SMCCC_ARCH_WORKAROUND_1 401e13d1040SJens Wiklander smc #0 402e13d1040SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 403fecdfb75SJens Wiklander .endm 404fecdfb75SJens Wiklander 4050d57f57cSJens Wiklander .balign 2048, INV_INSN 406a9869a4cSJens Wiklander .global thread_excp_vect_wa_spectre_v2 407a9869a4cSJens Wiklanderthread_excp_vect_wa_spectre_v2: 408fecdfb75SJens Wiklander /* ----------------------------------------------------- 409fecdfb75SJens Wiklander * EL1 with SP0 : 0x0 - 0x180 410fecdfb75SJens Wiklander * ----------------------------------------------------- 411fecdfb75SJens Wiklander */ 4120d57f57cSJens Wiklander .balign 128, INV_INSN 413a9869a4cSJens Wiklanderwa_spectre_v2_el1_sync_sp0: 414fecdfb75SJens Wiklander b el1_sync_sp0 415a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_sync_sp0 416fecdfb75SJens Wiklander 4170d57f57cSJens Wiklander .balign 128, INV_INSN 418a9869a4cSJens Wiklanderwa_spectre_v2_el1_irq_sp0: 419fecdfb75SJens Wiklander b el1_irq_sp0 420a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_irq_sp0 421fecdfb75SJens Wiklander 4220d57f57cSJens Wiklander .balign 128, INV_INSN 423a9869a4cSJens Wiklanderwa_spectre_v2_el1_fiq_sp0: 424fecdfb75SJens Wiklander b el1_fiq_sp0 425a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_fiq_sp0 426fecdfb75SJens Wiklander 4270d57f57cSJens Wiklander .balign 128, INV_INSN 428a9869a4cSJens Wiklanderwa_spectre_v2_el1_serror_sp0: 429fecdfb75SJens Wiklander b el1_serror_sp0 430a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_serror_sp0 431fecdfb75SJens Wiklander 432fecdfb75SJens Wiklander /* ----------------------------------------------------- 433fecdfb75SJens Wiklander * Current EL with SP1: 0x200 - 0x380 434fecdfb75SJens Wiklander * ----------------------------------------------------- 435fecdfb75SJens Wiklander */ 4360d57f57cSJens Wiklander .balign 128, INV_INSN 437a9869a4cSJens Wiklanderwa_spectre_v2_el1_sync_sp1: 438a9869a4cSJens Wiklander b wa_spectre_v2_el1_sync_sp1 439a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_sync_sp1 440fecdfb75SJens Wiklander 4410d57f57cSJens Wiklander .balign 128, INV_INSN 442a9869a4cSJens Wiklanderwa_spectre_v2_el1_irq_sp1: 443a9869a4cSJens Wiklander b wa_spectre_v2_el1_irq_sp1 444a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_irq_sp1 445fecdfb75SJens Wiklander 4460d57f57cSJens Wiklander .balign 128, INV_INSN 447a9869a4cSJens Wiklanderwa_spectre_v2_el1_fiq_sp1: 448a9869a4cSJens Wiklander b wa_spectre_v2_el1_fiq_sp1 449a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_fiq_sp1 450fecdfb75SJens Wiklander 4510d57f57cSJens Wiklander .balign 128, INV_INSN 452a9869a4cSJens Wiklanderwa_spectre_v2_el1_serror_sp1: 453a9869a4cSJens Wiklander b wa_spectre_v2_el1_serror_sp1 454a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el1_serror_sp1 455fecdfb75SJens Wiklander 456fecdfb75SJens Wiklander /* ----------------------------------------------------- 457fecdfb75SJens Wiklander * Lower EL using AArch64 : 0x400 - 0x580 458fecdfb75SJens Wiklander * ----------------------------------------------------- 459fecdfb75SJens Wiklander */ 4600d57f57cSJens Wiklander .balign 128, INV_INSN 461a9869a4cSJens Wiklanderwa_spectre_v2_el0_sync_a64: 462fecdfb75SJens Wiklander invalidate_branch_predictor 463fecdfb75SJens Wiklander b el0_sync_a64 464a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_sync_a64 465fecdfb75SJens Wiklander 4660d57f57cSJens Wiklander .balign 128, INV_INSN 467a9869a4cSJens Wiklanderwa_spectre_v2_el0_irq_a64: 468fecdfb75SJens Wiklander invalidate_branch_predictor 469fecdfb75SJens Wiklander b el0_irq_a64 470a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_irq_a64 471fecdfb75SJens Wiklander 4720d57f57cSJens Wiklander .balign 128, INV_INSN 473a9869a4cSJens Wiklanderwa_spectre_v2_el0_fiq_a64: 474fecdfb75SJens Wiklander invalidate_branch_predictor 475fecdfb75SJens Wiklander b el0_fiq_a64 476a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_fiq_a64 477fecdfb75SJens Wiklander 4780d57f57cSJens Wiklander .balign 128, INV_INSN 479a9869a4cSJens Wiklanderwa_spectre_v2_el0_serror_a64: 480a9869a4cSJens Wiklander b wa_spectre_v2_el0_serror_a64 481a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_serror_a64 482fecdfb75SJens Wiklander 483fecdfb75SJens Wiklander /* ----------------------------------------------------- 484fecdfb75SJens Wiklander * Lower EL using AArch32 : 0x0 - 0x180 485fecdfb75SJens Wiklander * ----------------------------------------------------- 486fecdfb75SJens Wiklander */ 4870d57f57cSJens Wiklander .balign 128, INV_INSN 488a9869a4cSJens Wiklanderwa_spectre_v2_el0_sync_a32: 489fecdfb75SJens Wiklander invalidate_branch_predictor 490fecdfb75SJens Wiklander b el0_sync_a32 491a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_sync_a32 492fecdfb75SJens Wiklander 4930d57f57cSJens Wiklander .balign 128, INV_INSN 494a9869a4cSJens Wiklanderwa_spectre_v2_el0_irq_a32: 495fecdfb75SJens Wiklander invalidate_branch_predictor 496fecdfb75SJens Wiklander b el0_irq_a32 497a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_irq_a32 498fecdfb75SJens Wiklander 4990d57f57cSJens Wiklander .balign 128, INV_INSN 500a9869a4cSJens Wiklanderwa_spectre_v2_el0_fiq_a32: 501fecdfb75SJens Wiklander invalidate_branch_predictor 502fecdfb75SJens Wiklander b el0_fiq_a32 503a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_fiq_a32 504fecdfb75SJens Wiklander 5050d57f57cSJens Wiklander .balign 128, INV_INSN 506a9869a4cSJens Wiklanderwa_spectre_v2_el0_serror_a32: 507a9869a4cSJens Wiklander b wa_spectre_v2_el0_serror_a32 508a9869a4cSJens Wiklander check_vector_size wa_spectre_v2_el0_serror_a32 509ce08459aSJens Wiklander 510ce08459aSJens Wiklander .macro discard_branch_history 511ce08459aSJens Wiklander str x0, [sp, #THREAD_CORE_LOCAL_X0] 512ce08459aSJens Wiklander ldrb w0, [sp, #THREAD_CORE_LOCAL_BHB_LOOP_COUNT] 513ce08459aSJens Wiklander 1: b 2f 514ce08459aSJens Wiklander 2: subs w0, w0, #1 515ce08459aSJens Wiklander bne 1b 516ce08459aSJens Wiklander dsb sy 517ce08459aSJens Wiklander isb 518ce08459aSJens Wiklander ldr x0, [sp, #THREAD_CORE_LOCAL_X0] 519ce08459aSJens Wiklander .endm 520ce08459aSJens Wiklander 521ce08459aSJens Wiklander .balign 2048, INV_INSN 522ce08459aSJens Wiklander .global thread_excp_vect_wa_spectre_bhb 523ce08459aSJens Wiklanderthread_excp_vect_wa_spectre_bhb: 524ce08459aSJens Wiklander /* ----------------------------------------------------- 525ce08459aSJens Wiklander * EL1 with SP0 : 0x0 - 0x180 526ce08459aSJens Wiklander * ----------------------------------------------------- 527ce08459aSJens Wiklander */ 528ce08459aSJens Wiklander .balign 128, INV_INSN 529ce08459aSJens Wiklanderwa_spectre_bhb_el1_sync_sp0: 530ce08459aSJens Wiklander b el1_sync_sp0 531ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_sync_sp0 532ce08459aSJens Wiklander 533ce08459aSJens Wiklander .balign 128, INV_INSN 534ce08459aSJens Wiklanderwa_spectre_bhb_el1_irq_sp0: 535ce08459aSJens Wiklander b el1_irq_sp0 536ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_irq_sp0 537ce08459aSJens Wiklander 538ce08459aSJens Wiklander .balign 128, INV_INSN 539ce08459aSJens Wiklanderwa_spectre_bhb_el1_fiq_sp0: 540ce08459aSJens Wiklander b el1_fiq_sp0 541ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_fiq_sp0 542ce08459aSJens Wiklander 543ce08459aSJens Wiklander .balign 128, INV_INSN 544ce08459aSJens Wiklanderwa_spectre_bhb_el1_serror_sp0: 545ce08459aSJens Wiklander b el1_serror_sp0 546ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_serror_sp0 547ce08459aSJens Wiklander 548ce08459aSJens Wiklander /* ----------------------------------------------------- 549ce08459aSJens Wiklander * Current EL with SP1: 0x200 - 0x380 550ce08459aSJens Wiklander * ----------------------------------------------------- 551ce08459aSJens Wiklander */ 552ce08459aSJens Wiklander .balign 128, INV_INSN 553ce08459aSJens Wiklanderwa_spectre_bhb_el1_sync_sp1: 554ce08459aSJens Wiklander b wa_spectre_bhb_el1_sync_sp1 555ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_sync_sp1 556ce08459aSJens Wiklander 557ce08459aSJens Wiklander .balign 128, INV_INSN 558ce08459aSJens Wiklanderwa_spectre_bhb_el1_irq_sp1: 559ce08459aSJens Wiklander b wa_spectre_bhb_el1_irq_sp1 560ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_irq_sp1 561ce08459aSJens Wiklander 562ce08459aSJens Wiklander .balign 128, INV_INSN 563ce08459aSJens Wiklanderwa_spectre_bhb_el1_fiq_sp1: 564ce08459aSJens Wiklander b wa_spectre_bhb_el1_fiq_sp1 565ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_fiq_sp1 566ce08459aSJens Wiklander 567ce08459aSJens Wiklander .balign 128, INV_INSN 568ce08459aSJens Wiklanderwa_spectre_bhb_el1_serror_sp1: 569ce08459aSJens Wiklander b wa_spectre_bhb_el1_serror_sp1 570ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el1_serror_sp1 571ce08459aSJens Wiklander 572ce08459aSJens Wiklander /* ----------------------------------------------------- 573ce08459aSJens Wiklander * Lower EL using AArch64 : 0x400 - 0x580 574ce08459aSJens Wiklander * ----------------------------------------------------- 575ce08459aSJens Wiklander */ 576ce08459aSJens Wiklander .balign 128, INV_INSN 577ce08459aSJens Wiklanderwa_spectre_bhb_el0_sync_a64: 578ce08459aSJens Wiklander discard_branch_history 579ce08459aSJens Wiklander b el0_sync_a64 580ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_sync_a64 581ce08459aSJens Wiklander 582ce08459aSJens Wiklander .balign 128, INV_INSN 583ce08459aSJens Wiklanderwa_spectre_bhb_el0_irq_a64: 584ce08459aSJens Wiklander discard_branch_history 585ce08459aSJens Wiklander b el0_irq_a64 586ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_irq_a64 587ce08459aSJens Wiklander 588ce08459aSJens Wiklander .balign 128, INV_INSN 589ce08459aSJens Wiklanderwa_spectre_bhb_el0_fiq_a64: 590ce08459aSJens Wiklander discard_branch_history 591ce08459aSJens Wiklander b el0_fiq_a64 592ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_fiq_a64 593ce08459aSJens Wiklander 594ce08459aSJens Wiklander .balign 128, INV_INSN 595ce08459aSJens Wiklanderwa_spectre_bhb_el0_serror_a64: 596ce08459aSJens Wiklander b wa_spectre_bhb_el0_serror_a64 597ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_serror_a64 598ce08459aSJens Wiklander 599ce08459aSJens Wiklander /* ----------------------------------------------------- 600ce08459aSJens Wiklander * Lower EL using AArch32 : 0x0 - 0x180 601ce08459aSJens Wiklander * ----------------------------------------------------- 602ce08459aSJens Wiklander */ 603ce08459aSJens Wiklander .balign 128, INV_INSN 604ce08459aSJens Wiklanderwa_spectre_bhb_el0_sync_a32: 605ce08459aSJens Wiklander discard_branch_history 606ce08459aSJens Wiklander b el0_sync_a32 607ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_sync_a32 608ce08459aSJens Wiklander 609ce08459aSJens Wiklander .balign 128, INV_INSN 610ce08459aSJens Wiklanderwa_spectre_bhb_el0_irq_a32: 611ce08459aSJens Wiklander discard_branch_history 612ce08459aSJens Wiklander b el0_irq_a32 613ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_irq_a32 614ce08459aSJens Wiklander 615ce08459aSJens Wiklander .balign 128, INV_INSN 616ce08459aSJens Wiklanderwa_spectre_bhb_el0_fiq_a32: 617ce08459aSJens Wiklander discard_branch_history 618ce08459aSJens Wiklander b el0_fiq_a32 619ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_fiq_a32 620ce08459aSJens Wiklander 621ce08459aSJens Wiklander .balign 128, INV_INSN 622ce08459aSJens Wiklanderwa_spectre_bhb_el0_serror_a32: 623ce08459aSJens Wiklander b wa_spectre_bhb_el0_serror_a32 624ce08459aSJens Wiklander check_vector_size wa_spectre_bhb_el0_serror_a32 625fecdfb75SJens Wiklander#endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ 626fecdfb75SJens Wiklander 6275b8a58b4SJens Wiklander/* 6285b8a58b4SJens Wiklander * We're keeping this code in the same section as the vector to make sure 6295b8a58b4SJens Wiklander * that it's always available. 6305b8a58b4SJens Wiklander */ 6315b8a58b4SJens Wiklandereret_to_el0: 63293dc6b29SJens Wiklander pauth_el1_to_el0 x1 6335b8a58b4SJens Wiklander 6345b8a58b4SJens Wiklander#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 6355b8a58b4SJens Wiklander /* Point to the vector into the reduced mapping */ 63615081979SIlias Apalodimas adr_l x0, thread_user_kcode_offset 6375b8a58b4SJens Wiklander ldr x0, [x0] 638ab61a1dcSJens Wiklander mrs x1, vbar_el1 6395b8a58b4SJens Wiklander sub x1, x1, x0 6405b8a58b4SJens Wiklander msr vbar_el1, x1 6415b8a58b4SJens Wiklander isb 6425b8a58b4SJens Wiklander 643657d02f2SJens Wiklander#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC 644657d02f2SJens Wiklander /* Store the SP offset in tpidr_el1 to be used below to update SP */ 64515081979SIlias Apalodimas adr_l x1, thread_user_kdata_sp_offset 646657d02f2SJens Wiklander ldr x1, [x1] 647657d02f2SJens Wiklander msr tpidr_el1, x1 648657d02f2SJens Wiklander#endif 649657d02f2SJens Wiklander 6505b8a58b4SJens Wiklander /* Jump into the reduced mapping and continue execution */ 65109608235SJerome Forissier adr_l x1, 1f 6525b8a58b4SJens Wiklander sub x1, x1, x0 6535b8a58b4SJens Wiklander br x1 6545b8a58b4SJens Wiklander1: 6557ad2713dSRuchika GuptaBTI( bti j) 6565b8a58b4SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 657657d02f2SJens Wiklander msr tpidrro_el0, x0 6585b8a58b4SJens Wiklander 6595b8a58b4SJens Wiklander /* Update the mapping to exclude the full kernel mapping */ 6605b8a58b4SJens Wiklander mrs x0, ttbr0_el1 661f9f2a146SJens Wiklander add_imm x0, __CORE_MMU_BASE_TABLE_OFFSET 6625b8a58b4SJens Wiklander orr x0, x0, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ 6635b8a58b4SJens Wiklander msr ttbr0_el1, x0 6645b8a58b4SJens Wiklander isb 6655b8a58b4SJens Wiklander 666657d02f2SJens Wiklander#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC 667657d02f2SJens Wiklander /* 668657d02f2SJens Wiklander * Update the SP with thread_user_kdata_sp_offset as described in 669657d02f2SJens Wiklander * init_user_kcode(). 670657d02f2SJens Wiklander */ 6715b8a58b4SJens Wiklander mrs x0, tpidr_el1 672657d02f2SJens Wiklander sub sp, sp, x0 673657d02f2SJens Wiklander#endif 674657d02f2SJens Wiklander 675657d02f2SJens Wiklander mrs x0, tpidrro_el0 6765b8a58b4SJens Wiklander#else 6775b8a58b4SJens Wiklander mrs x0, ttbr0_el1 6785b8a58b4SJens Wiklander orr x0, x0, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ 6795b8a58b4SJens Wiklander msr ttbr0_el1, x0 6805b8a58b4SJens Wiklander isb 6815b8a58b4SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 6825b8a58b4SJens Wiklander#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ 6835b8a58b4SJens Wiklander 684abfd092aSAnthony Steinhauser return_from_exception 68579083642SJens Wiklander 68628f6da21SJerome Forissierel0_sync_a64_finish: 68728f6da21SJerome Forissier mrs x2, esr_el1 68828f6da21SJerome Forissier mrs x3, sp_el0 68928f6da21SJerome Forissier lsr x2, x2, #ESR_EC_SHIFT 69028f6da21SJerome Forissier cmp x2, #ESR_EC_AARCH64_SVC 69128f6da21SJerome Forissier b.eq el0_svc 69228f6da21SJerome Forissier b el0_sync_abort 69328f6da21SJerome Forissier 69428f6da21SJerome Forissierel0_sync_a32_finish: 69528f6da21SJerome Forissier mrs x2, esr_el1 69628f6da21SJerome Forissier mrs x3, sp_el0 69728f6da21SJerome Forissier lsr x2, x2, #ESR_EC_SHIFT 69828f6da21SJerome Forissier cmp x2, #ESR_EC_AARCH32_SVC 69928f6da21SJerome Forissier b.eq el0_svc 70028f6da21SJerome Forissier b el0_sync_abort 70128f6da21SJerome Forissier 70279083642SJens Wiklander /* 70379083642SJens Wiklander * void icache_inv_user_range(void *addr, size_t size); 70479083642SJens Wiklander * 70579083642SJens Wiklander * This function has to execute with the user space ASID active, 70679083642SJens Wiklander * this means executing with reduced mapping and the code needs 70779083642SJens Wiklander * to be located here together with the vector. 70879083642SJens Wiklander */ 70979083642SJens Wiklander .global icache_inv_user_range 71079083642SJens Wiklander .type icache_inv_user_range , %function 71179083642SJens Wiklandericache_inv_user_range: 71279083642SJens Wiklander /* Mask all exceptions */ 71379083642SJens Wiklander mrs x6, daif /* this register must be preserved */ 71479083642SJens Wiklander msr daifset, #DAIFBIT_ALL 71579083642SJens Wiklander 71679083642SJens Wiklander#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 71779083642SJens Wiklander /* Point to the vector into the reduced mapping */ 7187611c8eeSJerome Forissier adr_l x7, thread_user_kcode_offset 7197611c8eeSJerome Forissier ldr x7, [x7] /* this register must be preserved */ 72079083642SJens Wiklander mrs x4, vbar_el1 /* this register must be preserved */ 7217611c8eeSJerome Forissier sub x3, x4, x7 72279083642SJens Wiklander msr vbar_el1, x3 72379083642SJens Wiklander isb 72479083642SJens Wiklander 72579083642SJens Wiklander /* Jump into the reduced mapping and continue execution */ 7267611c8eeSJerome Forissier adr x3, 1f 7277611c8eeSJerome Forissier sub x3, x3, x7 72879083642SJens Wiklander br x3 72979083642SJens Wiklander1: 7307ad2713dSRuchika GuptaBTI( bti j) 73179083642SJens Wiklander /* Update the mapping to exclude the full kernel mapping */ 73279083642SJens Wiklander mrs x5, ttbr0_el1 /* this register must be preserved */ 733f9f2a146SJens Wiklander orr x2, x5, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ 734f9f2a146SJens Wiklander add_imm x2, __CORE_MMU_BASE_TABLE_OFFSET 73579083642SJens Wiklander msr ttbr0_el1, x2 73679083642SJens Wiklander isb 73779083642SJens Wiklander 73879083642SJens Wiklander#else 73979083642SJens Wiklander mrs x5, ttbr0_el1 /* this register must be preserved */ 7402852c5c9SJens Wiklander orr x2, x5, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ 74179083642SJens Wiklander msr ttbr0_el1, x2 74279083642SJens Wiklander isb 74379083642SJens Wiklander#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ 74479083642SJens Wiklander 74579083642SJens Wiklander /* 74679083642SJens Wiklander * Do the actual icache invalidation 74779083642SJens Wiklander */ 74879083642SJens Wiklander 74979083642SJens Wiklander /* Calculate minimum icache line size, result in x2 */ 75079083642SJens Wiklander mrs x3, ctr_el0 75179083642SJens Wiklander and x3, x3, #CTR_IMINLINE_MASK 75279083642SJens Wiklander mov x2, #CTR_WORD_SIZE 75379083642SJens Wiklander lsl x2, x2, x3 75479083642SJens Wiklander 75579083642SJens Wiklander add x1, x0, x1 75679083642SJens Wiklander sub x3, x2, #1 75779083642SJens Wiklander bic x0, x0, x3 75879083642SJens Wiklander1: 75979083642SJens Wiklander ic ivau, x0 76079083642SJens Wiklander add x0, x0, x2 76179083642SJens Wiklander cmp x0, x1 76279083642SJens Wiklander b.lo 1b 76379083642SJens Wiklander dsb ish 76479083642SJens Wiklander 76579083642SJens Wiklander#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 76679083642SJens Wiklander /* Update the mapping to use the full kernel mapping and ASID */ 76779083642SJens Wiklander msr ttbr0_el1, x5 76879083642SJens Wiklander isb 76979083642SJens Wiklander 77079083642SJens Wiklander /* Jump into the full mapping and continue execution */ 7717611c8eeSJerome Forissier adr x0, 1f 7727611c8eeSJerome Forissier add x0, x0, x7 77379083642SJens Wiklander br x0 77479083642SJens Wiklander1: 7757ad2713dSRuchika GuptaBTI( bti j) 77679083642SJens Wiklander /* Point to the vector into the full mapping */ 77779083642SJens Wiklander msr vbar_el1, x4 77879083642SJens Wiklander isb 77979083642SJens Wiklander#else 78079083642SJens Wiklander /* switch to kernel mode ASID */ 78179083642SJens Wiklander msr ttbr0_el1, x5 78279083642SJens Wiklander isb 78379083642SJens Wiklander#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ 78479083642SJens Wiklander 78579083642SJens Wiklander msr daif, x6 /* restore exceptions */ 78679083642SJens Wiklander ret /* End of icache_inv_user_range() */ 78779083642SJens Wiklander 788a8948228SJens Wiklander /* 789a8948228SJens Wiklander * Make sure that literals are placed before the 790a8948228SJens Wiklander * thread_excp_vect_end label. 791a8948228SJens Wiklander */ 792a8948228SJens Wiklander .pool 79374977ea7SJens Wiklander .global thread_excp_vect_end 79474977ea7SJens Wiklanderthread_excp_vect_end: 795f8031323SJens WiklanderEND_FUNC thread_excp_vect 796e0cbf7deSJens Wiklander 797bee02359SJens WiklanderLOCAL_FUNC el0_svc , : 79893dc6b29SJens Wiklander pauth_el0_to_el1 x1 799e0cbf7deSJens Wiklander /* get pointer to current thread context in x0 */ 800f07647d4SJens Wiklander get_thread_ctx sp, 0, 1, 2 80104752110SJerome Forissier mrs x1, tpidr_el0 80204752110SJerome Forissier str x1, [x0, #THREAD_CTX_REGS_TPIDR_EL0] 803e0cbf7deSJens Wiklander /* load saved kernel sp */ 80493dc6b29SJens Wiklander ldr x3, [x0, #THREAD_CTX_KERN_SP] 805e0cbf7deSJens Wiklander /* Keep pointer to initial recod in x1 */ 806e0cbf7deSJens Wiklander mov x1, sp 807e0cbf7deSJens Wiklander /* Switch to SP_EL0 and restore kernel sp */ 808e0cbf7deSJens Wiklander msr spsel, #0 809bee02359SJens Wiklander mov x2, sp /* Save SP_EL0 */ 81093dc6b29SJens Wiklander mov sp, x3 811bee02359SJens Wiklander 812ab5363c6SJens Wiklander /* Make room for struct thread_scall_regs */ 813ab5363c6SJens Wiklander sub sp, sp, #THREAD_SCALL_REG_SIZE 814ab5363c6SJens Wiklander stp x30, x2, [sp, #THREAD_SCALL_REG_X30] 815bee02359SJens Wiklander 81693dc6b29SJens Wiklander#ifdef CFG_TA_PAUTH 81793dc6b29SJens Wiklander /* Save APIAKEY */ 81893dc6b29SJens Wiklander read_apiakeyhi x2 81993dc6b29SJens Wiklander read_apiakeylo x3 820ab5363c6SJens Wiklander stp x2, x3, [sp, #THREAD_SCALL_REG_APIAKEY_HI] 82193dc6b29SJens Wiklander#endif 82293dc6b29SJens Wiklander 82393dc6b29SJens Wiklander#ifdef CFG_CORE_PAUTH 82493dc6b29SJens Wiklander ldp x2, x3, [x0, #THREAD_CTX_KEYS] 82593dc6b29SJens Wiklander write_apiakeyhi x2 82693dc6b29SJens Wiklander write_apiakeylo x3 82793dc6b29SJens Wiklander#endif 82893dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) 82993dc6b29SJens Wiklander /* SCTLR or the APIA key has changed */ 83093dc6b29SJens Wiklander isb 83193dc6b29SJens Wiklander#endif 83293dc6b29SJens Wiklander 833e0cbf7deSJens Wiklander /* Restore x0-x3 */ 834c02f9fb0SJens Wiklander ldp x2, x3, [x1, #THREAD_CORE_LOCAL_X2] 835c02f9fb0SJens Wiklander ldp x0, x1, [x1, #THREAD_CORE_LOCAL_X0] 836e0cbf7deSJens Wiklander 837e0cbf7deSJens Wiklander /* Prepare the argument for the handler */ 838ab5363c6SJens Wiklander store_xregs sp, THREAD_SCALL_REG_X0, 0, 14 839e0cbf7deSJens Wiklander mrs x0, elr_el1 840e0cbf7deSJens Wiklander mrs x1, spsr_el1 841ab5363c6SJens Wiklander store_xregs sp, THREAD_SCALL_REG_ELR, 0, 1 8422b06f9deSRuchika Gupta 843e0cbf7deSJens Wiklander mov x0, sp 844e0cbf7deSJens Wiklander 845e0cbf7deSJens Wiklander /* 8465acb1bc6SDavid Wang * Unmask native interrupts, Serror, and debug exceptions since we have 8475acb1bc6SDavid Wang * nothing left in sp_el1. Note that the SVC handler is excepted to 8485acb1bc6SDavid Wang * re-enable foreign interrupts by itself. 849e0cbf7deSJens Wiklander */ 850087c9fbbSJens Wiklander#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) 85123e2942eSZhizhou Zhang msr daifclr, #(DAIFBIT_IRQ | DAIFBIT_ABT | DAIFBIT_DBG) 85223e2942eSZhizhou Zhang#else 853e0cbf7deSJens Wiklander msr daifclr, #(DAIFBIT_FIQ | DAIFBIT_ABT | DAIFBIT_DBG) 85423e2942eSZhizhou Zhang#endif 855e0cbf7deSJens Wiklander 8561aa8bb32SJens Wiklander /* Call the handler */ 857ab5363c6SJens Wiklander bl thread_scall_handler 858e0cbf7deSJens Wiklander 859e0cbf7deSJens Wiklander /* Mask all maskable exceptions since we're switching back to sp_el1 */ 860e0cbf7deSJens Wiklander msr daifset, #DAIFBIT_ALL 861e0cbf7deSJens Wiklander 862bee02359SJens Wiklander /* 863bee02359SJens Wiklander * Save kernel sp we'll had at the beginning of this function. 864bee02359SJens Wiklander * This is when this TA has called another TA because 865bee02359SJens Wiklander * __thread_enter_user_mode() also saves the stack pointer in this 866bee02359SJens Wiklander * field. 867bee02359SJens Wiklander */ 868e0cbf7deSJens Wiklander msr spsel, #1 869f07647d4SJens Wiklander get_thread_ctx sp, 0, 1, 2 870e0cbf7deSJens Wiklander msr spsel, #0 871ab5363c6SJens Wiklander add x1, sp, #THREAD_SCALL_REG_SIZE 872c02f9fb0SJens Wiklander str x1, [x0, #THREAD_CTX_KERN_SP] 873e0cbf7deSJens Wiklander 874e0cbf7deSJens Wiklander /* Restore registers to the required state and return*/ 87504752110SJerome Forissier ldr x1, [x0, #THREAD_CTX_REGS_TPIDR_EL0] 87604752110SJerome Forissier msr tpidr_el0, x1 877ab5363c6SJens Wiklander load_xregs sp, THREAD_SCALL_REG_ELR, 0, 1 878e0cbf7deSJens Wiklander msr elr_el1, x0 879e0cbf7deSJens Wiklander msr spsr_el1, x1 880ab5363c6SJens Wiklander load_xregs sp, THREAD_SCALL_REG_X2, 2, 14 881bee02359SJens Wiklander mov x30, sp 882ab5363c6SJens Wiklander ldr x0, [x30, #THREAD_SCALL_REG_SP_EL0] 883bee02359SJens Wiklander mov sp, x0 8845b8a58b4SJens Wiklander b_if_spsr_is_el0 w1, 1f 885ab5363c6SJens Wiklander ldp x0, x1, [x30, THREAD_SCALL_REG_X0] 886ab5363c6SJens Wiklander ldr x30, [x30, #THREAD_SCALL_REG_X30] 887e0cbf7deSJens Wiklander 888abfd092aSAnthony Steinhauser return_from_exception 8895b8a58b4SJens Wiklander 8902b06f9deSRuchika Gupta1: 8912b06f9deSRuchika Gupta#ifdef CFG_TA_PAUTH 8922b06f9deSRuchika Gupta /* Restore APIAKEY */ 893ab5363c6SJens Wiklander load_xregs x30, THREAD_SCALL_REG_APIAKEY_HI, 0, 1 8942b06f9deSRuchika Gupta write_apiakeyhi x0 8952b06f9deSRuchika Gupta write_apiakeylo x1 8962b06f9deSRuchika Gupta#endif 8972b06f9deSRuchika Gupta 898ab5363c6SJens Wiklander ldp x0, x1, [x30, THREAD_SCALL_REG_X0] 899ab5363c6SJens Wiklander ldr x30, [x30, #THREAD_SCALL_REG_X30] 9005b8a58b4SJens Wiklander 9015b8a58b4SJens Wiklander msr spsel, #1 9025b8a58b4SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 9035b8a58b4SJens Wiklander b eret_to_el0 904bee02359SJens WiklanderEND_FUNC el0_svc 905e0cbf7deSJens Wiklander 906e0cbf7deSJens WiklanderLOCAL_FUNC el1_sync_abort , : 907e0cbf7deSJens Wiklander mov x0, sp 908e0cbf7deSJens Wiklander msr spsel, #0 9095dd05ba7SJens Wiklander mov x3, sp /* Save original sp */ 910e0cbf7deSJens Wiklander 9115dd05ba7SJens Wiklander /* 9125dd05ba7SJens Wiklander * Update core local flags. 9135dd05ba7SJens Wiklander * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT; 9145dd05ba7SJens Wiklander */ 915c02f9fb0SJens Wiklander ldr w1, [x0, #THREAD_CORE_LOCAL_FLAGS] 916e0cbf7deSJens Wiklander lsl w1, w1, #THREAD_CLF_SAVED_SHIFT 917e0cbf7deSJens Wiklander orr w1, w1, #THREAD_CLF_ABORT 9185dd05ba7SJens Wiklander tbnz w1, #(THREAD_CLF_SAVED_SHIFT + THREAD_CLF_ABORT_SHIFT), \ 9195dd05ba7SJens Wiklander .Lsel_tmp_sp 920e0cbf7deSJens Wiklander 9215dd05ba7SJens Wiklander /* Select abort stack */ 922c02f9fb0SJens Wiklander ldr x2, [x0, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] 9235dd05ba7SJens Wiklander b .Lset_sp 9245dd05ba7SJens Wiklander 9255dd05ba7SJens Wiklander.Lsel_tmp_sp: 92693dc6b29SJens Wiklander /* We have an abort while using the abort stack, select tmp stack */ 927c02f9fb0SJens Wiklander ldr x2, [x0, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] 9285dd05ba7SJens Wiklander orr w1, w1, #THREAD_CLF_TMP /* flags |= THREAD_CLF_TMP; */ 9295dd05ba7SJens Wiklander 9305dd05ba7SJens Wiklander.Lset_sp: 931e0cbf7deSJens Wiklander mov sp, x2 932c02f9fb0SJens Wiklander str w1, [x0, #THREAD_CORE_LOCAL_FLAGS] 933e0cbf7deSJens Wiklander 934e0cbf7deSJens Wiklander /* 935e0cbf7deSJens Wiklander * Save state on stack 936e0cbf7deSJens Wiklander */ 937e0cbf7deSJens Wiklander sub sp, sp, #THREAD_ABT_REGS_SIZE 938e0cbf7deSJens Wiklander mrs x2, spsr_el1 939e0cbf7deSJens Wiklander /* Store spsr, sp_el0 */ 940c02f9fb0SJens Wiklander stp x2, x3, [sp, #THREAD_ABT_REG_SPSR] 941e0cbf7deSJens Wiklander /* Store original x0, x1 */ 942c02f9fb0SJens Wiklander ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X0] 943c02f9fb0SJens Wiklander stp x2, x3, [sp, #THREAD_ABT_REG_X0] 944e0cbf7deSJens Wiklander /* Store original x2, x3 and x4 to x29 */ 945c02f9fb0SJens Wiklander ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X2] 946c02f9fb0SJens Wiklander store_xregs sp, THREAD_ABT_REG_X2, 2, 29 947e0cbf7deSJens Wiklander /* Store x30, elr_el1 */ 94893dc6b29SJens Wiklander mrs x1, elr_el1 94993dc6b29SJens Wiklander stp x30, x1, [sp, #THREAD_ABT_REG_X30] 95093dc6b29SJens Wiklander 95193dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 95293dc6b29SJens Wiklander read_apiakeyhi x2 95393dc6b29SJens Wiklander read_apiakeylo x3 95493dc6b29SJens Wiklander stp x2, x3, [sp, #THREAD_ABT_REGS_APIAKEY_HI] 95593dc6b29SJens Wiklander ldp x2, x3, [x0, #THREAD_CORE_LOCAL_KEYS] 95693dc6b29SJens Wiklander write_apiakeyhi x2 95793dc6b29SJens Wiklander write_apiakeylo x3 95893dc6b29SJens Wiklander isb 95993dc6b29SJens Wiklander#endif 960e0cbf7deSJens Wiklander 961e0cbf7deSJens Wiklander /* 962e0cbf7deSJens Wiklander * Call handler 963e0cbf7deSJens Wiklander */ 964e0cbf7deSJens Wiklander mov x0, #0 965e0cbf7deSJens Wiklander mov x1, sp 9661aa8bb32SJens Wiklander bl abort_handler 967e0cbf7deSJens Wiklander 968e0cbf7deSJens Wiklander /* 969e0cbf7deSJens Wiklander * Restore state from stack 970e0cbf7deSJens Wiklander */ 971e0cbf7deSJens Wiklander /* Load x30, elr_el1 */ 972c02f9fb0SJens Wiklander ldp x30, x0, [sp, #THREAD_ABT_REG_X30] 973e0cbf7deSJens Wiklander msr elr_el1, x0 974e0cbf7deSJens Wiklander /* Load x0 to x29 */ 975c02f9fb0SJens Wiklander load_xregs sp, THREAD_ABT_REG_X0, 0, 29 976e0cbf7deSJens Wiklander /* Switch to SP_EL1 */ 977e0cbf7deSJens Wiklander msr spsel, #1 978e0cbf7deSJens Wiklander /* Save x0 to x3 in CORE_LOCAL */ 979c02f9fb0SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 980e0cbf7deSJens Wiklander /* Restore spsr_el1 and sp_el0 */ 981e0cbf7deSJens Wiklander mrs x3, sp_el0 982c02f9fb0SJens Wiklander ldp x0, x1, [x3, #THREAD_ABT_REG_SPSR] 983e0cbf7deSJens Wiklander msr spsr_el1, x0 984e0cbf7deSJens Wiklander msr sp_el0, x1 985e0cbf7deSJens Wiklander 986e0cbf7deSJens Wiklander /* Update core local flags */ 987c02f9fb0SJens Wiklander ldr w0, [sp, #THREAD_CORE_LOCAL_FLAGS] 988e0cbf7deSJens Wiklander lsr w0, w0, #THREAD_CLF_SAVED_SHIFT 989c02f9fb0SJens Wiklander str w0, [sp, #THREAD_CORE_LOCAL_FLAGS] 990e0cbf7deSJens Wiklander 99193dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 99293dc6b29SJens Wiklander ldp x0, x1, [x3, #THREAD_ABT_REGS_APIAKEY_HI] 99393dc6b29SJens Wiklander write_apiakeyhi x0 99493dc6b29SJens Wiklander write_apiakeylo x1 99593dc6b29SJens Wiklander isb 99693dc6b29SJens Wiklander#endif 99793dc6b29SJens Wiklander 998e0cbf7deSJens Wiklander /* Restore x0 to x3 */ 999c02f9fb0SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 1000e0cbf7deSJens Wiklander 1001e0cbf7deSJens Wiklander /* Return from exception */ 1002abfd092aSAnthony Steinhauser return_from_exception 1003e0cbf7deSJens WiklanderEND_FUNC el1_sync_abort 1004e0cbf7deSJens Wiklander 1005e0cbf7deSJens Wiklander /* sp_el0 in x3 */ 1006e0cbf7deSJens WiklanderLOCAL_FUNC el0_sync_abort , : 100793dc6b29SJens Wiklander pauth_el0_to_el1 x1 10085dd05ba7SJens Wiklander /* 10095dd05ba7SJens Wiklander * Update core local flags 10105dd05ba7SJens Wiklander */ 1011c02f9fb0SJens Wiklander ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 10125dd05ba7SJens Wiklander lsl w1, w1, #THREAD_CLF_SAVED_SHIFT 10135dd05ba7SJens Wiklander orr w1, w1, #THREAD_CLF_ABORT 1014c02f9fb0SJens Wiklander str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 10155dd05ba7SJens Wiklander 10165dd05ba7SJens Wiklander /* 10175dd05ba7SJens Wiklander * Save state on stack 10185dd05ba7SJens Wiklander */ 10195dd05ba7SJens Wiklander 1020e0cbf7deSJens Wiklander /* load abt_stack_va_end */ 1021c02f9fb0SJens Wiklander ldr x1, [sp, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] 1022e0cbf7deSJens Wiklander /* Keep pointer to initial record in x0 */ 1023e0cbf7deSJens Wiklander mov x0, sp 1024e0cbf7deSJens Wiklander /* Switch to SP_EL0 */ 1025e0cbf7deSJens Wiklander msr spsel, #0 1026e0cbf7deSJens Wiklander mov sp, x1 1027e0cbf7deSJens Wiklander sub sp, sp, #THREAD_ABT_REGS_SIZE 1028e0cbf7deSJens Wiklander mrs x2, spsr_el1 1029e0cbf7deSJens Wiklander /* Store spsr, sp_el0 */ 1030c02f9fb0SJens Wiklander stp x2, x3, [sp, #THREAD_ABT_REG_SPSR] 1031e0cbf7deSJens Wiklander /* Store original x0, x1 */ 1032c02f9fb0SJens Wiklander ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X0] 1033c02f9fb0SJens Wiklander stp x2, x3, [sp, #THREAD_ABT_REG_X0] 1034e0cbf7deSJens Wiklander /* Store original x2, x3 and x4 to x29 */ 1035c02f9fb0SJens Wiklander ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X2] 1036c02f9fb0SJens Wiklander store_xregs sp, THREAD_ABT_REG_X2, 2, 29 1037e0cbf7deSJens Wiklander /* Store x30, elr_el1 */ 103893dc6b29SJens Wiklander mrs x1, elr_el1 103993dc6b29SJens Wiklander stp x30, x1, [sp, #THREAD_ABT_REG_X30] 104093dc6b29SJens Wiklander 104193dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) 104293dc6b29SJens Wiklander read_apiakeyhi x2 104393dc6b29SJens Wiklander read_apiakeylo x3 104493dc6b29SJens Wiklander stp x2, x3, [sp, #THREAD_ABT_REGS_APIAKEY_HI] 104593dc6b29SJens Wiklander#endif 104693dc6b29SJens Wiklander 104793dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 104893dc6b29SJens Wiklander ldp x2, x3, [x0, #THREAD_CORE_LOCAL_KEYS] 104993dc6b29SJens Wiklander write_apiakeyhi x2 105093dc6b29SJens Wiklander write_apiakeylo x3 105193dc6b29SJens Wiklander#endif 105293dc6b29SJens Wiklander 105393dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) 105493dc6b29SJens Wiklander /* SCTLR or the APIA key has changed */ 105593dc6b29SJens Wiklander isb 105693dc6b29SJens Wiklander#endif 10575dd05ba7SJens Wiklander 10585dd05ba7SJens Wiklander /* 10595dd05ba7SJens Wiklander * Call handler 10605dd05ba7SJens Wiklander */ 1061e0cbf7deSJens Wiklander mov x0, #0 1062e0cbf7deSJens Wiklander mov x1, sp 10631aa8bb32SJens Wiklander bl abort_handler 10645dd05ba7SJens Wiklander 10655dd05ba7SJens Wiklander /* 10665dd05ba7SJens Wiklander * Restore state from stack 10675dd05ba7SJens Wiklander */ 10685dd05ba7SJens Wiklander 1069e0cbf7deSJens Wiklander /* Load x30, elr_el1 */ 1070c02f9fb0SJens Wiklander ldp x30, x0, [sp, #THREAD_ABT_REG_X30] 1071e0cbf7deSJens Wiklander msr elr_el1, x0 1072e0cbf7deSJens Wiklander /* Load x0 to x29 */ 1073c02f9fb0SJens Wiklander load_xregs sp, THREAD_ABT_REG_X0, 0, 29 1074e0cbf7deSJens Wiklander /* Switch to SP_EL1 */ 1075e0cbf7deSJens Wiklander msr spsel, #1 1076e0cbf7deSJens Wiklander /* Save x0 to x3 in EL1_REC */ 1077c02f9fb0SJens Wiklander store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 1078e0cbf7deSJens Wiklander /* Restore spsr_el1 and sp_el0 */ 1079e0cbf7deSJens Wiklander mrs x3, sp_el0 1080c02f9fb0SJens Wiklander ldp x0, x1, [x3, #THREAD_ABT_REG_SPSR] 1081e0cbf7deSJens Wiklander msr spsr_el1, x0 1082e0cbf7deSJens Wiklander msr sp_el0, x1 10835dd05ba7SJens Wiklander 10845dd05ba7SJens Wiklander /* Update core local flags */ 10855b8a58b4SJens Wiklander ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 10865b8a58b4SJens Wiklander lsr w1, w1, #THREAD_CLF_SAVED_SHIFT 10875b8a58b4SJens Wiklander str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 10885dd05ba7SJens Wiklander 108993dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 109093dc6b29SJens Wiklander ldp x1, x2, [x3, #THREAD_ABT_REGS_APIAKEY_HI] 109193dc6b29SJens Wiklander write_apiakeyhi x1 109293dc6b29SJens Wiklander write_apiakeylo x2 109393dc6b29SJens Wiklander#endif 109493dc6b29SJens Wiklander 10955b8a58b4SJens Wiklander /* Restore x2 to x3 */ 10965b8a58b4SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3 10975b8a58b4SJens Wiklander 10986e093e31SJens Wiklander b_if_spsr_is_el0 w0, 1f 10995b8a58b4SJens Wiklander 110093dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 110193dc6b29SJens Wiklander /* the APIA key has changed */ 110293dc6b29SJens Wiklander isb 110393dc6b29SJens Wiklander#endif 110493dc6b29SJens Wiklander 11055b8a58b4SJens Wiklander /* Restore x0 to x1 */ 11065b8a58b4SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 11075dd05ba7SJens Wiklander 1108e0cbf7deSJens Wiklander /* Return from exception */ 1109abfd092aSAnthony Steinhauser return_from_exception 11106e093e31SJens Wiklander1: b eret_to_el0 1111e0cbf7deSJens WiklanderEND_FUNC el0_sync_abort 1112e0cbf7deSJens Wiklander 11133361bca8SDavid Wang/* The handler of foreign interrupt. */ 11143361bca8SDavid Wang.macro foreign_intr_handler mode:req 11155dd05ba7SJens Wiklander /* 11165dd05ba7SJens Wiklander * Update core local flags 11175dd05ba7SJens Wiklander */ 1118c02f9fb0SJens Wiklander ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 11195dd05ba7SJens Wiklander lsl w1, w1, #THREAD_CLF_SAVED_SHIFT 11205dd05ba7SJens Wiklander orr w1, w1, #THREAD_CLF_TMP 11213361bca8SDavid Wang .ifc \mode\(),fiq 11223361bca8SDavid Wang orr w1, w1, #THREAD_CLF_FIQ 11233361bca8SDavid Wang .else 11245dd05ba7SJens Wiklander orr w1, w1, #THREAD_CLF_IRQ 11253361bca8SDavid Wang .endif 1126c02f9fb0SJens Wiklander str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 11275dd05ba7SJens Wiklander 1128d5fbeadcSJens Wiklander /* get pointer to current thread context in x0 */ 11295dd05ba7SJens Wiklander get_thread_ctx sp, 0, 1, 2 1130e0cbf7deSJens Wiklander /* Keep original SP_EL0 */ 1131e0cbf7deSJens Wiklander mrs x2, sp_el0 1132e0cbf7deSJens Wiklander 1133e0cbf7deSJens Wiklander /* Store original sp_el0 */ 1134c02f9fb0SJens Wiklander str x2, [x0, #THREAD_CTX_REGS_SP] 113504752110SJerome Forissier /* Store tpidr_el0 */ 113604752110SJerome Forissier mrs x2, tpidr_el0 113704752110SJerome Forissier str x2, [x0, #THREAD_CTX_REGS_TPIDR_EL0] 113804752110SJerome Forissier /* Store x4..x30 */ 1139c02f9fb0SJens Wiklander store_xregs x0, THREAD_CTX_REGS_X4, 4, 30 1140e0cbf7deSJens Wiklander /* Load original x0..x3 into x10..x13 */ 1141c02f9fb0SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 10, 13 1142e0cbf7deSJens Wiklander /* Save original x0..x3 */ 1143c02f9fb0SJens Wiklander store_xregs x0, THREAD_CTX_REGS_X0, 10, 13 1144e0cbf7deSJens Wiklander 114593dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 1146b8cb4501SJens Wiklander /* Save APIAKEY */ 1147b8cb4501SJens Wiklander read_apiakeyhi x1 1148b8cb4501SJens Wiklander read_apiakeylo x2 1149b8cb4501SJens Wiklander store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 1150b8cb4501SJens Wiklander#endif 115193dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 115293dc6b29SJens Wiklander ldp x1, x2, [sp, #THREAD_CORE_LOCAL_KEYS] 115393dc6b29SJens Wiklander write_apiakeyhi x1 115493dc6b29SJens Wiklander write_apiakeylo x2 115593dc6b29SJens Wiklander isb 115693dc6b29SJens Wiklander#endif 1157539836f9SJens Wiklander 1158539836f9SJens Wiklander#ifdef CFG_CORE_FFA 1159539836f9SJens Wiklander /* x0 is still pointing to the current thread_ctx */ 1160539836f9SJens Wiklander /* load curr_thread_ctx->tsd.rpc_target_info into w19 */ 1161539836f9SJens Wiklander ldr w19, [x0, #THREAD_CTX_TSD_RPC_TARGET_INFO] 1162539836f9SJens Wiklander /* load curr_thread_ctx->flags into w19 */ 1163539836f9SJens Wiklander ldr w20, [x0, #THREAD_CTX_FLAGS] 1164539836f9SJens Wiklander#endif 1165539836f9SJens Wiklander 1166d5fbeadcSJens Wiklander /* load tmp_stack_va_end */ 1167c02f9fb0SJens Wiklander ldr x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] 1168d5fbeadcSJens Wiklander /* Switch to SP_EL0 */ 1169d5fbeadcSJens Wiklander msr spsel, #0 1170d5fbeadcSJens Wiklander mov sp, x1 1171e0cbf7deSJens Wiklander 117214d6d42bSJens Wiklander#ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME 117314d6d42bSJens Wiklander /* 117414d6d42bSJens Wiklander * Prevent leaking information about which entries has been used in 117514d6d42bSJens Wiklander * cache. We're relying on the dispatcher in TF-A to take care of 117614d6d42bSJens Wiklander * the BTB. 117714d6d42bSJens Wiklander */ 117814d6d42bSJens Wiklander mov x0, #DCACHE_OP_CLEAN_INV 117914d6d42bSJens Wiklander bl dcache_op_louis 118014d6d42bSJens Wiklander ic iallu 118114d6d42bSJens Wiklander#endif 1182e0cbf7deSJens Wiklander /* 1183e0cbf7deSJens Wiklander * Mark current thread as suspended 1184e0cbf7deSJens Wiklander */ 11855acb1bc6SDavid Wang mov w0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR 1186e0cbf7deSJens Wiklander mrs x1, spsr_el1 1187e0cbf7deSJens Wiklander mrs x2, elr_el1 1188e0cbf7deSJens Wiklander bl thread_state_suspend 1189e0cbf7deSJens Wiklander 11905dd05ba7SJens Wiklander /* Update core local flags */ 11915dd05ba7SJens Wiklander /* Switch to SP_EL1 */ 11925dd05ba7SJens Wiklander msr spsel, #1 11932786f143SJens Wiklander ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 11942786f143SJens Wiklander lsr w1, w1, #THREAD_CLF_SAVED_SHIFT 11950733f3d1SJerome Forissier orr w1, w1, #THREAD_CLF_TMP 11962786f143SJens Wiklander str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 11975dd05ba7SJens Wiklander msr spsel, #0 11985dd05ba7SJens Wiklander 11995dd05ba7SJens Wiklander /* 12005dd05ba7SJens Wiklander * Note that we're exiting with SP_EL0 selected since the entry 12015dd05ba7SJens Wiklander * functions expects to have SP_EL0 selected with the tmp stack 12025dd05ba7SJens Wiklander * set. 12035dd05ba7SJens Wiklander */ 12045dd05ba7SJens Wiklander 12052786f143SJens Wiklander /* Passing thread index in w0 */ 1206539836f9SJens Wiklander#ifdef CFG_CORE_FFA 1207539836f9SJens Wiklander mov w1, w19 /* rpc_target_info */ 1208539836f9SJens Wiklander mov w2, w20 /* flags */ 1209539836f9SJens Wiklander#endif 12102786f143SJens Wiklander b thread_foreign_intr_exit 12113361bca8SDavid Wang.endm 1212e0cbf7deSJens Wiklander 1213d5fbeadcSJens Wiklander/* 12145dd05ba7SJens Wiklander * This struct is never used from C it's only here to visualize the 12155dd05ba7SJens Wiklander * layout. 12165dd05ba7SJens Wiklander * 12173361bca8SDavid Wang * struct elx_nintr_rec { 1218d5fbeadcSJens Wiklander * uint64_t x[19 - 4]; x4..x18 1219d5fbeadcSJens Wiklander * uint64_t lr; 1220d5fbeadcSJens Wiklander * uint64_t sp_el0; 122193dc6b29SJens Wiklander * #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 122293dc6b29SJens Wiklander * uint64_t apiakey_hi; 122393dc6b29SJens Wiklander * uint64_t apiakey_lo; 122493dc6b29SJens Wiklander * #endif 1225d5fbeadcSJens Wiklander * }; 1226d5fbeadcSJens Wiklander */ 12273361bca8SDavid Wang#define ELX_NINTR_REC_X(x) (8 * ((x) - 4)) 12283361bca8SDavid Wang#define ELX_NINTR_REC_LR (8 + ELX_NINTR_REC_X(19)) 12293361bca8SDavid Wang#define ELX_NINTR_REC_SP_EL0 (8 + ELX_NINTR_REC_LR) 123093dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 123193dc6b29SJens Wiklander#define ELX_NINTR_REG_APIAKEY_HI (8 + ELX_NINTR_REC_SP_EL0) 123293dc6b29SJens Wiklander#define ELX_NINTR_REG_APIAKEY_LO (8 + ELX_NINTR_REG_APIAKEY_HI) 123393dc6b29SJens Wiklander#define ELX_NINTR_REC_SIZE (8 + ELX_NINTR_REG_APIAKEY_LO) 123493dc6b29SJens Wiklander#else 12353361bca8SDavid Wang#define ELX_NINTR_REC_SIZE (8 + ELX_NINTR_REC_SP_EL0) 123693dc6b29SJens Wiklander#endif 123793dc6b29SJens Wiklander 1238d5fbeadcSJens Wiklander 12393361bca8SDavid Wang/* The handler of native interrupt. */ 12403361bca8SDavid Wang.macro native_intr_handler mode:req 12415dd05ba7SJens Wiklander /* 12425dd05ba7SJens Wiklander * Update core local flags 12435dd05ba7SJens Wiklander */ 1244c02f9fb0SJens Wiklander ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 12455dd05ba7SJens Wiklander lsl w1, w1, #THREAD_CLF_SAVED_SHIFT 12463361bca8SDavid Wang .ifc \mode\(),fiq 12475dd05ba7SJens Wiklander orr w1, w1, #THREAD_CLF_FIQ 12483361bca8SDavid Wang .else 12493361bca8SDavid Wang orr w1, w1, #THREAD_CLF_IRQ 12503361bca8SDavid Wang .endif 12515dd05ba7SJens Wiklander orr w1, w1, #THREAD_CLF_TMP 1252c02f9fb0SJens Wiklander str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] 12535dd05ba7SJens Wiklander 125493dc6b29SJens Wiklander /* 125593dc6b29SJens Wiklander * Save registers on the temp stack that can be corrupted by a call 125693dc6b29SJens Wiklander * to a C function. 125793dc6b29SJens Wiklander * 125893dc6b29SJens Wiklander * Note that we're temporarily using x1 to access the temp stack 125993dc6b29SJens Wiklander * until we're ready to switch to sp_el0 and update sp. 126093dc6b29SJens Wiklander */ 1261e0cbf7deSJens Wiklander /* load tmp_stack_va_end */ 1262c02f9fb0SJens Wiklander ldr x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] 126393dc6b29SJens Wiklander /* Make room for struct elx_nintr_rec */ 126493dc6b29SJens Wiklander sub x1, x1, #ELX_NINTR_REC_SIZE 126593dc6b29SJens Wiklander /* Store lr and original sp_el0 */ 1266e0cbf7deSJens Wiklander mrs x2, sp_el0 126793dc6b29SJens Wiklander stp x30, x2, [x1, #ELX_NINTR_REC_LR] 126893dc6b29SJens Wiklander /* Store x4..x18 */ 126993dc6b29SJens Wiklander store_xregs x1, ELX_NINTR_REC_X(4), 4, 18 127093dc6b29SJens Wiklander 127193dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 127293dc6b29SJens Wiklander read_apiakeyhi x2 127393dc6b29SJens Wiklander read_apiakeylo x3 127493dc6b29SJens Wiklander stp x2, x3, [x1, #ELX_NINTR_REG_APIAKEY_HI] 127593dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 127693dc6b29SJens Wiklander ldp x2, x3, [sp, #THREAD_CORE_LOCAL_KEYS] 127793dc6b29SJens Wiklander write_apiakeyhi x2 127893dc6b29SJens Wiklander write_apiakeylo x3 127993dc6b29SJens Wiklander#endif 128093dc6b29SJens Wiklander /* SCTLR or the APIA key has changed */ 128193dc6b29SJens Wiklander isb 128293dc6b29SJens Wiklander#endif 128393dc6b29SJens Wiklander 1284e0cbf7deSJens Wiklander /* Switch to SP_EL0 */ 1285e0cbf7deSJens Wiklander msr spsel, #0 1286e0cbf7deSJens Wiklander mov sp, x1 1287e0cbf7deSJens Wiklander 1288e0cbf7deSJens Wiklander bl thread_check_canaries 1289358bf47cSEtienne Carriere bl interrupt_main_handler 1290e0cbf7deSJens Wiklander 1291e0cbf7deSJens Wiklander /* 1292e0cbf7deSJens Wiklander * Restore registers 1293e0cbf7deSJens Wiklander */ 129493dc6b29SJens Wiklander 129593dc6b29SJens Wiklander#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) 129693dc6b29SJens Wiklander ldp x0, x1, [sp, #ELX_NINTR_REG_APIAKEY_HI] 129793dc6b29SJens Wiklander write_apiakeyhi x0 129893dc6b29SJens Wiklander write_apiakeylo x1 129993dc6b29SJens Wiklander#endif 130093dc6b29SJens Wiklander 1301e0cbf7deSJens Wiklander /* Restore x4..x18 */ 13023361bca8SDavid Wang load_xregs sp, ELX_NINTR_REC_X(4), 4, 18 1303e0cbf7deSJens Wiklander /* Load lr and original sp_el0 */ 13043361bca8SDavid Wang ldp x30, x2, [sp, #ELX_NINTR_REC_LR] 1305d5fbeadcSJens Wiklander /* Restore SP_El0 */ 1306e0cbf7deSJens Wiklander mov sp, x2 1307d5fbeadcSJens Wiklander /* Switch back to SP_EL1 */ 1308e0cbf7deSJens Wiklander msr spsel, #1 13095dd05ba7SJens Wiklander 13105dd05ba7SJens Wiklander /* Update core local flags */ 1311c02f9fb0SJens Wiklander ldr w0, [sp, #THREAD_CORE_LOCAL_FLAGS] 13125dd05ba7SJens Wiklander lsr w0, w0, #THREAD_CLF_SAVED_SHIFT 1313c02f9fb0SJens Wiklander str w0, [sp, #THREAD_CORE_LOCAL_FLAGS] 13145dd05ba7SJens Wiklander 13155b8a58b4SJens Wiklander mrs x0, spsr_el1 131693dc6b29SJens Wiklander 13175b8a58b4SJens Wiklander /* Restore x2..x3 */ 13185b8a58b4SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3 13196e093e31SJens Wiklander b_if_spsr_is_el0 w0, 1f 13205b8a58b4SJens Wiklander 132193dc6b29SJens Wiklander#if defined(CFG_CORE_PAUTH) 132293dc6b29SJens Wiklander /* APIA key has changed */ 132393dc6b29SJens Wiklander isb 132493dc6b29SJens Wiklander#endif 132593dc6b29SJens Wiklander 13265b8a58b4SJens Wiklander /* Restore x0..x1 */ 13275b8a58b4SJens Wiklander load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 1328e0cbf7deSJens Wiklander 1329e0cbf7deSJens Wiklander /* Return from exception */ 1330abfd092aSAnthony Steinhauser return_from_exception 13316e093e31SJens Wiklander1: b eret_to_el0 13323361bca8SDavid Wang.endm 13333361bca8SDavid Wang 13343361bca8SDavid WangLOCAL_FUNC elx_irq , : 1335087c9fbbSJens Wiklander#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) 133618901324SDavid Wang native_intr_handler irq 133718901324SDavid Wang#else 13383361bca8SDavid Wang foreign_intr_handler irq 133918901324SDavid Wang#endif 13403361bca8SDavid WangEND_FUNC elx_irq 13413361bca8SDavid Wang 13423361bca8SDavid WangLOCAL_FUNC elx_fiq , : 1343087c9fbbSJens Wiklander#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) 134418901324SDavid Wang foreign_intr_handler fiq 134518901324SDavid Wang#else 13463361bca8SDavid Wang native_intr_handler fiq 134718901324SDavid Wang#endif 1348e0cbf7deSJens WiklanderEND_FUNC elx_fiq 1349181f8492SRuchika Gupta 1350181f8492SRuchika GuptaBTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) 1351