blob: 93e9927ca1cde6b83abd60ebbcaeb6d640c36dea [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
18#define STATUS_HANDLER(_id)[_id] = #_id
19
20const char *status_handler[] = {
21 STATUS_HANDLER(RMI_SUCCESS),
22 STATUS_HANDLER(RMI_ERROR_INPUT),
23 STATUS_HANDLER(RMI_ERROR_REALM),
24 STATUS_HANDLER(RMI_ERROR_REC),
25 STATUS_HANDLER(RMI_ERROR_RTT),
26 STATUS_HANDLER(RMI_ERROR_IN_USE)
27};
28COMPILER_ASSERT(ARRAY_LEN(status_handler) == RMI_ERROR_COUNT);
29
30/*
31 * At this level (in handle_ns_smc) we distinguish the RMI calls only on:
32 * - The number of input arguments [0..4], and whether
33 * - The function returns up to three output values in addition
34 * to the return status code.
35 * Hence, the naming syntax is:
36 * - `*_[0..4]` when no output values are returned, and
37 * - `*_[0..4]_o` when the function returns some output values.
38 */
39
40typedef unsigned long (*handler_0)(void);
41typedef unsigned long (*handler_1)(unsigned long arg0);
42typedef unsigned long (*handler_2)(unsigned long arg0, unsigned long arg1);
43typedef unsigned long (*handler_3)(unsigned long arg0, unsigned long arg1,
44 unsigned long arg2);
45typedef unsigned long (*handler_4)(unsigned long arg0, unsigned long arg1,
46 unsigned long arg2, unsigned long arg3);
47typedef unsigned long (*handler_5)(unsigned long arg0, unsigned long arg1,
48 unsigned long arg2, unsigned long arg3,
49 unsigned long arg4);
50typedef void (*handler_1_o)(unsigned long arg0, struct smc_result *ret);
51typedef void (*handler_3_o)(unsigned long arg0, unsigned long arg1,
52 unsigned long arg2, struct smc_result *ret);
53
54enum rmi_type {
55 rmi_type_0,
56 rmi_type_1,
57 rmi_type_2,
58 rmi_type_3,
59 rmi_type_4,
60 rmi_type_5,
61 rmi_type_1_o,
62 rmi_type_3_o
63};
64
65struct smc_handler {
66 const char *fn_name;
67 enum rmi_type type;
68 union {
69 handler_0 f0;
70 handler_1 f1;
71 handler_2 f2;
72 handler_3 f3;
73 handler_4 f4;
74 handler_5 f5;
75 handler_1_o f1_o;
76 handler_3_o f3_o;
77 void *fn_dummy;
78 };
79 bool log_exec; /* print handler execution */
80 bool log_error; /* print in case of error status */
81 unsigned int out_values; /* number of output values */
82};
83
84/*
85 * Get handler ID from FID
86 * Precondition: FID is an RMI call
87 */
88#define SMC_RMI_HANDLER_ID(_fid) SMC64_FID_OFFSET_FROM_RANGE_MIN(RMI, _fid)
89
90#define HANDLER_0(_id, _fn, _exec, _error)[SMC_RMI_HANDLER_ID(_id)] = { \
91 .fn_name = #_id, \
92 .type = rmi_type_0, .f0 = _fn, .log_exec = _exec, .log_error = _error, \
93 .out_values = 0U }
94#define HANDLER_1(_id, _fn, _exec, _error)[SMC_RMI_HANDLER_ID(_id)] = { \
95 .fn_name = #_id, \
96 .type = rmi_type_1, .f1 = _fn, .log_exec = _exec, .log_error = _error, \
97 .out_values = 0U }
98#define HANDLER_2(_id, _fn, _exec, _error)[SMC_RMI_HANDLER_ID(_id)] = { \
99 .fn_name = #_id, \
100 .type = rmi_type_2, .f2 = _fn, .log_exec = _exec, .log_error = _error, \
101 .out_values = 0U }
102#define HANDLER_3(_id, _fn, _exec, _error)[SMC_RMI_HANDLER_ID(_id)] = { \
103 .fn_name = #_id, \
104 .type = rmi_type_3, .f3 = _fn, .log_exec = _exec, .log_error = _error, \
105 .out_values = 0U }
106#define HANDLER_4(_id, _fn, _exec, _error)[SMC_RMI_HANDLER_ID(_id)] = { \
107 .fn_name = #_id, \
108 .type = rmi_type_4, .f4 = _fn, .log_exec = _exec, .log_error = _error, \
109 .out_values = 0U }
110#define HANDLER_5(_id, _fn, _exec, _error)[SMC_RMI_HANDLER_ID(_id)] = { \
111 .fn_name = #_id, \
112 .type = rmi_type_5, .f5 = _fn, .log_exec = _exec, .log_error = _error, \
113 .out_values = 0U }
114#define HANDLER_1_O(_id, _fn, _exec, _error, _values)[SMC_RMI_HANDLER_ID(_id)] = { \
115 .fn_name = #_id, \
116 .type = rmi_type_1_o, .f1_o = _fn, .log_exec = _exec, .log_error = _error, \
117 .out_values = _values }
118#define HANDLER_3_O(_id, _fn, _exec, _error, _values)[SMC_RMI_HANDLER_ID(_id)] = { \
119 .fn_name = #_id, \
120 .type = rmi_type_3_o, .f3_o = _fn, .log_exec = _exec, .log_error = _error, \
121 .out_values = _values }
122
123/*
124 * The 3rd value enables the execution log.
125 * The 4th value enables the error log.
126 */
127static const struct smc_handler smc_handlers[] = {
128 HANDLER_0(SMC_RMM_VERSION, smc_version, true, true),
129 HANDLER_1_O(SMC_RMM_FEATURES, smc_read_feature_register, true, true, 1U),
130 HANDLER_1(SMC_RMM_GRANULE_DELEGATE, smc_granule_delegate, false, true),
131 HANDLER_1(SMC_RMM_GRANULE_UNDELEGATE, smc_granule_undelegate, false, true),
132 HANDLER_2(SMC_RMM_REALM_CREATE, smc_realm_create, true, true),
133 HANDLER_1(SMC_RMM_REALM_DESTROY, smc_realm_destroy, true, true),
134 HANDLER_1(SMC_RMM_REALM_ACTIVATE, smc_realm_activate, true, true),
135 HANDLER_3(SMC_RMM_REC_CREATE, smc_rec_create, true, true),
136 HANDLER_1(SMC_RMM_REC_DESTROY, smc_rec_destroy, true, true),
137 HANDLER_2(SMC_RMM_REC_ENTER, smc_rec_enter, false, true),
138 HANDLER_5(SMC_RMM_DATA_CREATE, smc_data_create, false, false),
139 HANDLER_3(SMC_RMM_DATA_CREATE_UNKNOWN, smc_data_create_unknown, false, false),
140 HANDLER_2(SMC_RMM_DATA_DESTROY, smc_data_destroy, false, true),
141 HANDLER_4(SMC_RMM_RTT_CREATE, smc_rtt_create, false, true),
142 HANDLER_4(SMC_RMM_RTT_DESTROY, smc_rtt_destroy, false, true),
143 HANDLER_4(SMC_RMM_RTT_FOLD, smc_rtt_fold, false, true),
144 HANDLER_4(SMC_RMM_RTT_MAP_UNPROTECTED, smc_rtt_map_unprotected, false, false),
145 HANDLER_3(SMC_RMM_RTT_UNMAP_UNPROTECTED, smc_rtt_unmap_unprotected, false, false),
146 HANDLER_3_O(SMC_RMM_RTT_READ_ENTRY, smc_rtt_read_entry, false, true, 4U),
147 HANDLER_2(SMC_RMM_PSCI_COMPLETE, smc_psci_complete, true, true),
148 HANDLER_1_O(SMC_RMM_REC_AUX_COUNT, smc_rec_aux_count, true, true, 1U),
149 HANDLER_3(SMC_RMM_RTT_INIT_RIPAS, smc_rtt_init_ripas, false, true),
150 HANDLER_5(SMC_RMM_RTT_SET_RIPAS, smc_rtt_set_ripas, false, true)
151};
152
153COMPILER_ASSERT(ARRAY_LEN(smc_handlers) == SMC64_NUM_FIDS_IN_RANGE(RMI));
154
155static bool rmi_call_log_enabled = true;
156
157static void rmi_log_on_exit(unsigned long handler_id,
158 unsigned long arg0,
159 unsigned long arg1,
160 unsigned long arg2,
161 unsigned long arg3,
162 unsigned long arg4,
163 struct smc_result *ret)
164{
165 const struct smc_handler *handler = &smc_handlers[handler_id];
166 unsigned long function_id = SMC64_RMI_FID(handler_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000167 return_code_t rc;
168
169 if (!handler->log_exec && !handler->log_error) {
170 return;
171 }
172
173 if (function_id == SMC_RMM_VERSION) {
174 /*
175 * RMM_VERSION is special because it returns the
176 * version number, not the error code.
177 */
178 INFO("%-29s %8lx %8lx %8lx %8lx %8lx > %lx\n",
179 handler->fn_name, arg0, arg1, arg2, arg3, arg4,
180 ret->x[0]);
181 return;
182 }
183
184 rc = unpack_return_code(ret->x[0]);
185
186 if ((handler->log_exec) ||
187 (handler->log_error && (rc.status != RMI_SUCCESS))) {
188 INFO("%-29s %8lx %8lx %8lx %8lx %8lx > ",
189 handler->fn_name, arg0, arg1, arg2, arg3, arg4);
190 if (rc.status >= RMI_ERROR_COUNT) {
191 INFO("%lx", ret->x[0]);
192 } else {
193 INFO("%s", status_handler[rc.status]);
194 }
195
196 /* Check for index */
197 if (((function_id == SMC_RMM_REC_ENTER) &&
198 (rc.status == RMI_ERROR_REALM)) ||
199 (rc.status == RMI_ERROR_RTT)) {
200 INFO(" %x", rc.index);
201 }
202
203 /* Print output values */
Shruti Gupta9debb132022-12-13 14:38:49 +0000204 for (unsigned int i = 1U; i <= handler->out_values; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000205 INFO(" %8lx", ret->x[i]);
206 }
207
208 INFO("\n");
209 }
210}
211
212void handle_ns_smc(unsigned long function_id,
213 unsigned long arg0,
214 unsigned long arg1,
215 unsigned long arg2,
216 unsigned long arg3,
217 unsigned long arg4,
218 unsigned long arg5,
219 struct smc_result *ret)
220{
221 unsigned long handler_id;
222 const struct smc_handler *handler = NULL;
223
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +0000224 /* Ignore SVE hint bit, until RMM supports SVE hint bit */
225 function_id &= ~MASK(SMC_SVE_HINT);
226
Soby Mathewb4c6df42022-11-09 11:13:29 +0000227 if (IS_SMC64_RMI_FID(function_id)) {
228 handler_id = SMC_RMI_HANDLER_ID(function_id);
229 if (handler_id < ARRAY_LEN(smc_handlers)) {
230 handler = &smc_handlers[handler_id];
231 }
232 }
233
234 /*
235 * Check if handler exists and 'fn_dummy' is not NULL
236 * for not implemented 'function_id' calls in SMC RMI range.
237 */
238 if ((handler == NULL) || (handler->fn_dummy == NULL)) {
239 VERBOSE("[%s] unknown function_id: %lx\n",
240 __func__, function_id);
241 ret->x[0] = SMC_UNKNOWN;
242 return;
243 }
244
245 assert_cpu_slots_empty();
246
247 switch (handler->type) {
248 case rmi_type_0:
249 ret->x[0] = handler->f0();
250 break;
251 case rmi_type_1:
252 ret->x[0] = handler->f1(arg0);
253 break;
254 case rmi_type_2:
255 ret->x[0] = handler->f2(arg0, arg1);
256 break;
257 case rmi_type_3:
258 ret->x[0] = handler->f3(arg0, arg1, arg2);
259 break;
260 case rmi_type_4:
261 ret->x[0] = handler->f4(arg0, arg1, arg2, arg3);
262 break;
263 case rmi_type_5:
264 ret->x[0] = handler->f5(arg0, arg1, arg2, arg3, arg4);
265 break;
266 case rmi_type_1_o:
267 handler->f1_o(arg0, ret);
268 break;
269 case rmi_type_3_o:
270 handler->f3_o(arg0, arg1, arg2, ret);
271 break;
272 default:
273 assert(false);
274 }
275
276 if (rmi_call_log_enabled) {
277 rmi_log_on_exit(handler_id, arg0, arg1, arg2, arg3, arg4, ret);
278 }
279
280 assert_cpu_slots_empty();
281}
282
283static void report_unexpected(void)
284{
285 unsigned long spsr = read_spsr_el2();
286 unsigned long esr = read_esr_el2();
287 unsigned long elr = read_elr_el2();
288 unsigned long far = read_far_el2();
289
290 INFO("----\n");
291 INFO("Unexpected exception:\n");
292 INFO("SPSR_EL2: 0x%016lx\n", spsr);
293 INFO("ESR_EL2: 0x%016lx\n", esr);
294 INFO("ELR_EL2: 0x%016lx\n", elr);
295 INFO("FAR_EL2: 0x%016lx\n", far);
296 INFO("----\n");
297
298}
299
300unsigned long handle_realm_trap(unsigned long *regs)
301{
302 report_unexpected();
303
304 while (1) {
305 wfe();
306 }
307}
308
309/*
310 * Identifies an abort that the RMM may recover from.
311 */
312struct rmm_trap_element {
313 /*
314 * The PC at the time of abort.
315 */
316 unsigned long aborted_pc;
317 /*
318 * New value of the PC.
319 */
320 unsigned long new_pc;
321};
322
323#define RMM_TRAP_HANDLER(_aborted_pc, _new_pc) \
324 { .aborted_pc = (unsigned long)(&_aborted_pc), \
325 .new_pc = (unsigned long)(&_new_pc) }
326
327/*
328 * The registered locations of load/store instructions that access NS memory.
329 */
330extern void *ns_read;
331extern void *ns_write;
332
333/*
334 * The new value of the PC when the GPF occurs on a registered location.
335 */
336extern void *ns_access_ret_0;
337
338struct rmm_trap_element rmm_trap_list[] = {
339 RMM_TRAP_HANDLER(ns_read, ns_access_ret_0),
340 RMM_TRAP_HANDLER(ns_write, ns_access_ret_0),
341};
342#define RMM_TRAP_LIST_SIZE (sizeof(rmm_trap_list)/sizeof(struct rmm_trap_element))
343
344static void fatal_abort(void)
345{
346 report_unexpected();
347
348 while (1) {
349 wfe();
350 }
351}
352
353static bool is_el2_data_abort_gpf(unsigned long esr)
354{
AlexeiFedorov537bee02023-02-02 13:38:23 +0000355 if (((esr & MASK(ESR_EL2_EC)) == ESR_EL2_EC_DATA_ABORT_SEL) &&
356 ((esr & MASK(ESR_EL2_ABORT_FSC)) == ESR_EL2_ABORT_FSC_GPF))
Soby Mathewb4c6df42022-11-09 11:13:29 +0000357 return true;
358 return false;
359}
360
361/*
362 * Handles the RMM's aborts.
363 * It compares the PC at the time of the abort with the registered addresses.
364 * If it finds a match, it returns the new value of the PC that the RMM should
365 * continue from. Other register values are preserved.
366 * If no match is found, it aborts the RMM.
367 */
368unsigned long handle_rmm_trap(void)
369{
370 int i;
371
372 unsigned long esr = read_esr_el2();
373 unsigned long elr = read_elr_el2();
374
375 /*
376 * Only the GPF data aborts are recoverable.
377 */
378 if (!is_el2_data_abort_gpf(esr)) {
379 fatal_abort();
380 }
381
382 for (i = 0; i < RMM_TRAP_LIST_SIZE; i++) {
383 if (rmm_trap_list[i].aborted_pc == elr) {
384 return rmm_trap_list[i].new_pc;
385 }
386 }
387
388 fatal_abort();
389 return 0;
390}