blob: eebb873a11bcb8b7b5ccb7c023468cc6c87bd100 [file] [log] [blame]
nabkah01002e5692022-10-10 12:36:46 +01001/*
AlexeiFedorov2f30f102023-03-13 19:37:46 +00002 * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
nabkah01002e5692022-10-10 12:36:46 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
AlexeiFedorov380b2af2022-11-23 17:31:27 +00008#include <assert.h>
nabkah01002e5692022-10-10 12:36:46 +01009#include <string.h>
10
11#include <debug.h>
12#include <heap/page_alloc.h>
AlexeiFedorov2f30f102023-03-13 19:37:46 +000013#include <test_helpers.h>
nabkah01002e5692022-10-10 12:36:46 +010014#include <host_realm_helper.h>
15#include <host_realm_mem_layout.h>
16#include <host_realm_rmi.h>
AlexeiFedorov2f30f102023-03-13 19:37:46 +000017#include <host_shared_data.h>
nabkah01002e5692022-10-10 12:36:46 +010018#include <plat/common/platform.h>
19#include <realm_def.h>
20#include <tftf_lib.h>
21
AlexeiFedorov380b2af2022-11-23 17:31:27 +000022#define SET_ARG(_n) { \
23 case _n: \
AlexeiFedorov2f30f102023-03-13 19:37:46 +000024 regs[_n] = rand64(); \
AlexeiFedorov380b2af2022-11-23 17:31:27 +000025 CONC(args->arg, _n) = regs[_n]; \
26 __attribute__((fallthrough)); \
27}
28
29#define CHECK_RET(_n) { \
30 if (CONC(ret_val.ret, _n) != regs[_n]) { \
31 cmp_flag |= (1U << _n); \
32 } \
33}
34
35static bool rmi_cmp_result;
AlexeiFedorov2f30f102023-03-13 19:37:46 +000036static unsigned short vmid;
AlexeiFedorov380b2af2022-11-23 17:31:27 +000037
AlexeiFedorov2f30f102023-03-13 19:37:46 +000038static smc_ret_values host_rmi_handler(smc_args *args, unsigned int in_reg)
AlexeiFedorov380b2af2022-11-23 17:31:27 +000039{
40 u_register_t regs[8];
41 smc_ret_values ret_val;
42 unsigned int cmp_flag = 0U;
43
44 assert(args != NULL);
45 assert((in_reg >= 1U) && (in_reg <= 7U));
46
47 /* Function identifier */
48 regs[0] = (u_register_t)args->fid;
49
50 /* X4 and X5 can be passed as parameters */
51 regs[4] = args->arg4;
52 regs[5] = args->arg5;
53
54 /* SMC calls arguments in X1-X7 */
55 switch (in_reg) {
56 SET_ARG(1);
57 SET_ARG(2);
58 SET_ARG(3);
59 SET_ARG(4);
60 SET_ARG(5);
61 SET_ARG(6);
62 default:
63 regs[7] = rand();
64 args->arg7 = regs[7];
65 }
66
67 ret_val = tftf_smc(args);
68
69 /*
70 * According to SMCCC v1.2 X4-X7 registers' values
71 * must be preserved unless they contain result,
72 * as specified in the function definition.
73 */
74 if (regs[0] != RMI_RTT_READ_ENTRY) {
75 CHECK_RET(4);
76 }
77
78 CHECK_RET(5);
79 CHECK_RET(6);
80 CHECK_RET(7);
81
82 if (cmp_flag != 0U) {
83 rmi_cmp_result = false;
84
85 ERROR("RMI SMC 0x%lx corrupted registers: %s %s %s %s\n",
86 regs[0],
87 (((cmp_flag & (1U << 4)) != 0U) ? "X4" : ""),
88 (((cmp_flag & (1U << 5)) != 0U) ? "X5" : ""),
89 (((cmp_flag & (1U << 6)) != 0U) ? "X6" : ""),
90 (((cmp_flag & (1U << 7)) != 0U) ? "X7" : ""));
91 }
92
93 return ret_val;
94}
95
AlexeiFedorov2f30f102023-03-13 19:37:46 +000096void host_rmi_init_cmp_result(void)
AlexeiFedorov380b2af2022-11-23 17:31:27 +000097{
98 rmi_cmp_result = true;
99}
100
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000101bool host_rmi_get_cmp_result(void)
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000102{
103 return rmi_cmp_result;
104}
105
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000106static inline u_register_t host_rmi_data_create(bool unknown, u_register_t data,
107 u_register_t rd, u_register_t map_addr, u_register_t src)
nabkah01002e5692022-10-10 12:36:46 +0100108{
109 if (unknown) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000110 return host_rmi_handler(&(smc_args){RMI_DATA_CREATE_UNKNOWN,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000111 data, rd, map_addr}, 4U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100112 } else {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000113 return host_rmi_handler(&(smc_args){RMI_DATA_CREATE,
114 /* X5 = flags */
115 data, rd, map_addr, src, 0UL}, 6U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100116 }
117}
118
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000119static inline u_register_t host_rmi_realm_activate(u_register_t rd)
nabkah01002e5692022-10-10 12:36:46 +0100120{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000121 return host_rmi_handler(&(smc_args){RMI_REALM_ACTIVATE, rd}, 2U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100122}
123
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000124u_register_t host_rmi_realm_create(u_register_t rd, u_register_t params_ptr)
nabkah01002e5692022-10-10 12:36:46 +0100125{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000126 return host_rmi_handler(&(smc_args){RMI_REALM_CREATE,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000127 rd, params_ptr}, 3U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100128}
129
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000130u_register_t host_rmi_realm_destroy(u_register_t rd)
nabkah01002e5692022-10-10 12:36:46 +0100131{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000132 return host_rmi_handler(&(smc_args){RMI_REALM_DESTROY, rd}, 2U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100133}
134
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000135static inline u_register_t host_rmi_data_destroy(u_register_t rd,
136 u_register_t map_addr)
nabkah01002e5692022-10-10 12:36:46 +0100137{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000138 return host_rmi_handler(&(smc_args){RMI_DATA_DESTROY, rd, map_addr},
139 3U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100140}
141
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000142static inline u_register_t host_rmi_rec_create(u_register_t rec,
143 u_register_t rd,
144 u_register_t params_ptr)
nabkah01002e5692022-10-10 12:36:46 +0100145{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000146 return host_rmi_handler(&(smc_args){RMI_REC_CREATE, rec, rd, params_ptr},
147 4U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100148}
149
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000150static inline u_register_t host_rmi_rec_destroy(u_register_t rec)
nabkah01002e5692022-10-10 12:36:46 +0100151{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000152 return host_rmi_handler(&(smc_args){RMI_REC_DESTROY, rec}, 2U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100153}
154
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000155static inline u_register_t host_rmi_rtt_create(u_register_t rtt,
156 u_register_t rd,
157 u_register_t map_addr,
158 u_register_t level)
nabkah01002e5692022-10-10 12:36:46 +0100159{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000160 return host_rmi_handler(&(smc_args){RMI_RTT_CREATE,
161 rtt, rd, map_addr, level}, 5U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100162}
163
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000164static inline u_register_t host_rmi_rtt_destroy(u_register_t rtt,
165 u_register_t rd,
166 u_register_t map_addr,
167 u_register_t level)
nabkah01002e5692022-10-10 12:36:46 +0100168{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000169 return host_rmi_handler(&(smc_args){RMI_RTT_DESTROY,
170 rtt, rd, map_addr, level}, 5U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100171}
172
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000173u_register_t host_rmi_features(u_register_t index, u_register_t *features)
nabkah01002e5692022-10-10 12:36:46 +0100174{
175 smc_ret_values rets;
176
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000177 rets = host_rmi_handler(&(smc_args){RMI_FEATURES, index}, 2U);
nabkah01002e5692022-10-10 12:36:46 +0100178 *features = rets.ret1;
179 return rets.ret0;
180}
181
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000182static inline u_register_t host_rmi_rtt_init_ripas(u_register_t rd,
183 u_register_t map_addr,
184 u_register_t level)
nabkah01002e5692022-10-10 12:36:46 +0100185{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000186 return host_rmi_handler(&(smc_args){RMI_RTT_INIT_RIPAS,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000187 rd, map_addr, level}, 4U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100188}
189
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000190static inline u_register_t host_rmi_rtt_fold(u_register_t rtt, u_register_t rd,
191 u_register_t map_addr,
192 u_register_t level)
nabkah01002e5692022-10-10 12:36:46 +0100193{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000194 return host_rmi_handler(&(smc_args){RMI_RTT_FOLD,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000195 rtt, rd, map_addr, level}, 5U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100196}
197
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000198static inline u_register_t host_rmi_rec_aux_count(u_register_t rd,
199 u_register_t *aux_count)
nabkah01002e5692022-10-10 12:36:46 +0100200{
201 smc_ret_values rets;
202
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000203 rets = host_rmi_handler(&(smc_args){RMI_REC_AUX_COUNT, rd}, 2U);
nabkah01002e5692022-10-10 12:36:46 +0100204 *aux_count = rets.ret1;
205 return rets.ret0;
206}
207
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000208static inline u_register_t host_rmi_rtt_set_ripas(u_register_t rd,
209 u_register_t rec,
210 u_register_t map_addr,
211 u_register_t level,
212 u_register_t ripas)
nabkah01002e5692022-10-10 12:36:46 +0100213{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000214 return host_rmi_handler(&(smc_args){RMI_RTT_SET_RIPAS,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000215 rd, rec, map_addr, level, ripas}, 6U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100216}
217
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000218static inline u_register_t host_rmi_rtt_mapunprotected(u_register_t rd,
219 u_register_t map_addr,
220 u_register_t level,
221 u_register_t ns_pa)
nabkah01002e5692022-10-10 12:36:46 +0100222{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000223 return host_rmi_handler(&(smc_args){RMI_RTT_MAP_UNPROTECTED,
224 rd, map_addr, level, ns_pa}, 5U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100225}
226
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000227static u_register_t host_rmi_rtt_readentry(u_register_t rd,
228 u_register_t map_addr,
229 u_register_t level,
230 struct rtt_entry *rtt)
nabkah01002e5692022-10-10 12:36:46 +0100231{
232 smc_ret_values rets;
233
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000234 rets = host_rmi_handler(&(smc_args){RMI_RTT_READ_ENTRY,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000235 rd, map_addr, level}, 4U);
nabkah01002e5692022-10-10 12:36:46 +0100236 rtt->walk_level = rets.ret1;
237 rtt->state = rets.ret2 & 0xFF;
238 rtt->out_addr = rets.ret3;
239 return rets.ret0;
240}
241
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000242static inline u_register_t host_rmi_rtt_unmap_unprotected(u_register_t rd,
243 u_register_t map_addr,
244 u_register_t level,
245 u_register_t ns_pa)
nabkah01002e5692022-10-10 12:36:46 +0100246{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000247 return host_rmi_handler(&(smc_args){RMI_RTT_UNMAP_UNPROTECTED,
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000248 rd, map_addr, level, ns_pa}, 5U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100249}
250
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000251static inline u_register_t host_rtt_level_mapsize(u_register_t level)
nabkah01002e5692022-10-10 12:36:46 +0100252{
253 if (level > RTT_MAX_LEVEL) {
254 return PAGE_SIZE;
255 }
256
257 return (1UL << RTT_LEVEL_SHIFT(level));
258}
259
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000260static inline u_register_t host_realm_rtt_create(struct realm *realm,
261 u_register_t addr,
262 u_register_t level,
263 u_register_t phys)
nabkah01002e5692022-10-10 12:36:46 +0100264{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000265 addr = ALIGN_DOWN(addr, host_rtt_level_mapsize(level - 1U));
266 return host_rmi_rtt_create(phys, realm->rd, addr, level);
nabkah01002e5692022-10-10 12:36:46 +0100267}
268
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000269static u_register_t host_rmi_create_rtt_levels(struct realm *realm,
270 u_register_t map_addr,
271 u_register_t level,
272 u_register_t max_level)
nabkah01002e5692022-10-10 12:36:46 +0100273{
274 u_register_t rtt, ret;
275
276 while (level++ < max_level) {
277 rtt = (u_register_t)page_alloc(PAGE_SIZE);
278 if (rtt == HEAP_NULL_PTR) {
279 ERROR("Failed to allocate memory for rtt\n");
280 return REALM_ERROR;
281 } else {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000282 ret = host_rmi_granule_delegate(rtt);
nabkah01002e5692022-10-10 12:36:46 +0100283 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000284 ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
285 "host_rmi_granule_delegate", rtt, ret);
nabkah01002e5692022-10-10 12:36:46 +0100286 return REALM_ERROR;
287 }
288 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000289 ret = host_realm_rtt_create(realm, map_addr, level, rtt);
nabkah01002e5692022-10-10 12:36:46 +0100290 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000291 ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
292 "host_realm_rtt_create", rtt, ret);
293 host_rmi_granule_undelegate(rtt);
nabkah01002e5692022-10-10 12:36:46 +0100294 page_free(rtt);
295 return REALM_ERROR;
296 }
297 }
298
299 return REALM_SUCCESS;
300}
301
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000302static u_register_t host_realm_fold_rtt(u_register_t rd, u_register_t addr,
303 u_register_t level)
nabkah01002e5692022-10-10 12:36:46 +0100304{
305 struct rtt_entry rtt;
306 u_register_t ret;
307
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000308 ret = host_rmi_rtt_readentry(rd, addr, level, &rtt);
nabkah01002e5692022-10-10 12:36:46 +0100309 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000310 ERROR("%s() failed, level=0x%lx addr=0x%lx ret=0x%lx\n",
311 "host_rmi_rtt_readentry", level, addr, ret);
nabkah01002e5692022-10-10 12:36:46 +0100312 return REALM_ERROR;
313 }
314
315 if (rtt.state != RMI_TABLE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000316 ERROR("%s() failed, rtt.state=0x%x\n", "rmi_rtt_readentry",
317 rtt.state);
nabkah01002e5692022-10-10 12:36:46 +0100318 return REALM_ERROR;
319 }
320
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000321 ret = host_rmi_rtt_fold(rtt.out_addr, rd, addr, level + 1U);
nabkah01002e5692022-10-10 12:36:46 +0100322 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000323 ERROR("%s() failed, rtt.out_addr=0x%llx addr=0x%lx ret=0x%lx\n",
324 "host_rmi_rtt_fold", rtt.out_addr, addr, ret);
nabkah01002e5692022-10-10 12:36:46 +0100325 return REALM_ERROR;
326 }
327
328 page_free(rtt.out_addr);
329
330 return REALM_SUCCESS;
331
332}
333
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000334static u_register_t host_realm_map_protected_data(bool unknown,
335 struct realm *realm,
336 u_register_t target_pa,
337 u_register_t map_size,
338 u_register_t src_pa)
nabkah01002e5692022-10-10 12:36:46 +0100339{
340 u_register_t rd = realm->rd;
341 u_register_t map_level, level;
342 u_register_t ret = 0UL;
343 u_register_t size;
344 u_register_t phys = target_pa;
345 u_register_t map_addr = target_pa;
346
347 if (!IS_ALIGNED(map_addr, map_size)) {
348 return REALM_ERROR;
349 }
350
351 switch (map_size) {
352 case PAGE_SIZE:
353 map_level = 3UL;
354 break;
355 case RTT_L2_BLOCK_SIZE:
356 map_level = 2UL;
357 break;
358 default:
359 ERROR("Unknown map_size=0x%lx\n", map_size);
360 return REALM_ERROR;
361 }
362
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000363 ret = host_rmi_rtt_init_ripas(rd, map_addr, map_level);
nabkah01002e5692022-10-10 12:36:46 +0100364 if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000365 ret = host_rmi_create_rtt_levels(realm, map_addr,
366 RMI_RETURN_INDEX(ret),
367 map_level);
nabkah01002e5692022-10-10 12:36:46 +0100368 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000369 ERROR("%s() failed, ret=0x%lx line=%u\n",
370 "host_rmi_create_rtt_levels", ret, __LINE__);
nabkah01002e5692022-10-10 12:36:46 +0100371 goto err;
372 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000373 ret = host_rmi_rtt_init_ripas(rd, map_addr, map_level);
nabkah01002e5692022-10-10 12:36:46 +0100374 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000375 ERROR("%s() failed, ret=0x%lx line=%u\n",
376 "host_rmi_rtt_init_ripas", ret, __LINE__);
nabkah01002e5692022-10-10 12:36:46 +0100377 goto err;
378 }
379 }
380 for (size = 0UL; size < map_size; size += PAGE_SIZE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000381 ret = host_rmi_granule_delegate(phys);
nabkah01002e5692022-10-10 12:36:46 +0100382 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000383 ERROR("%s() failed, PA=0x%lx ret=0x%lx\n",
384 "host_rmi_granule_delegate", phys, ret);
nabkah01002e5692022-10-10 12:36:46 +0100385 return REALM_ERROR;
386 }
387
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000388 ret = host_rmi_data_create(unknown, phys, rd, map_addr, src_pa);
nabkah01002e5692022-10-10 12:36:46 +0100389
390 if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
391 /* Create missing RTTs and retry */
392 level = RMI_RETURN_INDEX(ret);
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000393 ret = host_rmi_create_rtt_levels(realm, map_addr, level,
394 map_level);
nabkah01002e5692022-10-10 12:36:46 +0100395 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000396 ERROR("%s() failed, ret=0x%lx line=%u\n",
397 "host_rmi_create_rtt_levels",
nabkah01002e5692022-10-10 12:36:46 +0100398 ret, __LINE__);
399 goto err;
400 }
401
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000402 ret = host_rmi_data_create(unknown, phys, rd, map_addr,
403 src_pa);
nabkah01002e5692022-10-10 12:36:46 +0100404 }
405
406 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000407 ERROR("%s() failed, ret=0x%lx\n",
408 "host_rmi_data_create", ret);
nabkah01002e5692022-10-10 12:36:46 +0100409 goto err;
410 }
411
412 phys += PAGE_SIZE;
413 src_pa += PAGE_SIZE;
414 map_addr += PAGE_SIZE;
415 }
416
417 if (map_size == RTT_L2_BLOCK_SIZE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000418 ret = host_realm_fold_rtt(rd, target_pa, map_level);
nabkah01002e5692022-10-10 12:36:46 +0100419 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000420 ERROR("%s() failed, ret=0x%lx\n",
421 "host_realm_fold_rtt", ret);
nabkah01002e5692022-10-10 12:36:46 +0100422 goto err;
423 }
424 }
425
426 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000427 ERROR("%s() failed, ret=0x%lx\n", __func__, ret);
nabkah01002e5692022-10-10 12:36:46 +0100428 goto err;
429 }
430
431 return REALM_SUCCESS;
432
433err:
434 while (size >= PAGE_SIZE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000435 ret = host_rmi_data_destroy(rd, map_addr);
nabkah01002e5692022-10-10 12:36:46 +0100436 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000437 ERROR("%s() failed, ret=0x%lx\n",
438 "host_rmi_data_destroy", ret);
nabkah01002e5692022-10-10 12:36:46 +0100439 }
440
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000441 ret = host_rmi_granule_undelegate(phys);
nabkah01002e5692022-10-10 12:36:46 +0100442 if (ret != RMI_SUCCESS) {
443 /* Page can't be returned to NS world so is lost */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000444 ERROR("%s() failed, ret=0x%lx\n",
445 "host_rmi_granule_undelegate", ret);
nabkah01002e5692022-10-10 12:36:46 +0100446 }
447 phys -= PAGE_SIZE;
448 size -= PAGE_SIZE;
449 map_addr -= PAGE_SIZE;
450 }
451
452 return REALM_ERROR;
453}
454
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000455u_register_t host_realm_map_unprotected(struct realm *realm,
456 u_register_t ns_pa,
457 u_register_t map_size)
nabkah01002e5692022-10-10 12:36:46 +0100458{
459 u_register_t rd = realm->rd;
460 u_register_t map_level, level;
461 u_register_t ret = 0UL;
462 u_register_t phys = ns_pa;
463 u_register_t map_addr = ns_pa |
464 (1UL << (EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ,
465 realm->rmm_feat_reg0) - 1UL)) ;
466
nabkah01002e5692022-10-10 12:36:46 +0100467 if (!IS_ALIGNED(map_addr, map_size)) {
468 return REALM_ERROR;
469 }
470
471 switch (map_size) {
472 case PAGE_SIZE:
473 map_level = 3UL;
474 break;
475 case RTT_L2_BLOCK_SIZE:
476 map_level = 2UL;
477 break;
478 default:
479 ERROR("Unknown map_size=0x%lx\n", map_size);
480 return REALM_ERROR;
481 }
482
483 u_register_t desc = phys | S2TTE_ATTR_FWB_WB_RW;
484
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000485 ret = host_rmi_rtt_mapunprotected(rd, map_addr, map_level, desc);
nabkah01002e5692022-10-10 12:36:46 +0100486
487 if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
488 /* Create missing RTTs and retry */
489 level = RMI_RETURN_INDEX(ret);
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000490 ret = host_rmi_create_rtt_levels(realm, map_addr, level,
491 map_level);
nabkah01002e5692022-10-10 12:36:46 +0100492 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000493 ERROR("%s() failed, ret=0x%lx line=%u\n",
494 "host_rmi_create_rtt_levels", ret, __LINE__);
nabkah01002e5692022-10-10 12:36:46 +0100495 return REALM_ERROR;
496 }
497
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000498 ret = host_rmi_rtt_mapunprotected(rd, map_addr, map_level,
499 desc);
nabkah01002e5692022-10-10 12:36:46 +0100500 }
501 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000502 ERROR("%s() failed, ret=0x%lx\n", "host_rmi_rtt_mapunprotected",
503 ret);
nabkah01002e5692022-10-10 12:36:46 +0100504 return REALM_ERROR;
505 }
506
507 return REALM_SUCCESS;
508}
509
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000510static u_register_t host_realm_rtt_destroy(struct realm *realm,
511 u_register_t addr,
512 u_register_t level,
513 u_register_t rtt_granule)
nabkah01002e5692022-10-10 12:36:46 +0100514{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000515 addr = ALIGN_DOWN(addr, host_rtt_level_mapsize(level - 1U));
516 return host_rmi_rtt_destroy(rtt_granule, realm->rd, addr, level);
nabkah01002e5692022-10-10 12:36:46 +0100517}
518
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000519static u_register_t host_realm_destroy_free_rtt(struct realm *realm,
520 u_register_t addr,
521 u_register_t level,
522 u_register_t rtt_granule)
nabkah01002e5692022-10-10 12:36:46 +0100523{
524 u_register_t ret;
525
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000526 ret = host_realm_rtt_destroy(realm, addr, level, rtt_granule);
nabkah01002e5692022-10-10 12:36:46 +0100527 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000528 ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
529 "host_realm_rtt_destroy", rtt_granule, ret);
nabkah01002e5692022-10-10 12:36:46 +0100530 return REALM_ERROR;
531 }
532
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000533 ret = host_rmi_granule_undelegate(rtt_granule);
nabkah01002e5692022-10-10 12:36:46 +0100534 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000535 ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
536 "host_rmi_granule_undelegate", rtt_granule, ret);
nabkah01002e5692022-10-10 12:36:46 +0100537 return REALM_ERROR;
538 }
539
540 page_free(rtt_granule);
541 return REALM_SUCCESS;
542}
543
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000544static void host_realm_destroy_undelegate_range(struct realm *realm,
545 u_register_t ipa,
546 u_register_t addr,
547 u_register_t size)
nabkah01002e5692022-10-10 12:36:46 +0100548{
549 u_register_t rd = realm->rd;
550 u_register_t ret;
551
552 while (size >= PAGE_SIZE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000553 ret = host_rmi_data_destroy(rd, ipa);
nabkah01002e5692022-10-10 12:36:46 +0100554 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000555 ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
556 "host_rmi_data_destroy", ipa, ret);
nabkah01002e5692022-10-10 12:36:46 +0100557 }
558
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000559 ret = host_rmi_granule_undelegate(addr);
nabkah01002e5692022-10-10 12:36:46 +0100560 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000561 ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
562 "host_rmi_granule_undelegate", ipa, ret);
nabkah01002e5692022-10-10 12:36:46 +0100563 }
564
565 page_free(addr);
566
567 addr += PAGE_SIZE;
568 ipa += PAGE_SIZE;
569 size -= PAGE_SIZE;
570 }
571}
572
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000573static u_register_t host_realm_tear_down_rtt_range(struct realm *realm,
574 u_register_t level,
575 u_register_t start,
576 u_register_t end)
nabkah01002e5692022-10-10 12:36:46 +0100577{
578 u_register_t rd = realm->rd, ret;
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000579 u_register_t map_size = host_rtt_level_mapsize(level);
nabkah01002e5692022-10-10 12:36:46 +0100580 u_register_t map_addr, next_addr, rtt_out_addr, end_addr;
581 struct rtt_entry rtt;
582
583 for (map_addr = start; map_addr < end; map_addr = next_addr) {
584 next_addr = ALIGN(map_addr + 1U, map_size);
585 end_addr = MIN(next_addr, end);
586
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000587 ret = host_rmi_rtt_readentry(rd, ALIGN_DOWN(map_addr, map_size),
588 level, &rtt);
nabkah01002e5692022-10-10 12:36:46 +0100589 if (ret != RMI_SUCCESS) {
590 continue;
591 }
592
593 rtt_out_addr = rtt.out_addr;
594
595 switch (rtt.state) {
596 case RMI_ASSIGNED:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000597 host_realm_destroy_undelegate_range(realm, map_addr,
598 rtt_out_addr,
599 map_size);
nabkah01002e5692022-10-10 12:36:46 +0100600 break;
601 case RMI_UNASSIGNED:
602 case RMI_DESTROYED:
603 break;
604 case RMI_TABLE:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000605 ret = host_realm_tear_down_rtt_range(realm, level + 1U,
606 map_addr,
607 end_addr);
nabkah01002e5692022-10-10 12:36:46 +0100608 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000609 ERROR("%s() failed, map_addr=0x%lx ret=0x%lx\n",
610 "host_realm_tear_down_rtt_range",
nabkah01002e5692022-10-10 12:36:46 +0100611 map_addr, ret);
612 return REALM_ERROR;
613 }
614
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000615 ret = host_realm_destroy_free_rtt(realm, map_addr,
616 level + 1U,
617 rtt_out_addr);
nabkah01002e5692022-10-10 12:36:46 +0100618 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000619 ERROR("%s() failed, map_addr=0x%lx ret=0x%lx\n",
620 "host_realm_destroy_free_rtt",
nabkah01002e5692022-10-10 12:36:46 +0100621 map_addr, ret);
622 return REALM_ERROR;
623 }
624 break;
625 case RMI_VALID_NS:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000626 ret = host_rmi_rtt_unmap_unprotected(rd, map_addr, level,
627 rtt_out_addr);
nabkah01002e5692022-10-10 12:36:46 +0100628 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000629 ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
630 "host_rmi_rtt_unmap_unprotected",
631 map_addr, ret);
nabkah01002e5692022-10-10 12:36:46 +0100632 return REALM_ERROR;
633 }
634 break;
635 default:
636 return REALM_ERROR;
637 }
638 }
639
640 return REALM_SUCCESS;
641}
642
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000643u_register_t host_rmi_granule_delegate(u_register_t addr)
nabkah01002e5692022-10-10 12:36:46 +0100644{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000645 return host_rmi_handler(&(smc_args){RMI_GRANULE_DELEGATE, addr}, 2U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100646}
647
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000648u_register_t host_rmi_granule_undelegate(u_register_t addr)
nabkah01002e5692022-10-10 12:36:46 +0100649{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000650 return host_rmi_handler(&(smc_args){RMI_GRANULE_UNDELEGATE, addr}, 2U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100651}
652
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000653u_register_t host_rmi_version(void)
nabkah01002e5692022-10-10 12:36:46 +0100654{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000655 return host_rmi_handler(&(smc_args){RMI_VERSION}, 1U).ret0;
nabkah01002e5692022-10-10 12:36:46 +0100656}
657
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000658u_register_t host_realm_create(struct realm *realm)
nabkah01002e5692022-10-10 12:36:46 +0100659{
660 struct rmi_realm_params *params;
661 u_register_t ret;
662
663 realm->par_size = REALM_MAX_LOAD_IMG_SIZE;
664
665 realm->state = REALM_STATE_NULL;
666 /*
667 * Allocate memory for PAR - Realm image. Granule delegation
668 * of PAR will be performed during rtt creation.
669 */
670 realm->par_base = (u_register_t)page_alloc(realm->par_size);
671 if (realm->par_base == HEAP_NULL_PTR) {
672 ERROR("page_alloc failed, base=0x%lx, size=0x%lx\n",
673 realm->par_base, realm->par_size);
674 return REALM_ERROR;
675 }
676
677 /* Allocate and delegate RD */
678 realm->rd = (u_register_t)page_alloc(PAGE_SIZE);
679 if (realm->rd == HEAP_NULL_PTR) {
680 ERROR("Failed to allocate memory for rd\n");
681 goto err_free_par;
682 } else {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000683 ret = host_rmi_granule_delegate(realm->rd);
nabkah01002e5692022-10-10 12:36:46 +0100684 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000685 ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
686 "host_rmi_granule_delegate", realm->rd, ret);
nabkah01002e5692022-10-10 12:36:46 +0100687 goto err_free_rd;
688 }
689 }
690
691 /* Allocate and delegate RTT */
692 realm->rtt_addr = (u_register_t)page_alloc(PAGE_SIZE);
693 if (realm->rtt_addr == HEAP_NULL_PTR) {
694 ERROR("Failed to allocate memory for rtt_addr\n");
695 goto err_undelegate_rd;
696 } else {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000697 ret = host_rmi_granule_delegate(realm->rtt_addr);
nabkah01002e5692022-10-10 12:36:46 +0100698 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000699 ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
700 "host_rmi_granule_delegate", realm->rtt_addr, ret);
nabkah01002e5692022-10-10 12:36:46 +0100701 goto err_free_rtt;
702 }
703 }
704
705 /* Allocate memory for params */
706 params = (struct rmi_realm_params *)page_alloc(PAGE_SIZE);
707 if (params == NULL) {
708 ERROR("Failed to allocate memory for params\n");
709 goto err_undelegate_rtt;
710 }
711
712 /* Populate params */
713 params->features_0 = realm->rmm_feat_reg0;
714 params->rtt_level_start = 0L;
715 params->rtt_num_start = 1U;
716 params->rtt_base = realm->rtt_addr;
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000717 params->vmid = vmid++;
nabkah01002e5692022-10-10 12:36:46 +0100718 params->hash_algo = RMI_HASH_SHA_256;
719
720 /* Create Realm */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000721 ret = host_rmi_realm_create(realm->rd, (u_register_t)params);
nabkah01002e5692022-10-10 12:36:46 +0100722 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000723 ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
724 "host_rmi_realm_create", realm->rd, ret);
nabkah01002e5692022-10-10 12:36:46 +0100725 goto err_free_params;
726 }
727
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000728 ret = host_rmi_rec_aux_count(realm->rd, &realm->num_aux);
nabkah01002e5692022-10-10 12:36:46 +0100729 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000730 ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
731 "host_rmi_rec_aux_count", realm->rd, ret);
732 host_rmi_realm_destroy(realm->rd);
nabkah01002e5692022-10-10 12:36:46 +0100733 goto err_free_params;
734 }
735
736 realm->state = REALM_STATE_NEW;
737
738 /* Free params */
739 page_free((u_register_t)params);
740 return REALM_SUCCESS;
741
742err_free_params:
743 page_free((u_register_t)params);
744
745err_undelegate_rtt:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000746 ret = host_rmi_granule_undelegate(realm->rtt_addr);
nabkah01002e5692022-10-10 12:36:46 +0100747 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000748 WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
749 "host_rmi_granule_undelegate", realm->rtt_addr, ret);
nabkah01002e5692022-10-10 12:36:46 +0100750 }
751
752err_free_rtt:
753 page_free(realm->rtt_addr);
754
755err_undelegate_rd:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000756 ret = host_rmi_granule_undelegate(realm->rd);
nabkah01002e5692022-10-10 12:36:46 +0100757 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000758 WARN("%s() failed, rd=0x%lx ret=0x%lx\n",
759 "host_rmi_granule_undelegate", realm->rd, ret);
nabkah01002e5692022-10-10 12:36:46 +0100760 }
761err_free_rd:
762 page_free(realm->rd);
763
764err_free_par:
765 page_free(realm->par_base);
766
767 return REALM_ERROR;
768}
769
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000770u_register_t host_realm_map_payload_image(struct realm *realm,
771 u_register_t realm_payload_adr)
nabkah01002e5692022-10-10 12:36:46 +0100772{
773 u_register_t src_pa = realm_payload_adr;
774 u_register_t i = 0UL;
775 u_register_t ret;
776
777 /* MAP image regions */
778 while (i < (realm->par_size / PAGE_SIZE)) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000779 ret = host_realm_map_protected_data(false, realm,
780 realm->par_base + i * PAGE_SIZE,
781 PAGE_SIZE,
782 src_pa + i * PAGE_SIZE);
nabkah01002e5692022-10-10 12:36:46 +0100783 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000784 ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
785 "host_realm_map_protected_data",
nabkah01002e5692022-10-10 12:36:46 +0100786 realm->par_base, ret);
787 return REALM_ERROR;
788 }
789 i++;
790 }
791
792 return REALM_SUCCESS;
793}
794
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000795u_register_t host_realm_init_ipa_state(struct realm *realm, u_register_t level,
796 u_register_t start, uint64_t end)
nabkah01002e5692022-10-10 12:36:46 +0100797{
798 u_register_t rd = realm->rd, ret;
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000799 u_register_t map_size = host_rtt_level_mapsize(level);
nabkah01002e5692022-10-10 12:36:46 +0100800
801 while (start < end) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000802 ret = host_rmi_rtt_init_ripas(rd, start, level);
nabkah01002e5692022-10-10 12:36:46 +0100803
804 if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
805 int cur_level = RMI_RETURN_INDEX(ret);
806
807 if (cur_level < level) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000808 ret = host_rmi_create_rtt_levels(realm,
809 start,
810 cur_level,
811 level);
nabkah01002e5692022-10-10 12:36:46 +0100812 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000813 ERROR("%s() failed, ret=0x%lx line=%u\n",
814 "host_rmi_create_rtt_levels",
nabkah01002e5692022-10-10 12:36:46 +0100815 ret, __LINE__);
816 return ret;
817 }
818 /* Retry with the RTT levels in place */
819 continue;
820 }
821
822 if (level >= RTT_MAX_LEVEL) {
823 return REALM_ERROR;
824 }
825
826 /* There's an entry at a lower level, recurse */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000827 host_realm_init_ipa_state(realm, start,
828 start + map_size, level + 1);
nabkah01002e5692022-10-10 12:36:46 +0100829 } else if (ret != RMI_SUCCESS) {
830 return REALM_ERROR;
831 }
832
833 start += map_size;
834 }
835
836 return RMI_SUCCESS;
837}
838
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000839u_register_t host_realm_map_ns_shared(struct realm *realm,
840 u_register_t ns_shared_mem_adr,
841 u_register_t ns_shared_mem_size)
nabkah01002e5692022-10-10 12:36:46 +0100842{
843 u_register_t i = 0UL;
844 u_register_t ret;
845
846 realm->ipa_ns_buffer = ns_shared_mem_adr |
847 (1UL << (EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ,
848 realm->rmm_feat_reg0) - 1));
849 realm->ns_buffer_size = ns_shared_mem_size;
850 /* MAP SHARED_NS region */
851 while (i < ns_shared_mem_size / PAGE_SIZE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000852 ret = host_realm_map_unprotected(realm, ns_shared_mem_adr +
853 (i * PAGE_SIZE), PAGE_SIZE);
nabkah01002e5692022-10-10 12:36:46 +0100854 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000855 ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
856 "host_realm_map_unprotected",
857 (ns_shared_mem_adr + i * PAGE_SIZE), ret);
nabkah01002e5692022-10-10 12:36:46 +0100858 return REALM_ERROR;
859 }
860 i++;
861 }
862 return REALM_SUCCESS;
863}
864
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000865static void host_realm_free_rec_aux(u_register_t *aux_pages,
866 unsigned int num_aux)
nabkah01002e5692022-10-10 12:36:46 +0100867{
868 u_register_t ret;
869
870 for (unsigned int i = 0U; i < num_aux; i++) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000871 ret = host_rmi_granule_undelegate(aux_pages[i]);
nabkah01002e5692022-10-10 12:36:46 +0100872 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000873 WARN("%s() failed, index=%u ret=0x%lx\n",
874 "host_rmi_granule_undelegate", i, ret);
nabkah01002e5692022-10-10 12:36:46 +0100875 }
876 page_free(aux_pages[i]);
877 }
878}
879
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000880static u_register_t host_realm_alloc_rec_aux(struct realm *realm,
881 struct rmi_rec_params *params)
nabkah01002e5692022-10-10 12:36:46 +0100882{
883 u_register_t ret;
884 unsigned int i;
885
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000886 for (i = 0U; i < realm->num_aux; i++) {
nabkah01002e5692022-10-10 12:36:46 +0100887 params->aux[i] = (u_register_t)page_alloc(PAGE_SIZE);
888 if (params->aux[i] == HEAP_NULL_PTR) {
889 ERROR("Failed to allocate memory for aux rec\n");
890 goto err_free_mem;
891 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000892 ret = host_rmi_granule_delegate(params->aux[i]);
nabkah01002e5692022-10-10 12:36:46 +0100893 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000894 ERROR("%s() failed, index=%u ret=0x%lx\n",
895 "host_rmi_granule_delegate", i, ret);
nabkah01002e5692022-10-10 12:36:46 +0100896 goto err_free_mem;
897 }
898
899 /* We need a copy in Realm object for final destruction */
900 realm->aux_pages[i] = params->aux[i];
901 }
902 return RMI_SUCCESS;
903err_free_mem:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000904 host_realm_free_rec_aux(params->aux, i);
nabkah01002e5692022-10-10 12:36:46 +0100905 return ret;
906}
907
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000908u_register_t host_realm_rec_create(struct realm *realm)
nabkah01002e5692022-10-10 12:36:46 +0100909{
910 struct rmi_rec_params *rec_params = HEAP_NULL_PTR;
911 u_register_t ret;
912
913 /* Allocate memory for run object */
914 realm->run = (u_register_t)page_alloc(PAGE_SIZE);
915 if (realm->run == HEAP_NULL_PTR) {
916 ERROR("Failed to allocate memory for run\n");
917 return REALM_ERROR;
918 }
919 (void)memset((void *)realm->run, 0x0, PAGE_SIZE);
920
921 /* Allocate and delegate REC */
922 realm->rec = (u_register_t)page_alloc(PAGE_SIZE);
923 if (realm->rec == HEAP_NULL_PTR) {
924 ERROR("Failed to allocate memory for REC\n");
925 goto err_free_mem;
926 } else {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000927 ret = host_rmi_granule_delegate(realm->rec);
nabkah01002e5692022-10-10 12:36:46 +0100928 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000929 ERROR("%s() failed, rec=0x%lx ret=0x%lx\n",
930 "host_rmi_granule_delegate", realm->rd, ret);
nabkah01002e5692022-10-10 12:36:46 +0100931 goto err_free_mem;
932 }
933 }
934
935 /* Allocate memory for rec_params */
936 rec_params = (struct rmi_rec_params *)page_alloc(PAGE_SIZE);
937 if (rec_params == NULL) {
938 ERROR("Failed to allocate memory for rec_params\n");
939 goto err_undelegate_rec;
940 }
941 (void)memset(rec_params, 0x0, PAGE_SIZE);
942
943 /* Populate rec_params */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000944 for (unsigned int i = 0U; i < (sizeof(rec_params->gprs) /
nabkah01002e5692022-10-10 12:36:46 +0100945 sizeof(rec_params->gprs[0]));
946 i++) {
947 rec_params->gprs[i] = 0x0UL;
948 }
949
950 /* Delegate the required number of auxiliary Granules */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000951 ret = host_realm_alloc_rec_aux(realm, rec_params);
nabkah01002e5692022-10-10 12:36:46 +0100952 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000953 ERROR("%s() failed, ret=0x%lx\n", "host_realm_alloc_rec_aux",
954 ret);
nabkah01002e5692022-10-10 12:36:46 +0100955 goto err_free_mem;
956 }
957
958 rec_params->pc = realm->par_base;
959 rec_params->flags = RMI_RUNNABLE;
960 rec_params->mpidr = 0x0UL;
961 rec_params->num_aux = realm->num_aux;
962
963 /* Create REC */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000964 ret = host_rmi_rec_create(realm->rec, realm->rd, (u_register_t)rec_params);
nabkah01002e5692022-10-10 12:36:46 +0100965 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000966 ERROR("%s() failed, ret=0x%lx\n", "host_rmi_rec_create", ret);
nabkah01002e5692022-10-10 12:36:46 +0100967 goto err_free_rec_aux;
968 }
969
970 /* Free rec_params */
971 page_free((u_register_t)rec_params);
972 return REALM_SUCCESS;
973
974err_free_rec_aux:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000975 host_realm_free_rec_aux(rec_params->aux, realm->num_aux);
nabkah01002e5692022-10-10 12:36:46 +0100976
977err_undelegate_rec:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000978 ret = host_rmi_granule_undelegate(realm->rec);
nabkah01002e5692022-10-10 12:36:46 +0100979 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000980 WARN("%s() failed, rec=0x%lx ret=0x%lx\n",
981 "host_rmi_granule_undelegate", realm->rec, ret);
nabkah01002e5692022-10-10 12:36:46 +0100982 }
983
984err_free_mem:
985 page_free(realm->run);
986 page_free(realm->rec);
987 page_free((u_register_t)rec_params);
988
989 return REALM_ERROR;
990}
991
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000992u_register_t host_realm_activate(struct realm *realm)
nabkah01002e5692022-10-10 12:36:46 +0100993{
994 u_register_t ret;
995
996 /* Activate Realm */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000997 ret = host_rmi_realm_activate(realm->rd);
nabkah01002e5692022-10-10 12:36:46 +0100998 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000999 ERROR("%s() failed, ret=0x%lx\n", "host_rmi_realm_activate",
1000 ret);
nabkah01002e5692022-10-10 12:36:46 +01001001 return REALM_ERROR;
1002 }
1003
1004 realm->state = REALM_STATE_ACTIVE;
1005
1006 return REALM_SUCCESS;
1007}
1008
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001009u_register_t host_realm_destroy(struct realm *realm)
nabkah01002e5692022-10-10 12:36:46 +01001010{
1011 u_register_t ret;
1012
1013 if (realm->state == REALM_STATE_NULL) {
1014 return REALM_SUCCESS;
1015 }
1016
1017 if (realm->state == REALM_STATE_NEW) {
1018 goto undo_from_new_state;
1019 }
1020
1021 if (realm->state != REALM_STATE_ACTIVE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001022 ERROR("Invalid realm state found 0x%x\n", realm->state);
nabkah01002e5692022-10-10 12:36:46 +01001023 return REALM_ERROR;
1024 }
1025
1026 /* For each REC - Destroy, undelegate and free */
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001027 ret = host_rmi_rec_destroy(realm->rec);
nabkah01002e5692022-10-10 12:36:46 +01001028 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001029 ERROR("%s() failed, rec=0x%lx ret=0x%lx\n",
1030 "host_rmi_rec_destroy", realm->rec, ret);
nabkah01002e5692022-10-10 12:36:46 +01001031 return REALM_ERROR;
1032 }
1033
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001034 ret = host_rmi_granule_undelegate(realm->rec);
nabkah01002e5692022-10-10 12:36:46 +01001035 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001036 ERROR("%s() failed, rec=0x%lx ret=0x%lx\n",
1037 "host_rmi_granule_undelegate", realm->rec, ret);
nabkah01002e5692022-10-10 12:36:46 +01001038 return REALM_ERROR;
1039 }
1040
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001041 host_realm_free_rec_aux(realm->aux_pages, realm->num_aux);
nabkah01002e5692022-10-10 12:36:46 +01001042 page_free(realm->rec);
1043
1044 /* Free run object */
1045 page_free(realm->run);
1046
1047 /*
1048 * For each data granule - Destroy, undelegate and free
1049 * RTTs (level 1U and below) must be destroyed leaf-upwards,
1050 * using RMI_DATA_DESTROY, RMI_RTT_DESTROY and RMI_GRANULE_UNDELEGATE
1051 * commands.
1052 */
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001053 if (host_realm_tear_down_rtt_range(realm, 0UL, 0UL,
1054 (1UL << (EXTRACT(RMM_FEATURE_REGISTER_0_S2SZ,
1055 realm->rmm_feat_reg0) - 1))) != RMI_SUCCESS) {
1056 ERROR("host_realm_tear_down_rtt_range() line=%u\n", __LINE__);
nabkah01002e5692022-10-10 12:36:46 +01001057 return REALM_ERROR;
1058 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001059 if (host_realm_tear_down_rtt_range(realm, 0UL, realm->ipa_ns_buffer,
nabkah01002e5692022-10-10 12:36:46 +01001060 (realm->ipa_ns_buffer + realm->ns_buffer_size)) !=
1061 RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001062 ERROR("host_realm_tear_down_rtt_range() line=%u\n", __LINE__);
nabkah01002e5692022-10-10 12:36:46 +01001063 return REALM_ERROR;
1064 }
1065undo_from_new_state:
1066
1067 /*
1068 * RD Destroy, undelegate and free
1069 * RTT(L0) undelegate and free
1070 * PAR free
1071 */
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001072 ret = host_rmi_realm_destroy(realm->rd);
nabkah01002e5692022-10-10 12:36:46 +01001073 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001074 ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
1075 "host_rmi_realm_destroy", realm->rd, ret);
nabkah01002e5692022-10-10 12:36:46 +01001076 return REALM_ERROR;
1077 }
1078
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001079 ret = host_rmi_granule_undelegate(realm->rd);
nabkah01002e5692022-10-10 12:36:46 +01001080 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001081 ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
1082 "host_rmi_granule_undelegate", realm->rd, ret);
nabkah01002e5692022-10-10 12:36:46 +01001083 return REALM_ERROR;
1084 }
1085
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001086 ret = host_rmi_granule_undelegate(realm->rtt_addr);
nabkah01002e5692022-10-10 12:36:46 +01001087 if (ret != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001088 ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
1089 "host_rmi_granule_undelegate", realm->rtt_addr, ret);
nabkah01002e5692022-10-10 12:36:46 +01001090 return REALM_ERROR;
1091 }
1092
1093 page_free(realm->rd);
1094 page_free(realm->rtt_addr);
1095 page_free(realm->par_base);
1096
1097 return REALM_SUCCESS;
1098}
1099
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001100u_register_t host_realm_rec_enter(struct realm *realm,
1101 u_register_t *exit_reason,
1102 unsigned int *host_call_result)
nabkah01002e5692022-10-10 12:36:46 +01001103{
1104 struct rmi_rec_run *run = (struct rmi_rec_run *)realm->run;
1105 u_register_t ret;
1106 bool re_enter_rec;
1107
1108 do {
1109 re_enter_rec = false;
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001110 ret = host_rmi_handler(&(smc_args){RMI_REC_ENTER,
AlexeiFedorov380b2af2022-11-23 17:31:27 +00001111 realm->rec, realm->run}, 3U).ret0;
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001112 VERBOSE("%s() run->exit.exit_reason=%lu "
1113 "run->exit.esr=0x%lx EC_BITS=%u ISS_DFSC_MASK=0x%lx\n",
1114 __func__, run->exit.exit_reason, run->exit.esr,
1115 ((EC_BITS(run->exit.esr) == EC_DABORT_CUR_EL)),
1116 (ISS_BITS(run->exit.esr) & ISS_DFSC_MASK));
nabkah01002e5692022-10-10 12:36:46 +01001117
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001118 /* If a data abort because of a GPF */
nabkah01002e5692022-10-10 12:36:46 +01001119 if (EC_BITS(run->exit.esr) == EC_DABORT_CUR_EL) {
1120 ERROR("EC_BITS(run->exit.esr) == EC_DABORT_CUR_EL\n");
1121 if ((ISS_BITS(run->exit.esr) & ISS_DFSC_MASK) ==
1122 DFSC_GPF_DABORT) {
1123 ERROR("DFSC_GPF_DABORT\n");
1124 }
1125 }
1126
nabkah01002e5692022-10-10 12:36:46 +01001127 if (ret != RMI_SUCCESS) {
1128 return ret;
1129 }
1130
1131 if (run->exit.exit_reason == RMI_EXIT_HOST_CALL) {
1132 switch (run->exit.imm) {
1133 case HOST_CALL_GET_SHARED_BUFF_CMD:
1134 run->entry.gprs[0] = realm->ipa_ns_buffer;
1135 re_enter_rec = true;
1136 break;
1137 case HOST_CALL_EXIT_SUCCESS_CMD:
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001138 *host_call_result = TEST_RESULT_SUCCESS;
nabkah01002e5692022-10-10 12:36:46 +01001139 break;
1140 case HOST_CALL_EXIT_FAILED_CMD:
AlexeiFedorov2f30f102023-03-13 19:37:46 +00001141 *host_call_result = TEST_RESULT_FAIL;
nabkah01002e5692022-10-10 12:36:46 +01001142 default:
1143 break;
1144 }
nabkah01002e5692022-10-10 12:36:46 +01001145 }
nabkah01002e5692022-10-10 12:36:46 +01001146 } while (re_enter_rec);
1147
1148 *exit_reason = run->exit.exit_reason;
nabkah01002e5692022-10-10 12:36:46 +01001149 return ret;
1150}