blob: 2684d8919a7b2677d9e0ccb25194297964f5f9ba [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>
AlexeiFedorov4c7d4852024-01-25 14:37:34 +000010#include <cpuid.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000011#include <debug.h>
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +010012#include <run.h>
Arunachalam Ganapathy51119932023-03-23 12:32:49 +000013#include <simd.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000014#include <smc-handler.h>
15#include <smc-rmi.h>
16#include <smc.h>
17#include <status.h>
18#include <utils_def.h>
AlexeiFedorov4c7d4852024-01-25 14:37:34 +000019#include <xlat_high_va.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +000020
AlexeiFedorov6c119692023-04-21 12:31:15 +010021/* Maximum number of supported arguments */
AlexeiFedorov93f5ec52023-08-31 14:26:53 +010022#define MAX_NUM_ARGS 5U
Soby Mathewb4c6df42022-11-09 11:13:29 +000023
AlexeiFedorov6c119692023-04-21 12:31:15 +010024/* Maximum number of output values */
AlexeiFedorov93f5ec52023-08-31 14:26:53 +010025#define MAX_NUM_OUTPUT_VALS 4U
AlexeiFedorov6c119692023-04-21 12:31:15 +010026
27#define RMI_STATUS_STRING(_id)[RMI_##_id] = #_id
28
AlexeiFedorov04418f42023-09-13 10:50:33 +010029static const char * const rmi_status_string[] = {
AlexeiFedorov6c119692023-04-21 12:31:15 +010030 RMI_STATUS_STRING(SUCCESS),
31 RMI_STATUS_STRING(ERROR_INPUT),
32 RMI_STATUS_STRING(ERROR_REALM),
33 RMI_STATUS_STRING(ERROR_REC),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +010034 RMI_STATUS_STRING(ERROR_RTT),
35 RMI_STATUS_STRING(ERROR_DEVICE),
36 RMI_STATUS_STRING(ERROR_NOT_SUPPORTED),
37 RMI_STATUS_STRING(ERROR_RTT_AUX)
Soby Mathewb4c6df42022-11-09 11:13:29 +000038};
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010039
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +010040COMPILER_ASSERT(ARRAY_SIZE(rmi_status_string) == RMI_ERROR_COUNT_MAX);
Soby Mathewb4c6df42022-11-09 11:13:29 +000041
42/*
43 * At this level (in handle_ns_smc) we distinguish the RMI calls only on:
AlexeiFedorov6c119692023-04-21 12:31:15 +010044 * - The number of input arguments [0..5], and whether
Soby Mathewb4c6df42022-11-09 11:13:29 +000045 * - The function returns up to three output values in addition
46 * to the return status code.
47 * Hence, the naming syntax is:
AlexeiFedorov6c119692023-04-21 12:31:15 +010048 * - `*_[0..5]` when no output values are returned, and
49 * - `*_[0..3]_o` when the function returns some output values.
Soby Mathewb4c6df42022-11-09 11:13:29 +000050 */
Soby Mathewb4c6df42022-11-09 11:13:29 +000051typedef unsigned long (*handler_0)(void);
52typedef unsigned long (*handler_1)(unsigned long arg0);
53typedef unsigned long (*handler_2)(unsigned long arg0, unsigned long arg1);
54typedef unsigned long (*handler_3)(unsigned long arg0, unsigned long arg1,
55 unsigned long arg2);
56typedef unsigned long (*handler_4)(unsigned long arg0, unsigned long arg1,
57 unsigned long arg2, unsigned long arg3);
58typedef unsigned long (*handler_5)(unsigned long arg0, unsigned long arg1,
59 unsigned long arg2, unsigned long arg3,
60 unsigned long arg4);
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010061typedef void (*handler_1_o)(unsigned long arg0, struct smc_result *res);
AlexeiFedorov892abce2023-04-06 16:32:12 +010062typedef void (*handler_2_o)(unsigned long arg0, unsigned long arg1,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010063 struct smc_result *res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000064typedef void (*handler_3_o)(unsigned long arg0, unsigned long arg1,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010065 unsigned long arg2, struct smc_result *res);
AlexeiFedorov892abce2023-04-06 16:32:12 +010066typedef void (*handler_4_o)(unsigned long arg0, unsigned long arg1,
67 unsigned long arg2, unsigned long arg3,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +010068 struct smc_result *res);
Soby Mathewb4c6df42022-11-09 11:13:29 +000069
AlexeiFedorov6c119692023-04-21 12:31:15 +010070/*
71 * SMC RMI handler type encoding:
72 * [0:7] - number of arguments
73 * [8:15] - number of output values
74 */
Shruti Gupta9e966b82024-03-21 13:45:24 +000075#define RMI_TYPE(_in, _out) (U(_in) | (U(_out) << 8U))
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010076#define set_rmi_type(_in, _out) rmi_type_##_in##_out = RMI_TYPE(_in, _out)
AlexeiFedorov6c119692023-04-21 12:31:15 +010077
Soby Mathewb4c6df42022-11-09 11:13:29 +000078enum rmi_type {
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010079 set_rmi_type(0, 0), /* 0 arguments, 0 output values */
80 set_rmi_type(1, 0), /* 1 argument, 0 output values */
81 set_rmi_type(2, 0), /* 2 arguments, 0 output values */
82 set_rmi_type(3, 0), /* 3 arguments, 0 output values */
83 set_rmi_type(4, 0), /* 4 arguments, 0 output values */
84 set_rmi_type(5, 0), /* 5 arguments, 0 output values */
85 set_rmi_type(1, 1), /* 1 argument, 1 output value */
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +010086 set_rmi_type(1, 2), /* 1 argument, 2 output values */
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +010087 set_rmi_type(2, 2), /* 2 arguments, 2 output values */
88 set_rmi_type(3, 1), /* 3 arguments, 1 output value */
89 set_rmi_type(3, 2), /* 3 arguments, 2 output values */
90 set_rmi_type(3, 4), /* 3 arguments, 4 output values */
91 set_rmi_type(4, 1) /* 4 arguments, 1 output value */
Soby Mathewb4c6df42022-11-09 11:13:29 +000092};
93
94struct smc_handler {
95 const char *fn_name;
Soby Mathewb4c6df42022-11-09 11:13:29 +000096 union {
AlexeiFedorov6c119692023-04-21 12:31:15 +010097 handler_0 f_00;
98 handler_1 f_10;
99 handler_2 f_20;
100 handler_3 f_30;
101 handler_4 f_40;
102 handler_5 f_50;
103 handler_1_o f_11;
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +0100104 handler_1_o f_12;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100105 handler_2_o f_22;
106 handler_3_o f_31;
107 handler_3_o f_32;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100108 handler_3_o f_34;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100109 handler_4_o f_41;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000110 void *fn_dummy;
111 };
Chuyue Luo819aa312023-11-03 10:41:27 +0000112 enum rmi_type type;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000113 bool log_exec; /* print handler execution */
114 bool log_error; /* print in case of error status */
Soby Mathewb4c6df42022-11-09 11:13:29 +0000115};
116
117/*
118 * Get handler ID from FID
119 * Precondition: FID is an RMI call
120 */
AlexeiFedorov6c119692023-04-21 12:31:15 +0100121#define RMI_HANDLER_ID(_id) SMC64_FID_OFFSET_FROM_RANGE_MIN(RMI, _id)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000122
Arunachalam Ganapathy807dda82024-05-03 14:22:43 +0100123#define HANDLER(_id, _in, _out, _fn, _exec, _error)[RMI_HANDLER_ID(SMC_RMI_##_id)] = { \
AlexeiFedorov6a4314e2023-10-20 15:40:14 +0100124 .fn_name = (#_id), \
125 .type = (enum rmi_type)RMI_TYPE(_in, _out), \
126 .f_##_in##_out = (_fn), \
127 .log_exec = (_exec), \
128 .log_error = (_error) \
AlexeiFedorov6c119692023-04-21 12:31:15 +0100129}
Soby Mathewb4c6df42022-11-09 11:13:29 +0000130
131/*
132 * The 3rd value enables the execution log.
133 * The 4th value enables the error log.
134 */
135static const struct smc_handler smc_handlers[] = {
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +0100136 HANDLER(VERSION, 1, 2, smc_version, true, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100137 HANDLER(GRANULE_DELEGATE, 1, 0, smc_granule_delegate, false, true),
138 HANDLER(GRANULE_UNDELEGATE, 1, 0, smc_granule_undelegate, false, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100139 HANDLER(DATA_CREATE, 5, 0, smc_data_create, false, false),
140 HANDLER(DATA_CREATE_UNKNOWN, 3, 0, smc_data_create_unknown, false, false),
AlexeiFedorove2002be2023-04-19 17:20:12 +0100141 HANDLER(DATA_DESTROY, 2, 2, smc_data_destroy, false, true),
Arunachalam Ganapathy8f6f6262024-10-10 11:42:00 +0100142 HANDLER(PDEV_AUX_COUNT, 1, 1, smc_pdev_aux_count, true, true),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100143 HANDLER(REALM_ACTIVATE, 1, 0, smc_realm_activate, true, true),
144 HANDLER(REALM_CREATE, 2, 0, smc_realm_create, true, true),
145 HANDLER(REALM_DESTROY, 1, 0, smc_realm_destroy, true, true),
146 HANDLER(REC_CREATE, 3, 0, smc_rec_create, true, true),
147 HANDLER(REC_DESTROY, 1, 0, smc_rec_destroy, true, true),
148 HANDLER(REC_ENTER, 2, 0, smc_rec_enter, false, true),
AlexeiFedorov5db2aaa2024-08-07 11:16:15 +0100149 HANDLER(RTT_CREATE, 4, 0, smc_rtt_create, false, true),
150 HANDLER(RTT_DESTROY, 3, 2, smc_rtt_destroy, false, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100151 HANDLER(RTT_MAP_UNPROTECTED, 4, 0, smc_rtt_map_unprotected, false, false),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100152 HANDLER(VDEV_AUX_COUNT, 0, 0, NULL, true, true),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100153 HANDLER(RTT_READ_ENTRY, 3, 4, smc_rtt_read_entry, false, true),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100154 HANDLER(RTT_UNMAP_UNPROTECTED, 3, 1, smc_rtt_unmap_unprotected, false, false),
Arunachalam Ganapathycf718fb2024-11-28 16:03:11 +0000155 HANDLER(RTT_DEV_MEM_VALIDATE, 4, 1, NULL, false, true),
AlexeiFedorov120d7d02023-08-02 16:51:48 +0100156 HANDLER(PSCI_COMPLETE, 3, 0, smc_psci_complete, true, true),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100157 HANDLER(FEATURES, 1, 1, smc_read_feature_register, true, true),
158 HANDLER(RTT_FOLD, 3, 1, smc_rtt_fold, false, false),
AlexeiFedorov6c119692023-04-21 12:31:15 +0100159 HANDLER(REC_AUX_COUNT, 1, 1, smc_rec_aux_count, true, true),
AlexeiFedorov960d1612023-04-25 13:23:39 +0100160 HANDLER(RTT_INIT_RIPAS, 3, 1, smc_rtt_init_ripas, false, true),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100161 HANDLER(RTT_SET_RIPAS, 4, 1, smc_rtt_set_ripas, false, true),
AlexeiFedorovd2e93932025-01-13 17:24:37 +0000162 HANDLER(DEV_MEM_MAP, 4, 0, smc_dev_mem_map, false, true),
163 HANDLER(DEV_MEM_UNMAP, 3, 2, smc_dev_mem_unmap, false, true),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100164 HANDLER(PDEV_ABORT, 0, 0, NULL, true, true),
165 HANDLER(PDEV_COMMUNICATE, 2, 0, NULL, true, true),
Soby Mathewe7cf1822025-04-24 07:51:33 +0100166 HANDLER(PDEV_CREATE, 2, 0, smc_pdev_create, true, true),
Arunachalam Ganapathydb98da62024-10-09 12:06:57 +0100167 HANDLER(PDEV_DESTROY, 1, 0, smc_pdev_destroy, true, true),
Arunachalam Ganapathy294d1022024-07-17 12:31:26 +0100168 HANDLER(PDEV_GET_STATE, 1, 1, smc_pdev_get_state, true, true),
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100169 HANDLER(PDEV_IDE_RESET, 0, 0, NULL, true, true),
170 HANDLER(PDEV_NOTIFY, 0, 0, NULL, true, true),
171 HANDLER(PDEV_SET_PUBKEY, 4, 0, NULL, true, true),
172 HANDLER(PDEV_STOP, 0, 0, NULL, true, true),
173 HANDLER(RTT_AUX_CREATE, 0, 0, NULL, true, true),
174 HANDLER(RTT_AUX_DESTROY, 0, 0, NULL, true, true),
175 HANDLER(RTT_AUX_FOLD, 0, 0, NULL, true, true),
176 HANDLER(RTT_AUX_MAP_PROTECTED, 0, 0, NULL, true, true),
177 HANDLER(RTT_AUX_MAP_UNPROTECTED, 0, 0, NULL, true, true),
178 HANDLER(RTT_AUX_UNMAP_PROTECTED, 0, 0, NULL, true, true),
179 HANDLER(RTT_AUX_UNMAP_UNPROTECTED, 0, 0, NULL, true, true),
180 HANDLER(VDEV_ABORT, 0, 0, NULL, true, true),
181 HANDLER(VDEV_COMMUNICATE, 0, 0, NULL, true, true),
182 HANDLER(VDEV_CREATE, 0, 0, NULL, true, true),
183 HANDLER(VDEV_DESTROY, 0, 0, NULL, true, true),
184 HANDLER(VDEV_GET_STATE, 0, 0, NULL, true, true),
185 HANDLER(VDEV_STOP, 0, 0, NULL, true, true),
186 HANDLER(RTT_SET_S2AP, 0, 0, NULL, true, true),
187 HANDLER(MEC_SET_SHARED, 0, 0, NULL, true, true),
188 HANDLER(MEC_SET_PRIVATE, 0, 0, NULL, true, true),
189 HANDLER(VDEV_COMPLETE, 0, 0, NULL, true, true)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000190};
191
Soby Mathew1ceb0082024-10-10 17:22:38 +0100192COMPILER_ASSERT(ARRAY_SIZE(smc_handlers) == SMC64_NUM_FIDS_IN_RANGE(RMI));
Soby Mathewb4c6df42022-11-09 11:13:29 +0000193
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100194static inline bool rmi_handler_needs_fpu(unsigned int id)
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000195{
196#ifdef RMM_FPU_USE_AT_REL2
Arunachalam Ganapathy807dda82024-05-03 14:22:43 +0100197 if ((id == SMC_RMI_REALM_CREATE) || (id == SMC_RMI_DATA_CREATE) ||
198 (id == SMC_RMI_REC_CREATE) || (id == SMC_RMI_RTT_INIT_RIPAS)) {
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000199 return true;
200 }
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100201#else
202 (void)id;
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000203#endif
204 return false;
205}
206
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100207static void rmi_log_on_exit(unsigned int handler_id,
AlexeiFedorov6c119692023-04-21 12:31:15 +0100208 unsigned long args[],
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100209 struct smc_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000210{
211 const struct smc_handler *handler = &smc_handlers[handler_id];
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100212 unsigned int function_id = SMC64_RMI_FID(handler_id);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000213 return_code_t rc;
214
215 if (!handler->log_exec && !handler->log_error) {
216 return;
217 }
218
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100219 rc = unpack_return_code(res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000220
221 if ((handler->log_exec) ||
222 (handler->log_error && (rc.status != RMI_SUCCESS))) {
Shruti Gupta9e966b82024-03-21 13:45:24 +0000223 unsigned int num;
224
AlexeiFedorovd416f142025-05-15 13:53:30 +0100225 /*
226 * Print function name.
227 * RSI handler function SMC_RSI_RDEV_GET_INTERFACE_REPORT has
228 * maximum name length of 33 chars excluding the null terminator.
229 */
230 INFO("SMC_RMI_%-25s", handler->fn_name);
AlexeiFedorov6c119692023-04-21 12:31:15 +0100231
232 /* Print arguments */
AlexeiFedorov84cba4f2023-08-25 13:45:48 +0100233 num = (unsigned int)handler->type & 0xFFU;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100234 assert(num <= MAX_NUM_ARGS);
235
236 for (unsigned int i = 0U; i < num; i++) {
237 INFO(" %lx", args[i]);
238 }
239
240 /* Print status */
Arunachalam Ganapathyf36187e2024-05-07 11:49:33 +0100241 if (rc.status >= RMI_ERROR_COUNT_MAX) {
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100242 INFO(" > %lx", res->x[0]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000243 } else {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100244 INFO(" > RMI_%s", rmi_status_string[rc.status]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000245 }
246
247 /* Check for index */
Arunachalam Ganapathy807dda82024-05-03 14:22:43 +0100248 if (((function_id == SMC_RMI_REC_ENTER) &&
Soby Mathewb4c6df42022-11-09 11:13:29 +0000249 (rc.status == RMI_ERROR_REALM)) ||
250 (rc.status == RMI_ERROR_RTT)) {
251 INFO(" %x", rc.index);
AlexeiFedorov697445b2023-04-25 15:27:57 +0100252 }
253
254 if ((rc.status == RMI_SUCCESS) ||
255 ((rc.status == RMI_ERROR_RTT) &&
AlexeiFedorov33c1db72024-08-05 11:42:25 +0100256 ((function_id == SMC_RMI_RTT_DESTROY) ||
257 (function_id == SMC_RMI_DATA_DESTROY) ||
258 (function_id == SMC_RMI_RTT_UNMAP_UNPROTECTED)))) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100259 /* Print output values */
AlexeiFedorov84cba4f2023-08-25 13:45:48 +0100260 num = ((unsigned int)handler->type >> 8) & 0xFFU;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100261 assert(num <= MAX_NUM_OUTPUT_VALS);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000262
AlexeiFedorov6c119692023-04-21 12:31:15 +0100263 for (unsigned int i = 1U; i <= num; i++) {
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100264 INFO(" %lx", res->x[i]);
AlexeiFedorov6c119692023-04-21 12:31:15 +0100265 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000266 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000267 INFO("\n");
268 }
269}
270
Shruti Gupta0a0d4ee2024-04-22 21:37:25 +0100271/* cppcheck-suppress misra-c2012-8.4 */
AlexeiFedorovee2fc822023-10-31 14:54:39 +0000272/* coverity[misra_c_2012_rule_8_4_violation:SUPPRESS] */
AlexeiFedorovb0de4d52023-10-10 11:46:16 +0100273/* coverity[misra_c_2012_rule_8_7_violation:SUPPRESS] */
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100274void handle_ns_smc(unsigned int function_id,
Soby Mathewb4c6df42022-11-09 11:13:29 +0000275 unsigned long arg0,
276 unsigned long arg1,
277 unsigned long arg2,
278 unsigned long arg3,
279 unsigned long arg4,
280 unsigned long arg5,
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100281 struct smc_result *res)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000282{
AlexeiFedorov56e1a8e2023-09-01 17:06:13 +0100283 (void)arg5;
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100284 unsigned int handler_id;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000285 const struct smc_handler *handler = NULL;
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000286 bool restore_ns_simd_state = false;
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100287 struct simd_context *ns_simd_ctx;
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100288 bool sve_hint = false;
AlexeiFedorov7c38ef42023-11-28 11:39:19 +0000289 unsigned long args[] __unused = {arg0, arg1, arg2, arg3, arg4};
Soby Mathewb4c6df42022-11-09 11:13:29 +0000290
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100291 /* Save the SVE hint bit and clear it from the function ID */
292 if ((function_id & SMC_SVE_HINT) != 0U) {
293 sve_hint = true;
294 function_id &= ~SMC_SVE_HINT;
295 }
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +0000296
Soby Mathewb4c6df42022-11-09 11:13:29 +0000297 if (IS_SMC64_RMI_FID(function_id)) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100298 handler_id = RMI_HANDLER_ID(function_id);
Shruti Gupta0a0d4ee2024-04-22 21:37:25 +0100299 /* cppcheck-suppress misra-c2012-17.3 */
Soby Mathew1ceb0082024-10-10 17:22:38 +0100300 if (handler_id < ARRAY_SIZE(smc_handlers)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000301 handler = &smc_handlers[handler_id];
302 }
303 }
304
305 /*
306 * Check if handler exists and 'fn_dummy' is not NULL
307 * for not implemented 'function_id' calls in SMC RMI range.
308 */
309 if ((handler == NULL) || (handler->fn_dummy == NULL)) {
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100310 VERBOSE("[%s] unknown function_id: %x\n",
Soby Mathewb4c6df42022-11-09 11:13:29 +0000311 __func__, function_id);
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100312 res->x[0] = SMC_UNKNOWN;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000313 return;
314 }
315
AlexeiFedorov7c38ef42023-11-28 11:39:19 +0000316 assert(check_cpu_slots_empty());
Soby Mathewb4c6df42022-11-09 11:13:29 +0000317
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000318 /* Current CPU's SIMD state must not be saved when entering RMM */
319 assert(simd_is_state_saved() == false);
320
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100321 /* Get current CPU's NS SIMD context */
322 ns_simd_ctx = get_cpu_ns_simd_context();
323
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +0100324 /* Set or clear SVE hint bit in the NS SIMD context */
325 simd_update_smc_sve_hint(ns_simd_ctx, sve_hint);
326
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000327 /* If the handler needs FPU, actively save NS simd context. */
328 if (rmi_handler_needs_fpu(function_id) == true) {
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100329 simd_context_save(ns_simd_ctx);
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000330 restore_ns_simd_state = true;
331 }
332
Soby Mathewb4c6df42022-11-09 11:13:29 +0000333 switch (handler->type) {
AlexeiFedorov6c119692023-04-21 12:31:15 +0100334 case rmi_type_00:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100335 res->x[0] = handler->f_00();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000336 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100337 case rmi_type_10:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100338 res->x[0] = handler->f_10(arg0);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000339 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100340 case rmi_type_20:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100341 res->x[0] = handler->f_20(arg0, arg1);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000342 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100343 case rmi_type_30:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100344 res->x[0] = handler->f_30(arg0, arg1, arg2);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000345 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100346 case rmi_type_40:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100347 res->x[0] = handler->f_40(arg0, arg1, arg2, arg3);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000348 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100349 case rmi_type_50:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100350 res->x[0] = handler->f_50(arg0, arg1, arg2, arg3, arg4);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000351 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100352 case rmi_type_11:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100353 handler->f_11(arg0, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000354 break;
AlexeiFedorov2cc6cee2023-10-09 16:19:05 +0100355 case rmi_type_12:
356 handler->f_12(arg0, res);
357 break;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100358 case rmi_type_22:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100359 handler->f_22(arg0, arg1, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100360 break;
361 case rmi_type_31:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100362 handler->f_31(arg0, arg1, arg2, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100363 break;
364 case rmi_type_32:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100365 handler->f_32(arg0, arg1, arg2, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100366 break;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100367 case rmi_type_34:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100368 handler->f_34(arg0, arg1, arg2, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000369 break;
AlexeiFedorov892abce2023-04-06 16:32:12 +0100370 case rmi_type_41:
AlexeiFedorovccce3ad2023-04-28 18:29:47 +0100371 handler->f_41(arg0, arg1, arg2, arg3, res);
AlexeiFedorov892abce2023-04-06 16:32:12 +0100372 break;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000373 default:
374 assert(false);
375 }
376
AlexeiFedorov7c38ef42023-11-28 11:39:19 +0000377 rmi_log_on_exit(handler_id, args, res);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000378
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100379 /* If the handler uses FPU, restore the saved NS simd context. */
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000380 if (restore_ns_simd_state) {
Arunachalam Ganapathy4f601e72023-05-22 11:49:29 +0100381 simd_context_restore(ns_simd_ctx);
Arunachalam Ganapathy51119932023-03-23 12:32:49 +0000382 }
383
384 /* Current CPU's SIMD state must not be saved when exiting RMM */
385 assert(simd_is_state_saved() == false);
AlexeiFedorov7c38ef42023-11-28 11:39:19 +0000386 assert(check_cpu_slots_empty());
Soby Mathewb4c6df42022-11-09 11:13:29 +0000387}
388
Soby Mathewb4c6df42022-11-09 11:13:29 +0000389/*
390 * Identifies an abort that the RMM may recover from.
391 */
392struct rmm_trap_element {
393 /*
394 * The PC at the time of abort.
395 */
396 unsigned long aborted_pc;
397 /*
398 * New value of the PC.
399 */
400 unsigned long new_pc;
401};
402
403#define RMM_TRAP_HANDLER(_aborted_pc, _new_pc) \
Chuyue Luod7386682023-09-22 11:55:47 +0100404 { .aborted_pc = (unsigned long)(&(_aborted_pc)), \
405 .new_pc = (unsigned long)(&(_new_pc)) }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000406
407/*
408 * The registered locations of load/store instructions that access NS memory.
409 */
410extern void *ns_read;
411extern void *ns_write;
412
413/*
414 * The new value of the PC when the GPF occurs on a registered location.
415 */
416extern void *ns_access_ret_0;
417
AlexeiFedorov53518ba2023-08-22 14:46:26 +0100418static struct rmm_trap_element rmm_trap_list[] = {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000419 RMM_TRAP_HANDLER(ns_read, ns_access_ret_0),
420 RMM_TRAP_HANDLER(ns_write, ns_access_ret_0),
421};
422#define RMM_TRAP_LIST_SIZE (sizeof(rmm_trap_list)/sizeof(struct rmm_trap_element))
423
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000424/* Crash dump registers X0 - X29 */
425#define DUMP_REGS 30U
Soby Mathewb4c6df42022-11-09 11:13:29 +0000426
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000427typedef struct {
428 uint64_t x[DUMP_REGS];
429 uint64_t lr;
430} dump_regs_t;
431
432__dead2 static void fatal_abort(dump_regs_t *regs)
433{
434 __unused uint64_t sp_el2;
435 __unused uint64_t sp_el0 = (uint64_t)regs + sizeof(dump_regs_t);
436 __unused uint64_t lr = regs->lr;
437
438 ERROR("Unexpected exception on CPU #%u:\n", my_cpuid());
439
440 for (unsigned int i = 0U; i < DUMP_REGS; i += 2U) {
441 INFO("X%u:\t\t0x%016lx X%u:\t\t0x%016lx\n",
442 i, regs->x[i], i + 1U, regs->x[i + 1U]);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000443 }
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000444
445 /* Demangle return address */
446 xpaci(lr);
447
448 /* Switch SPSEL to read SP_EL2 register */
449 write_spsel(MODE_SP_ELX);
450 read_sp(sp_el2);
451 write_spsel(MODE_SP_EL0);
452
453 INFO("LR:\t\t0x%016lx\n", lr);
454 INFO("SP_EL0:\t\t0x%016lx\n", sp_el0);
455 INFO("SP_EL2:\t\t0x%016lx%c (0x%016lx-0x%016lx)\n", sp_el2,
456 ((sp_el2 < CPU_STACK_VIRT) ||
457 (sp_el2 >= RMM_CPU_STACK_END_VA)) ? '*' : ' ',
458 CPU_STACK_VIRT, (RMM_CPU_STACK_END_VA - 1UL));
459 INFO("ESR_EL2:\t0x%016lx\n", read_esr_el2());
460 INFO("ELR_EL2:\t0x%016lx\n", read_elr_el2());
461 INFO("FAR_EL2:\t0x%016lx\n", read_far_el2());
462 INFO("SPSR_EL2:\t0x%016lx\n", read_spsr_el2());
463 INFO("HCR_EL2:\t0x%016lx E2H = %c\n", read_hcr_el2(),
464 ((read_hcr_el2() & HCR_E2H) == 0UL) ? '0' : '1');
465 INFO("CPTR_EL2:\t0x%016lx\n", read_cptr_el2());
466 INFO("MDCR_EL2:\t0x%016lx\n", read_mdcr_el2());
467 INFO("SCTLR_EL2:\t0x%016lx\n", read_sctlr_el2());
468
AlexeiFedorovbe9209c2024-02-27 15:16:00 +0000469 /* The AArch64 AAPCS mandates the usage of x29 as Frame Pointer */
470 backtrace((uintptr_t)regs->x[29]);
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000471 panic();
Soby Mathewb4c6df42022-11-09 11:13:29 +0000472}
473
474static bool is_el2_data_abort_gpf(unsigned long esr)
475{
AlexeiFedorov537bee02023-02-02 13:38:23 +0000476 if (((esr & MASK(ESR_EL2_EC)) == ESR_EL2_EC_DATA_ABORT_SEL) &&
AlexeiFedorov6c119692023-04-21 12:31:15 +0100477 ((esr & MASK(ESR_EL2_ABORT_FSC)) == ESR_EL2_ABORT_FSC_GPF)) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000478 return true;
AlexeiFedorov6c119692023-04-21 12:31:15 +0100479 }
Soby Mathewb4c6df42022-11-09 11:13:29 +0000480 return false;
481}
482
483/*
484 * Handles the RMM's aborts.
485 * It compares the PC at the time of the abort with the registered addresses.
486 * If it finds a match, it returns the new value of the PC that the RMM should
487 * continue from. Other register values are preserved.
488 * If no match is found, it aborts the RMM.
489 */
Shruti Gupta0a0d4ee2024-04-22 21:37:25 +0100490/* cppcheck-suppress misra-c2012-8.4 */
AlexeiFedorovee2fc822023-10-31 14:54:39 +0000491/* coverity[misra_c_2012_rule_8_4_violation:SUPPRESS] */
Shruti Gupta0a0d4ee2024-04-22 21:37:25 +0100492/* coverity[misra_c_2012_rule_8_7_violation:SUPPRESS] */
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000493unsigned long handle_rmm_trap(dump_regs_t *regs)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000494{
Soby Mathewb4c6df42022-11-09 11:13:29 +0000495 unsigned long esr = read_esr_el2();
496 unsigned long elr = read_elr_el2();
497
498 /*
499 * Only the GPF data aborts are recoverable.
500 */
501 if (!is_el2_data_abort_gpf(esr)) {
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000502 fatal_abort(regs);
Soby Mathewb4c6df42022-11-09 11:13:29 +0000503 }
504
AlexeiFedorov6c119692023-04-21 12:31:15 +0100505 for (unsigned int i = 0U; i < RMM_TRAP_LIST_SIZE; i++) {
Soby Mathewb4c6df42022-11-09 11:13:29 +0000506 if (rmm_trap_list[i].aborted_pc == elr) {
507 return rmm_trap_list[i].new_pc;
508 }
509 }
510
AlexeiFedorov4c7d4852024-01-25 14:37:34 +0000511 fatal_abort(regs);
AlexeiFedorov6c119692023-04-21 12:31:15 +0100512 return 0UL;
Soby Mathewb4c6df42022-11-09 11:13:29 +0000513}