blob: 1af375cf6215269771ec5be8407813ea21f6f172 [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 Ganapathy4f601e72023-05-22 11:49:29 +010011#include <run.h>
Arunachalam Ganapathy51119932023-03-23 12:32:49 +000012#include <simd.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000013#include <smc-handler.h>
14#include <smc-rmi.h>
15#include <smc.h>
16#include <status.h>
17#include <utils_def.h>
18
AlexeiFedorov6c119692023-04-21 12:31:15 +010019/* Maximum number of supported arguments */
AlexeiFedorov93f5ec52023-08-31 14:26:53 +010020#define MAX_NUM_ARGS 5U
Soby Mathewb4c6df42022-11-09 11:13:29 +000021
AlexeiFedorov6c119692023-04-21 12:31:15 +010022/* Maximum number of output values */
AlexeiFedorov93f5ec52023-08-31 14:26:53 +010023#define MAX_NUM_OUTPUT_VALS 4U
AlexeiFedorov6c119692023-04-21 12:31:15 +010024
25#define RMI_STATUS_STRING(_id)[RMI_##_id] = #_id
26
AlexeiFedorov04418f42023-09-13 10:50:33 +010027static const char * const rmi_status_string[] = {
AlexeiFedorov6c119692023-04-21 12:31:15 +010028 RMI_STATUS_STRING(SUCCESS),
29 RMI_STATUS_STRING(ERROR_INPUT),
30 RMI_STATUS_STRING(ERROR_REALM),
31 RMI_STATUS_STRING(ERROR_REC),
AlexeiFedorov892abce2023-04-06 16:32:12 +010032 RMI_STATUS_STRING(ERROR_RTT)
Soby Mathewb4c6df42022-11-09 11:13:29 +000033};
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010034
AlexeiFedorov6c119692023-04-21 12:31:15 +010035COMPILER_ASSERT(ARRAY_LEN(rmi_status_string) == RMI_ERROR_COUNT);
Soby Mathewb4c6df42022-11-09 11:13:29 +000036
37/*
38 * At this level (in handle_ns_smc) we distinguish the RMI calls only on:
AlexeiFedorov6c119692023-04-21 12:31:15 +010039 * - The number of input arguments [0..5], and whether
Soby Mathewb4c6df42022-11-09 11:13:29 +000040 * - The function returns up to three output values in addition
41 * to the return status code.
42 * Hence, the naming syntax is:
AlexeiFedorov6c119692023-04-21 12:31:15 +010043 * - `*_[0..5]` when no output values are returned, and
44 * - `*_[0..3]_o` when the function returns some output values.
Soby Mathewb4c6df42022-11-09 11:13:29 +000045 */
Soby Mathewb4c6df42022-11-09 11:13:29 +000046typedef unsigned long (*handler_0)(void);
47typedef unsigned long (*handler_1)(unsigned long arg0);
48typedef unsigned long (*handler_2)(unsigned long arg0, unsigned long arg1);
49typedef unsigned long (*handler_3)(unsigned long arg0, unsigned long arg1,
50 unsigned long arg2);
51typedef unsigned long (*handler_4)(unsigned long arg0, unsigned long arg1,
52 unsigned long arg2, unsigned long arg3);
53typedef unsigned long (*handler_5)(unsigned long arg0, unsigned long arg1,
54 unsigned long arg2, unsigned long arg3,
55 unsigned long arg4);
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010056typedef void (*handler_1_o)(unsigned long arg0, struct smc_result *res);
AlexeiFedorov892abce2023-04-06 16:32:12 +010057typedef void (*handler_2_o)(unsigned long arg0, unsigned long arg1,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010058 struct smc_result *res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000059typedef void (*handler_3_o)(unsigned long arg0, unsigned long arg1,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010060 unsigned long arg2, struct smc_result *res);
AlexeiFedorov892abce2023-04-06 16:32:12 +010061typedef void (*handler_4_o)(unsigned long arg0, unsigned long arg1,
62 unsigned long arg2, unsigned long arg3,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010063 struct smc_result *res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000064
AlexeiFedorov6c119692023-04-21 12:31:15 +010065/*
66 * SMC RMI handler type encoding:
67 * [0:7] - number of arguments
68 * [8:15] - number of output values
69 */
Chuyue Luod7386682023-09-22 11:55:47 +010070#define RMI_TYPE(_in, _out) ((_in) | ((_out) << 8))
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010071#define set_rmi_type(_in, _out) rmi_type_##_in##_out = RMI_TYPE(_in, _out)
AlexeiFedorov6c119692023-04-21 12:31:15 +010072
Soby Mathewb4c6df42022-11-09 11:13:29 +000073enum rmi_type {
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010074 set_rmi_type(0, 0), /* 0 arguments, 0 output values */
75 set_rmi_type(1, 0), /* 1 argument, 0 output values */
76 set_rmi_type(2, 0), /* 2 arguments, 0 output values */
77 set_rmi_type(3, 0), /* 3 arguments, 0 output values */
78 set_rmi_type(4, 0), /* 4 arguments, 0 output values */
79 set_rmi_type(5, 0), /* 5 arguments, 0 output values */
80 set_rmi_type(1, 1), /* 1 argument, 1 output value */
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +010081 set_rmi_type(1, 2), /* 1 argument, 2 output values */
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010082 set_rmi_type(2, 2), /* 2 arguments, 2 output values */
83 set_rmi_type(3, 1), /* 3 arguments, 1 output value */
84 set_rmi_type(3, 2), /* 3 arguments, 2 output values */
85 set_rmi_type(3, 4), /* 3 arguments, 4 output values */
86 set_rmi_type(4, 1) /* 4 arguments, 1 output value */
Soby Mathewb4c6df42022-11-09 11:13:29 +000087};
88
89struct smc_handler {
90 const char *fn_name;
91 enum rmi_type type;
92 union {
AlexeiFedorov6c119692023-04-21 12:31:15 +010093 handler_0 f_00;
94 handler_1 f_10;
95 handler_2 f_20;
96 handler_3 f_30;
97 handler_4 f_40;
98 handler_5 f_50;
99 handler_1_o f_11;
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +0100100 handler_1_o f_12;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100101 handler_2_o f_22;
102 handler_3_o f_31;
103 handler_3_o f_32;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100104 handler_3_o f_34;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100105 handler_4_o f_41;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000106 void *fn_dummy;
107 };
108 bool log_exec; /* print handler execution */
109 bool log_error; /* print in case of error status */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000110};
111
112/*
113 * Get handler ID from FID
114 * Precondition: FID is an RMI call
115 */
AlexeiFedorov6c119692023-04-21 12:31:15 +0100116#define RMI_HANDLER_ID(_id) SMC64_FID_OFFSET_FROM_RANGE_MIN(RMI, _id)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000117
AlexeiFedorov6c119692023-04-21 12:31:15 +0100118#define HANDLER(_id, _in, _out, _fn, _exec, _error)[RMI_HANDLER_ID(SMC_RMM_##_id)] = { \
Chuyue Luod7386682023-09-22 11:55:47 +0100119 .fn_name = (#_id), \
AlexeiFedorov6c119692023-04-21 12:31:15 +0100120 .type = RMI_TYPE(_in, _out), \
Chuyue Luod7386682023-09-22 11:55:47 +0100121 .f_##_in##_out = (_fn), \
122 .log_exec = (_exec), \
123 .log_error = (_error) \
AlexeiFedorov6c119692023-04-21 12:31:15 +0100124}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000125
126/*
127 * The 3rd value enables the execution log.
128 * The 4th value enables the error log.
129 */
130static const struct smc_handler smc_handlers[] = {
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +0100131 HANDLER(VERSION, 1, 2, smc_version, true, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100132 HANDLER(FEATURES, 1, 1, smc_read_feature_register, true, true),
133 HANDLER(GRANULE_DELEGATE, 1, 0, smc_granule_delegate, false, true),
134 HANDLER(GRANULE_UNDELEGATE, 1, 0, smc_granule_undelegate, false, true),
135 HANDLER(REALM_CREATE, 2, 0, smc_realm_create, true, true),
136 HANDLER(REALM_DESTROY, 1, 0, smc_realm_destroy, true, true),
137 HANDLER(REALM_ACTIVATE, 1, 0, smc_realm_activate, true, true),
138 HANDLER(REC_CREATE, 3, 0, smc_rec_create, true, true),
139 HANDLER(REC_DESTROY, 1, 0, smc_rec_destroy, true, true),
140 HANDLER(REC_ENTER, 2, 0, smc_rec_enter, false, true),
141 HANDLER(DATA_CREATE, 5, 0, smc_data_create, false, false),
142 HANDLER(DATA_CREATE_UNKNOWN, 3, 0, smc_data_create_unknown, false, false),
AlexeiFedorove2002be2023-04-19 17:20:12 +0100143 HANDLER(DATA_DESTROY, 2, 2, smc_data_destroy, false, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100144 HANDLER(RTT_CREATE, 4, 0, smc_rtt_create, false, true),
AlexeiFedorove2002be2023-04-19 17:20:12 +0100145 HANDLER(RTT_DESTROY, 3, 2, smc_rtt_destroy, false, true),
146 HANDLER(RTT_FOLD, 3, 1, smc_rtt_fold, false, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100147 HANDLER(RTT_MAP_UNPROTECTED, 4, 0, smc_rtt_map_unprotected, false, false),
AlexeiFedorov917eabf2023-04-24 12:20:41 +0100148 HANDLER(RTT_UNMAP_UNPROTECTED, 3, 1, smc_rtt_unmap_unprotected, false, false),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100149 HANDLER(RTT_READ_ENTRY, 3, 4, smc_rtt_read_entry, false, true),
AlexeiFedorov120d7d02023-08-02 16:51:48 +0100150 HANDLER(PSCI_COMPLETE, 3, 0, smc_psci_complete, true, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100151 HANDLER(REC_AUX_COUNT, 1, 1, smc_rec_aux_count, true, true),
AlexeiFedorov960d1612023-04-25 13:23:39 +0100152 HANDLER(RTT_INIT_RIPAS, 3, 1, smc_rtt_init_ripas, false, true),
AlexeiFedorov5cf35ba2023-04-25 10:02:20 +0100153 HANDLER(RTT_SET_RIPAS, 4, 1, smc_rtt_set_ripas, false, true)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000154};
155
156COMPILER_ASSERT(ARRAY_LEN(smc_handlers) == SMC64_NUM_FIDS_IN_RANGE(RMI));
157
158static bool rmi_call_log_enabled = true;
159
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100160static inline bool rmi_handler_needs_fpu(unsigned int id)
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000161{
162#ifdef RMM_FPU_USE_AT_REL2
163 if (id == SMC_RMM_REALM_CREATE || id == SMC_RMM_DATA_CREATE ||
164 id == SMC_RMM_REC_CREATE || id == SMC_RMM_RTT_INIT_RIPAS) {
165 return true;
166 }
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100167#else
168 (void)id;
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000169#endif
170 return false;
171}
172
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100173static void rmi_log_on_exit(unsigned int handler_id,
AlexeiFedorov6c119692023-04-21 12:31:15 +0100174 unsigned long args[],
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100175 struct smc_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000176{
177 const struct smc_handler *handler = &smc_handlers[handler_id];
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100178 unsigned int function_id = SMC64_RMI_FID(handler_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000179 return_code_t rc;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100180 unsigned int num;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000181
182 if (!handler->log_exec && !handler->log_error) {
183 return;
184 }
185
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100186 rc = unpack_return_code(res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000187
188 if ((handler->log_exec) ||
189 (handler->log_error && (rc.status != RMI_SUCCESS))) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100190 /* Print function name */
191 INFO("SMC_RMM_%-21s", handler->fn_name);
192
193 /* Print arguments */
AlexeiFedorov84cba4f2023-08-25 13:45:48 +0100194 num = (unsigned int)handler->type & 0xFFU;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100195 assert(num <= MAX_NUM_ARGS);
196
197 for (unsigned int i = 0U; i < num; i++) {
198 INFO(" %lx", args[i]);
199 }
200
201 /* Print status */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000202 if (rc.status >= RMI_ERROR_COUNT) {
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100203 INFO(" > %lx", res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000204 } else {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100205 INFO(" > RMI_%s", rmi_status_string[rc.status]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000206 }
207
208 /* Check for index */
209 if (((function_id == SMC_RMM_REC_ENTER) &&
210 (rc.status == RMI_ERROR_REALM)) ||
211 (rc.status == RMI_ERROR_RTT)) {
212 INFO(" %x", rc.index);
AlexeiFedorov697445b2023-04-25 15:27:57 +0100213 }
214
215 if ((rc.status == RMI_SUCCESS) ||
216 ((rc.status == RMI_ERROR_RTT) &&
217 ((function_id == SMC_RMM_RTT_DESTROY) ||
218 (function_id == SMC_RMM_DATA_DESTROY)))) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100219 /* Print output values */
AlexeiFedorov84cba4f2023-08-25 13:45:48 +0100220 num = ((unsigned int)handler->type >> 8) & 0xFFU;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100221 assert(num <= MAX_NUM_OUTPUT_VALS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000222
AlexeiFedorov6c119692023-04-21 12:31:15 +0100223 for (unsigned int i = 1U; i <= num; i++) {
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100224 INFO(" %lx", res->x[i]);
AlexeiFedorov6c119692023-04-21 12:31:15 +0100225 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000226 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000227 INFO("\n");
228 }
229}
230
AlexeiFedorovb0de4d52023-10-10 11:46:16 +0100231/* coverity[misra_c_2012_rule_8_7_violation:SUPPRESS] */
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100232void handle_ns_smc(unsigned int function_id,
Soby Mathewb4c6df42022-11-09 11:13:29 +0000233 unsigned long arg0,
234 unsigned long arg1,
235 unsigned long arg2,
236 unsigned long arg3,
237 unsigned long arg4,
238 unsigned long arg5,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100239 struct smc_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000240{
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100241 (void)arg5;
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100242 unsigned int handler_id;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000243 const struct smc_handler *handler = NULL;
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000244 bool restore_ns_simd_state = false;
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100245 struct simd_context *ns_simd_ctx;
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100246 bool sve_hint = false;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000247
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100248 /* Save the SVE hint bit and clear it from the function ID */
249 if ((function_id & SMC_SVE_HINT) != 0U) {
250 sve_hint = true;
251 function_id &= ~SMC_SVE_HINT;
252 }
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +0000253
Soby Mathewb4c6df42022-11-09 11:13:29 +0000254 if (IS_SMC64_RMI_FID(function_id)) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100255 handler_id = RMI_HANDLER_ID(function_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000256 if (handler_id < ARRAY_LEN(smc_handlers)) {
257 handler = &smc_handlers[handler_id];
258 }
259 }
260
261 /*
262 * Check if handler exists and 'fn_dummy' is not NULL
263 * for not implemented 'function_id' calls in SMC RMI range.
264 */
265 if ((handler == NULL) || (handler->fn_dummy == NULL)) {
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100266 VERBOSE("[%s] unknown function_id: %x\n",
Soby Mathewb4c6df42022-11-09 11:13:29 +0000267 __func__, function_id);
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100268 res->x[0] = SMC_UNKNOWN;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000269 return;
270 }
271
272 assert_cpu_slots_empty();
273
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000274 /* Current CPU's SIMD state must not be saved when entering RMM */
275 assert(simd_is_state_saved() == false);
276
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100277 /* Get current CPU's NS SIMD context */
278 ns_simd_ctx = get_cpu_ns_simd_context();
279
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100280 /* Set or clear SVE hint bit in the NS SIMD context */
281 simd_update_smc_sve_hint(ns_simd_ctx, sve_hint);
282
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000283 /* If the handler needs FPU, actively save NS simd context. */
284 if (rmi_handler_needs_fpu(function_id) == true) {
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100285 simd_context_save(ns_simd_ctx);
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000286 restore_ns_simd_state = true;
287 }
288
Soby Mathewb4c6df42022-11-09 11:13:29 +0000289 switch (handler->type) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100290 case rmi_type_00:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100291 res->x[0] = handler->f_00();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000292 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100293 case rmi_type_10:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100294 res->x[0] = handler->f_10(arg0);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000295 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100296 case rmi_type_20:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100297 res->x[0] = handler->f_20(arg0, arg1);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000298 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100299 case rmi_type_30:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100300 res->x[0] = handler->f_30(arg0, arg1, arg2);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000301 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100302 case rmi_type_40:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100303 res->x[0] = handler->f_40(arg0, arg1, arg2, arg3);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000304 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100305 case rmi_type_50:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100306 res->x[0] = handler->f_50(arg0, arg1, arg2, arg3, arg4);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000307 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100308 case rmi_type_11:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100309 handler->f_11(arg0, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000310 break;
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +0100311 case rmi_type_12:
312 handler->f_12(arg0, res);
313 break;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100314 case rmi_type_22:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100315 handler->f_22(arg0, arg1, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100316 break;
317 case rmi_type_31:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100318 handler->f_31(arg0, arg1, arg2, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100319 break;
320 case rmi_type_32:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100321 handler->f_32(arg0, arg1, arg2, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100322 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100323 case rmi_type_34:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100324 handler->f_34(arg0, arg1, arg2, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000325 break;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100326 case rmi_type_41:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100327 handler->f_41(arg0, arg1, arg2, arg3, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100328 break;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000329 default:
330 assert(false);
331 }
332
333 if (rmi_call_log_enabled) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100334 unsigned long args[] = {arg0, arg1, arg2, arg3, arg4};
335
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100336 rmi_log_on_exit(handler_id, args, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000337 }
338
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100339 /* If the handler uses FPU, restore the saved NS simd context. */
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000340 if (restore_ns_simd_state) {
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100341 simd_context_restore(ns_simd_ctx);
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000342 }
343
344 /* Current CPU's SIMD state must not be saved when exiting RMM */
345 assert(simd_is_state_saved() == false);
346
Soby Mathewb4c6df42022-11-09 11:13:29 +0000347 assert_cpu_slots_empty();
348}
349
350static void report_unexpected(void)
351{
352 unsigned long spsr = read_spsr_el2();
353 unsigned long esr = read_esr_el2();
354 unsigned long elr = read_elr_el2();
355 unsigned long far = read_far_el2();
356
357 INFO("----\n");
358 INFO("Unexpected exception:\n");
359 INFO("SPSR_EL2: 0x%016lx\n", spsr);
360 INFO("ESR_EL2: 0x%016lx\n", esr);
361 INFO("ELR_EL2: 0x%016lx\n", elr);
362 INFO("FAR_EL2: 0x%016lx\n", far);
363 INFO("----\n");
Soby Mathewb4c6df42022-11-09 11:13:29 +0000364}
365
AlexeiFedorov57f40fc2023-08-17 14:33:33 +0100366__dead2 unsigned long handle_realm_trap(unsigned long *regs)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000367{
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100368 (void)regs;
369
Soby Mathewb4c6df42022-11-09 11:13:29 +0000370 report_unexpected();
371
AlexeiFedorov6c119692023-04-21 12:31:15 +0100372 while (true) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000373 wfe();
374 }
375}
376
377/*
378 * Identifies an abort that the RMM may recover from.
379 */
380struct rmm_trap_element {
381 /*
382 * The PC at the time of abort.
383 */
384 unsigned long aborted_pc;
385 /*
386 * New value of the PC.
387 */
388 unsigned long new_pc;
389};
390
391#define RMM_TRAP_HANDLER(_aborted_pc, _new_pc) \
Chuyue Luod7386682023-09-22 11:55:47 +0100392 { .aborted_pc = (unsigned long)(&(_aborted_pc)), \
393 .new_pc = (unsigned long)(&(_new_pc)) }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000394
395/*
396 * The registered locations of load/store instructions that access NS memory.
397 */
398extern void *ns_read;
399extern void *ns_write;
400
401/*
402 * The new value of the PC when the GPF occurs on a registered location.
403 */
404extern void *ns_access_ret_0;
405
AlexeiFedorov53518ba2023-08-22 14:46:26 +0100406static struct rmm_trap_element rmm_trap_list[] = {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000407 RMM_TRAP_HANDLER(ns_read, ns_access_ret_0),
408 RMM_TRAP_HANDLER(ns_write, ns_access_ret_0),
409};
410#define RMM_TRAP_LIST_SIZE (sizeof(rmm_trap_list)/sizeof(struct rmm_trap_element))
411
AlexeiFedorov57f40fc2023-08-17 14:33:33 +0100412__dead2 static void fatal_abort(void)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000413{
414 report_unexpected();
415
AlexeiFedorov6c119692023-04-21 12:31:15 +0100416 while (true) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000417 wfe();
418 }
419}
420
421static bool is_el2_data_abort_gpf(unsigned long esr)
422{
AlexeiFedorov537bee02023-02-02 13:38:23 +0000423 if (((esr & MASK(ESR_EL2_EC)) == ESR_EL2_EC_DATA_ABORT_SEL) &&
AlexeiFedorov6c119692023-04-21 12:31:15 +0100424 ((esr & MASK(ESR_EL2_ABORT_FSC)) == ESR_EL2_ABORT_FSC_GPF)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000425 return true;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100426 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000427 return false;
428}
429
430/*
431 * Handles the RMM's aborts.
432 * It compares the PC at the time of the abort with the registered addresses.
433 * If it finds a match, it returns the new value of the PC that the RMM should
434 * continue from. Other register values are preserved.
435 * If no match is found, it aborts the RMM.
436 */
437unsigned long handle_rmm_trap(void)
438{
Soby Mathewb4c6df42022-11-09 11:13:29 +0000439 unsigned long esr = read_esr_el2();
440 unsigned long elr = read_elr_el2();
441
442 /*
443 * Only the GPF data aborts are recoverable.
444 */
445 if (!is_el2_data_abort_gpf(esr)) {
446 fatal_abort();
447 }
448
AlexeiFedorov6c119692023-04-21 12:31:15 +0100449 for (unsigned int i = 0U; i < RMM_TRAP_LIST_SIZE; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000450 if (rmm_trap_list[i].aborted_pc == elr) {
451 return rmm_trap_list[i].new_pc;
452 }
453 }
454
455 fatal_abort();
AlexeiFedorov6c119692023-04-21 12:31:15 +0100456 return 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000457}