xref: /optee_os/core/arch/arm/kernel/thread_a64.S (revision 91d4649de98c6beeb8217d40f1fafa50720fe785)
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