xref: /rk3399_ARM-atf/bl31/aarch64/ea_delegate.S (revision df8f3188d7b318b3b486f0ec4016b2ad271c85a7)
1/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7
8#include <asm_macros.S>
9#include <context.h>
10#include <ea_handle.h>
11
12
13	.globl	handle_lower_el_ea_esb
14	.globl	enter_lower_el_sync_ea
15	.globl	enter_lower_el_async_ea
16
17
18/*
19 * Function to delegate External Aborts synchronized by ESB instruction at EL3
20 * vector entry. This function assumes GP registers x0-x29 have been saved, and
21 * are available for use. It delegates the handling of the EA to platform
22 * handler, and returns only upon successfully handling the EA; otherwise
23 * panics. On return from this function, the original exception handler is
24 * expected to resume.
25 */
26func handle_lower_el_ea_esb
27	mov	x0, #ERROR_EA_ESB
28	mrs	x1, DISR_EL1
29	b	ea_proceed
30endfunc handle_lower_el_ea_esb
31
32
33/*
34 * This function forms the tail end of Synchronous Exception entry from lower
35 * EL, and expects to handle only Synchronous External Aborts from lower EL. If
36 * any other kind of exception is detected, then this function reports unhandled
37 * exception.
38 *
39 * Since it's part of exception vector, this function doesn't expect any GP
40 * registers to have been saved. It delegates the handling of the EA to platform
41 * handler, and upon successfully handling the EA, exits EL3; otherwise panics.
42 */
43func enter_lower_el_sync_ea
44	/*
45	 * Explicitly save x30 so as to free up a register and to enable
46	 * branching.
47	 */
48	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
49
50	mrs	x30, esr_el3
51	ubfx	x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
52
53	/* Check for I/D aborts from lower EL */
54	cmp	x30, #EC_IABORT_LOWER_EL
55	b.eq	1f
56
57	cmp	x30, #EC_DABORT_LOWER_EL
58	b.ne	2f
59
601:
61	/* Test for EA bit in the instruction syndrome */
62	mrs	x30, esr_el3
63	tbz	x30, #ESR_ISS_EABORT_EA_BIT, 2f
64
65	/* Save GP registers */
66	bl	save_gp_registers
67
68	/* Setup exception class and syndrome arguments for platform handler */
69	mov	x0, #ERROR_EA_SYNC
70	mrs	x1, esr_el3
71	adr	x30, el3_exit
72	b	ea_proceed
73
742:
75	/* Synchronous exceptions other than the above are assumed to be EA */
76	ldr	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
77	no_ret	report_unhandled_exception
78endfunc enter_lower_el_sync_ea
79
80
81/*
82 * This function handles SErrors from lower ELs.
83 *
84 * Since it's part of exception vector, this function doesn't expect any GP
85 * registers to have been saved. It delegates the handling of the EA to platform
86 * handler, and upon successfully handling the EA, exits EL3; otherwise panics.
87 */
88func enter_lower_el_async_ea
89	/*
90	 * Explicitly save x30 so as to free up a register and to enable
91	 * branching
92	 */
93	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
94
95	/* Save GP registers */
96	bl	save_gp_registers
97
98	/* Setup exception class and syndrome arguments for platform handler */
99	mov	x0, #ERROR_EA_ASYNC
100	mrs	x1, esr_el3
101	adr	x30, el3_exit
102	b	ea_proceed
103endfunc enter_lower_el_async_ea
104
105
106/*
107 * Delegate External Abort handling to platform's EA handler. This function
108 * assumes that all GP registers have been saved by the caller.
109 *
110 * x0: EA reason
111 * x1: EA syndrome
112 */
113func ea_proceed
114	/* Save EL3 state */
115	mrs	x2, spsr_el3
116	mrs	x3, elr_el3
117	stp	x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
118
119	/*
120	 * Save ESR as handling might involve lower ELs, and returning back to
121	 * EL3 from there would trample the original ESR.
122	 */
123	mrs	x4, scr_el3
124	mrs	x5, esr_el3
125	stp	x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
126
127	/*
128	 * Setup rest of arguments, and call platform External Abort handler.
129	 *
130	 * x0: EA reason (already in place)
131	 * x1: Exception syndrome (already in place).
132	 * x2: Cookie (unused for now).
133	 * x3: Context pointer.
134	 * x4: Flags (security state from SCR for now).
135	 */
136	mov	x2, xzr
137	mov	x3, sp
138	ubfx	x4, x4, #0, #1
139
140	/* Switch to runtime stack */
141	ldr	x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
142	msr	spsel, #0
143	mov	sp, x5
144
145	mov	x29, x30
146	bl	plat_ea_handler
147	mov	x30, x29
148
149	/* Make SP point to context */
150	msr	spsel, #1
151
152	/* Restore EL3 state */
153	ldp	x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
154	msr	spsr_el3, x1
155	msr	elr_el3, x2
156
157	/* Restore ESR_EL3 and SCR_EL3 */
158	ldp	x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
159	msr	scr_el3, x3
160	msr	esr_el3, x4
161
162	ret
163endfunc ea_proceed
164