xref: /openbmc/linux/arch/arm64/kernel/entry.S (revision 51f6b410)
1/*
2 * Low-level exception handling code
3 *
4 * Copyright (C) 2012 ARM Ltd.
5 * Authors:	Catalin Marinas <catalin.marinas@arm.com>
6 *		Will Deacon <will.deacon@arm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/arm-smccc.h>
22#include <linux/init.h>
23#include <linux/linkage.h>
24
25#include <asm/alternative.h>
26#include <asm/assembler.h>
27#include <asm/asm-offsets.h>
28#include <asm/cpufeature.h>
29#include <asm/errno.h>
30#include <asm/esr.h>
31#include <asm/irq.h>
32#include <asm/memory.h>
33#include <asm/mmu.h>
34#include <asm/processor.h>
35#include <asm/ptrace.h>
36#include <asm/thread_info.h>
37#include <asm/asm-uaccess.h>
38#include <asm/unistd.h>
39
40/*
41 * Context tracking subsystem.  Used to instrument transitions
42 * between user and kernel mode.
43 */
44	.macro ct_user_exit
45#ifdef CONFIG_CONTEXT_TRACKING
46	bl	context_tracking_user_exit
47#endif
48	.endm
49
50	.macro ct_user_enter
51#ifdef CONFIG_CONTEXT_TRACKING
52	bl	context_tracking_user_enter
53#endif
54	.endm
55
56	.macro	clear_gp_regs
57	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
58	mov	x\n, xzr
59	.endr
60	.endm
61
62/*
63 * Bad Abort numbers
64 *-----------------
65 */
66#define BAD_SYNC	0
67#define BAD_IRQ		1
68#define BAD_FIQ		2
69#define BAD_ERROR	3
70
71	.macro kernel_ventry, el, label, regsize = 64
72	.align 7
73#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
74alternative_if ARM64_UNMAP_KERNEL_AT_EL0
75	.if	\el == 0
76	.if	\regsize == 64
77	mrs	x30, tpidrro_el0
78	msr	tpidrro_el0, xzr
79	.else
80	mov	x30, xzr
81	.endif
82	.endif
83alternative_else_nop_endif
84#endif
85
86	sub	sp, sp, #S_FRAME_SIZE
87#ifdef CONFIG_VMAP_STACK
88	/*
89	 * Test whether the SP has overflowed, without corrupting a GPR.
90	 * Task and IRQ stacks are aligned to (1 << THREAD_SHIFT).
91	 */
92	add	sp, sp, x0			// sp' = sp + x0
93	sub	x0, sp, x0			// x0' = sp' - x0 = (sp + x0) - x0 = sp
94	tbnz	x0, #THREAD_SHIFT, 0f
95	sub	x0, sp, x0			// x0'' = sp' - x0' = (sp + x0) - sp = x0
96	sub	sp, sp, x0			// sp'' = sp' - x0 = (sp + x0) - x0 = sp
97	b	el\()\el\()_\label
98
990:
100	/*
101	 * Either we've just detected an overflow, or we've taken an exception
102	 * while on the overflow stack. Either way, we won't return to
103	 * userspace, and can clobber EL0 registers to free up GPRs.
104	 */
105
106	/* Stash the original SP (minus S_FRAME_SIZE) in tpidr_el0. */
107	msr	tpidr_el0, x0
108
109	/* Recover the original x0 value and stash it in tpidrro_el0 */
110	sub	x0, sp, x0
111	msr	tpidrro_el0, x0
112
113	/* Switch to the overflow stack */
114	adr_this_cpu sp, overflow_stack + OVERFLOW_STACK_SIZE, x0
115
116	/*
117	 * Check whether we were already on the overflow stack. This may happen
118	 * after panic() re-enables interrupts.
119	 */
120	mrs	x0, tpidr_el0			// sp of interrupted context
121	sub	x0, sp, x0			// delta with top of overflow stack
122	tst	x0, #~(OVERFLOW_STACK_SIZE - 1)	// within range?
123	b.ne	__bad_stack			// no? -> bad stack pointer
124
125	/* We were already on the overflow stack. Restore sp/x0 and carry on. */
126	sub	sp, sp, x0
127	mrs	x0, tpidrro_el0
128#endif
129	b	el\()\el\()_\label
130	.endm
131
132	.macro tramp_alias, dst, sym
133	mov_q	\dst, TRAMP_VALIAS
134	add	\dst, \dst, #(\sym - .entry.tramp.text)
135	.endm
136
137	// This macro corrupts x0-x3. It is the caller's duty
138	// to save/restore them if required.
139	.macro	apply_ssbd, state, tmp1, tmp2
140#ifdef CONFIG_ARM64_SSBD
141alternative_cb	arm64_enable_wa2_handling
142	b	.L__asm_ssbd_skip\@
143alternative_cb_end
144	ldr_this_cpu	\tmp2, arm64_ssbd_callback_required, \tmp1
145	cbz	\tmp2,	.L__asm_ssbd_skip\@
146	ldr	\tmp2, [tsk, #TSK_TI_FLAGS]
147	tbnz	\tmp2, #TIF_SSBD, .L__asm_ssbd_skip\@
148	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_2
149	mov	w1, #\state
150alternative_cb	arm64_update_smccc_conduit
151	nop					// Patched to SMC/HVC #0
152alternative_cb_end
153.L__asm_ssbd_skip\@:
154#endif
155	.endm
156
157	.macro	kernel_entry, el, regsize = 64
158	.if	\regsize == 32
159	mov	w0, w0				// zero upper 32 bits of x0
160	.endif
161	stp	x0, x1, [sp, #16 * 0]
162	stp	x2, x3, [sp, #16 * 1]
163	stp	x4, x5, [sp, #16 * 2]
164	stp	x6, x7, [sp, #16 * 3]
165	stp	x8, x9, [sp, #16 * 4]
166	stp	x10, x11, [sp, #16 * 5]
167	stp	x12, x13, [sp, #16 * 6]
168	stp	x14, x15, [sp, #16 * 7]
169	stp	x16, x17, [sp, #16 * 8]
170	stp	x18, x19, [sp, #16 * 9]
171	stp	x20, x21, [sp, #16 * 10]
172	stp	x22, x23, [sp, #16 * 11]
173	stp	x24, x25, [sp, #16 * 12]
174	stp	x26, x27, [sp, #16 * 13]
175	stp	x28, x29, [sp, #16 * 14]
176
177	.if	\el == 0
178	clear_gp_regs
179	mrs	x21, sp_el0
180	ldr_this_cpu	tsk, __entry_task, x20	// Ensure MDSCR_EL1.SS is clear,
181	ldr	x19, [tsk, #TSK_TI_FLAGS]	// since we can unmask debug
182	disable_step_tsk x19, x20		// exceptions when scheduling.
183
184	apply_ssbd 1, x22, x23
185
186	.else
187	add	x21, sp, #S_FRAME_SIZE
188	get_thread_info tsk
189	/* Save the task's original addr_limit and set USER_DS */
190	ldr	x20, [tsk, #TSK_TI_ADDR_LIMIT]
191	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
192	mov	x20, #USER_DS
193	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
194	/* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
195	.endif /* \el == 0 */
196	mrs	x22, elr_el1
197	mrs	x23, spsr_el1
198	stp	lr, x21, [sp, #S_LR]
199
200	/*
201	 * In order to be able to dump the contents of struct pt_regs at the
202	 * time the exception was taken (in case we attempt to walk the call
203	 * stack later), chain it together with the stack frames.
204	 */
205	.if \el == 0
206	stp	xzr, xzr, [sp, #S_STACKFRAME]
207	.else
208	stp	x29, x22, [sp, #S_STACKFRAME]
209	.endif
210	add	x29, sp, #S_STACKFRAME
211
212#ifdef CONFIG_ARM64_SW_TTBR0_PAN
213	/*
214	 * Set the TTBR0 PAN bit in SPSR. When the exception is taken from
215	 * EL0, there is no need to check the state of TTBR0_EL1 since
216	 * accesses are always enabled.
217	 * Note that the meaning of this bit differs from the ARMv8.1 PAN
218	 * feature as all TTBR0_EL1 accesses are disabled, not just those to
219	 * user mappings.
220	 */
221alternative_if ARM64_HAS_PAN
222	b	1f				// skip TTBR0 PAN
223alternative_else_nop_endif
224
225	.if	\el != 0
226	mrs	x21, ttbr0_el1
227	tst	x21, #TTBR_ASID_MASK		// Check for the reserved ASID
228	orr	x23, x23, #PSR_PAN_BIT		// Set the emulated PAN in the saved SPSR
229	b.eq	1f				// TTBR0 access already disabled
230	and	x23, x23, #~PSR_PAN_BIT		// Clear the emulated PAN in the saved SPSR
231	.endif
232
233	__uaccess_ttbr0_disable x21
2341:
235#endif
236
237	stp	x22, x23, [sp, #S_PC]
238
239	/* Not in a syscall by default (el0_svc overwrites for real syscall) */
240	.if	\el == 0
241	mov	w21, #NO_SYSCALL
242	str	w21, [sp, #S_SYSCALLNO]
243	.endif
244
245	/*
246	 * Set sp_el0 to current thread_info.
247	 */
248	.if	\el == 0
249	msr	sp_el0, tsk
250	.endif
251
252	/*
253	 * Registers that may be useful after this macro is invoked:
254	 *
255	 * x21 - aborted SP
256	 * x22 - aborted PC
257	 * x23 - aborted PSTATE
258	*/
259	.endm
260
261	.macro	kernel_exit, el
262	.if	\el != 0
263	disable_daif
264
265	/* Restore the task's original addr_limit. */
266	ldr	x20, [sp, #S_ORIG_ADDR_LIMIT]
267	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
268
269	/* No need to restore UAO, it will be restored from SPSR_EL1 */
270	.endif
271
272	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
273	.if	\el == 0
274	ct_user_enter
275	.endif
276
277#ifdef CONFIG_ARM64_SW_TTBR0_PAN
278	/*
279	 * Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR
280	 * PAN bit checking.
281	 */
282alternative_if ARM64_HAS_PAN
283	b	2f				// skip TTBR0 PAN
284alternative_else_nop_endif
285
286	.if	\el != 0
287	tbnz	x22, #22, 1f			// Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set
288	.endif
289
290	__uaccess_ttbr0_enable x0, x1
291
292	.if	\el == 0
293	/*
294	 * Enable errata workarounds only if returning to user. The only
295	 * workaround currently required for TTBR0_EL1 changes are for the
296	 * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache
297	 * corruption).
298	 */
299	bl	post_ttbr_update_workaround
300	.endif
3011:
302	.if	\el != 0
303	and	x22, x22, #~PSR_PAN_BIT		// ARMv8.0 CPUs do not understand this bit
304	.endif
3052:
306#endif
307
308	.if	\el == 0
309	ldr	x23, [sp, #S_SP]		// load return stack pointer
310	msr	sp_el0, x23
311	tst	x22, #PSR_MODE32_BIT		// native task?
312	b.eq	3f
313
314#ifdef CONFIG_ARM64_ERRATUM_845719
315alternative_if ARM64_WORKAROUND_845719
316#ifdef CONFIG_PID_IN_CONTEXTIDR
317	mrs	x29, contextidr_el1
318	msr	contextidr_el1, x29
319#else
320	msr contextidr_el1, xzr
321#endif
322alternative_else_nop_endif
323#endif
3243:
325	apply_ssbd 0, x0, x1
326	.endif
327
328	msr	elr_el1, x21			// set up the return data
329	msr	spsr_el1, x22
330	ldp	x0, x1, [sp, #16 * 0]
331	ldp	x2, x3, [sp, #16 * 1]
332	ldp	x4, x5, [sp, #16 * 2]
333	ldp	x6, x7, [sp, #16 * 3]
334	ldp	x8, x9, [sp, #16 * 4]
335	ldp	x10, x11, [sp, #16 * 5]
336	ldp	x12, x13, [sp, #16 * 6]
337	ldp	x14, x15, [sp, #16 * 7]
338	ldp	x16, x17, [sp, #16 * 8]
339	ldp	x18, x19, [sp, #16 * 9]
340	ldp	x20, x21, [sp, #16 * 10]
341	ldp	x22, x23, [sp, #16 * 11]
342	ldp	x24, x25, [sp, #16 * 12]
343	ldp	x26, x27, [sp, #16 * 13]
344	ldp	x28, x29, [sp, #16 * 14]
345	ldr	lr, [sp, #S_LR]
346	add	sp, sp, #S_FRAME_SIZE		// restore sp
347	/*
348	 * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on eret context synchronization
349	 * when returning from IPI handler, and when returning to user-space.
350	 */
351
352	.if	\el == 0
353alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
354#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
355	bne	4f
356	msr	far_el1, x30
357	tramp_alias	x30, tramp_exit_native
358	br	x30
3594:
360	tramp_alias	x30, tramp_exit_compat
361	br	x30
362#endif
363	.else
364	eret
365	.endif
366	.endm
367
368	.macro	irq_stack_entry
369	mov	x19, sp			// preserve the original sp
370
371	/*
372	 * Compare sp with the base of the task stack.
373	 * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
374	 * and should switch to the irq stack.
375	 */
376	ldr	x25, [tsk, TSK_STACK]
377	eor	x25, x25, x19
378	and	x25, x25, #~(THREAD_SIZE - 1)
379	cbnz	x25, 9998f
380
381	ldr_this_cpu x25, irq_stack_ptr, x26
382	mov	x26, #IRQ_STACK_SIZE
383	add	x26, x25, x26
384
385	/* switch to the irq stack */
386	mov	sp, x26
3879998:
388	.endm
389
390	/*
391	 * x19 should be preserved between irq_stack_entry and
392	 * irq_stack_exit.
393	 */
394	.macro	irq_stack_exit
395	mov	sp, x19
396	.endm
397
398/*
399 * These are the registers used in the syscall handler, and allow us to
400 * have in theory up to 7 arguments to a function - x0 to x6.
401 *
402 * x7 is reserved for the system call number in 32-bit mode.
403 */
404wsc_nr	.req	w25		// number of system calls
405xsc_nr	.req	x25		// number of system calls (zero-extended)
406wscno	.req	w26		// syscall number
407xscno	.req	x26		// syscall number (zero-extended)
408stbl	.req	x27		// syscall table pointer
409tsk	.req	x28		// current thread_info
410
411/*
412 * Interrupt handling.
413 */
414	.macro	irq_handler
415	ldr_l	x1, handle_arch_irq
416	mov	x0, sp
417	irq_stack_entry
418	blr	x1
419	irq_stack_exit
420	.endm
421
422	.text
423
424/*
425 * Exception vectors.
426 */
427	.pushsection ".entry.text", "ax"
428
429	.align	11
430ENTRY(vectors)
431	kernel_ventry	1, sync_invalid			// Synchronous EL1t
432	kernel_ventry	1, irq_invalid			// IRQ EL1t
433	kernel_ventry	1, fiq_invalid			// FIQ EL1t
434	kernel_ventry	1, error_invalid		// Error EL1t
435
436	kernel_ventry	1, sync				// Synchronous EL1h
437	kernel_ventry	1, irq				// IRQ EL1h
438	kernel_ventry	1, fiq_invalid			// FIQ EL1h
439	kernel_ventry	1, error			// Error EL1h
440
441	kernel_ventry	0, sync				// Synchronous 64-bit EL0
442	kernel_ventry	0, irq				// IRQ 64-bit EL0
443	kernel_ventry	0, fiq_invalid			// FIQ 64-bit EL0
444	kernel_ventry	0, error			// Error 64-bit EL0
445
446#ifdef CONFIG_COMPAT
447	kernel_ventry	0, sync_compat, 32		// Synchronous 32-bit EL0
448	kernel_ventry	0, irq_compat, 32		// IRQ 32-bit EL0
449	kernel_ventry	0, fiq_invalid_compat, 32	// FIQ 32-bit EL0
450	kernel_ventry	0, error_compat, 32		// Error 32-bit EL0
451#else
452	kernel_ventry	0, sync_invalid, 32		// Synchronous 32-bit EL0
453	kernel_ventry	0, irq_invalid, 32		// IRQ 32-bit EL0
454	kernel_ventry	0, fiq_invalid, 32		// FIQ 32-bit EL0
455	kernel_ventry	0, error_invalid, 32		// Error 32-bit EL0
456#endif
457END(vectors)
458
459#ifdef CONFIG_VMAP_STACK
460	/*
461	 * We detected an overflow in kernel_ventry, which switched to the
462	 * overflow stack. Stash the exception regs, and head to our overflow
463	 * handler.
464	 */
465__bad_stack:
466	/* Restore the original x0 value */
467	mrs	x0, tpidrro_el0
468
469	/*
470	 * Store the original GPRs to the new stack. The orginal SP (minus
471	 * S_FRAME_SIZE) was stashed in tpidr_el0 by kernel_ventry.
472	 */
473	sub	sp, sp, #S_FRAME_SIZE
474	kernel_entry 1
475	mrs	x0, tpidr_el0
476	add	x0, x0, #S_FRAME_SIZE
477	str	x0, [sp, #S_SP]
478
479	/* Stash the regs for handle_bad_stack */
480	mov	x0, sp
481
482	/* Time to die */
483	bl	handle_bad_stack
484	ASM_BUG()
485#endif /* CONFIG_VMAP_STACK */
486
487/*
488 * Invalid mode handlers
489 */
490	.macro	inv_entry, el, reason, regsize = 64
491	kernel_entry \el, \regsize
492	mov	x0, sp
493	mov	x1, #\reason
494	mrs	x2, esr_el1
495	bl	bad_mode
496	ASM_BUG()
497	.endm
498
499el0_sync_invalid:
500	inv_entry 0, BAD_SYNC
501ENDPROC(el0_sync_invalid)
502
503el0_irq_invalid:
504	inv_entry 0, BAD_IRQ
505ENDPROC(el0_irq_invalid)
506
507el0_fiq_invalid:
508	inv_entry 0, BAD_FIQ
509ENDPROC(el0_fiq_invalid)
510
511el0_error_invalid:
512	inv_entry 0, BAD_ERROR
513ENDPROC(el0_error_invalid)
514
515#ifdef CONFIG_COMPAT
516el0_fiq_invalid_compat:
517	inv_entry 0, BAD_FIQ, 32
518ENDPROC(el0_fiq_invalid_compat)
519#endif
520
521el1_sync_invalid:
522	inv_entry 1, BAD_SYNC
523ENDPROC(el1_sync_invalid)
524
525el1_irq_invalid:
526	inv_entry 1, BAD_IRQ
527ENDPROC(el1_irq_invalid)
528
529el1_fiq_invalid:
530	inv_entry 1, BAD_FIQ
531ENDPROC(el1_fiq_invalid)
532
533el1_error_invalid:
534	inv_entry 1, BAD_ERROR
535ENDPROC(el1_error_invalid)
536
537/*
538 * EL1 mode handlers.
539 */
540	.align	6
541el1_sync:
542	kernel_entry 1
543	mrs	x1, esr_el1			// read the syndrome register
544	lsr	x24, x1, #ESR_ELx_EC_SHIFT	// exception class
545	cmp	x24, #ESR_ELx_EC_DABT_CUR	// data abort in EL1
546	b.eq	el1_da
547	cmp	x24, #ESR_ELx_EC_IABT_CUR	// instruction abort in EL1
548	b.eq	el1_ia
549	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
550	b.eq	el1_undef
551	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
552	b.eq	el1_sp_pc
553	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
554	b.eq	el1_sp_pc
555	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL1
556	b.eq	el1_undef
557	cmp	x24, #ESR_ELx_EC_BREAKPT_CUR	// debug exception in EL1
558	b.ge	el1_dbg
559	b	el1_inv
560
561el1_ia:
562	/*
563	 * Fall through to the Data abort case
564	 */
565el1_da:
566	/*
567	 * Data abort handling
568	 */
569	mrs	x3, far_el1
570	inherit_daif	pstate=x23, tmp=x2
571	clear_address_tag x0, x3
572	mov	x2, sp				// struct pt_regs
573	bl	do_mem_abort
574
575	kernel_exit 1
576el1_sp_pc:
577	/*
578	 * Stack or PC alignment exception handling
579	 */
580	mrs	x0, far_el1
581	inherit_daif	pstate=x23, tmp=x2
582	mov	x2, sp
583	bl	do_sp_pc_abort
584	ASM_BUG()
585el1_undef:
586	/*
587	 * Undefined instruction
588	 */
589	inherit_daif	pstate=x23, tmp=x2
590	mov	x0, sp
591	bl	do_undefinstr
592	ASM_BUG()
593el1_dbg:
594	/*
595	 * Debug exception handling
596	 */
597	cmp	x24, #ESR_ELx_EC_BRK64		// if BRK64
598	cinc	x24, x24, eq			// set bit '0'
599	tbz	x24, #0, el1_inv		// EL1 only
600	mrs	x0, far_el1
601	mov	x2, sp				// struct pt_regs
602	bl	do_debug_exception
603	kernel_exit 1
604el1_inv:
605	// TODO: add support for undefined instructions in kernel mode
606	inherit_daif	pstate=x23, tmp=x2
607	mov	x0, sp
608	mov	x2, x1
609	mov	x1, #BAD_SYNC
610	bl	bad_mode
611	ASM_BUG()
612ENDPROC(el1_sync)
613
614	.align	6
615el1_irq:
616	kernel_entry 1
617	enable_da_f
618#ifdef CONFIG_TRACE_IRQFLAGS
619	bl	trace_hardirqs_off
620#endif
621
622	irq_handler
623
624#ifdef CONFIG_PREEMPT
625	ldr	w24, [tsk, #TSK_TI_PREEMPT]	// get preempt count
626	cbnz	w24, 1f				// preempt count != 0
627	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get flags
628	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling?
629	bl	el1_preempt
6301:
631#endif
632#ifdef CONFIG_TRACE_IRQFLAGS
633	bl	trace_hardirqs_on
634#endif
635	kernel_exit 1
636ENDPROC(el1_irq)
637
638#ifdef CONFIG_PREEMPT
639el1_preempt:
640	mov	x24, lr
6411:	bl	preempt_schedule_irq		// irq en/disable is done inside
642	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get new tasks TI_FLAGS
643	tbnz	x0, #TIF_NEED_RESCHED, 1b	// needs rescheduling?
644	ret	x24
645#endif
646
647/*
648 * EL0 mode handlers.
649 */
650	.align	6
651el0_sync:
652	kernel_entry 0
653	mrs	x25, esr_el1			// read the syndrome register
654	lsr	x24, x25, #ESR_ELx_EC_SHIFT	// exception class
655	cmp	x24, #ESR_ELx_EC_SVC64		// SVC in 64-bit state
656	b.eq	el0_svc
657	cmp	x24, #ESR_ELx_EC_DABT_LOW	// data abort in EL0
658	b.eq	el0_da
659	cmp	x24, #ESR_ELx_EC_IABT_LOW	// instruction abort in EL0
660	b.eq	el0_ia
661	cmp	x24, #ESR_ELx_EC_FP_ASIMD	// FP/ASIMD access
662	b.eq	el0_fpsimd_acc
663	cmp	x24, #ESR_ELx_EC_SVE		// SVE access
664	b.eq	el0_sve_acc
665	cmp	x24, #ESR_ELx_EC_FP_EXC64	// FP/ASIMD exception
666	b.eq	el0_fpsimd_exc
667	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
668	b.eq	el0_sys
669	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
670	b.eq	el0_sp_pc
671	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
672	b.eq	el0_sp_pc
673	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
674	b.eq	el0_undef
675	cmp	x24, #ESR_ELx_EC_BREAKPT_LOW	// debug exception in EL0
676	b.ge	el0_dbg
677	b	el0_inv
678
679#ifdef CONFIG_COMPAT
680	.align	6
681el0_sync_compat:
682	kernel_entry 0, 32
683	mrs	x25, esr_el1			// read the syndrome register
684	lsr	x24, x25, #ESR_ELx_EC_SHIFT	// exception class
685	cmp	x24, #ESR_ELx_EC_SVC32		// SVC in 32-bit state
686	b.eq	el0_svc_compat
687	cmp	x24, #ESR_ELx_EC_DABT_LOW	// data abort in EL0
688	b.eq	el0_da
689	cmp	x24, #ESR_ELx_EC_IABT_LOW	// instruction abort in EL0
690	b.eq	el0_ia
691	cmp	x24, #ESR_ELx_EC_FP_ASIMD	// FP/ASIMD access
692	b.eq	el0_fpsimd_acc
693	cmp	x24, #ESR_ELx_EC_FP_EXC32	// FP/ASIMD exception
694	b.eq	el0_fpsimd_exc
695	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
696	b.eq	el0_sp_pc
697	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
698	b.eq	el0_undef
699	cmp	x24, #ESR_ELx_EC_CP15_32	// CP15 MRC/MCR trap
700	b.eq	el0_undef
701	cmp	x24, #ESR_ELx_EC_CP15_64	// CP15 MRRC/MCRR trap
702	b.eq	el0_undef
703	cmp	x24, #ESR_ELx_EC_CP14_MR	// CP14 MRC/MCR trap
704	b.eq	el0_undef
705	cmp	x24, #ESR_ELx_EC_CP14_LS	// CP14 LDC/STC trap
706	b.eq	el0_undef
707	cmp	x24, #ESR_ELx_EC_CP14_64	// CP14 MRRC/MCRR trap
708	b.eq	el0_undef
709	cmp	x24, #ESR_ELx_EC_BREAKPT_LOW	// debug exception in EL0
710	b.ge	el0_dbg
711	b	el0_inv
712el0_svc_compat:
713	mov	x0, sp
714	bl	el0_svc_compat_handler
715	b	ret_to_user
716
717	.align	6
718el0_irq_compat:
719	kernel_entry 0, 32
720	b	el0_irq_naked
721
722el0_error_compat:
723	kernel_entry 0, 32
724	b	el0_error_naked
725#endif
726
727el0_da:
728	/*
729	 * Data abort handling
730	 */
731	mrs	x26, far_el1
732	enable_daif
733	ct_user_exit
734	clear_address_tag x0, x26
735	mov	x1, x25
736	mov	x2, sp
737	bl	do_mem_abort
738	b	ret_to_user
739el0_ia:
740	/*
741	 * Instruction abort handling
742	 */
743	mrs	x26, far_el1
744	enable_da_f
745#ifdef CONFIG_TRACE_IRQFLAGS
746	bl	trace_hardirqs_off
747#endif
748	ct_user_exit
749	mov	x0, x26
750	mov	x1, x25
751	mov	x2, sp
752	bl	do_el0_ia_bp_hardening
753	b	ret_to_user
754el0_fpsimd_acc:
755	/*
756	 * Floating Point or Advanced SIMD access
757	 */
758	enable_daif
759	ct_user_exit
760	mov	x0, x25
761	mov	x1, sp
762	bl	do_fpsimd_acc
763	b	ret_to_user
764el0_sve_acc:
765	/*
766	 * Scalable Vector Extension access
767	 */
768	enable_daif
769	ct_user_exit
770	mov	x0, x25
771	mov	x1, sp
772	bl	do_sve_acc
773	b	ret_to_user
774el0_fpsimd_exc:
775	/*
776	 * Floating Point, Advanced SIMD or SVE exception
777	 */
778	enable_daif
779	ct_user_exit
780	mov	x0, x25
781	mov	x1, sp
782	bl	do_fpsimd_exc
783	b	ret_to_user
784el0_sp_pc:
785	/*
786	 * Stack or PC alignment exception handling
787	 */
788	mrs	x26, far_el1
789	enable_da_f
790#ifdef CONFIG_TRACE_IRQFLAGS
791	bl	trace_hardirqs_off
792#endif
793	ct_user_exit
794	mov	x0, x26
795	mov	x1, x25
796	mov	x2, sp
797	bl	do_sp_pc_abort
798	b	ret_to_user
799el0_undef:
800	/*
801	 * Undefined instruction
802	 */
803	enable_daif
804	ct_user_exit
805	mov	x0, sp
806	bl	do_undefinstr
807	b	ret_to_user
808el0_sys:
809	/*
810	 * System instructions, for trapped cache maintenance instructions
811	 */
812	enable_daif
813	ct_user_exit
814	mov	x0, x25
815	mov	x1, sp
816	bl	do_sysinstr
817	b	ret_to_user
818el0_dbg:
819	/*
820	 * Debug exception handling
821	 */
822	tbnz	x24, #0, el0_inv		// EL0 only
823	mrs	x0, far_el1
824	mov	x1, x25
825	mov	x2, sp
826	bl	do_debug_exception
827	enable_daif
828	ct_user_exit
829	b	ret_to_user
830el0_inv:
831	enable_daif
832	ct_user_exit
833	mov	x0, sp
834	mov	x1, #BAD_SYNC
835	mov	x2, x25
836	bl	bad_el0_sync
837	b	ret_to_user
838ENDPROC(el0_sync)
839
840	.align	6
841el0_irq:
842	kernel_entry 0
843el0_irq_naked:
844	enable_da_f
845#ifdef CONFIG_TRACE_IRQFLAGS
846	bl	trace_hardirqs_off
847#endif
848
849	ct_user_exit
850#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
851	tbz	x22, #55, 1f
852	bl	do_el0_irq_bp_hardening
8531:
854#endif
855	irq_handler
856
857#ifdef CONFIG_TRACE_IRQFLAGS
858	bl	trace_hardirqs_on
859#endif
860	b	ret_to_user
861ENDPROC(el0_irq)
862
863el1_error:
864	kernel_entry 1
865	mrs	x1, esr_el1
866	enable_dbg
867	mov	x0, sp
868	bl	do_serror
869	kernel_exit 1
870ENDPROC(el1_error)
871
872el0_error:
873	kernel_entry 0
874el0_error_naked:
875	mrs	x1, esr_el1
876	enable_dbg
877	mov	x0, sp
878	bl	do_serror
879	enable_daif
880	ct_user_exit
881	b	ret_to_user
882ENDPROC(el0_error)
883
884/*
885 * Ok, we need to do extra processing, enter the slow path.
886 */
887work_pending:
888	mov	x0, sp				// 'regs'
889	bl	do_notify_resume
890#ifdef CONFIG_TRACE_IRQFLAGS
891	bl	trace_hardirqs_on		// enabled while in userspace
892#endif
893	ldr	x1, [tsk, #TSK_TI_FLAGS]	// re-check for single-step
894	b	finish_ret_to_user
895/*
896 * "slow" syscall return path.
897 */
898ret_to_user:
899	disable_daif
900	ldr	x1, [tsk, #TSK_TI_FLAGS]
901	and	x2, x1, #_TIF_WORK_MASK
902	cbnz	x2, work_pending
903finish_ret_to_user:
904	enable_step_tsk x1, x2
905#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
906	bl	stackleak_erase
907#endif
908	kernel_exit 0
909ENDPROC(ret_to_user)
910
911/*
912 * SVC handler.
913 */
914	.align	6
915el0_svc:
916	mov	x0, sp
917	bl	el0_svc_handler
918	b	ret_to_user
919ENDPROC(el0_svc)
920
921	.popsection				// .entry.text
922
923#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
924/*
925 * Exception vectors trampoline.
926 */
927	.pushsection ".entry.tramp.text", "ax"
928
929	.macro tramp_map_kernel, tmp
930	mrs	\tmp, ttbr1_el1
931	add	\tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
932	bic	\tmp, \tmp, #USER_ASID_FLAG
933	msr	ttbr1_el1, \tmp
934#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
935alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1003
936	/* ASID already in \tmp[63:48] */
937	movk	\tmp, #:abs_g2_nc:(TRAMP_VALIAS >> 12)
938	movk	\tmp, #:abs_g1_nc:(TRAMP_VALIAS >> 12)
939	/* 2MB boundary containing the vectors, so we nobble the walk cache */
940	movk	\tmp, #:abs_g0_nc:((TRAMP_VALIAS & ~(SZ_2M - 1)) >> 12)
941	isb
942	tlbi	vae1, \tmp
943	dsb	nsh
944alternative_else_nop_endif
945#endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */
946	.endm
947
948	.macro tramp_unmap_kernel, tmp
949	mrs	\tmp, ttbr1_el1
950	sub	\tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
951	orr	\tmp, \tmp, #USER_ASID_FLAG
952	msr	ttbr1_el1, \tmp
953	/*
954	 * We avoid running the post_ttbr_update_workaround here because
955	 * it's only needed by Cavium ThunderX, which requires KPTI to be
956	 * disabled.
957	 */
958	.endm
959
960	.macro tramp_ventry, regsize = 64
961	.align	7
9621:
963	.if	\regsize == 64
964	msr	tpidrro_el0, x30	// Restored in kernel_ventry
965	.endif
966	/*
967	 * Defend against branch aliasing attacks by pushing a dummy
968	 * entry onto the return stack and using a RET instruction to
969	 * enter the full-fat kernel vectors.
970	 */
971	bl	2f
972	b	.
9732:
974	tramp_map_kernel	x30
975#ifdef CONFIG_RANDOMIZE_BASE
976	adr	x30, tramp_vectors + PAGE_SIZE
977alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003
978	ldr	x30, [x30]
979#else
980	ldr	x30, =vectors
981#endif
982	prfm	plil1strm, [x30, #(1b - tramp_vectors)]
983	msr	vbar_el1, x30
984	add	x30, x30, #(1b - tramp_vectors)
985	isb
986	ret
987	.endm
988
989	.macro tramp_exit, regsize = 64
990	adr	x30, tramp_vectors
991	msr	vbar_el1, x30
992	tramp_unmap_kernel	x30
993	.if	\regsize == 64
994	mrs	x30, far_el1
995	.endif
996	eret
997	.endm
998
999	.align	11
1000ENTRY(tramp_vectors)
1001	.space	0x400
1002
1003	tramp_ventry
1004	tramp_ventry
1005	tramp_ventry
1006	tramp_ventry
1007
1008	tramp_ventry	32
1009	tramp_ventry	32
1010	tramp_ventry	32
1011	tramp_ventry	32
1012END(tramp_vectors)
1013
1014ENTRY(tramp_exit_native)
1015	tramp_exit
1016END(tramp_exit_native)
1017
1018ENTRY(tramp_exit_compat)
1019	tramp_exit	32
1020END(tramp_exit_compat)
1021
1022	.ltorg
1023	.popsection				// .entry.tramp.text
1024#ifdef CONFIG_RANDOMIZE_BASE
1025	.pushsection ".rodata", "a"
1026	.align PAGE_SHIFT
1027	.globl	__entry_tramp_data_start
1028__entry_tramp_data_start:
1029	.quad	vectors
1030	.popsection				// .rodata
1031#endif /* CONFIG_RANDOMIZE_BASE */
1032#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
1033
1034/*
1035 * Register switch for AArch64. The callee-saved registers need to be saved
1036 * and restored. On entry:
1037 *   x0 = previous task_struct (must be preserved across the switch)
1038 *   x1 = next task_struct
1039 * Previous and next are guaranteed not to be the same.
1040 *
1041 */
1042ENTRY(cpu_switch_to)
1043	mov	x10, #THREAD_CPU_CONTEXT
1044	add	x8, x0, x10
1045	mov	x9, sp
1046	stp	x19, x20, [x8], #16		// store callee-saved registers
1047	stp	x21, x22, [x8], #16
1048	stp	x23, x24, [x8], #16
1049	stp	x25, x26, [x8], #16
1050	stp	x27, x28, [x8], #16
1051	stp	x29, x9, [x8], #16
1052	str	lr, [x8]
1053	add	x8, x1, x10
1054	ldp	x19, x20, [x8], #16		// restore callee-saved registers
1055	ldp	x21, x22, [x8], #16
1056	ldp	x23, x24, [x8], #16
1057	ldp	x25, x26, [x8], #16
1058	ldp	x27, x28, [x8], #16
1059	ldp	x29, x9, [x8], #16
1060	ldr	lr, [x8]
1061	mov	sp, x9
1062	msr	sp_el0, x1
1063	ret
1064ENDPROC(cpu_switch_to)
1065NOKPROBE(cpu_switch_to)
1066
1067/*
1068 * This is how we return from a fork.
1069 */
1070ENTRY(ret_from_fork)
1071	bl	schedule_tail
1072	cbz	x19, 1f				// not a kernel thread
1073	mov	x0, x20
1074	blr	x19
10751:	get_thread_info tsk
1076	b	ret_to_user
1077ENDPROC(ret_from_fork)
1078NOKPROBE(ret_from_fork)
1079
1080#ifdef CONFIG_ARM_SDE_INTERFACE
1081
1082#include <asm/sdei.h>
1083#include <uapi/linux/arm_sdei.h>
1084
1085.macro sdei_handler_exit exit_mode
1086	/* On success, this call never returns... */
1087	cmp	\exit_mode, #SDEI_EXIT_SMC
1088	b.ne	99f
1089	smc	#0
1090	b	.
109199:	hvc	#0
1092	b	.
1093.endm
1094
1095#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
1096/*
1097 * The regular SDEI entry point may have been unmapped along with the rest of
1098 * the kernel. This trampoline restores the kernel mapping to make the x1 memory
1099 * argument accessible.
1100 *
1101 * This clobbers x4, __sdei_handler() will restore this from firmware's
1102 * copy.
1103 */
1104.ltorg
1105.pushsection ".entry.tramp.text", "ax"
1106ENTRY(__sdei_asm_entry_trampoline)
1107	mrs	x4, ttbr1_el1
1108	tbz	x4, #USER_ASID_BIT, 1f
1109
1110	tramp_map_kernel tmp=x4
1111	isb
1112	mov	x4, xzr
1113
1114	/*
1115	 * Use reg->interrupted_regs.addr_limit to remember whether to unmap
1116	 * the kernel on exit.
1117	 */
11181:	str	x4, [x1, #(SDEI_EVENT_INTREGS + S_ORIG_ADDR_LIMIT)]
1119
1120#ifdef CONFIG_RANDOMIZE_BASE
1121	adr	x4, tramp_vectors + PAGE_SIZE
1122	add	x4, x4, #:lo12:__sdei_asm_trampoline_next_handler
1123	ldr	x4, [x4]
1124#else
1125	ldr	x4, =__sdei_asm_handler
1126#endif
1127	br	x4
1128ENDPROC(__sdei_asm_entry_trampoline)
1129NOKPROBE(__sdei_asm_entry_trampoline)
1130
1131/*
1132 * Make the exit call and restore the original ttbr1_el1
1133 *
1134 * x0 & x1: setup for the exit API call
1135 * x2: exit_mode
1136 * x4: struct sdei_registered_event argument from registration time.
1137 */
1138ENTRY(__sdei_asm_exit_trampoline)
1139	ldr	x4, [x4, #(SDEI_EVENT_INTREGS + S_ORIG_ADDR_LIMIT)]
1140	cbnz	x4, 1f
1141
1142	tramp_unmap_kernel	tmp=x4
1143
11441:	sdei_handler_exit exit_mode=x2
1145ENDPROC(__sdei_asm_exit_trampoline)
1146NOKPROBE(__sdei_asm_exit_trampoline)
1147	.ltorg
1148.popsection		// .entry.tramp.text
1149#ifdef CONFIG_RANDOMIZE_BASE
1150.pushsection ".rodata", "a"
1151__sdei_asm_trampoline_next_handler:
1152	.quad	__sdei_asm_handler
1153.popsection		// .rodata
1154#endif /* CONFIG_RANDOMIZE_BASE */
1155#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
1156
1157/*
1158 * Software Delegated Exception entry point.
1159 *
1160 * x0: Event number
1161 * x1: struct sdei_registered_event argument from registration time.
1162 * x2: interrupted PC
1163 * x3: interrupted PSTATE
1164 * x4: maybe clobbered by the trampoline
1165 *
1166 * Firmware has preserved x0->x17 for us, we must save/restore the rest to
1167 * follow SMC-CC. We save (or retrieve) all the registers as the handler may
1168 * want them.
1169 */
1170ENTRY(__sdei_asm_handler)
1171	stp     x2, x3, [x1, #SDEI_EVENT_INTREGS + S_PC]
1172	stp     x4, x5, [x1, #SDEI_EVENT_INTREGS + 16 * 2]
1173	stp     x6, x7, [x1, #SDEI_EVENT_INTREGS + 16 * 3]
1174	stp     x8, x9, [x1, #SDEI_EVENT_INTREGS + 16 * 4]
1175	stp     x10, x11, [x1, #SDEI_EVENT_INTREGS + 16 * 5]
1176	stp     x12, x13, [x1, #SDEI_EVENT_INTREGS + 16 * 6]
1177	stp     x14, x15, [x1, #SDEI_EVENT_INTREGS + 16 * 7]
1178	stp     x16, x17, [x1, #SDEI_EVENT_INTREGS + 16 * 8]
1179	stp     x18, x19, [x1, #SDEI_EVENT_INTREGS + 16 * 9]
1180	stp     x20, x21, [x1, #SDEI_EVENT_INTREGS + 16 * 10]
1181	stp     x22, x23, [x1, #SDEI_EVENT_INTREGS + 16 * 11]
1182	stp     x24, x25, [x1, #SDEI_EVENT_INTREGS + 16 * 12]
1183	stp     x26, x27, [x1, #SDEI_EVENT_INTREGS + 16 * 13]
1184	stp     x28, x29, [x1, #SDEI_EVENT_INTREGS + 16 * 14]
1185	mov	x4, sp
1186	stp     lr, x4, [x1, #SDEI_EVENT_INTREGS + S_LR]
1187
1188	mov	x19, x1
1189
1190#ifdef CONFIG_VMAP_STACK
1191	/*
1192	 * entry.S may have been using sp as a scratch register, find whether
1193	 * this is a normal or critical event and switch to the appropriate
1194	 * stack for this CPU.
1195	 */
1196	ldrb	w4, [x19, #SDEI_EVENT_PRIORITY]
1197	cbnz	w4, 1f
1198	ldr_this_cpu dst=x5, sym=sdei_stack_normal_ptr, tmp=x6
1199	b	2f
12001:	ldr_this_cpu dst=x5, sym=sdei_stack_critical_ptr, tmp=x6
12012:	mov	x6, #SDEI_STACK_SIZE
1202	add	x5, x5, x6
1203	mov	sp, x5
1204#endif
1205
1206	/*
1207	 * We may have interrupted userspace, or a guest, or exit-from or
1208	 * return-to either of these. We can't trust sp_el0, restore it.
1209	 */
1210	mrs	x28, sp_el0
1211	ldr_this_cpu	dst=x0, sym=__entry_task, tmp=x1
1212	msr	sp_el0, x0
1213
1214	/* If we interrupted the kernel point to the previous stack/frame. */
1215	and     x0, x3, #0xc
1216	mrs     x1, CurrentEL
1217	cmp     x0, x1
1218	csel	x29, x29, xzr, eq	// fp, or zero
1219	csel	x4, x2, xzr, eq		// elr, or zero
1220
1221	stp	x29, x4, [sp, #-16]!
1222	mov	x29, sp
1223
1224	add	x0, x19, #SDEI_EVENT_INTREGS
1225	mov	x1, x19
1226	bl	__sdei_handler
1227
1228	msr	sp_el0, x28
1229	/* restore regs >x17 that we clobbered */
1230	mov	x4, x19         // keep x4 for __sdei_asm_exit_trampoline
1231	ldp	x28, x29, [x4, #SDEI_EVENT_INTREGS + 16 * 14]
1232	ldp	x18, x19, [x4, #SDEI_EVENT_INTREGS + 16 * 9]
1233	ldp	lr, x1, [x4, #SDEI_EVENT_INTREGS + S_LR]
1234	mov	sp, x1
1235
1236	mov	x1, x0			// address to complete_and_resume
1237	/* x0 = (x0 <= 1) ? EVENT_COMPLETE:EVENT_COMPLETE_AND_RESUME */
1238	cmp	x0, #1
1239	mov_q	x2, SDEI_1_0_FN_SDEI_EVENT_COMPLETE
1240	mov_q	x3, SDEI_1_0_FN_SDEI_EVENT_COMPLETE_AND_RESUME
1241	csel	x0, x2, x3, ls
1242
1243	ldr_l	x2, sdei_exit_mode
1244
1245alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0
1246	sdei_handler_exit exit_mode=x2
1247alternative_else_nop_endif
1248
1249#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
1250	tramp_alias	dst=x5, sym=__sdei_asm_exit_trampoline
1251	br	x5
1252#endif
1253ENDPROC(__sdei_asm_handler)
1254NOKPROBE(__sdei_asm_handler)
1255#endif /* CONFIG_ARM_SDE_INTERFACE */
1256