blob: 09ac9a0e0ba4d78aef31fa19e8c06ad6a8a3fe62 [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;
nabkah01002e5692022-10-10 12:36:46 +010027static volatile bool timer_enabled;
28
AlexeiFedorov2f30f102023-03-13 19:37:46 +000029#define RMI_EXIT(id) \
30 [RMI_EXIT_##id] = #id
31
32const char *rmi_exit[] = {
33 RMI_EXIT(SYNC),
34 RMI_EXIT(IRQ),
35 RMI_EXIT(FIQ),
36 RMI_EXIT(FIQ),
37 RMI_EXIT(PSCI),
38 RMI_EXIT(RIPAS_CHANGE),
39 RMI_EXIT(HOST_CALL),
40 RMI_EXIT(SERROR)
41};
42
nabkah01002e5692022-10-10 12:36:46 +010043/*
44 * The function handler to print the Realm logged buffer,
45 * executed by the secondary core
46 */
47static inline test_result_t timer_handler(void)
48{
49 size_t str_len = 0UL;
50 host_shared_data_t *host_shared_data = host_get_shared_structure();
51 char *log_buffer = (char *)host_shared_data->log_buffer;
52
53 do {
54 spin_lock((spinlock_t *)&host_shared_data->printf_lock);
55 str_len = strlen((const char *)log_buffer);
56
57 /*
58 * Read Realm message from shared printf location and print
AlexeiFedorov2f30f102023-03-13 19:37:46 +000059 * them using UART
nabkah01002e5692022-10-10 12:36:46 +010060 */
61 if (str_len != 0UL) {
62 /* Avoid memory overflow */
63 log_buffer[MAX_BUF_SIZE - 1] = 0U;
64
65 mp_printf("%s", log_buffer);
66 (void)memset((char *)log_buffer, 0, MAX_BUF_SIZE);
67 }
68 spin_unlock((spinlock_t *)&host_shared_data->printf_lock);
69
70 } while ((timer_enabled || (str_len != 0UL)));
71
72 return TEST_RESULT_SUCCESS;
73}
74
75/*
76 * Initialisation function which will clear the shared region,
77 * and try to find another CPU other than the lead one to
AlexeiFedorov2f30f102023-03-13 19:37:46 +000078 * handle the Realm message logging.
nabkah01002e5692022-10-10 12:36:46 +010079 */
80void host_init_realm_print_buffer(void)
81{
82 u_register_t other_mpidr, my_mpidr;
nabkah01002e5692022-10-10 12:36:46 +010083 host_shared_data_t *host_shared_data = host_get_shared_structure();
AlexeiFedorov2f30f102023-03-13 19:37:46 +000084 int ret;
nabkah01002e5692022-10-10 12:36:46 +010085
86 (void)memset((char *)host_shared_data, 0, sizeof(host_shared_data_t));
AlexeiFedorov2f30f102023-03-13 19:37:46 +000087
nabkah01002e5692022-10-10 12:36:46 +010088 /* Program timer */
89 timer_enabled = false;
90
91 /* Find a valid CPU to power on */
92 my_mpidr = read_mpidr_el1() & MPID_MASK;
93 other_mpidr = tftf_find_any_cpu_other_than(my_mpidr);
94 if (other_mpidr == INVALID_MPID) {
95 ERROR("Couldn't find a valid other CPU\n");
96 return;
97 }
98
99 /* Power on the other CPU */
100 ret = tftf_cpu_on(other_mpidr, (uintptr_t)timer_handler, 0);
101 if (ret != PSCI_E_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000102 ERROR("Powering on %lx failed\n", other_mpidr);
nabkah01002e5692022-10-10 12:36:46 +0100103 return;
104 }
105 timer_enabled = true;
106}
107
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000108static bool host_enter_realm(u_register_t *exit_reason,
109 unsigned int *host_call_result)
nabkah01002e5692022-10-10 12:36:46 +0100110{
111 u_register_t ret;
112
113 if (!realm_payload_created) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000114 ERROR("%s() failed\n", "realm_payload_created");
nabkah01002e5692022-10-10 12:36:46 +0100115 return false;
116 }
117 if (!shared_mem_created) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000118 ERROR("%s() failed\n", "shared_mem_created");
nabkah01002e5692022-10-10 12:36:46 +0100119 return false;
120 }
121
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000122 /* Enter Realm */
123 ret = host_realm_rec_enter(&realm, exit_reason, host_call_result);
nabkah01002e5692022-10-10 12:36:46 +0100124 if (ret != REALM_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000125 ERROR("%s() failed, ret=%lx\n", "host_realm_rec_enter", ret);
nabkah01002e5692022-10-10 12:36:46 +0100126
127 /* Free test resources */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000128 if (host_realm_destroy(&realm) != REALM_SUCCESS) {
129 ERROR("%s() failed\n", "host_realm_destroy");
nabkah01002e5692022-10-10 12:36:46 +0100130 }
131 realm_payload_created = false;
132 return false;
133 }
134
135 return true;
136}
137
138bool host_create_realm_payload(u_register_t realm_payload_adr,
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000139 u_register_t plat_mem_pool_adr,
140 u_register_t plat_mem_pool_size,
141 u_register_t realm_pages_size,
142 u_register_t feature_flag)
nabkah01002e5692022-10-10 12:36:46 +0100143{
AlexeiFedorovf81345c2023-06-07 17:30:10 +0100144 int8_t value;
145
nabkah01002e5692022-10-10 12:36:46 +0100146 if (realm_payload_adr == TFTF_BASE) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000147 ERROR("realm_payload_adr should be grater then TFTF_BASE\n");
nabkah01002e5692022-10-10 12:36:46 +0100148 return false;
149 }
150
151 if (plat_mem_pool_adr == 0UL ||
152 plat_mem_pool_size == 0UL ||
153 realm_pages_size == 0UL) {
154 ERROR("plat_mem_pool_size or "
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000155 "plat_mem_pool_size or realm_pages_size is NULL\n");
nabkah01002e5692022-10-10 12:36:46 +0100156 return false;
157 }
Soby Mathew6e5c9962023-10-06 16:38:13 +0100158
159 INFO("Realm base adr=0x%lx\n", realm_payload_adr);
nabkah01002e5692022-10-10 12:36:46 +0100160 /* Initialize Host NS heap memory to be used in Realm creation*/
161 if (page_pool_init(plat_mem_pool_adr, realm_pages_size)
162 != HEAP_INIT_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000163 ERROR("%s() failed\n", "page_pool_init");
nabkah01002e5692022-10-10 12:36:46 +0100164 return false;
165 }
166
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000167 /* Read Realm Feature Reg 0 */
168 if (host_rmi_features(0UL, &realm.rmm_feat_reg0) != REALM_SUCCESS) {
169 ERROR("%s() failed\n", "host_rmi_features");
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100170 return false;
nabkah01002e5692022-10-10 12:36:46 +0100171 }
172
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000173 /* Disable PMU if not required */
174 if ((feature_flag & RMI_FEATURE_REGISTER_0_PMU_EN) == 0UL) {
AlexeiFedorovf81345c2023-06-07 17:30:10 +0100175 realm.rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_PMU_EN;
176 realm.pmu_num_ctrs = 0U;
177 } else {
178 value = EXTRACT(FEATURE_PMU_NUM_CTRS, feature_flag);
179 if (value != -1) {
180 realm.pmu_num_ctrs = (unsigned int)value;
181 } else {
182 realm.pmu_num_ctrs =
183 EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS,
184 realm.rmm_feat_reg0);
185 }
186 }
187
188 /* Disable SVE if not required */
189 if ((feature_flag & RMI_FEATURE_REGISTER_0_SVE_EN) == 0UL) {
190 realm.rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_SVE_EN;
191 realm.sve_vl = 0U;
192 } else {
193 realm.sve_vl = EXTRACT(FEATURE_SVE_VL, feature_flag);
194 }
195
196 /* Requested number of breakpoints */
197 value = EXTRACT(FEATURE_NUM_BPS, feature_flag);
198 if (value != -1) {
199 realm.num_bps = (unsigned int)value;
200 } else {
201 realm.num_bps = EXTRACT(RMI_FEATURE_REGISTER_0_NUM_BPS,
202 realm.rmm_feat_reg0);
203 }
204
205 /* Requested number of watchpoints */
206 value = EXTRACT(FEATURE_NUM_WPS, feature_flag);
207 if (value != -1) {
208 realm.num_wps = (unsigned int)value;
209 } else {
210 realm.num_wps = EXTRACT(RMI_FEATURE_REGISTER_0_NUM_WPS,
211 realm.rmm_feat_reg0);
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000212 }
213
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100214 /* Set SVE bits from feature_flag */
AlexeiFedorovb69eae02023-04-06 10:27:58 +0100215 realm.rmm_feat_reg0 &= ~(RMI_FEATURE_REGISTER_0_SVE_EN |
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100216 MASK(RMI_FEATURE_REGISTER_0_SVE_VL));
AlexeiFedorovb69eae02023-04-06 10:27:58 +0100217 if ((feature_flag & RMI_FEATURE_REGISTER_0_SVE_EN) != 0UL) {
218 realm.rmm_feat_reg0 |= RMI_FEATURE_REGISTER_0_SVE_EN |
219 INPLACE(RMI_FEATURE_REGISTER_0_SVE_VL,
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100220 EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL,
AlexeiFedorovb69eae02023-04-06 10:27:58 +0100221 feature_flag));
222 }
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +0100223
nabkah01002e5692022-10-10 12:36:46 +0100224 /* Create Realm */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000225 if (host_realm_create(&realm) != REALM_SUCCESS) {
226 ERROR("%s() failed\n", "host_realm_create");
AlexeiFedorovf81345c2023-06-07 17:30:10 +0100227 return false;
nabkah01002e5692022-10-10 12:36:46 +0100228 }
229
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000230 if (host_realm_init_ipa_state(&realm, 0U, 0U, 1ULL << 32)
nabkah01002e5692022-10-10 12:36:46 +0100231 != RMI_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000232 ERROR("%s() failed\n", "host_realm_init_ipa_state");
nabkah01002e5692022-10-10 12:36:46 +0100233 goto destroy_realm;
234 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000235
nabkah01002e5692022-10-10 12:36:46 +0100236 /* RTT map Realm image */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000237 if (host_realm_map_payload_image(&realm, realm_payload_adr) !=
nabkah01002e5692022-10-10 12:36:46 +0100238 REALM_SUCCESS) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000239 ERROR("%s() failed\n", "host_realm_map_payload_image");
nabkah01002e5692022-10-10 12:36:46 +0100240 goto destroy_realm;
241 }
242
243 /* Create REC */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000244 if (host_realm_rec_create(&realm) != REALM_SUCCESS) {
245 ERROR("%s() failed\n", "host_realm_rec_create");
nabkah01002e5692022-10-10 12:36:46 +0100246 goto destroy_realm;
247 }
248
249 /* Activate Realm */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000250 if (host_realm_activate(&realm) != REALM_SUCCESS) {
251 ERROR("%s() failed\n", "host_realm_activate");
nabkah01002e5692022-10-10 12:36:46 +0100252 goto destroy_realm;
253 }
254
255 realm_payload_created = true;
256
257 return realm_payload_created;
258
259 /* Free test resources */
260destroy_realm:
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000261 if (host_realm_destroy(&realm) != REALM_SUCCESS) {
262 ERROR("%s() failed\n", "host_realm_destroy");
nabkah01002e5692022-10-10 12:36:46 +0100263 }
264 realm_payload_created = false;
265
266 return realm_payload_created;
267}
268
269bool host_create_shared_mem(u_register_t ns_shared_mem_adr,
270 u_register_t ns_shared_mem_size)
271{
272 /* RTT map NS shared region */
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000273 if (host_realm_map_ns_shared(&realm, ns_shared_mem_adr,
274 ns_shared_mem_size) != REALM_SUCCESS) {
275 ERROR("%s() failed\n", "host_realm_map_ns_shared");
nabkah01002e5692022-10-10 12:36:46 +0100276 shared_mem_created = false;
277 return false;
278 }
279
280 host_init_realm_print_buffer();
281 realm_shared_data_clear_realm_val();
282 shared_mem_created = true;
283
284 return shared_mem_created;
285}
286
287bool host_destroy_realm(void)
288{
289 /* Free test resources */
290 timer_enabled = false;
291 page_pool_reset();
292
293 if (!realm_payload_created) {
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000294 ERROR("%s() failed\n", "realm_payload_created");
nabkah01002e5692022-10-10 12:36:46 +0100295 return false;
296 }
297
298 realm_payload_created = false;
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000299 if (host_realm_destroy(&realm) != REALM_SUCCESS) {
300 ERROR("%s() failed\n", "host_realm_destroy");
nabkah01002e5692022-10-10 12:36:46 +0100301 return false;
302 }
303
304 return true;
305}
306
nabkah01cd668462022-11-06 15:29:44 +0000307bool host_enter_realm_execute(uint8_t cmd, struct realm **realm_ptr, int test_exit_reason)
nabkah01002e5692022-10-10 12:36:46 +0100308{
nabkah01cd668462022-11-06 15:29:44 +0000309 u_register_t exit_reason = RMI_EXIT_INVALID;
310 unsigned int host_call_result = TEST_RESULT_FAIL;
nabkah01002e5692022-10-10 12:36:46 +0100311
312 realm_shared_data_set_realm_cmd(cmd);
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000313 if (!host_enter_realm(&exit_reason, &host_call_result)) {
nabkah01002e5692022-10-10 12:36:46 +0100314 return false;
315 }
316
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000317 if (realm_ptr != NULL) {
318 *realm_ptr = &realm;
319 }
320
nabkah01cd668462022-11-06 15:29:44 +0000321 if ((exit_reason == RMI_EXIT_HOST_CALL) && (host_call_result == TEST_RESULT_SUCCESS)) {
nabkah01002e5692022-10-10 12:36:46 +0100322 return true;
323 }
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000324
nabkah01cd668462022-11-06 15:29:44 +0000325 if (test_exit_reason == exit_reason) {
326 return true;
327 }
328
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000329 if (exit_reason <= RMI_EXIT_SERROR) {
330 ERROR("%s(%u) RMI_EXIT_%s host_call_result=%u\n",
331 __func__, cmd, rmi_exit[exit_reason], host_call_result);
332 } else {
333 ERROR("%s(%u) 0x%lx host_call_result=%u\n",
334 __func__, cmd, exit_reason, host_call_result);
335 }
nabkah01002e5692022-10-10 12:36:46 +0100336 return false;
337}
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000338
339test_result_t host_cmp_result(void)
340{
AlexeiFedorov2f30f102023-03-13 19:37:46 +0000341 if (host_rmi_get_cmp_result()) {
AlexeiFedorov380b2af2022-11-23 17:31:27 +0000342 return TEST_RESULT_SUCCESS;
343 }
344
345 ERROR("RMI registers comparison failed\n");
346 return TEST_RESULT_FAIL;
347}
348