blob: 4787da48bac6f2ca7df4bc3147e9cfcd44df7c58 [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
8#include <stdint.h>
9
10#include <arch_helpers.h>
11#include <debug.h>
12#include <events.h>
13#include <heap/page_alloc.h>
14#include <host_realm_helper.h>
15#include <host_realm_mem_layout.h>
16#include <host_realm_rmi.h>
17#include <host_shared_data.h>
18#include <plat_topology.h>
19#include <power_management.h>
20#include <realm_def.h>
21#include <test_helpers.h>
22#include <xlat_tables_v2.h>
23
24static struct realm realm;
25static bool realm_payload_created;
26static bool shared_mem_created;
27static bool realm_payload_mmaped;
28static u_register_t exit_reason = RMI_EXIT_INVALID;
AlexeiFedorov2f30f102023-03-13 19:37:46 +000029static unsigned int host_call_result = TEST_RESULT_FAIL;
nabkah01002e5692022-10-10 12:36:46 +010030static volatile bool timer_enabled;
31
32/* From the TFTF_BASE offset, memory used by TFTF + Shared + Realm + POOL should
33 * not exceed DRAM_END offset
34 * NS_REALM_SHARED_MEM_BASE + NS_REALM_SHARED_MEM_SIZE is considered last offset
35 */
36CASSERT((((uint64_t)NS_REALM_SHARED_MEM_BASE + (uint64_t)NS_REALM_SHARED_MEM_SIZE)\
37 < ((uint64_t)DRAM_BASE + (uint64_t)DRAM_SIZE)),\
38 error_ns_memory_and_realm_payload_exceed_DRAM_SIZE);
39
AlexeiFedorov2f30f102023-03-13 19:37:46 +000040#define RMI_EXIT(id) \
41 [RMI_EXIT_##id] = #id
42
43const char *rmi_exit[] = {
44 RMI_EXIT(SYNC),
45 RMI_EXIT(IRQ),
46 RMI_EXIT(FIQ),
47 RMI_EXIT(FIQ),
48 RMI_EXIT(PSCI),
49 RMI_EXIT(RIPAS_CHANGE),
50 RMI_EXIT(HOST_CALL),
51 RMI_EXIT(SERROR)
52};
53
nabkah01002e5692022-10-10 12:36:46 +010054/*
55 * The function handler to print the Realm logged buffer,
56 * executed by the secondary core
57 */
58static inline test_result_t timer_handler(void)
59{
60 size_t str_len = 0UL;
61 host_shared_data_t *host_shared_data = host_get_shared_structure();
62 char *log_buffer = (char *)host_shared_data->log_buffer;
63
64 do {
65 spin_lock((spinlock_t *)&host_shared_data->printf_lock);
66 str_len = strlen((const char *)log_buffer);
67
68 /*
69 * Read Realm message from shared printf location and print
AlexeiFedorov2f30f102023-03-13 19:37:46 +000070 * them using UART
nabkah01002e5692022-10-10 12:36:46 +010071 */
72 if (str_len != 0UL) {
73 /* Avoid memory overflow */
74 log_buffer[MAX_BUF_SIZE - 1] = 0U;
75
76 mp_printf("%s", log_buffer);
77 (void)memset((char *)log_buffer, 0, MAX_BUF_SIZE);
78 }
79 spin_unlock((spinlock_t *)&host_shared_data->printf_lock);
80
81 } while ((timer_enabled || (str_len != 0UL)));
82
83 return TEST_RESULT_SUCCESS;
84}
85
86/*
87 * Initialisation function which will clear the shared region,
88 * and try to find another CPU other than the lead one to
AlexeiFedorov2f30f102023-03-13 19:37:46 +000089 * handle the Realm message logging.
nabkah01002e5692022-10-10 12:36:46 +010090 */
91void host_init_realm_print_buffer(void)
92{
93 u_register_t other_mpidr, my_mpidr;
nabkah01002e5692022-10-10 12:36:46 +010094 host_shared_data_t *host_shared_data = host_get_shared_structure();
AlexeiFedorov2f30f102023-03-13 19:37:46 +000095 int ret;
nabkah01002e5692022-10-10 12:36:46 +010096
97 (void)memset((char *)host_shared_data, 0, sizeof(host_shared_data_t));
AlexeiFedorov2f30f102023-03-13 19:37:46 +000098
nabkah01002e5692022-10-10 12:36:46 +010099 /* Program timer */
100 timer_enabled = false;
101
102 /* Find a valid CPU to power on */
103 my_mpidr = read_mpidr_el1() & MPID_MASK;
104 other_mpidr = tftf_find_any_cpu_other_than(my_mpidr);
105 if (other_mpidr == INVALID_MPID) {
106 ERROR("Couldn't find a valid other CPU\n");
107 return;
108 }
109
110 /* Power on the other CPU */
111 ret = tftf_cpu_on(other_mpidr, (uintptr_t)timer_handler, 0);
112 if (ret != PSCI_E_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000113 ERROR("Powering on %lx failed\n", other_mpidr);
nabkah01002e5692022-10-10 12:36:46 +0100114 return;
115 }
116 timer_enabled = true;
117}
118
119/**
120 * @brief - Add regions assigned to Host into its translation table data
121 * structure.
122 **/
123static test_result_t host_mmap_realm_payload(u_register_t realm_payload_adr,
124 u_register_t plat_mem_pool_adr,
125 u_register_t plat_mem_pool_size)
126{
127 if (realm_payload_mmaped) {
128 return REALM_SUCCESS;
129 }
130
131 /* Memory Pool region */
132 int rc = mmap_add_dynamic_region(plat_mem_pool_adr,
133 plat_mem_pool_adr,
134 plat_mem_pool_size,
135 MT_RW_DATA | MT_NS);
nabkah01002e5692022-10-10 12:36:46 +0100136 if (rc != 0) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000137 ERROR("%u: mmap_add_dynamic_region() %d\n", __LINE__, rc);
nabkah01002e5692022-10-10 12:36:46 +0100138 return TEST_RESULT_FAIL;
139 }
140
141 /* Realm Image region */
142 rc = mmap_add_dynamic_region(realm_payload_adr,
143 realm_payload_adr,
144 REALM_MAX_LOAD_IMG_SIZE,
145 MT_RW_DATA | MT_NS);
nabkah01002e5692022-10-10 12:36:46 +0100146 if (rc != 0) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000147 ERROR("%u: mmap_add_dynamic_region() %d\n", __LINE__, rc);
nabkah01002e5692022-10-10 12:36:46 +0100148 return TEST_RESULT_FAIL;
149 }
150 realm_payload_mmaped = true;
151 return REALM_SUCCESS;
152}
153
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000154static bool host_enter_realm(u_register_t *exit_reason,
155 unsigned int *host_call_result)
nabkah01002e5692022-10-10 12:36:46 +0100156{
157 u_register_t ret;
158
159 if (!realm_payload_created) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000160 ERROR("%s() failed\n", "realm_payload_created");
nabkah01002e5692022-10-10 12:36:46 +0100161 return false;
162 }
163 if (!shared_mem_created) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000164 ERROR("%s() failed\n", "shared_mem_created");
nabkah01002e5692022-10-10 12:36:46 +0100165 return false;
166 }
167
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000168 /* Enter Realm */
169 ret = host_realm_rec_enter(&realm, exit_reason, host_call_result);
nabkah01002e5692022-10-10 12:36:46 +0100170 if (ret != REALM_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000171 ERROR("%s() failed, ret=%lx\n", "host_realm_rec_enter", ret);
nabkah01002e5692022-10-10 12:36:46 +0100172
173 /* Free test resources */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000174 if (host_realm_destroy(&realm) != REALM_SUCCESS) {
175 ERROR("%s() failed\n", "host_realm_destroy");
nabkah01002e5692022-10-10 12:36:46 +0100176 }
177 realm_payload_created = false;
178 return false;
179 }
180
181 return true;
182}
183
184bool host_create_realm_payload(u_register_t realm_payload_adr,
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000185 u_register_t plat_mem_pool_adr,
186 u_register_t plat_mem_pool_size,
187 u_register_t realm_pages_size,
188 u_register_t feature_flag)
nabkah01002e5692022-10-10 12:36:46 +0100189{
190 if (realm_payload_adr == TFTF_BASE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000191 ERROR("realm_payload_adr should be grater then TFTF_BASE\n");
nabkah01002e5692022-10-10 12:36:46 +0100192 return false;
193 }
194
195 if (plat_mem_pool_adr == 0UL ||
196 plat_mem_pool_size == 0UL ||
197 realm_pages_size == 0UL) {
198 ERROR("plat_mem_pool_size or "
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000199 "plat_mem_pool_size or realm_pages_size is NULL\n");
nabkah01002e5692022-10-10 12:36:46 +0100200 return false;
201 }
202 /* Initialize Host NS heap memory to be used in Realm creation*/
203 if (page_pool_init(plat_mem_pool_adr, realm_pages_size)
204 != HEAP_INIT_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000205 ERROR("%s() failed\n", "page_pool_init");
nabkah01002e5692022-10-10 12:36:46 +0100206 return false;
207 }
208
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000209 /* Mmap Realm payload region */
nabkah01002e5692022-10-10 12:36:46 +0100210 if (host_mmap_realm_payload(realm_payload_adr,
211 plat_mem_pool_adr,
212 plat_mem_pool_size) != REALM_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000213 ERROR("%s() failed\n", "host_mmap_realm_payload");
nabkah01002e5692022-10-10 12:36:46 +0100214 return false;
215 }
216
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000217 /* Read Realm Feature Reg 0 */
218 if (host_rmi_features(0UL, &realm.rmm_feat_reg0) != REALM_SUCCESS) {
219 ERROR("%s() failed\n", "host_rmi_features");
nabkah01002e5692022-10-10 12:36:46 +0100220 goto destroy_realm;
221 }
222
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000223 /* Disable PMU if not required */
224 if ((feature_flag & RMI_FEATURE_REGISTER_0_PMU_EN) == 0UL) {
225 realm.rmm_feat_reg0 &=
226 ~(RMI_FEATURE_REGISTER_0_PMU_EN |
227 RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS);
228 }
229
nabkah01002e5692022-10-10 12:36:46 +0100230 /* Create Realm */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000231 if (host_realm_create(&realm) != REALM_SUCCESS) {
232 ERROR("%s() failed\n", "host_realm_create");
nabkah01002e5692022-10-10 12:36:46 +0100233 goto destroy_realm;
234 }
235
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000236 if (host_realm_init_ipa_state(&realm, 0U, 0U, 1ULL << 32)
nabkah01002e5692022-10-10 12:36:46 +0100237 != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000238 ERROR("%s() failed\n", "host_realm_init_ipa_state");
nabkah01002e5692022-10-10 12:36:46 +0100239 goto destroy_realm;
240 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000241
nabkah01002e5692022-10-10 12:36:46 +0100242 /* RTT map Realm image */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000243 if (host_realm_map_payload_image(&realm, realm_payload_adr) !=
nabkah01002e5692022-10-10 12:36:46 +0100244 REALM_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000245 ERROR("%s() failed\n", "host_realm_map_payload_image");
nabkah01002e5692022-10-10 12:36:46 +0100246 goto destroy_realm;
247 }
248
249 /* Create REC */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000250 if (host_realm_rec_create(&realm) != REALM_SUCCESS) {
251 ERROR("%s() failed\n", "host_realm_rec_create");
nabkah01002e5692022-10-10 12:36:46 +0100252 goto destroy_realm;
253 }
254
255 /* Activate Realm */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000256 if (host_realm_activate(&realm) != REALM_SUCCESS) {
257 ERROR("%s() failed\n", "host_realm_activate");
nabkah01002e5692022-10-10 12:36:46 +0100258 goto destroy_realm;
259 }
260
261 realm_payload_created = true;
262
263 return realm_payload_created;
264
265 /* Free test resources */
266destroy_realm:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000267 if (host_realm_destroy(&realm) != REALM_SUCCESS) {
268 ERROR("%s() failed\n", "host_realm_destroy");
nabkah01002e5692022-10-10 12:36:46 +0100269 }
270 realm_payload_created = false;
271
272 return realm_payload_created;
273}
274
275bool host_create_shared_mem(u_register_t ns_shared_mem_adr,
276 u_register_t ns_shared_mem_size)
277{
278 /* RTT map NS shared region */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000279 if (host_realm_map_ns_shared(&realm, ns_shared_mem_adr,
280 ns_shared_mem_size) != REALM_SUCCESS) {
281 ERROR("%s() failed\n", "host_realm_map_ns_shared");
nabkah01002e5692022-10-10 12:36:46 +0100282 shared_mem_created = false;
283 return false;
284 }
285
286 host_init_realm_print_buffer();
287 realm_shared_data_clear_realm_val();
288 shared_mem_created = true;
289
290 return shared_mem_created;
291}
292
293bool host_destroy_realm(void)
294{
295 /* Free test resources */
296 timer_enabled = false;
297 page_pool_reset();
298
299 if (!realm_payload_created) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000300 ERROR("%s() failed\n", "realm_payload_created");
nabkah01002e5692022-10-10 12:36:46 +0100301 return false;
302 }
303
304 realm_payload_created = false;
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000305 if (host_realm_destroy(&realm) != REALM_SUCCESS) {
306 ERROR("%s() failed\n", "host_realm_destroy");
nabkah01002e5692022-10-10 12:36:46 +0100307 return false;
308 }
309
310 return true;
311}
312
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000313bool host_enter_realm_execute(uint8_t cmd, struct realm **realm_ptr)
nabkah01002e5692022-10-10 12:36:46 +0100314{
315 exit_reason = RMI_EXIT_INVALID;
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000316 host_call_result = TEST_RESULT_FAIL;
nabkah01002e5692022-10-10 12:36:46 +0100317
318 realm_shared_data_set_realm_cmd(cmd);
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000319 if (!host_enter_realm(&exit_reason, &host_call_result)) {
nabkah01002e5692022-10-10 12:36:46 +0100320 return false;
321 }
322
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000323 if (realm_ptr != NULL) {
324 *realm_ptr = &realm;
325 }
326
327 if (((exit_reason == RMI_EXIT_IRQ) &&
328 (cmd == REALM_PMU_INTERRUPT)) ||
329 ((exit_reason == RMI_EXIT_HOST_CALL) &&
330 (host_call_result == TEST_RESULT_SUCCESS))) {
nabkah01002e5692022-10-10 12:36:46 +0100331 return true;
332 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000333
334 if (exit_reason <= RMI_EXIT_SERROR) {
335 ERROR("%s(%u) RMI_EXIT_%s host_call_result=%u\n",
336 __func__, cmd, rmi_exit[exit_reason], host_call_result);
337 } else {
338 ERROR("%s(%u) 0x%lx host_call_result=%u\n",
339 __func__, cmd, exit_reason, host_call_result);
340 }
nabkah01002e5692022-10-10 12:36:46 +0100341 return false;
342}
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000343
344test_result_t host_cmp_result(void)
345{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000346 if (host_rmi_get_cmp_result()) {
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000347 return TEST_RESULT_SUCCESS;
348 }
349
350 ERROR("RMI registers comparison failed\n");
351 return TEST_RESULT_FAIL;
352}
353