blob: 50e655ee60b45f40c5570059f992ed739c8466c7 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <arch.h>
7#include <arch_helpers.h>
8#include <assert.h>
9#include <buffer.h>
10#include <debug.h>
Arunachalam Ganapathy51119932023-03-23 12:32:49 +000011#include <simd.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000012#include <smc-handler.h>
13#include <smc-rmi.h>
14#include <smc.h>
15#include <status.h>
16#include <utils_def.h>
17
AlexeiFedorov6c119692023-04-21 12:31:15 +010018/* Maximum number of supported arguments */
AlexeiFedorov93f5ec52023-08-31 14:26:53 +010019#define MAX_NUM_ARGS 5U
Soby Mathewb4c6df42022-11-09 11:13:29 +000020
AlexeiFedorov6c119692023-04-21 12:31:15 +010021/* Maximum number of output values */
AlexeiFedorov93f5ec52023-08-31 14:26:53 +010022#define MAX_NUM_OUTPUT_VALS 4U
AlexeiFedorov6c119692023-04-21 12:31:15 +010023
24#define RMI_STATUS_STRING(_id)[RMI_##_id] = #_id
25
AlexeiFedorov53518ba2023-08-22 14:46:26 +010026static const char *rmi_status_string[] = {
AlexeiFedorov6c119692023-04-21 12:31:15 +010027 RMI_STATUS_STRING(SUCCESS),
28 RMI_STATUS_STRING(ERROR_INPUT),
29 RMI_STATUS_STRING(ERROR_REALM),
30 RMI_STATUS_STRING(ERROR_REC),
AlexeiFedorov892abce2023-04-06 16:32:12 +010031 RMI_STATUS_STRING(ERROR_RTT)
Soby Mathewb4c6df42022-11-09 11:13:29 +000032};
AlexeiFedorov6c119692023-04-21 12:31:15 +010033COMPILER_ASSERT(ARRAY_LEN(rmi_status_string) == RMI_ERROR_COUNT);
Soby Mathewb4c6df42022-11-09 11:13:29 +000034
35/*
36 * At this level (in handle_ns_smc) we distinguish the RMI calls only on:
AlexeiFedorov6c119692023-04-21 12:31:15 +010037 * - The number of input arguments [0..5], and whether
Soby Mathewb4c6df42022-11-09 11:13:29 +000038 * - The function returns up to three output values in addition
39 * to the return status code.
40 * Hence, the naming syntax is:
AlexeiFedorov6c119692023-04-21 12:31:15 +010041 * - `*_[0..5]` when no output values are returned, and
42 * - `*_[0..3]_o` when the function returns some output values.
Soby Mathewb4c6df42022-11-09 11:13:29 +000043 */
Soby Mathewb4c6df42022-11-09 11:13:29 +000044typedef unsigned long (*handler_0)(void);
45typedef unsigned long (*handler_1)(unsigned long arg0);
46typedef unsigned long (*handler_2)(unsigned long arg0, unsigned long arg1);
47typedef unsigned long (*handler_3)(unsigned long arg0, unsigned long arg1,
48 unsigned long arg2);
49typedef unsigned long (*handler_4)(unsigned long arg0, unsigned long arg1,
50 unsigned long arg2, unsigned long arg3);
51typedef unsigned long (*handler_5)(unsigned long arg0, unsigned long arg1,
52 unsigned long arg2, unsigned long arg3,
53 unsigned long arg4);
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010054typedef void (*handler_1_o)(unsigned long arg0, struct smc_result *res);
AlexeiFedorov892abce2023-04-06 16:32:12 +010055typedef void (*handler_2_o)(unsigned long arg0, unsigned long arg1,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010056 struct smc_result *res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000057typedef void (*handler_3_o)(unsigned long arg0, unsigned long arg1,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010058 unsigned long arg2, struct smc_result *res);
AlexeiFedorov892abce2023-04-06 16:32:12 +010059typedef void (*handler_4_o)(unsigned long arg0, unsigned long arg1,
60 unsigned long arg2, unsigned long arg3,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010061 struct smc_result *res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000062
AlexeiFedorov6c119692023-04-21 12:31:15 +010063/*
64 * SMC RMI handler type encoding:
65 * [0:7] - number of arguments
66 * [8:15] - number of output values
67 */
68#define RMI_TYPE(_in, _out) (_in | (_out << 8))
69#define rmi_type(_in, _out) rmi_type_##_in##_out = RMI_TYPE(_in, _out)
70
Soby Mathewb4c6df42022-11-09 11:13:29 +000071enum rmi_type {
AlexeiFedorov6c119692023-04-21 12:31:15 +010072 rmi_type(0, 0), /* 0 arguments, 0 output values */
73 rmi_type(1, 0), /* 1 argument, 0 output values */
74 rmi_type(2, 0), /* 2 arguments, 0 output values */
75 rmi_type(3, 0), /* 3 arguments, 0 output values */
76 rmi_type(4, 0), /* 4 arguments, 0 output values */
77 rmi_type(5, 0), /* 5 arguments, 0 output values */
78 rmi_type(1, 1), /* 1 argument, 1 output value */
AlexeiFedorov892abce2023-04-06 16:32:12 +010079 rmi_type(2, 2), /* 2 arguments, 2 output values */
80 rmi_type(3, 1), /* 3 arguments, 1 output value */
81 rmi_type(3, 2), /* 3 arguments, 2 output values */
82 rmi_type(3, 4), /* 3 arguments, 4 output values */
83 rmi_type(4, 1) /* 4 arguments, 1 output value */
Soby Mathewb4c6df42022-11-09 11:13:29 +000084};
85
86struct smc_handler {
87 const char *fn_name;
88 enum rmi_type type;
89 union {
AlexeiFedorov6c119692023-04-21 12:31:15 +010090 handler_0 f_00;
91 handler_1 f_10;
92 handler_2 f_20;
93 handler_3 f_30;
94 handler_4 f_40;
95 handler_5 f_50;
96 handler_1_o f_11;
AlexeiFedorov892abce2023-04-06 16:32:12 +010097 handler_2_o f_22;
98 handler_3_o f_31;
99 handler_3_o f_32;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100100 handler_3_o f_34;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100101 handler_4_o f_41;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000102 void *fn_dummy;
103 };
104 bool log_exec; /* print handler execution */
105 bool log_error; /* print in case of error status */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000106};
107
108/*
109 * Get handler ID from FID
110 * Precondition: FID is an RMI call
111 */
AlexeiFedorov6c119692023-04-21 12:31:15 +0100112#define RMI_HANDLER_ID(_id) SMC64_FID_OFFSET_FROM_RANGE_MIN(RMI, _id)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000113
AlexeiFedorov6c119692023-04-21 12:31:15 +0100114#define HANDLER(_id, _in, _out, _fn, _exec, _error)[RMI_HANDLER_ID(SMC_RMM_##_id)] = { \
115 .fn_name = #_id, \
116 .type = RMI_TYPE(_in, _out), \
117 .f_##_in##_out = _fn, \
118 .log_exec = _exec, \
119 .log_error = _error \
120}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000121
122/*
123 * The 3rd value enables the execution log.
124 * The 4th value enables the error log.
125 */
126static const struct smc_handler smc_handlers[] = {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100127 HANDLER(VERSION, 0, 0, smc_version, true, true),
128 HANDLER(FEATURES, 1, 1, smc_read_feature_register, true, true),
129 HANDLER(GRANULE_DELEGATE, 1, 0, smc_granule_delegate, false, true),
130 HANDLER(GRANULE_UNDELEGATE, 1, 0, smc_granule_undelegate, false, true),
131 HANDLER(REALM_CREATE, 2, 0, smc_realm_create, true, true),
132 HANDLER(REALM_DESTROY, 1, 0, smc_realm_destroy, true, true),
133 HANDLER(REALM_ACTIVATE, 1, 0, smc_realm_activate, true, true),
134 HANDLER(REC_CREATE, 3, 0, smc_rec_create, true, true),
135 HANDLER(REC_DESTROY, 1, 0, smc_rec_destroy, true, true),
136 HANDLER(REC_ENTER, 2, 0, smc_rec_enter, false, true),
137 HANDLER(DATA_CREATE, 5, 0, smc_data_create, false, false),
138 HANDLER(DATA_CREATE_UNKNOWN, 3, 0, smc_data_create_unknown, false, false),
AlexeiFedorove2002be2023-04-19 17:20:12 +0100139 HANDLER(DATA_DESTROY, 2, 2, smc_data_destroy, false, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100140 HANDLER(RTT_CREATE, 4, 0, smc_rtt_create, false, true),
AlexeiFedorove2002be2023-04-19 17:20:12 +0100141 HANDLER(RTT_DESTROY, 3, 2, smc_rtt_destroy, false, true),
142 HANDLER(RTT_FOLD, 3, 1, smc_rtt_fold, false, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100143 HANDLER(RTT_MAP_UNPROTECTED, 4, 0, smc_rtt_map_unprotected, false, false),
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100144 HANDLER(RTT_UNMAP_UNPROTECTED, 3, 1, smc_rtt_unmap_unprotected, false, false),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100145 HANDLER(RTT_READ_ENTRY, 3, 4, smc_rtt_read_entry, false, true),
146 HANDLER(PSCI_COMPLETE, 2, 0, smc_psci_complete, true, true),
147 HANDLER(REC_AUX_COUNT, 1, 1, smc_rec_aux_count, true, true),
AlexeiFedorov960d1612023-04-25 13:23:39 +0100148 HANDLER(RTT_INIT_RIPAS, 3, 1, smc_rtt_init_ripas, false, true),
AlexeiFedorov5cf35ba2023-04-25 10:02:20 +0100149 HANDLER(RTT_SET_RIPAS, 4, 1, smc_rtt_set_ripas, false, true)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000150};
151
152COMPILER_ASSERT(ARRAY_LEN(smc_handlers) == SMC64_NUM_FIDS_IN_RANGE(RMI));
153
154static bool rmi_call_log_enabled = true;
155
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000156static inline bool rmi_handler_needs_fpu(unsigned long id)
157{
158#ifdef RMM_FPU_USE_AT_REL2
159 if (id == SMC_RMM_REALM_CREATE || id == SMC_RMM_DATA_CREATE ||
160 id == SMC_RMM_REC_CREATE || id == SMC_RMM_RTT_INIT_RIPAS) {
161 return true;
162 }
163#endif
164 return false;
165}
166
Soby Mathewb4c6df42022-11-09 11:13:29 +0000167static void rmi_log_on_exit(unsigned long handler_id,
AlexeiFedorov6c119692023-04-21 12:31:15 +0100168 unsigned long args[],
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100169 struct smc_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000170{
171 const struct smc_handler *handler = &smc_handlers[handler_id];
172 unsigned long function_id = SMC64_RMI_FID(handler_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000173 return_code_t rc;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100174 unsigned int num;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000175
176 if (!handler->log_exec && !handler->log_error) {
177 return;
178 }
179
180 if (function_id == SMC_RMM_VERSION) {
181 /*
182 * RMM_VERSION is special because it returns the
183 * version number, not the error code.
184 */
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100185 INFO("SMC_RMM_%-21s > %lx\n", handler->fn_name, res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000186 return;
187 }
188
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100189 rc = unpack_return_code(res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000190
191 if ((handler->log_exec) ||
192 (handler->log_error && (rc.status != RMI_SUCCESS))) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100193 /* Print function name */
194 INFO("SMC_RMM_%-21s", handler->fn_name);
195
196 /* Print arguments */
AlexeiFedorov84cba4f2023-08-25 13:45:48 +0100197 num = (unsigned int)handler->type & 0xFFU;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100198 assert(num <= MAX_NUM_ARGS);
199
200 for (unsigned int i = 0U; i < num; i++) {
201 INFO(" %lx", args[i]);
202 }
203
204 /* Print status */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000205 if (rc.status >= RMI_ERROR_COUNT) {
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100206 INFO(" > %lx", res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000207 } else {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100208 INFO(" > RMI_%s", rmi_status_string[rc.status]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000209 }
210
211 /* Check for index */
212 if (((function_id == SMC_RMM_REC_ENTER) &&
213 (rc.status == RMI_ERROR_REALM)) ||
214 (rc.status == RMI_ERROR_RTT)) {
215 INFO(" %x", rc.index);
AlexeiFedorov697445b2023-04-25 15:27:57 +0100216 }
217
218 if ((rc.status == RMI_SUCCESS) ||
219 ((rc.status == RMI_ERROR_RTT) &&
220 ((function_id == SMC_RMM_RTT_DESTROY) ||
221 (function_id == SMC_RMM_DATA_DESTROY)))) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100222 /* Print output values */
AlexeiFedorov84cba4f2023-08-25 13:45:48 +0100223 num = ((unsigned int)handler->type >> 8) & 0xFFU;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100224 assert(num <= MAX_NUM_OUTPUT_VALS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000225
AlexeiFedorov6c119692023-04-21 12:31:15 +0100226 for (unsigned int i = 1U; i <= num; i++) {
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100227 INFO(" %lx", res->x[i]);
AlexeiFedorov6c119692023-04-21 12:31:15 +0100228 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000229 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000230 INFO("\n");
231 }
232}
233
234void handle_ns_smc(unsigned long function_id,
235 unsigned long arg0,
236 unsigned long arg1,
237 unsigned long arg2,
238 unsigned long arg3,
239 unsigned long arg4,
240 unsigned long arg5,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100241 struct smc_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000242{
243 unsigned long handler_id;
244 const struct smc_handler *handler = NULL;
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000245 bool restore_ns_simd_state = false;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000246
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +0000247 /* Ignore SVE hint bit, until RMM supports SVE hint bit */
AlexeiFedorov4faab852023-08-30 15:06:49 +0100248 function_id &= ~SMC_SVE_HINT;
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +0000249
Soby Mathewb4c6df42022-11-09 11:13:29 +0000250 if (IS_SMC64_RMI_FID(function_id)) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100251 handler_id = RMI_HANDLER_ID(function_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000252 if (handler_id < ARRAY_LEN(smc_handlers)) {
253 handler = &smc_handlers[handler_id];
254 }
255 }
256
257 /*
258 * Check if handler exists and 'fn_dummy' is not NULL
259 * for not implemented 'function_id' calls in SMC RMI range.
260 */
261 if ((handler == NULL) || (handler->fn_dummy == NULL)) {
262 VERBOSE("[%s] unknown function_id: %lx\n",
263 __func__, function_id);
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100264 res->x[0] = SMC_UNKNOWN;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000265 return;
266 }
267
268 assert_cpu_slots_empty();
269
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000270 /* Current CPU's SIMD state must not be saved when entering RMM */
271 assert(simd_is_state_saved() == false);
272
273 /* If the handler needs FPU, actively save NS simd context. */
274 if (rmi_handler_needs_fpu(function_id) == true) {
275 simd_save_ns_state();
276 restore_ns_simd_state = true;
277 }
278
Soby Mathewb4c6df42022-11-09 11:13:29 +0000279 switch (handler->type) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100280 case rmi_type_00:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100281 res->x[0] = handler->f_00();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000282 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100283 case rmi_type_10:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100284 res->x[0] = handler->f_10(arg0);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000285 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100286 case rmi_type_20:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100287 res->x[0] = handler->f_20(arg0, arg1);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000288 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100289 case rmi_type_30:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100290 res->x[0] = handler->f_30(arg0, arg1, arg2);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000291 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100292 case rmi_type_40:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100293 res->x[0] = handler->f_40(arg0, arg1, arg2, arg3);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000294 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100295 case rmi_type_50:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100296 res->x[0] = handler->f_50(arg0, arg1, arg2, arg3, arg4);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000297 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100298 case rmi_type_11:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100299 handler->f_11(arg0, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000300 break;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100301 case rmi_type_22:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100302 handler->f_22(arg0, arg1, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100303 break;
304 case rmi_type_31:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100305 handler->f_31(arg0, arg1, arg2, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100306 break;
307 case rmi_type_32:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100308 handler->f_32(arg0, arg1, arg2, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100309 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100310 case rmi_type_34:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100311 handler->f_34(arg0, arg1, arg2, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000312 break;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100313 case rmi_type_41:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100314 handler->f_41(arg0, arg1, arg2, arg3, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100315 break;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000316 default:
317 assert(false);
318 }
319
320 if (rmi_call_log_enabled) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100321 unsigned long args[] = {arg0, arg1, arg2, arg3, arg4};
322
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100323 rmi_log_on_exit(handler_id, args, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000324 }
325
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000326 /* If the handler uses FPU, restore the saved NS simd context. */
327 if (restore_ns_simd_state) {
328 simd_restore_ns_state();
329 }
330
331 /* Current CPU's SIMD state must not be saved when exiting RMM */
332 assert(simd_is_state_saved() == false);
333
Soby Mathewb4c6df42022-11-09 11:13:29 +0000334 assert_cpu_slots_empty();
335}
336
337static void report_unexpected(void)
338{
339 unsigned long spsr = read_spsr_el2();
340 unsigned long esr = read_esr_el2();
341 unsigned long elr = read_elr_el2();
342 unsigned long far = read_far_el2();
343
344 INFO("----\n");
345 INFO("Unexpected exception:\n");
346 INFO("SPSR_EL2: 0x%016lx\n", spsr);
347 INFO("ESR_EL2: 0x%016lx\n", esr);
348 INFO("ELR_EL2: 0x%016lx\n", elr);
349 INFO("FAR_EL2: 0x%016lx\n", far);
350 INFO("----\n");
Soby Mathewb4c6df42022-11-09 11:13:29 +0000351}
352
AlexeiFedorov57f40fc2023-08-17 14:33:33 +0100353__dead2 unsigned long handle_realm_trap(unsigned long *regs)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000354{
355 report_unexpected();
356
AlexeiFedorov6c119692023-04-21 12:31:15 +0100357 while (true) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000358 wfe();
359 }
360}
361
362/*
363 * Identifies an abort that the RMM may recover from.
364 */
365struct rmm_trap_element {
366 /*
367 * The PC at the time of abort.
368 */
369 unsigned long aborted_pc;
370 /*
371 * New value of the PC.
372 */
373 unsigned long new_pc;
374};
375
376#define RMM_TRAP_HANDLER(_aborted_pc, _new_pc) \
377 { .aborted_pc = (unsigned long)(&_aborted_pc), \
378 .new_pc = (unsigned long)(&_new_pc) }
379
380/*
381 * The registered locations of load/store instructions that access NS memory.
382 */
383extern void *ns_read;
384extern void *ns_write;
385
386/*
387 * The new value of the PC when the GPF occurs on a registered location.
388 */
389extern void *ns_access_ret_0;
390
AlexeiFedorov53518ba2023-08-22 14:46:26 +0100391static struct rmm_trap_element rmm_trap_list[] = {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000392 RMM_TRAP_HANDLER(ns_read, ns_access_ret_0),
393 RMM_TRAP_HANDLER(ns_write, ns_access_ret_0),
394};
395#define RMM_TRAP_LIST_SIZE (sizeof(rmm_trap_list)/sizeof(struct rmm_trap_element))
396
AlexeiFedorov57f40fc2023-08-17 14:33:33 +0100397__dead2 static void fatal_abort(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000398{
399 report_unexpected();
400
AlexeiFedorov6c119692023-04-21 12:31:15 +0100401 while (true) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000402 wfe();
403 }
404}
405
406static bool is_el2_data_abort_gpf(unsigned long esr)
407{
AlexeiFedorov537bee02023-02-02 13:38:23 +0000408 if (((esr & MASK(ESR_EL2_EC)) == ESR_EL2_EC_DATA_ABORT_SEL) &&
AlexeiFedorov6c119692023-04-21 12:31:15 +0100409 ((esr & MASK(ESR_EL2_ABORT_FSC)) == ESR_EL2_ABORT_FSC_GPF)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000410 return true;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100411 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000412 return false;
413}
414
415/*
416 * Handles the RMM's aborts.
417 * It compares the PC at the time of the abort with the registered addresses.
418 * If it finds a match, it returns the new value of the PC that the RMM should
419 * continue from. Other register values are preserved.
420 * If no match is found, it aborts the RMM.
421 */
422unsigned long handle_rmm_trap(void)
423{
Soby Mathewb4c6df42022-11-09 11:13:29 +0000424 unsigned long esr = read_esr_el2();
425 unsigned long elr = read_elr_el2();
426
427 /*
428 * Only the GPF data aborts are recoverable.
429 */
430 if (!is_el2_data_abort_gpf(esr)) {
431 fatal_abort();
432 }
433
AlexeiFedorov6c119692023-04-21 12:31:15 +0100434 for (unsigned int i = 0U; i < RMM_TRAP_LIST_SIZE; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000435 if (rmm_trap_list[i].aborted_pc == elr) {
436 return rmm_trap_list[i].new_pc;
437 }
438 }
439
440 fatal_abort();
AlexeiFedorov6c119692023-04-21 12:31:15 +0100441 return 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000442}