xref: /openbmc/u-boot/arch/arm/cpu/armv8/exceptions.S (revision bf494d7e)
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * (C) Copyright 2013
4 * David Feng <fenghua@phytium.com.cn>
5 */
6
7#include <asm-offsets.h>
8#include <config.h>
9#include <asm/ptrace.h>
10#include <asm/macro.h>
11#include <linux/linkage.h>
12
13/*
14 * AArch64 exception vectors:
15 * We have four types of exceptions:
16 * - synchronous: traps, data aborts, undefined instructions, ...
17 * - IRQ: group 1 (normal) interrupts
18 * - FIQ: group 0 or secure interrupts
19 * - SError: fatal system errors
20 * There are entries for all four of those for different contexts:
21 * - from same exception level, when using the SP_EL0 stack pointer
22 * - from same exception level, when using the SP_ELx stack pointer
23 * - from lower exception level, when this is AArch64
24 * - from lower exception level, when this is AArch32
25 * Each of those 16 entries have space for 32 instructions, each entry must
26 * be 128 byte aligned, the whole table must be 2K aligned.
27 * The 32 instructions are not enough to save and restore all registers and
28 * to branch to the actual handler, so we split this up:
29 * Each entry saves the LR, branches to the save routine, then to the actual
30 * handler, then to the restore routine. The save and restore routines are
31 * each split in half and stuffed in the unused gap between the entries.
32 * Also as we do not run anything in a lower exception level, we just provide
33 * the first 8 entries for exceptions from the same EL.
34 */
35	.align	11
36	.globl	vectors
37vectors:
38	.align	7		/* Current EL Synchronous Thread */
39	stp	x29, x30, [sp, #-16]!
40	bl	_exception_entry
41	bl	do_bad_sync
42	b	exception_exit
43
44/*
45 * Save (most of) the GP registers to the stack frame.
46 * This is the first part of the shared routine called into from all entries.
47 */
48_exception_entry:
49	stp	x27, x28, [sp, #-16]!
50	stp	x25, x26, [sp, #-16]!
51	stp	x23, x24, [sp, #-16]!
52	stp	x21, x22, [sp, #-16]!
53	stp	x19, x20, [sp, #-16]!
54	stp	x17, x18, [sp, #-16]!
55	stp	x15, x16, [sp, #-16]!
56	stp	x13, x14, [sp, #-16]!
57	stp	x11, x12, [sp, #-16]!
58	stp	x9, x10, [sp, #-16]!
59	stp	x7, x8, [sp, #-16]!
60	stp	x5, x6, [sp, #-16]!
61	stp	x3, x4, [sp, #-16]!
62	stp	x1, x2, [sp, #-16]!
63	b	_save_el_regs			/* jump to the second part */
64
65	.align	7		/* Current EL IRQ Thread */
66	stp	x29, x30, [sp, #-16]!
67	bl	_exception_entry
68	bl	do_bad_irq
69	b	exception_exit
70
71/*
72 * Save exception specific context: ESR and ELR, for all exception levels.
73 * This is the second part of the shared routine called into from all entries.
74 */
75_save_el_regs:
76	/* Could be running at EL3/EL2/EL1 */
77	switch_el x11, 3f, 2f, 1f
783:	mrs	x1, esr_el3
79	mrs	x2, elr_el3
80	b	0f
812:	mrs	x1, esr_el2
82	mrs	x2, elr_el2
83	b	0f
841:	mrs	x1, esr_el1
85	mrs	x2, elr_el1
860:
87	stp	x2, x0, [sp, #-16]!
88	mov	x0, sp
89	ret
90
91	.align	7		/* Current EL FIQ Thread */
92	stp	x29, x30, [sp, #-16]!
93	bl	_exception_entry
94	bl	do_bad_fiq
95				/* falling through to _exception_exit */
96/*
97 * Restore the exception return address, for all exception levels.
98 * This is the first part of the shared routine called into from all entries.
99 */
100exception_exit:
101	ldp	x2, x0, [sp],#16
102	switch_el x11, 3f, 2f, 1f
1033:	msr	elr_el3, x2
104	b	_restore_regs
1052:	msr	elr_el2, x2
106	b	_restore_regs
1071:	msr	elr_el1, x2
108	b	_restore_regs		/* jump to the second part */
109
110	.align	7		/* Current EL Error Thread */
111	stp	x29, x30, [sp, #-16]!
112	bl	_exception_entry
113	bl	do_bad_error
114	b	exception_exit
115
116/*
117 * Restore the general purpose registers from the exception stack, then return.
118 * This is the second part of the shared routine called into from all entries.
119 */
120_restore_regs:
121	ldp	x1, x2, [sp],#16
122	ldp	x3, x4, [sp],#16
123	ldp	x5, x6, [sp],#16
124	ldp	x7, x8, [sp],#16
125	ldp	x9, x10, [sp],#16
126	ldp	x11, x12, [sp],#16
127	ldp	x13, x14, [sp],#16
128	ldp	x15, x16, [sp],#16
129	ldp	x17, x18, [sp],#16
130	ldp	x19, x20, [sp],#16
131	ldp	x21, x22, [sp],#16
132	ldp	x23, x24, [sp],#16
133	ldp	x25, x26, [sp],#16
134	ldp	x27, x28, [sp],#16
135	ldp	x29, x30, [sp],#16
136	eret
137
138	.align	7		 /* Current EL (SP_ELx) Synchronous Handler */
139	stp	x29, x30, [sp, #-16]!
140	bl	_exception_entry
141	bl	do_sync
142	b	exception_exit
143
144	.align	7		 /* Current EL (SP_ELx) IRQ Handler */
145	stp	x29, x30, [sp, #-16]!
146	bl	_exception_entry
147	bl	do_irq
148	b	exception_exit
149
150	.align	7		 /* Current EL (SP_ELx) FIQ Handler */
151	stp	x29, x30, [sp, #-16]!
152	bl	_exception_entry
153	bl	do_fiq
154	b	exception_exit
155
156	.align	7		 /* Current EL (SP_ELx) Error Handler */
157	stp	x29, x30, [sp, #-16]!
158	bl	_exception_entry
159	bl	do_error
160	b	exception_exit
161