blob: 77c15170359b8590c9b13fb6ccbbd043683c0ce7 [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>
11#include <sizes.h>
12#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 */
19#define MAX_NUM_ARGS 5
Soby Mathewb4c6df42022-11-09 11:13:29 +000020
AlexeiFedorov6c119692023-04-21 12:31:15 +010021/* Maximum number of output values */
22#define MAX_NUM_OUTPUT_VALS 4
23
24#define RMI_STATUS_STRING(_id)[RMI_##_id] = #_id
25
26const char *rmi_status_string[] = {
27 RMI_STATUS_STRING(SUCCESS),
28 RMI_STATUS_STRING(ERROR_INPUT),
29 RMI_STATUS_STRING(ERROR_REALM),
30 RMI_STATUS_STRING(ERROR_REC),
31 RMI_STATUS_STRING(ERROR_RTT),
32 RMI_STATUS_STRING(ERROR_IN_USE)
Soby Mathewb4c6df42022-11-09 11:13:29 +000033};
AlexeiFedorov6c119692023-04-21 12:31:15 +010034COMPILER_ASSERT(ARRAY_LEN(rmi_status_string) == RMI_ERROR_COUNT);
Soby Mathewb4c6df42022-11-09 11:13:29 +000035
36/*
37 * At this level (in handle_ns_smc) we distinguish the RMI calls only on:
AlexeiFedorov6c119692023-04-21 12:31:15 +010038 * - The number of input arguments [0..5], and whether
Soby Mathewb4c6df42022-11-09 11:13:29 +000039 * - The function returns up to three output values in addition
40 * to the return status code.
41 * Hence, the naming syntax is:
AlexeiFedorov6c119692023-04-21 12:31:15 +010042 * - `*_[0..5]` when no output values are returned, and
43 * - `*_[0..3]_o` when the function returns some output values.
Soby Mathewb4c6df42022-11-09 11:13:29 +000044 */
Soby Mathewb4c6df42022-11-09 11:13:29 +000045typedef unsigned long (*handler_0)(void);
46typedef unsigned long (*handler_1)(unsigned long arg0);
47typedef unsigned long (*handler_2)(unsigned long arg0, unsigned long arg1);
48typedef unsigned long (*handler_3)(unsigned long arg0, unsigned long arg1,
49 unsigned long arg2);
50typedef unsigned long (*handler_4)(unsigned long arg0, unsigned long arg1,
51 unsigned long arg2, unsigned long arg3);
52typedef unsigned long (*handler_5)(unsigned long arg0, unsigned long arg1,
53 unsigned long arg2, unsigned long arg3,
54 unsigned long arg4);
55typedef void (*handler_1_o)(unsigned long arg0, struct smc_result *ret);
56typedef void (*handler_3_o)(unsigned long arg0, unsigned long arg1,
57 unsigned long arg2, struct smc_result *ret);
58
AlexeiFedorov6c119692023-04-21 12:31:15 +010059/*
60 * SMC RMI handler type encoding:
61 * [0:7] - number of arguments
62 * [8:15] - number of output values
63 */
64#define RMI_TYPE(_in, _out) (_in | (_out << 8))
65#define rmi_type(_in, _out) rmi_type_##_in##_out = RMI_TYPE(_in, _out)
66
Soby Mathewb4c6df42022-11-09 11:13:29 +000067enum rmi_type {
AlexeiFedorov6c119692023-04-21 12:31:15 +010068 rmi_type(0, 0), /* 0 arguments, 0 output values */
69 rmi_type(1, 0), /* 1 argument, 0 output values */
70 rmi_type(2, 0), /* 2 arguments, 0 output values */
71 rmi_type(3, 0), /* 3 arguments, 0 output values */
72 rmi_type(4, 0), /* 4 arguments, 0 output values */
73 rmi_type(5, 0), /* 5 arguments, 0 output values */
74 rmi_type(1, 1), /* 1 argument, 1 output value */
75 rmi_type(3, 4) /* 3 arguments, 4 output values */
Soby Mathewb4c6df42022-11-09 11:13:29 +000076};
77
78struct smc_handler {
79 const char *fn_name;
80 enum rmi_type type;
81 union {
AlexeiFedorov6c119692023-04-21 12:31:15 +010082 handler_0 f_00;
83 handler_1 f_10;
84 handler_2 f_20;
85 handler_3 f_30;
86 handler_4 f_40;
87 handler_5 f_50;
88 handler_1_o f_11;
89 handler_3_o f_34;
Soby Mathewb4c6df42022-11-09 11:13:29 +000090 void *fn_dummy;
91 };
92 bool log_exec; /* print handler execution */
93 bool log_error; /* print in case of error status */
Soby Mathewb4c6df42022-11-09 11:13:29 +000094};
95
96/*
97 * Get handler ID from FID
98 * Precondition: FID is an RMI call
99 */
AlexeiFedorov6c119692023-04-21 12:31:15 +0100100#define RMI_HANDLER_ID(_id) SMC64_FID_OFFSET_FROM_RANGE_MIN(RMI, _id)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000101
AlexeiFedorov6c119692023-04-21 12:31:15 +0100102#define HANDLER(_id, _in, _out, _fn, _exec, _error)[RMI_HANDLER_ID(SMC_RMM_##_id)] = { \
103 .fn_name = #_id, \
104 .type = RMI_TYPE(_in, _out), \
105 .f_##_in##_out = _fn, \
106 .log_exec = _exec, \
107 .log_error = _error \
108}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000109
110/*
111 * The 3rd value enables the execution log.
112 * The 4th value enables the error log.
113 */
114static const struct smc_handler smc_handlers[] = {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100115 HANDLER(VERSION, 0, 0, smc_version, true, true),
116 HANDLER(FEATURES, 1, 1, smc_read_feature_register, true, true),
117 HANDLER(GRANULE_DELEGATE, 1, 0, smc_granule_delegate, false, true),
118 HANDLER(GRANULE_UNDELEGATE, 1, 0, smc_granule_undelegate, false, true),
119 HANDLER(REALM_CREATE, 2, 0, smc_realm_create, true, true),
120 HANDLER(REALM_DESTROY, 1, 0, smc_realm_destroy, true, true),
121 HANDLER(REALM_ACTIVATE, 1, 0, smc_realm_activate, true, true),
122 HANDLER(REC_CREATE, 3, 0, smc_rec_create, true, true),
123 HANDLER(REC_DESTROY, 1, 0, smc_rec_destroy, true, true),
124 HANDLER(REC_ENTER, 2, 0, smc_rec_enter, false, true),
125 HANDLER(DATA_CREATE, 5, 0, smc_data_create, false, false),
126 HANDLER(DATA_CREATE_UNKNOWN, 3, 0, smc_data_create_unknown, false, false),
127 HANDLER(DATA_DESTROY, 2, 0, smc_data_destroy, false, true),
128 HANDLER(RTT_CREATE, 4, 0, smc_rtt_create, false, true),
129 HANDLER(RTT_DESTROY, 4, 0, smc_rtt_destroy, false, true),
130 HANDLER(RTT_FOLD, 4, 0, smc_rtt_fold, false, true),
131 HANDLER(RTT_MAP_UNPROTECTED, 4, 0, smc_rtt_map_unprotected, false, false),
132 HANDLER(RTT_UNMAP_UNPROTECTED, 3, 0, smc_rtt_unmap_unprotected, false, false),
133 HANDLER(RTT_READ_ENTRY, 3, 4, smc_rtt_read_entry, false, true),
134 HANDLER(PSCI_COMPLETE, 2, 0, smc_psci_complete, true, true),
135 HANDLER(REC_AUX_COUNT, 1, 1, smc_rec_aux_count, true, true),
136 HANDLER(RTT_INIT_RIPAS, 3, 0, smc_rtt_init_ripas, false, true),
137 HANDLER(RTT_SET_RIPAS, 5, 0, smc_rtt_set_ripas, false, true)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000138};
139
140COMPILER_ASSERT(ARRAY_LEN(smc_handlers) == SMC64_NUM_FIDS_IN_RANGE(RMI));
141
142static bool rmi_call_log_enabled = true;
143
144static void rmi_log_on_exit(unsigned long handler_id,
AlexeiFedorov6c119692023-04-21 12:31:15 +0100145 unsigned long args[],
Soby Mathewb4c6df42022-11-09 11:13:29 +0000146 struct smc_result *ret)
147{
148 const struct smc_handler *handler = &smc_handlers[handler_id];
149 unsigned long function_id = SMC64_RMI_FID(handler_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000150 return_code_t rc;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100151 unsigned int num;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000152
153 if (!handler->log_exec && !handler->log_error) {
154 return;
155 }
156
157 if (function_id == SMC_RMM_VERSION) {
158 /*
159 * RMM_VERSION is special because it returns the
160 * version number, not the error code.
161 */
AlexeiFedorov6c119692023-04-21 12:31:15 +0100162 INFO("SMC_RMM_%-21s > %lx\n", handler->fn_name, ret->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000163 return;
164 }
165
166 rc = unpack_return_code(ret->x[0]);
167
168 if ((handler->log_exec) ||
169 (handler->log_error && (rc.status != RMI_SUCCESS))) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100170 /* Print function name */
171 INFO("SMC_RMM_%-21s", handler->fn_name);
172
173 /* Print arguments */
174 num = handler->type & 0xFF;
175 assert(num <= MAX_NUM_ARGS);
176
177 for (unsigned int i = 0U; i < num; i++) {
178 INFO(" %lx", args[i]);
179 }
180
181 /* Print status */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000182 if (rc.status >= RMI_ERROR_COUNT) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100183 INFO(" > %lx", ret->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000184 } else {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100185 INFO(" > RMI_%s", rmi_status_string[rc.status]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000186 }
187
188 /* Check for index */
189 if (((function_id == SMC_RMM_REC_ENTER) &&
190 (rc.status == RMI_ERROR_REALM)) ||
191 (rc.status == RMI_ERROR_RTT)) {
192 INFO(" %x", rc.index);
AlexeiFedorov6c119692023-04-21 12:31:15 +0100193 } else if (rc.status == RMI_SUCCESS) {
194 /* Print output values */
195 num = (handler->type >> 8) & 0xFF;
196 assert(num <= MAX_NUM_OUTPUT_VALS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000197
AlexeiFedorov6c119692023-04-21 12:31:15 +0100198 for (unsigned int i = 1U; i <= num; i++) {
199 INFO(" %lx", ret->x[i]);
200 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000201 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000202 INFO("\n");
203 }
204}
205
206void handle_ns_smc(unsigned long function_id,
207 unsigned long arg0,
208 unsigned long arg1,
209 unsigned long arg2,
210 unsigned long arg3,
211 unsigned long arg4,
212 unsigned long arg5,
213 struct smc_result *ret)
214{
215 unsigned long handler_id;
216 const struct smc_handler *handler = NULL;
217
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +0000218 /* Ignore SVE hint bit, until RMM supports SVE hint bit */
219 function_id &= ~MASK(SMC_SVE_HINT);
220
Soby Mathewb4c6df42022-11-09 11:13:29 +0000221 if (IS_SMC64_RMI_FID(function_id)) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100222 handler_id = RMI_HANDLER_ID(function_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000223 if (handler_id < ARRAY_LEN(smc_handlers)) {
224 handler = &smc_handlers[handler_id];
225 }
226 }
227
228 /*
229 * Check if handler exists and 'fn_dummy' is not NULL
230 * for not implemented 'function_id' calls in SMC RMI range.
231 */
232 if ((handler == NULL) || (handler->fn_dummy == NULL)) {
233 VERBOSE("[%s] unknown function_id: %lx\n",
234 __func__, function_id);
235 ret->x[0] = SMC_UNKNOWN;
236 return;
237 }
238
239 assert_cpu_slots_empty();
240
241 switch (handler->type) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100242 case rmi_type_00:
243 ret->x[0] = handler->f_00();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000244 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100245 case rmi_type_10:
246 ret->x[0] = handler->f_10(arg0);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000247 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100248 case rmi_type_20:
249 ret->x[0] = handler->f_20(arg0, arg1);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000250 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100251 case rmi_type_30:
252 ret->x[0] = handler->f_30(arg0, arg1, arg2);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000253 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100254 case rmi_type_40:
255 ret->x[0] = handler->f_40(arg0, arg1, arg2, arg3);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000256 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100257 case rmi_type_50:
258 ret->x[0] = handler->f_50(arg0, arg1, arg2, arg3, arg4);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000259 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100260 case rmi_type_11:
261 handler->f_11(arg0, ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000262 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100263 case rmi_type_34:
264 handler->f_34(arg0, arg1, arg2, ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000265 break;
266 default:
267 assert(false);
268 }
269
270 if (rmi_call_log_enabled) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100271 unsigned long args[] = {arg0, arg1, arg2, arg3, arg4};
272
273 rmi_log_on_exit(handler_id, args, ret);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000274 }
275
276 assert_cpu_slots_empty();
277}
278
279static void report_unexpected(void)
280{
281 unsigned long spsr = read_spsr_el2();
282 unsigned long esr = read_esr_el2();
283 unsigned long elr = read_elr_el2();
284 unsigned long far = read_far_el2();
285
286 INFO("----\n");
287 INFO("Unexpected exception:\n");
288 INFO("SPSR_EL2: 0x%016lx\n", spsr);
289 INFO("ESR_EL2: 0x%016lx\n", esr);
290 INFO("ELR_EL2: 0x%016lx\n", elr);
291 INFO("FAR_EL2: 0x%016lx\n", far);
292 INFO("----\n");
Soby Mathewb4c6df42022-11-09 11:13:29 +0000293}
294
295unsigned long handle_realm_trap(unsigned long *regs)
296{
297 report_unexpected();
298
AlexeiFedorov6c119692023-04-21 12:31:15 +0100299 while (true) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000300 wfe();
301 }
302}
303
304/*
305 * Identifies an abort that the RMM may recover from.
306 */
307struct rmm_trap_element {
308 /*
309 * The PC at the time of abort.
310 */
311 unsigned long aborted_pc;
312 /*
313 * New value of the PC.
314 */
315 unsigned long new_pc;
316};
317
318#define RMM_TRAP_HANDLER(_aborted_pc, _new_pc) \
319 { .aborted_pc = (unsigned long)(&_aborted_pc), \
320 .new_pc = (unsigned long)(&_new_pc) }
321
322/*
323 * The registered locations of load/store instructions that access NS memory.
324 */
325extern void *ns_read;
326extern void *ns_write;
327
328/*
329 * The new value of the PC when the GPF occurs on a registered location.
330 */
331extern void *ns_access_ret_0;
332
333struct rmm_trap_element rmm_trap_list[] = {
334 RMM_TRAP_HANDLER(ns_read, ns_access_ret_0),
335 RMM_TRAP_HANDLER(ns_write, ns_access_ret_0),
336};
337#define RMM_TRAP_LIST_SIZE (sizeof(rmm_trap_list)/sizeof(struct rmm_trap_element))
338
339static void fatal_abort(void)
340{
341 report_unexpected();
342
AlexeiFedorov6c119692023-04-21 12:31:15 +0100343 while (true) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000344 wfe();
345 }
346}
347
348static bool is_el2_data_abort_gpf(unsigned long esr)
349{
AlexeiFedorov537bee02023-02-02 13:38:23 +0000350 if (((esr & MASK(ESR_EL2_EC)) == ESR_EL2_EC_DATA_ABORT_SEL) &&
AlexeiFedorov6c119692023-04-21 12:31:15 +0100351 ((esr & MASK(ESR_EL2_ABORT_FSC)) == ESR_EL2_ABORT_FSC_GPF)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000352 return true;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100353 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000354 return false;
355}
356
357/*
358 * Handles the RMM's aborts.
359 * It compares the PC at the time of the abort with the registered addresses.
360 * If it finds a match, it returns the new value of the PC that the RMM should
361 * continue from. Other register values are preserved.
362 * If no match is found, it aborts the RMM.
363 */
364unsigned long handle_rmm_trap(void)
365{
Soby Mathewb4c6df42022-11-09 11:13:29 +0000366 unsigned long esr = read_esr_el2();
367 unsigned long elr = read_elr_el2();
368
369 /*
370 * Only the GPF data aborts are recoverable.
371 */
372 if (!is_el2_data_abort_gpf(esr)) {
373 fatal_abort();
374 }
375
AlexeiFedorov6c119692023-04-21 12:31:15 +0100376 for (unsigned int i = 0U; i < RMM_TRAP_LIST_SIZE; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000377 if (rmm_trap_list[i].aborted_pc == elr) {
378 return rmm_trap_list[i].new_pc;
379 }
380 }
381
382 fatal_abort();
AlexeiFedorov6c119692023-04-21 12:31:15 +0100383 return 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000384}