xref: /openbmc/linux/arch/arm64/kernel/entry.S (revision 5b4cb650)
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	.if	\el == 0
349alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
350#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
351	bne	4f
352	msr	far_el1, x30
353	tramp_alias	x30, tramp_exit_native
354	br	x30
3554:
356	tramp_alias	x30, tramp_exit_compat
357	br	x30
358#endif
359	.else
360	eret
361	.endif
362	sb
363	.endm
364
365	.macro	irq_stack_entry
366	mov	x19, sp			// preserve the original sp
367
368	/*
369	 * Compare sp with the base of the task stack.
370	 * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
371	 * and should switch to the irq stack.
372	 */
373	ldr	x25, [tsk, TSK_STACK]
374	eor	x25, x25, x19
375	and	x25, x25, #~(THREAD_SIZE - 1)
376	cbnz	x25, 9998f
377
378	ldr_this_cpu x25, irq_stack_ptr, x26
379	mov	x26, #IRQ_STACK_SIZE
380	add	x26, x25, x26
381
382	/* switch to the irq stack */
383	mov	sp, x26
3849998:
385	.endm
386
387	/*
388	 * x19 should be preserved between irq_stack_entry and
389	 * irq_stack_exit.
390	 */
391	.macro	irq_stack_exit
392	mov	sp, x19
393	.endm
394
395/*
396 * These are the registers used in the syscall handler, and allow us to
397 * have in theory up to 7 arguments to a function - x0 to x6.
398 *
399 * x7 is reserved for the system call number in 32-bit mode.
400 */
401wsc_nr	.req	w25		// number of system calls
402xsc_nr	.req	x25		// number of system calls (zero-extended)
403wscno	.req	w26		// syscall number
404xscno	.req	x26		// syscall number (zero-extended)
405stbl	.req	x27		// syscall table pointer
406tsk	.req	x28		// current thread_info
407
408/*
409 * Interrupt handling.
410 */
411	.macro	irq_handler
412	ldr_l	x1, handle_arch_irq
413	mov	x0, sp
414	irq_stack_entry
415	blr	x1
416	irq_stack_exit
417	.endm
418
419	.text
420
421/*
422 * Exception vectors.
423 */
424	.pushsection ".entry.text", "ax"
425
426	.align	11
427ENTRY(vectors)
428	kernel_ventry	1, sync_invalid			// Synchronous EL1t
429	kernel_ventry	1, irq_invalid			// IRQ EL1t
430	kernel_ventry	1, fiq_invalid			// FIQ EL1t
431	kernel_ventry	1, error_invalid		// Error EL1t
432
433	kernel_ventry	1, sync				// Synchronous EL1h
434	kernel_ventry	1, irq				// IRQ EL1h
435	kernel_ventry	1, fiq_invalid			// FIQ EL1h
436	kernel_ventry	1, error			// Error EL1h
437
438	kernel_ventry	0, sync				// Synchronous 64-bit EL0
439	kernel_ventry	0, irq				// IRQ 64-bit EL0
440	kernel_ventry	0, fiq_invalid			// FIQ 64-bit EL0
441	kernel_ventry	0, error			// Error 64-bit EL0
442
443#ifdef CONFIG_COMPAT
444	kernel_ventry	0, sync_compat, 32		// Synchronous 32-bit EL0
445	kernel_ventry	0, irq_compat, 32		// IRQ 32-bit EL0
446	kernel_ventry	0, fiq_invalid_compat, 32	// FIQ 32-bit EL0
447	kernel_ventry	0, error_compat, 32		// Error 32-bit EL0
448#else
449	kernel_ventry	0, sync_invalid, 32		// Synchronous 32-bit EL0
450	kernel_ventry	0, irq_invalid, 32		// IRQ 32-bit EL0
451	kernel_ventry	0, fiq_invalid, 32		// FIQ 32-bit EL0
452	kernel_ventry	0, error_invalid, 32		// Error 32-bit EL0
453#endif
454END(vectors)
455
456#ifdef CONFIG_VMAP_STACK
457	/*
458	 * We detected an overflow in kernel_ventry, which switched to the
459	 * overflow stack. Stash the exception regs, and head to our overflow
460	 * handler.
461	 */
462__bad_stack:
463	/* Restore the original x0 value */
464	mrs	x0, tpidrro_el0
465
466	/*
467	 * Store the original GPRs to the new stack. The orginal SP (minus
468	 * S_FRAME_SIZE) was stashed in tpidr_el0 by kernel_ventry.
469	 */
470	sub	sp, sp, #S_FRAME_SIZE
471	kernel_entry 1
472	mrs	x0, tpidr_el0
473	add	x0, x0, #S_FRAME_SIZE
474	str	x0, [sp, #S_SP]
475
476	/* Stash the regs for handle_bad_stack */
477	mov	x0, sp
478
479	/* Time to die */
480	bl	handle_bad_stack
481	ASM_BUG()
482#endif /* CONFIG_VMAP_STACK */
483
484/*
485 * Invalid mode handlers
486 */
487	.macro	inv_entry, el, reason, regsize = 64
488	kernel_entry \el, \regsize
489	mov	x0, sp
490	mov	x1, #\reason
491	mrs	x2, esr_el1
492	bl	bad_mode
493	ASM_BUG()
494	.endm
495
496el0_sync_invalid:
497	inv_entry 0, BAD_SYNC
498ENDPROC(el0_sync_invalid)
499
500el0_irq_invalid:
501	inv_entry 0, BAD_IRQ
502ENDPROC(el0_irq_invalid)
503
504el0_fiq_invalid:
505	inv_entry 0, BAD_FIQ
506ENDPROC(el0_fiq_invalid)
507
508el0_error_invalid:
509	inv_entry 0, BAD_ERROR
510ENDPROC(el0_error_invalid)
511
512#ifdef CONFIG_COMPAT
513el0_fiq_invalid_compat:
514	inv_entry 0, BAD_FIQ, 32
515ENDPROC(el0_fiq_invalid_compat)
516#endif
517
518el1_sync_invalid:
519	inv_entry 1, BAD_SYNC
520ENDPROC(el1_sync_invalid)
521
522el1_irq_invalid:
523	inv_entry 1, BAD_IRQ
524ENDPROC(el1_irq_invalid)
525
526el1_fiq_invalid:
527	inv_entry 1, BAD_FIQ
528ENDPROC(el1_fiq_invalid)
529
530el1_error_invalid:
531	inv_entry 1, BAD_ERROR
532ENDPROC(el1_error_invalid)
533
534/*
535 * EL1 mode handlers.
536 */
537	.align	6
538el1_sync:
539	kernel_entry 1
540	mrs	x1, esr_el1			// read the syndrome register
541	lsr	x24, x1, #ESR_ELx_EC_SHIFT	// exception class
542	cmp	x24, #ESR_ELx_EC_DABT_CUR	// data abort in EL1
543	b.eq	el1_da
544	cmp	x24, #ESR_ELx_EC_IABT_CUR	// instruction abort in EL1
545	b.eq	el1_ia
546	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
547	b.eq	el1_undef
548	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
549	b.eq	el1_sp_pc
550	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
551	b.eq	el1_sp_pc
552	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL1
553	b.eq	el1_undef
554	cmp	x24, #ESR_ELx_EC_BREAKPT_CUR	// debug exception in EL1
555	b.ge	el1_dbg
556	b	el1_inv
557
558el1_ia:
559	/*
560	 * Fall through to the Data abort case
561	 */
562el1_da:
563	/*
564	 * Data abort handling
565	 */
566	mrs	x3, far_el1
567	inherit_daif	pstate=x23, tmp=x2
568	clear_address_tag x0, x3
569	mov	x2, sp				// struct pt_regs
570	bl	do_mem_abort
571
572	kernel_exit 1
573el1_sp_pc:
574	/*
575	 * Stack or PC alignment exception handling
576	 */
577	mrs	x0, far_el1
578	inherit_daif	pstate=x23, tmp=x2
579	mov	x2, sp
580	bl	do_sp_pc_abort
581	ASM_BUG()
582el1_undef:
583	/*
584	 * Undefined instruction
585	 */
586	inherit_daif	pstate=x23, tmp=x2
587	mov	x0, sp
588	bl	do_undefinstr
589	kernel_exit 1
590el1_dbg:
591	/*
592	 * Debug exception handling
593	 */
594	cmp	x24, #ESR_ELx_EC_BRK64		// if BRK64
595	cinc	x24, x24, eq			// set bit '0'
596	tbz	x24, #0, el1_inv		// EL1 only
597	mrs	x0, far_el1
598	mov	x2, sp				// struct pt_regs
599	bl	do_debug_exception
600	kernel_exit 1
601el1_inv:
602	// TODO: add support for undefined instructions in kernel mode
603	inherit_daif	pstate=x23, tmp=x2
604	mov	x0, sp
605	mov	x2, x1
606	mov	x1, #BAD_SYNC
607	bl	bad_mode
608	ASM_BUG()
609ENDPROC(el1_sync)
610
611	.align	6
612el1_irq:
613	kernel_entry 1
614	enable_da_f
615#ifdef CONFIG_TRACE_IRQFLAGS
616	bl	trace_hardirqs_off
617#endif
618
619	irq_handler
620
621#ifdef CONFIG_PREEMPT
622	ldr	x24, [tsk, #TSK_TI_PREEMPT]	// get preempt count
623	cbnz	x24, 1f				// preempt count != 0
624	bl	el1_preempt
6251:
626#endif
627#ifdef CONFIG_TRACE_IRQFLAGS
628	bl	trace_hardirqs_on
629#endif
630	kernel_exit 1
631ENDPROC(el1_irq)
632
633#ifdef CONFIG_PREEMPT
634el1_preempt:
635	mov	x24, lr
6361:	bl	preempt_schedule_irq		// irq en/disable is done inside
637	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get new tasks TI_FLAGS
638	tbnz	x0, #TIF_NEED_RESCHED, 1b	// needs rescheduling?
639	ret	x24
640#endif
641
642/*
643 * EL0 mode handlers.
644 */
645	.align	6
646el0_sync:
647	kernel_entry 0
648	mrs	x25, esr_el1			// read the syndrome register
649	lsr	x24, x25, #ESR_ELx_EC_SHIFT	// exception class
650	cmp	x24, #ESR_ELx_EC_SVC64		// SVC in 64-bit state
651	b.eq	el0_svc
652	cmp	x24, #ESR_ELx_EC_DABT_LOW	// data abort in EL0
653	b.eq	el0_da
654	cmp	x24, #ESR_ELx_EC_IABT_LOW	// instruction abort in EL0
655	b.eq	el0_ia
656	cmp	x24, #ESR_ELx_EC_FP_ASIMD	// FP/ASIMD access
657	b.eq	el0_fpsimd_acc
658	cmp	x24, #ESR_ELx_EC_SVE		// SVE access
659	b.eq	el0_sve_acc
660	cmp	x24, #ESR_ELx_EC_FP_EXC64	// FP/ASIMD exception
661	b.eq	el0_fpsimd_exc
662	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
663	ccmp	x24, #ESR_ELx_EC_WFx, #4, ne
664	b.eq	el0_sys
665	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
666	b.eq	el0_sp_pc
667	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
668	b.eq	el0_sp_pc
669	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
670	b.eq	el0_undef
671	cmp	x24, #ESR_ELx_EC_BREAKPT_LOW	// debug exception in EL0
672	b.ge	el0_dbg
673	b	el0_inv
674
675#ifdef CONFIG_COMPAT
676	.align	6
677el0_sync_compat:
678	kernel_entry 0, 32
679	mrs	x25, esr_el1			// read the syndrome register
680	lsr	x24, x25, #ESR_ELx_EC_SHIFT	// exception class
681	cmp	x24, #ESR_ELx_EC_SVC32		// SVC in 32-bit state
682	b.eq	el0_svc_compat
683	cmp	x24, #ESR_ELx_EC_DABT_LOW	// data abort in EL0
684	b.eq	el0_da
685	cmp	x24, #ESR_ELx_EC_IABT_LOW	// instruction abort in EL0
686	b.eq	el0_ia
687	cmp	x24, #ESR_ELx_EC_FP_ASIMD	// FP/ASIMD access
688	b.eq	el0_fpsimd_acc
689	cmp	x24, #ESR_ELx_EC_FP_EXC32	// FP/ASIMD exception
690	b.eq	el0_fpsimd_exc
691	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
692	b.eq	el0_sp_pc
693	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
694	b.eq	el0_undef
695	cmp	x24, #ESR_ELx_EC_CP15_32	// CP15 MRC/MCR trap
696	b.eq	el0_cp15
697	cmp	x24, #ESR_ELx_EC_CP15_64	// CP15 MRRC/MCRR trap
698	b.eq	el0_cp15
699	cmp	x24, #ESR_ELx_EC_CP14_MR	// CP14 MRC/MCR trap
700	b.eq	el0_undef
701	cmp	x24, #ESR_ELx_EC_CP14_LS	// CP14 LDC/STC trap
702	b.eq	el0_undef
703	cmp	x24, #ESR_ELx_EC_CP14_64	// CP14 MRRC/MCRR trap
704	b.eq	el0_undef
705	cmp	x24, #ESR_ELx_EC_BREAKPT_LOW	// debug exception in EL0
706	b.ge	el0_dbg
707	b	el0_inv
708el0_svc_compat:
709	mov	x0, sp
710	bl	el0_svc_compat_handler
711	b	ret_to_user
712
713	.align	6
714el0_irq_compat:
715	kernel_entry 0, 32
716	b	el0_irq_naked
717
718el0_error_compat:
719	kernel_entry 0, 32
720	b	el0_error_naked
721
722el0_cp15:
723	/*
724	 * Trapped CP15 (MRC, MCR, MRRC, MCRR) instructions
725	 */
726	enable_daif
727	ct_user_exit
728	mov	x0, x25
729	mov	x1, sp
730	bl	do_cp15instr
731	b	ret_to_user
732#endif
733
734el0_da:
735	/*
736	 * Data abort handling
737	 */
738	mrs	x26, far_el1
739	enable_daif
740	ct_user_exit
741	clear_address_tag x0, x26
742	mov	x1, x25
743	mov	x2, sp
744	bl	do_mem_abort
745	b	ret_to_user
746el0_ia:
747	/*
748	 * Instruction abort handling
749	 */
750	mrs	x26, far_el1
751	enable_da_f
752#ifdef CONFIG_TRACE_IRQFLAGS
753	bl	trace_hardirqs_off
754#endif
755	ct_user_exit
756	mov	x0, x26
757	mov	x1, x25
758	mov	x2, sp
759	bl	do_el0_ia_bp_hardening
760	b	ret_to_user
761el0_fpsimd_acc:
762	/*
763	 * Floating Point or Advanced SIMD access
764	 */
765	enable_daif
766	ct_user_exit
767	mov	x0, x25
768	mov	x1, sp
769	bl	do_fpsimd_acc
770	b	ret_to_user
771el0_sve_acc:
772	/*
773	 * Scalable Vector Extension access
774	 */
775	enable_daif
776	ct_user_exit
777	mov	x0, x25
778	mov	x1, sp
779	bl	do_sve_acc
780	b	ret_to_user
781el0_fpsimd_exc:
782	/*
783	 * Floating Point, Advanced SIMD or SVE exception
784	 */
785	enable_daif
786	ct_user_exit
787	mov	x0, x25
788	mov	x1, sp
789	bl	do_fpsimd_exc
790	b	ret_to_user
791el0_sp_pc:
792	/*
793	 * Stack or PC alignment exception handling
794	 */
795	mrs	x26, far_el1
796	enable_da_f
797#ifdef CONFIG_TRACE_IRQFLAGS
798	bl	trace_hardirqs_off
799#endif
800	ct_user_exit
801	mov	x0, x26
802	mov	x1, x25
803	mov	x2, sp
804	bl	do_sp_pc_abort
805	b	ret_to_user
806el0_undef:
807	/*
808	 * Undefined instruction
809	 */
810	enable_daif
811	ct_user_exit
812	mov	x0, sp
813	bl	do_undefinstr
814	b	ret_to_user
815el0_sys:
816	/*
817	 * System instructions, for trapped cache maintenance instructions
818	 */
819	enable_daif
820	ct_user_exit
821	mov	x0, x25
822	mov	x1, sp
823	bl	do_sysinstr
824	b	ret_to_user
825el0_dbg:
826	/*
827	 * Debug exception handling
828	 */
829	tbnz	x24, #0, el0_inv		// EL0 only
830	mrs	x0, far_el1
831	mov	x1, x25
832	mov	x2, sp
833	bl	do_debug_exception
834	enable_daif
835	ct_user_exit
836	b	ret_to_user
837el0_inv:
838	enable_daif
839	ct_user_exit
840	mov	x0, sp
841	mov	x1, #BAD_SYNC
842	mov	x2, x25
843	bl	bad_el0_sync
844	b	ret_to_user
845ENDPROC(el0_sync)
846
847	.align	6
848el0_irq:
849	kernel_entry 0
850el0_irq_naked:
851	enable_da_f
852#ifdef CONFIG_TRACE_IRQFLAGS
853	bl	trace_hardirqs_off
854#endif
855
856	ct_user_exit
857#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
858	tbz	x22, #55, 1f
859	bl	do_el0_irq_bp_hardening
8601:
861#endif
862	irq_handler
863
864#ifdef CONFIG_TRACE_IRQFLAGS
865	bl	trace_hardirqs_on
866#endif
867	b	ret_to_user
868ENDPROC(el0_irq)
869
870el1_error:
871	kernel_entry 1
872	mrs	x1, esr_el1
873	enable_dbg
874	mov	x0, sp
875	bl	do_serror
876	kernel_exit 1
877ENDPROC(el1_error)
878
879el0_error:
880	kernel_entry 0
881el0_error_naked:
882	mrs	x1, esr_el1
883	enable_dbg
884	mov	x0, sp
885	bl	do_serror
886	enable_daif
887	ct_user_exit
888	b	ret_to_user
889ENDPROC(el0_error)
890
891/*
892 * Ok, we need to do extra processing, enter the slow path.
893 */
894work_pending:
895	mov	x0, sp				// 'regs'
896	bl	do_notify_resume
897#ifdef CONFIG_TRACE_IRQFLAGS
898	bl	trace_hardirqs_on		// enabled while in userspace
899#endif
900	ldr	x1, [tsk, #TSK_TI_FLAGS]	// re-check for single-step
901	b	finish_ret_to_user
902/*
903 * "slow" syscall return path.
904 */
905ret_to_user:
906	disable_daif
907	ldr	x1, [tsk, #TSK_TI_FLAGS]
908	and	x2, x1, #_TIF_WORK_MASK
909	cbnz	x2, work_pending
910finish_ret_to_user:
911	enable_step_tsk x1, x2
912#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
913	bl	stackleak_erase
914#endif
915	kernel_exit 0
916ENDPROC(ret_to_user)
917
918/*
919 * SVC handler.
920 */
921	.align	6
922el0_svc:
923	mov	x0, sp
924	bl	el0_svc_handler
925	b	ret_to_user
926ENDPROC(el0_svc)
927
928	.popsection				// .entry.text
929
930#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
931/*
932 * Exception vectors trampoline.
933 */
934	.pushsection ".entry.tramp.text", "ax"
935
936	.macro tramp_map_kernel, tmp
937	mrs	\tmp, ttbr1_el1
938	add	\tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
939	bic	\tmp, \tmp, #USER_ASID_FLAG
940	msr	ttbr1_el1, \tmp
941#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
942alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1003
943	/* ASID already in \tmp[63:48] */
944	movk	\tmp, #:abs_g2_nc:(TRAMP_VALIAS >> 12)
945	movk	\tmp, #:abs_g1_nc:(TRAMP_VALIAS >> 12)
946	/* 2MB boundary containing the vectors, so we nobble the walk cache */
947	movk	\tmp, #:abs_g0_nc:((TRAMP_VALIAS & ~(SZ_2M - 1)) >> 12)
948	isb
949	tlbi	vae1, \tmp
950	dsb	nsh
951alternative_else_nop_endif
952#endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */
953	.endm
954
955	.macro tramp_unmap_kernel, tmp
956	mrs	\tmp, ttbr1_el1
957	sub	\tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
958	orr	\tmp, \tmp, #USER_ASID_FLAG
959	msr	ttbr1_el1, \tmp
960	/*
961	 * We avoid running the post_ttbr_update_workaround here because
962	 * it's only needed by Cavium ThunderX, which requires KPTI to be
963	 * disabled.
964	 */
965	.endm
966
967	.macro tramp_ventry, regsize = 64
968	.align	7
9691:
970	.if	\regsize == 64
971	msr	tpidrro_el0, x30	// Restored in kernel_ventry
972	.endif
973	/*
974	 * Defend against branch aliasing attacks by pushing a dummy
975	 * entry onto the return stack and using a RET instruction to
976	 * enter the full-fat kernel vectors.
977	 */
978	bl	2f
979	b	.
9802:
981	tramp_map_kernel	x30
982#ifdef CONFIG_RANDOMIZE_BASE
983	adr	x30, tramp_vectors + PAGE_SIZE
984alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003
985	ldr	x30, [x30]
986#else
987	ldr	x30, =vectors
988#endif
989	prfm	plil1strm, [x30, #(1b - tramp_vectors)]
990	msr	vbar_el1, x30
991	add	x30, x30, #(1b - tramp_vectors)
992	isb
993	ret
994	.endm
995
996	.macro tramp_exit, regsize = 64
997	adr	x30, tramp_vectors
998	msr	vbar_el1, x30
999	tramp_unmap_kernel	x30
1000	.if	\regsize == 64
1001	mrs	x30, far_el1
1002	.endif
1003	eret
1004	sb
1005	.endm
1006
1007	.align	11
1008ENTRY(tramp_vectors)
1009	.space	0x400
1010
1011	tramp_ventry
1012	tramp_ventry
1013	tramp_ventry
1014	tramp_ventry
1015
1016	tramp_ventry	32
1017	tramp_ventry	32
1018	tramp_ventry	32
1019	tramp_ventry	32
1020END(tramp_vectors)
1021
1022ENTRY(tramp_exit_native)
1023	tramp_exit
1024END(tramp_exit_native)
1025
1026ENTRY(tramp_exit_compat)
1027	tramp_exit	32
1028END(tramp_exit_compat)
1029
1030	.ltorg
1031	.popsection				// .entry.tramp.text
1032#ifdef CONFIG_RANDOMIZE_BASE
1033	.pushsection ".rodata", "a"
1034	.align PAGE_SHIFT
1035	.globl	__entry_tramp_data_start
1036__entry_tramp_data_start:
1037	.quad	vectors
1038	.popsection				// .rodata
1039#endif /* CONFIG_RANDOMIZE_BASE */
1040#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
1041
1042/*
1043 * Register switch for AArch64. The callee-saved registers need to be saved
1044 * and restored. On entry:
1045 *   x0 = previous task_struct (must be preserved across the switch)
1046 *   x1 = next task_struct
1047 * Previous and next are guaranteed not to be the same.
1048 *
1049 */
1050ENTRY(cpu_switch_to)
1051	mov	x10, #THREAD_CPU_CONTEXT
1052	add	x8, x0, x10
1053	mov	x9, sp
1054	stp	x19, x20, [x8], #16		// store callee-saved registers
1055	stp	x21, x22, [x8], #16
1056	stp	x23, x24, [x8], #16
1057	stp	x25, x26, [x8], #16
1058	stp	x27, x28, [x8], #16
1059	stp	x29, x9, [x8], #16
1060	str	lr, [x8]
1061	add	x8, x1, x10
1062	ldp	x19, x20, [x8], #16		// restore callee-saved registers
1063	ldp	x21, x22, [x8], #16
1064	ldp	x23, x24, [x8], #16
1065	ldp	x25, x26, [x8], #16
1066	ldp	x27, x28, [x8], #16
1067	ldp	x29, x9, [x8], #16
1068	ldr	lr, [x8]
1069	mov	sp, x9
1070	msr	sp_el0, x1
1071	ret
1072ENDPROC(cpu_switch_to)
1073NOKPROBE(cpu_switch_to)
1074
1075/*
1076 * This is how we return from a fork.
1077 */
1078ENTRY(ret_from_fork)
1079	bl	schedule_tail
1080	cbz	x19, 1f				// not a kernel thread
1081	mov	x0, x20
1082	blr	x19
10831:	get_thread_info tsk
1084	b	ret_to_user
1085ENDPROC(ret_from_fork)
1086NOKPROBE(ret_from_fork)
1087
1088#ifdef CONFIG_ARM_SDE_INTERFACE
1089
1090#include <asm/sdei.h>
1091#include <uapi/linux/arm_sdei.h>
1092
1093.macro sdei_handler_exit exit_mode
1094	/* On success, this call never returns... */
1095	cmp	\exit_mode, #SDEI_EXIT_SMC
1096	b.ne	99f
1097	smc	#0
1098	b	.
109999:	hvc	#0
1100	b	.
1101.endm
1102
1103#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
1104/*
1105 * The regular SDEI entry point may have been unmapped along with the rest of
1106 * the kernel. This trampoline restores the kernel mapping to make the x1 memory
1107 * argument accessible.
1108 *
1109 * This clobbers x4, __sdei_handler() will restore this from firmware's
1110 * copy.
1111 */
1112.ltorg
1113.pushsection ".entry.tramp.text", "ax"
1114ENTRY(__sdei_asm_entry_trampoline)
1115	mrs	x4, ttbr1_el1
1116	tbz	x4, #USER_ASID_BIT, 1f
1117
1118	tramp_map_kernel tmp=x4
1119	isb
1120	mov	x4, xzr
1121
1122	/*
1123	 * Use reg->interrupted_regs.addr_limit to remember whether to unmap
1124	 * the kernel on exit.
1125	 */
11261:	str	x4, [x1, #(SDEI_EVENT_INTREGS + S_ORIG_ADDR_LIMIT)]
1127
1128#ifdef CONFIG_RANDOMIZE_BASE
1129	adr	x4, tramp_vectors + PAGE_SIZE
1130	add	x4, x4, #:lo12:__sdei_asm_trampoline_next_handler
1131	ldr	x4, [x4]
1132#else
1133	ldr	x4, =__sdei_asm_handler
1134#endif
1135	br	x4
1136ENDPROC(__sdei_asm_entry_trampoline)
1137NOKPROBE(__sdei_asm_entry_trampoline)
1138
1139/*
1140 * Make the exit call and restore the original ttbr1_el1
1141 *
1142 * x0 & x1: setup for the exit API call
1143 * x2: exit_mode
1144 * x4: struct sdei_registered_event argument from registration time.
1145 */
1146ENTRY(__sdei_asm_exit_trampoline)
1147	ldr	x4, [x4, #(SDEI_EVENT_INTREGS + S_ORIG_ADDR_LIMIT)]
1148	cbnz	x4, 1f
1149
1150	tramp_unmap_kernel	tmp=x4
1151
11521:	sdei_handler_exit exit_mode=x2
1153ENDPROC(__sdei_asm_exit_trampoline)
1154NOKPROBE(__sdei_asm_exit_trampoline)
1155	.ltorg
1156.popsection		// .entry.tramp.text
1157#ifdef CONFIG_RANDOMIZE_BASE
1158.pushsection ".rodata", "a"
1159__sdei_asm_trampoline_next_handler:
1160	.quad	__sdei_asm_handler
1161.popsection		// .rodata
1162#endif /* CONFIG_RANDOMIZE_BASE */
1163#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
1164
1165/*
1166 * Software Delegated Exception entry point.
1167 *
1168 * x0: Event number
1169 * x1: struct sdei_registered_event argument from registration time.
1170 * x2: interrupted PC
1171 * x3: interrupted PSTATE
1172 * x4: maybe clobbered by the trampoline
1173 *
1174 * Firmware has preserved x0->x17 for us, we must save/restore the rest to
1175 * follow SMC-CC. We save (or retrieve) all the registers as the handler may
1176 * want them.
1177 */
1178ENTRY(__sdei_asm_handler)
1179	stp     x2, x3, [x1, #SDEI_EVENT_INTREGS + S_PC]
1180	stp     x4, x5, [x1, #SDEI_EVENT_INTREGS + 16 * 2]
1181	stp     x6, x7, [x1, #SDEI_EVENT_INTREGS + 16 * 3]
1182	stp     x8, x9, [x1, #SDEI_EVENT_INTREGS + 16 * 4]
1183	stp     x10, x11, [x1, #SDEI_EVENT_INTREGS + 16 * 5]
1184	stp     x12, x13, [x1, #SDEI_EVENT_INTREGS + 16 * 6]
1185	stp     x14, x15, [x1, #SDEI_EVENT_INTREGS + 16 * 7]
1186	stp     x16, x17, [x1, #SDEI_EVENT_INTREGS + 16 * 8]
1187	stp     x18, x19, [x1, #SDEI_EVENT_INTREGS + 16 * 9]
1188	stp     x20, x21, [x1, #SDEI_EVENT_INTREGS + 16 * 10]
1189	stp     x22, x23, [x1, #SDEI_EVENT_INTREGS + 16 * 11]
1190	stp     x24, x25, [x1, #SDEI_EVENT_INTREGS + 16 * 12]
1191	stp     x26, x27, [x1, #SDEI_EVENT_INTREGS + 16 * 13]
1192	stp     x28, x29, [x1, #SDEI_EVENT_INTREGS + 16 * 14]
1193	mov	x4, sp
1194	stp     lr, x4, [x1, #SDEI_EVENT_INTREGS + S_LR]
1195
1196	mov	x19, x1
1197
1198#ifdef CONFIG_VMAP_STACK
1199	/*
1200	 * entry.S may have been using sp as a scratch register, find whether
1201	 * this is a normal or critical event and switch to the appropriate
1202	 * stack for this CPU.
1203	 */
1204	ldrb	w4, [x19, #SDEI_EVENT_PRIORITY]
1205	cbnz	w4, 1f
1206	ldr_this_cpu dst=x5, sym=sdei_stack_normal_ptr, tmp=x6
1207	b	2f
12081:	ldr_this_cpu dst=x5, sym=sdei_stack_critical_ptr, tmp=x6
12092:	mov	x6, #SDEI_STACK_SIZE
1210	add	x5, x5, x6
1211	mov	sp, x5
1212#endif
1213
1214	/*
1215	 * We may have interrupted userspace, or a guest, or exit-from or
1216	 * return-to either of these. We can't trust sp_el0, restore it.
1217	 */
1218	mrs	x28, sp_el0
1219	ldr_this_cpu	dst=x0, sym=__entry_task, tmp=x1
1220	msr	sp_el0, x0
1221
1222	/* If we interrupted the kernel point to the previous stack/frame. */
1223	and     x0, x3, #0xc
1224	mrs     x1, CurrentEL
1225	cmp     x0, x1
1226	csel	x29, x29, xzr, eq	// fp, or zero
1227	csel	x4, x2, xzr, eq		// elr, or zero
1228
1229	stp	x29, x4, [sp, #-16]!
1230	mov	x29, sp
1231
1232	add	x0, x19, #SDEI_EVENT_INTREGS
1233	mov	x1, x19
1234	bl	__sdei_handler
1235
1236	msr	sp_el0, x28
1237	/* restore regs >x17 that we clobbered */
1238	mov	x4, x19         // keep x4 for __sdei_asm_exit_trampoline
1239	ldp	x28, x29, [x4, #SDEI_EVENT_INTREGS + 16 * 14]
1240	ldp	x18, x19, [x4, #SDEI_EVENT_INTREGS + 16 * 9]
1241	ldp	lr, x1, [x4, #SDEI_EVENT_INTREGS + S_LR]
1242	mov	sp, x1
1243
1244	mov	x1, x0			// address to complete_and_resume
1245	/* x0 = (x0 <= 1) ? EVENT_COMPLETE:EVENT_COMPLETE_AND_RESUME */
1246	cmp	x0, #1
1247	mov_q	x2, SDEI_1_0_FN_SDEI_EVENT_COMPLETE
1248	mov_q	x3, SDEI_1_0_FN_SDEI_EVENT_COMPLETE_AND_RESUME
1249	csel	x0, x2, x3, ls
1250
1251	ldr_l	x2, sdei_exit_mode
1252
1253alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0
1254	sdei_handler_exit exit_mode=x2
1255alternative_else_nop_endif
1256
1257#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
1258	tramp_alias	dst=x5, sym=__sdei_asm_exit_trampoline
1259	br	x5
1260#endif
1261ENDPROC(__sdei_asm_handler)
1262NOKPROBE(__sdei_asm_handler)
1263#endif /* CONFIG_ARM_SDE_INTERFACE */
1264