blob: b7f3a55e233147d461b98ec8754170236db6dc57 [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);
167 unsigned int i;
168 return_code_t rc;
169
170 if (!handler->log_exec && !handler->log_error) {
171 return;
172 }
173
174 if (function_id == SMC_RMM_VERSION) {
175 /*
176 * RMM_VERSION is special because it returns the
177 * version number, not the error code.
178 */
179 INFO("%-29s %8lx %8lx %8lx %8lx %8lx > %lx\n",
180 handler->fn_name, arg0, arg1, arg2, arg3, arg4,
181 ret->x[0]);
182 return;
183 }
184
185 rc = unpack_return_code(ret->x[0]);
186
187 if ((handler->log_exec) ||
188 (handler->log_error && (rc.status != RMI_SUCCESS))) {
189 INFO("%-29s %8lx %8lx %8lx %8lx %8lx > ",
190 handler->fn_name, arg0, arg1, arg2, arg3, arg4);
191 if (rc.status >= RMI_ERROR_COUNT) {
192 INFO("%lx", ret->x[0]);
193 } else {
194 INFO("%s", status_handler[rc.status]);
195 }
196
197 /* Check for index */
198 if (((function_id == SMC_RMM_REC_ENTER) &&
199 (rc.status == RMI_ERROR_REALM)) ||
200 (rc.status == RMI_ERROR_RTT)) {
201 INFO(" %x", rc.index);
202 }
203
204 /* Print output values */
205 for (i = 1U; i <= handler->out_values; i++) {
206 INFO(" %8lx", ret->x[i]);
207 }
208
209 INFO("\n");
210 }
211}
212
213void handle_ns_smc(unsigned long function_id,
214 unsigned long arg0,
215 unsigned long arg1,
216 unsigned long arg2,
217 unsigned long arg3,
218 unsigned long arg4,
219 unsigned long arg5,
220 struct smc_result *ret)
221{
222 unsigned long handler_id;
223 const struct smc_handler *handler = NULL;
224
225 if (IS_SMC64_RMI_FID(function_id)) {
226 handler_id = SMC_RMI_HANDLER_ID(function_id);
227 if (handler_id < ARRAY_LEN(smc_handlers)) {
228 handler = &smc_handlers[handler_id];
229 }
230 }
231
232 /*
233 * Check if handler exists and 'fn_dummy' is not NULL
234 * for not implemented 'function_id' calls in SMC RMI range.
235 */
236 if ((handler == NULL) || (handler->fn_dummy == NULL)) {
237 VERBOSE("[%s] unknown function_id: %lx\n",
238 __func__, function_id);
239 ret->x[0] = SMC_UNKNOWN;
240 return;
241 }
242
243 assert_cpu_slots_empty();
244
245 switch (handler->type) {
246 case rmi_type_0:
247 ret->x[0] = handler->f0();
248 break;
249 case rmi_type_1:
250 ret->x[0] = handler->f1(arg0);
251 break;
252 case rmi_type_2:
253 ret->x[0] = handler->f2(arg0, arg1);
254 break;
255 case rmi_type_3:
256 ret->x[0] = handler->f3(arg0, arg1, arg2);
257 break;
258 case rmi_type_4:
259 ret->x[0] = handler->f4(arg0, arg1, arg2, arg3);
260 break;
261 case rmi_type_5:
262 ret->x[0] = handler->f5(arg0, arg1, arg2, arg3, arg4);
263 break;
264 case rmi_type_1_o:
265 handler->f1_o(arg0, ret);
266 break;
267 case rmi_type_3_o:
268 handler->f3_o(arg0, arg1, arg2, ret);
269 break;
270 default:
271 assert(false);
272 }
273
274 if (rmi_call_log_enabled) {
275 rmi_log_on_exit(handler_id, arg0, arg1, arg2, arg3, arg4, ret);
276 }
277
278 assert_cpu_slots_empty();
279}
280
281static void report_unexpected(void)
282{
283 unsigned long spsr = read_spsr_el2();
284 unsigned long esr = read_esr_el2();
285 unsigned long elr = read_elr_el2();
286 unsigned long far = read_far_el2();
287
288 INFO("----\n");
289 INFO("Unexpected exception:\n");
290 INFO("SPSR_EL2: 0x%016lx\n", spsr);
291 INFO("ESR_EL2: 0x%016lx\n", esr);
292 INFO("ELR_EL2: 0x%016lx\n", elr);
293 INFO("FAR_EL2: 0x%016lx\n", far);
294 INFO("----\n");
295
296}
297
298unsigned long handle_realm_trap(unsigned long *regs)
299{
300 report_unexpected();
301
302 while (1) {
303 wfe();
304 }
305}
306
307/*
308 * Identifies an abort that the RMM may recover from.
309 */
310struct rmm_trap_element {
311 /*
312 * The PC at the time of abort.
313 */
314 unsigned long aborted_pc;
315 /*
316 * New value of the PC.
317 */
318 unsigned long new_pc;
319};
320
321#define RMM_TRAP_HANDLER(_aborted_pc, _new_pc) \
322 { .aborted_pc = (unsigned long)(&_aborted_pc), \
323 .new_pc = (unsigned long)(&_new_pc) }
324
325/*
326 * The registered locations of load/store instructions that access NS memory.
327 */
328extern void *ns_read;
329extern void *ns_write;
330
331/*
332 * The new value of the PC when the GPF occurs on a registered location.
333 */
334extern void *ns_access_ret_0;
335
336struct rmm_trap_element rmm_trap_list[] = {
337 RMM_TRAP_HANDLER(ns_read, ns_access_ret_0),
338 RMM_TRAP_HANDLER(ns_write, ns_access_ret_0),
339};
340#define RMM_TRAP_LIST_SIZE (sizeof(rmm_trap_list)/sizeof(struct rmm_trap_element))
341
342static void fatal_abort(void)
343{
344 report_unexpected();
345
346 while (1) {
347 wfe();
348 }
349}
350
351static bool is_el2_data_abort_gpf(unsigned long esr)
352{
353 if (((esr & ESR_EL2_EC_MASK) == ESR_EL2_EC_DATA_ABORT_SEL) &&
354 ((esr & ESR_EL2_ABORT_FSC_MASK) == ESR_EL2_ABORT_FSC_GPF))
355 return true;
356 return false;
357}
358
359/*
360 * Handles the RMM's aborts.
361 * It compares the PC at the time of the abort with the registered addresses.
362 * If it finds a match, it returns the new value of the PC that the RMM should
363 * continue from. Other register values are preserved.
364 * If no match is found, it aborts the RMM.
365 */
366unsigned long handle_rmm_trap(void)
367{
368 int i;
369
370 unsigned long esr = read_esr_el2();
371 unsigned long elr = read_elr_el2();
372
373 /*
374 * Only the GPF data aborts are recoverable.
375 */
376 if (!is_el2_data_abort_gpf(esr)) {
377 fatal_abort();
378 }
379
380 for (i = 0; i < RMM_TRAP_LIST_SIZE; i++) {
381 if (rmm_trap_list[i].aborted_pc == elr) {
382 return rmm_trap_list[i].new_pc;
383 }
384 }
385
386 fatal_abort();
387 return 0;
388}