blob: d18f9e5758cb35f5cdecb53a0ba4be8f32337b8a [file] [log] [blame]
Jeenu Viswambharane86a2472018-07-05 15:24:45 +01001/*
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>
Jeenu Viswambharan476c29f2018-02-19 12:25:53 +00009#include <assert_macros.S>
Jeenu Viswambharane86a2472018-07-05 15:24:45 +010010#include <context.h>
11#include <ea_handle.h>
12
13
14 .globl handle_lower_el_ea_esb
15 .globl enter_lower_el_sync_ea
16 .globl enter_lower_el_async_ea
17
18
19/*
20 * Function to delegate External Aborts synchronized by ESB instruction at EL3
21 * vector entry. This function assumes GP registers x0-x29 have been saved, and
22 * are available for use. It delegates the handling of the EA to platform
23 * handler, and returns only upon successfully handling the EA; otherwise
24 * panics. On return from this function, the original exception handler is
25 * expected to resume.
26 */
27func handle_lower_el_ea_esb
28 mov x0, #ERROR_EA_ESB
29 mrs x1, DISR_EL1
30 b ea_proceed
31endfunc handle_lower_el_ea_esb
32
33
34/*
35 * This function forms the tail end of Synchronous Exception entry from lower
36 * EL, and expects to handle only Synchronous External Aborts from lower EL. If
37 * any other kind of exception is detected, then this function reports unhandled
38 * exception.
39 *
40 * Since it's part of exception vector, this function doesn't expect any GP
41 * registers to have been saved. It delegates the handling of the EA to platform
42 * handler, and upon successfully handling the EA, exits EL3; otherwise panics.
43 */
44func enter_lower_el_sync_ea
45 /*
46 * Explicitly save x30 so as to free up a register and to enable
47 * branching.
48 */
49 str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
50
51 mrs x30, esr_el3
52 ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
53
54 /* Check for I/D aborts from lower EL */
55 cmp x30, #EC_IABORT_LOWER_EL
56 b.eq 1f
57
58 cmp x30, #EC_DABORT_LOWER_EL
59 b.ne 2f
60
611:
62 /* Test for EA bit in the instruction syndrome */
63 mrs x30, esr_el3
64 tbz x30, #ESR_ISS_EABORT_EA_BIT, 2f
65
66 /* Save GP registers */
67 bl save_gp_registers
68
69 /* Setup exception class and syndrome arguments for platform handler */
70 mov x0, #ERROR_EA_SYNC
71 mrs x1, esr_el3
72 adr x30, el3_exit
73 b ea_proceed
74
752:
76 /* Synchronous exceptions other than the above are assumed to be EA */
77 ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
78 no_ret report_unhandled_exception
79endfunc enter_lower_el_sync_ea
80
81
82/*
83 * This function handles SErrors from lower ELs.
84 *
85 * Since it's part of exception vector, this function doesn't expect any GP
86 * registers to have been saved. It delegates the handling of the EA to platform
87 * handler, and upon successfully handling the EA, exits EL3; otherwise panics.
88 */
89func enter_lower_el_async_ea
90 /*
91 * Explicitly save x30 so as to free up a register and to enable
92 * branching
93 */
94 str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
95
96 /* Save GP registers */
97 bl save_gp_registers
98
99 /* Setup exception class and syndrome arguments for platform handler */
100 mov x0, #ERROR_EA_ASYNC
101 mrs x1, esr_el3
102 adr x30, el3_exit
103 b ea_proceed
104endfunc enter_lower_el_async_ea
105
106
107/*
108 * Delegate External Abort handling to platform's EA handler. This function
109 * assumes that all GP registers have been saved by the caller.
110 *
111 * x0: EA reason
112 * x1: EA syndrome
113 */
114func ea_proceed
115 /* Save EL3 state */
116 mrs x2, spsr_el3
117 mrs x3, elr_el3
118 stp x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
119
120 /*
121 * Save ESR as handling might involve lower ELs, and returning back to
122 * EL3 from there would trample the original ESR.
123 */
124 mrs x4, scr_el3
125 mrs x5, esr_el3
126 stp x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
127
128 /*
129 * Setup rest of arguments, and call platform External Abort handler.
130 *
131 * x0: EA reason (already in place)
132 * x1: Exception syndrome (already in place).
133 * x2: Cookie (unused for now).
134 * x3: Context pointer.
135 * x4: Flags (security state from SCR for now).
136 */
137 mov x2, xzr
138 mov x3, sp
139 ubfx x4, x4, #0, #1
140
141 /* Switch to runtime stack */
142 ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
143 msr spsel, #0
144 mov sp, x5
145
146 mov x29, x30
Jeenu Viswambharan476c29f2018-02-19 12:25:53 +0000147#if ENABLE_ASSERTIONS
148 /* Stash the stack pointer */
149 mov x28, sp
150#endif
Jeenu Viswambharane86a2472018-07-05 15:24:45 +0100151 bl plat_ea_handler
152 mov x30, x29
153
Jeenu Viswambharan476c29f2018-02-19 12:25:53 +0000154#if ENABLE_ASSERTIONS
155 /*
156 * Error handling flows might involve long jumps; so upon returning from
157 * the platform error handler, validate that the we've completely
158 * unwound the stack.
159 */
160 mov x27, sp
161 cmp x28, x27
162 ASM_ASSERT(eq)
163#endif
164
Jeenu Viswambharane86a2472018-07-05 15:24:45 +0100165 /* Make SP point to context */
166 msr spsel, #1
167
168 /* Restore EL3 state */
169 ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
170 msr spsr_el3, x1
171 msr elr_el3, x2
172
173 /* Restore ESR_EL3 and SCR_EL3 */
174 ldp x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
175 msr scr_el3, x3
176 msr esr_el3, x4
177
178 ret
179endfunc ea_proceed