blob: fb60988d211b093e7102562afd4c09f17bbb3948 [file] [log] [blame]
Shruti Guptaf31bbe72023-09-27 14:04:53 +01001/*
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00002 * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
Shruti Guptaf31bbe72023-09-27 14:04:53 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdlib.h>
Shruti Gupta6bb95102023-10-02 13:21:37 +01008#include <drivers/arm/arm_gic.h>
Shruti Guptaf31bbe72023-09-27 14:04:53 +01009#include <debug.h>
Shruti Gupta6bb95102023-10-02 13:21:37 +010010#include <platform.h>
11#include <plat_topology.h>
Shruti Guptaf31bbe72023-09-27 14:04:53 +010012#include <power_management.h>
13#include <psci.h>
14#include <test_helpers.h>
15
16#include <host_realm_helper.h>
17#include <host_realm_mem_layout.h>
18#include <host_realm_pmu.h>
19#include <host_shared_data.h>
20
Shruti Gupta6bb95102023-10-02 13:21:37 +010021static uint64_t is_secondary_cpu_on;
Shruti Guptaec060832023-11-21 00:44:47 +000022static struct realm realm;
Shruti Guptab1b37922024-01-13 21:49:04 +000023static struct realm realm1;
Shruti Gupta47078f32025-01-16 18:54:24 +000024static struct pmu_registers pmu_state[PLATFORM_CORE_COUNT];
Shruti Guptaec060832023-11-21 00:44:47 +000025
Shruti Guptaf31bbe72023-09-27 14:04:53 +010026/*
27 * Test tries to create max Rec
28 * Enters all Rec from single CPU
29 */
30test_result_t host_realm_multi_rec_single_cpu(void)
31{
32 bool ret1, ret2;
AlexeiFedorov93d4df52024-10-03 09:44:52 +010033 u_register_t rec_flag[MAX_REC_COUNT];
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +010034 u_register_t feature_flag = 0U;
35 long sl = RTT_MIN_LEVEL;
AlexeiFedorov0db147a2024-10-03 16:46:35 +010036 unsigned int rec_num;
Shruti Guptaf31bbe72023-09-27 14:04:53 +010037
38 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
39
AlexeiFedorovc398c8f2025-01-16 14:35:48 +000040 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +010041 feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
42 sl = RTT_MIN_LEVEL_LPA2;
43 }
44
AlexeiFedorov93d4df52024-10-03 09:44:52 +010045 for (unsigned int i = 0U; i < MAX_REC_COUNT; i++) {
46 rec_flag[i] = RMI_RUNNABLE;
47 }
48
Shruti Gupta941c99a2023-12-15 02:10:55 +000049 if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +010050 feature_flag, 0U, sl, rec_flag, MAX_REC_COUNT, 0U, get_test_mecid())) {
Shruti Guptaf31bbe72023-09-27 14:04:53 +010051 return TEST_RESULT_FAIL;
52 }
Shruti Guptaf31bbe72023-09-27 14:04:53 +010053
AlexeiFedorov0db147a2024-10-03 16:46:35 +010054 /* Start random Rec */
55 rec_num = (unsigned int)rand() % MAX_REC_COUNT;
56
Shruti Guptaf31bbe72023-09-27 14:04:53 +010057 for (unsigned int i = 0; i < MAX_REC_COUNT; i++) {
Shruti Gupta69cae792024-11-27 04:30:00 +000058 host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID,
59 rec_num, HOST_ARG1_INDEX, 10U);
60
Shruti Guptaec060832023-11-21 00:44:47 +000061 ret1 = host_enter_realm_execute(&realm, REALM_SLEEP_CMD,
AlexeiFedorov0db147a2024-10-03 16:46:35 +010062 RMI_EXIT_HOST_CALL, rec_num);
Shruti Guptaf31bbe72023-09-27 14:04:53 +010063 if (!ret1) {
64 break;
65 }
AlexeiFedorov0db147a2024-10-03 16:46:35 +010066
67 /* Increment Rec number */
68 if (++rec_num == MAX_REC_COUNT) {
69 rec_num = 0U;
70 }
Shruti Guptaf31bbe72023-09-27 14:04:53 +010071 }
72
Shruti Guptaec060832023-11-21 00:44:47 +000073 ret2 = host_destroy_realm(&realm);
Shruti Guptaf31bbe72023-09-27 14:04:53 +010074
75 if (!ret1 || !ret2) {
76 ERROR("%s(): enter=%d destroy=%d\n",
77 __func__, ret1, ret2);
78 return TEST_RESULT_FAIL;
79 }
80
81 return TEST_RESULT_SUCCESS;
82}
Shruti Gupta24597d12023-10-02 10:40:19 +010083
84/*
85 * Test creates 3 Rec
86 * Rec0 requests CPU ON for rec 1
87 * Host denies CPU On for rec 1
88 * Host tried to enter rec 1 and fails
89 * Host re-enters rec 0
90 * Rec 0 checks CPU ON is denied
91 * Rec0 requests CPU ON for rec 2
92 * Host denies CPU On which should fail as rec is runnable
93 * Host allows CPU ON and re-enters rec 0
94 * Rec 0 checks return already_on
95 */
96test_result_t host_realm_multi_rec_psci_denied(void)
97{
Shruti Gupta24597d12023-10-02 10:40:19 +010098 bool ret1, ret2;
99 u_register_t ret;
100 unsigned int host_call_result;
101 u_register_t exit_reason;
102 unsigned int rec_num;
103 struct rmi_rec_run *run;
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100104 u_register_t feature_flag = 0U;
105 long sl = RTT_MIN_LEVEL;
Shruti Gupta24597d12023-10-02 10:40:19 +0100106 /* Create 3 rec Rec 0 and 2 are runnable, Rec 1 in not runnable */
107 u_register_t rec_flag[] = {RMI_RUNNABLE, RMI_NOT_RUNNABLE, RMI_RUNNABLE};
108
109 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
110
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000111 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100112 feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
113 sl = RTT_MIN_LEVEL_LPA2;
114 }
115
Shruti Gupta941c99a2023-12-15 02:10:55 +0000116 if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100117 feature_flag, 0U, sl, rec_flag, 3U, 0U, get_test_mecid())) {
Shruti Gupta24597d12023-10-02 10:40:19 +0100118 return TEST_RESULT_FAIL;
119 }
Shruti Gupta24597d12023-10-02 10:40:19 +0100120
Shruti Guptaec060832023-11-21 00:44:47 +0000121 ret1 = host_enter_realm_execute(&realm, REALM_MULTIPLE_REC_PSCI_DENIED_CMD,
Shruti Gupta24597d12023-10-02 10:40:19 +0100122 RMI_EXIT_PSCI, 0U);
Shruti Guptaec060832023-11-21 00:44:47 +0000123 run = (struct rmi_rec_run *)realm.run[0];
Shruti Gupta24597d12023-10-02 10:40:19 +0100124
125 if (run->exit.gprs[0] != SMC_PSCI_CPU_ON_AARCH64) {
126 ERROR("Host did not receive CPU ON request\n");
127 ret1 = false;
128 goto destroy_realm;
129 }
Shruti Guptaec060832023-11-21 00:44:47 +0000130 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
Shruti Gupta24597d12023-10-02 10:40:19 +0100131 if (rec_num != 1U) {
132 ERROR("Invalid mpidr requested\n");
133 ret1 = false;
134 goto destroy_realm;
135 }
136 INFO("Requesting PSCI Complete Status Denied REC %d\n", rec_num);
Shruti Guptaec060832023-11-21 00:44:47 +0000137 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
Shruti Gupta24597d12023-10-02 10:40:19 +0100138 (unsigned long)PSCI_E_DENIED);
139 if (ret != RMI_SUCCESS) {
140 ERROR("host_rmi_psci_complete failed\n");
141 ret1 = false;
142 goto destroy_realm;
143 }
144
145 /* Enter rec1, should fail */
Shruti Guptaec060832023-11-21 00:44:47 +0000146 ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 1U);
Shruti Gupta24597d12023-10-02 10:40:19 +0100147 if (ret == RMI_SUCCESS) {
148 ERROR("Rec1 enter should have failed\n");
149 ret1 = false;
150 goto destroy_realm;
151 }
Shruti Guptaec060832023-11-21 00:44:47 +0000152 ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 0U);
Shruti Gupta24597d12023-10-02 10:40:19 +0100153
154 if (run->exit.gprs[0] != SMC_PSCI_AFFINITY_INFO_AARCH64) {
155 ERROR("Host did not receive PSCI_AFFINITY_INFO request\n");
156 ret1 = false;
157 goto destroy_realm;
158 }
Shruti Guptaec060832023-11-21 00:44:47 +0000159 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
Shruti Gupta24597d12023-10-02 10:40:19 +0100160 if (rec_num != 1U) {
161 ERROR("Invalid mpidr requested\n");
162 goto destroy_realm;
163 }
164
165 INFO("Requesting PSCI Complete Affinity Info REC %d\n", rec_num);
Shruti Guptaec060832023-11-21 00:44:47 +0000166 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
Shruti Gupta24597d12023-10-02 10:40:19 +0100167 (unsigned long)PSCI_E_SUCCESS);
168 if (ret != RMI_SUCCESS) {
169 ERROR("host_rmi_psci_complete failed\n");
170 ret1 = false;
171 goto destroy_realm;
172 }
173
174 /* Re-enter REC0 complete PSCI_AFFINITY_INFO */
Shruti Guptaec060832023-11-21 00:44:47 +0000175 ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 0U);
Shruti Gupta24597d12023-10-02 10:40:19 +0100176
177
178 if (run->exit.gprs[0] != SMC_PSCI_CPU_ON_AARCH64) {
179 ERROR("Host did not receive CPU ON request\n");
180 ret1 = false;
181 goto destroy_realm;
182 }
Shruti Guptaec060832023-11-21 00:44:47 +0000183 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
Shruti Gupta24597d12023-10-02 10:40:19 +0100184 if (rec_num != 2U) {
185 ERROR("Invalid mpidr requested\n");
186 ret1 = false;
187 goto destroy_realm;
188 }
189
190 INFO("Requesting PSCI Complete Status Denied REC %d\n", rec_num);
191 /* PSCI_DENIED should fail as rec2 is RMI_RUNNABLE */
Shruti Guptaec060832023-11-21 00:44:47 +0000192 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
Shruti Gupta24597d12023-10-02 10:40:19 +0100193 (unsigned long)PSCI_E_DENIED);
194 if (ret == RMI_SUCCESS) {
195 ret1 = false;
196 ERROR("host_rmi_psci_complete should have failed\n");
197 goto destroy_realm;
198 }
199
Shruti Guptaec060832023-11-21 00:44:47 +0000200 ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 0U);
Shruti Gupta24597d12023-10-02 10:40:19 +0100201 if (ret != RMI_SUCCESS) {
202 ERROR("Rec0 re-enter failed\n");
203 ret1 = false;
204 goto destroy_realm;
205 }
206
207destroy_realm:
Shruti Guptaec060832023-11-21 00:44:47 +0000208 ret2 = host_destroy_realm(&realm);
Shruti Gupta24597d12023-10-02 10:40:19 +0100209
210 if (!ret1 || !ret2) {
211 ERROR("%s(): enter=%d destroy=%d\n",
212 __func__, ret1, ret2);
213 return TEST_RESULT_FAIL;
214 }
215
216 return host_cmp_result();
217}
Shruti Gupta6bb95102023-10-02 13:21:37 +0100218
219/* Lock used to avoid concurrent accesses to the secondary_cpu_on counter */
220spinlock_t secondary_cpu_lock;
221
222static test_result_t cpu_on_handler2(void)
223{
224 bool ret;
225
226 spin_lock(&secondary_cpu_lock);
227 is_secondary_cpu_on++;
228 spin_unlock(&secondary_cpu_lock);
229
Shruti Guptaec060832023-11-21 00:44:47 +0000230 ret = host_enter_realm_execute(&realm, REALM_LOOP_CMD,
231 RMI_EXIT_IRQ, is_secondary_cpu_on);
Shruti Gupta6bb95102023-10-02 13:21:37 +0100232 if (!ret) {
233 return TEST_RESULT_FAIL;
234 }
235 return TEST_RESULT_SUCCESS;
236}
237
238test_result_t host_realm_multi_rec_exit_irq(void)
239{
240 bool ret1, ret2;
Shruti Gupta6bb95102023-10-02 13:21:37 +0100241 u_register_t other_mpidr, my_mpidr, ret;
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100242 unsigned int cpu_node, rec_count;
Shruti Guptade01b5d2024-12-02 21:17:11 +0000243 u_register_t feature_flag0 = 0U;
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100244 long sl = RTT_MIN_LEVEL;
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100245 u_register_t rec_flag[MAX_REC_COUNT];
Shruti Gupta6bb95102023-10-02 13:21:37 +0100246
247 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100248
249 rec_count = tftf_get_total_cpus_count();
250 assert(rec_count <= MAX_REC_COUNT);
Shruti Gupta6bb95102023-10-02 13:21:37 +0100251
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000252 if (is_feat_52b_on_4k_2_supported()) {
Shruti Guptade01b5d2024-12-02 21:17:11 +0000253 feature_flag0 = RMI_FEATURE_REGISTER_0_LPA2;
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100254 sl = RTT_MIN_LEVEL_LPA2;
255 }
256
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100257 for (unsigned int i = 0U; i < rec_count; i++) {
258 rec_flag[i] = RMI_RUNNABLE;
259 }
260
Shruti Gupta941c99a2023-12-15 02:10:55 +0000261 if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100262 feature_flag0, 0U, sl, rec_flag, rec_count, 0U, get_test_mecid())) {
Shruti Gupta6bb95102023-10-02 13:21:37 +0100263 return TEST_RESULT_FAIL;
264 }
Shruti Gupta6bb95102023-10-02 13:21:37 +0100265
266 is_secondary_cpu_on = 0U;
267 my_mpidr = read_mpidr_el1() & MPID_MASK;
Shruti Guptaec060832023-11-21 00:44:47 +0000268 ret1 = host_enter_realm_execute(&realm, REALM_GET_RSI_VERSION, RMI_EXIT_HOST_CALL, 0U);
Shruti Gupta6bb95102023-10-02 13:21:37 +0100269 for_each_cpu(cpu_node) {
270 other_mpidr = tftf_get_mpidr_from_node(cpu_node);
271 if (other_mpidr == my_mpidr) {
272 continue;
273 }
274 /* Power on the other CPU */
275 ret = tftf_try_cpu_on(other_mpidr, (uintptr_t)cpu_on_handler2, 0);
276 if (ret != PSCI_E_SUCCESS) {
277 goto destroy_realm;
278 }
279 }
280
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100281 INFO("Wait for all CPUs to come up\n");
Shruti Gupta6bb95102023-10-02 13:21:37 +0100282 while (is_secondary_cpu_on != (rec_count - 1U)) {
283 waitms(100U);
284 }
285
286destroy_realm:
Boyan Karatotev6d144db2025-06-23 15:04:53 +0100287 tftf_irq_enable_sgi(IRQ_NS_SGI_7, GIC_HIGHEST_NS_PRIORITY);
Shruti Gupta6bb95102023-10-02 13:21:37 +0100288 for (unsigned int i = 1U; i < rec_count; i++) {
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100289 INFO("Raising NS IRQ for rec %u\n", i);
Shruti Guptaec060832023-11-21 00:44:47 +0000290 host_rec_send_sgi(&realm, IRQ_NS_SGI_7, i);
Shruti Gupta6bb95102023-10-02 13:21:37 +0100291 }
Boyan Karatotev6d144db2025-06-23 15:04:53 +0100292 tftf_irq_disable_sgi(IRQ_NS_SGI_7);
Shruti Guptaec060832023-11-21 00:44:47 +0000293 ret2 = host_destroy_realm(&realm);
Shruti Gupta6bb95102023-10-02 13:21:37 +0100294 if (!ret1 || !ret2) {
295 ERROR("%s(): enter=%d destroy=%d\n",
296 __func__, ret1, ret2);
297 return TEST_RESULT_FAIL;
298 }
299
300 return host_cmp_result();
301}
Shruti Guptaaffbae82023-08-22 12:51:11 +0100302
Shruti Guptabd729192025-01-24 17:02:15 +0000303static test_result_t plane_cpu_on_handler(void)
304{
305 bool ret;
306 struct rmi_rec_run *run;
307 unsigned int i;
308
309 spin_lock(&secondary_cpu_lock);
310 i = ++is_secondary_cpu_on;
311 spin_unlock(&secondary_cpu_lock);
312
313 /* Args for plane 0 to enter plane 1 on rec i */
314 host_realm_set_aux_plane_args(&realm, 1U, i);
315
316 /* CMD for Plane 1 Rec i */
317 host_shared_data_set_realm_cmd(&realm, REALM_PLANES_MULTIPLE_REC_MULTIPLE_CPU_CMD, 1U, i);
318
319 run = (struct rmi_rec_run *)realm.run[i];
320
321 /* Enter P0 and then P1 */
322 ret = host_enter_realm_execute(&realm, REALM_PLANES_MULTIPLE_REC_MULTIPLE_CPU_CMD,
323 RMI_EXIT_PSCI, i);
324 if (ret) {
325 if (run->exit.gprs[0] == SMC_PSCI_CPU_OFF) {
326 return TEST_RESULT_SUCCESS;
327 }
328 }
329 ERROR("Rec %d failed", i);
330 return TEST_RESULT_FAIL;
331}
332
333/*
334 * The test creates a realm with 2 planes and MAX recs
335 * Host enters P0 and then PN
336 * P1 issues PSCI_CPU_ON SMC, returns back to P0
337 * P0 forwards PSCI_CPU_ON to Host
338 * On receiving PSCI_CPU_ON call from P0 REC0 for all other recs,
339 * the test completes the PSCI call and re-enters P0 REC0 - followed by P1 REC0.
340 * Turn ON secondary CPUs upto a max of MAX_REC_COUNT.
341 * Each of the secondary then enters Realm (P0 followed by P1) with a different REC
342 * It is expected that the REC will exit with PSCI_CPU_OFF as the exit reason.
343 * P0 REC0 checks if all other CPUs are off, via PSCI_AFFINITY_INFO.
344 * Host completes the PSCI requests.
345 */
346test_result_t host_realm_multi_planes_multi_rec_multiple_cpu(void)
347{
348 bool ret1, ret2;
349 test_result_t ret3 = TEST_RESULT_FAIL;
350 int ret = RMI_ERROR_INPUT;
351 u_register_t rec_num;
352 u_register_t other_mpidr, my_mpidr;
353 struct rmi_rec_run *run;
354 unsigned int host_call_result, i;
355 u_register_t rec_flag[MAX_REC_COUNT] = {RMI_RUNNABLE};
356 u_register_t exit_reason;
357 unsigned int cpu_node, rec_count, num_aux_planes = 1U;
358 u_register_t feature_flag0 = 0U, feature_flag1 = 0U;
359 long sl = RTT_MIN_LEVEL;
360
361 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
362
363 rec_count = tftf_get_total_cpus_count();
364 assert(rec_count <= MAX_REC_COUNT);
365
366 if (is_feat_52b_on_4k_2_supported()) {
367 feature_flag0 = RMI_FEATURE_REGISTER_0_LPA2;
368 sl = RTT_MIN_LEVEL_LPA2;
369 }
370
371 if (!are_planes_supported()) {
372 return TEST_RESULT_SKIPPED;
373 }
374
375 if (is_single_rtt_supported()) {
376 /* Use single RTT with S2AP Indirect */
377 feature_flag0 |= INPLACE(RMI_FEATURE_REGISTER_0_PLANE_RTT,
378 RMI_PLANE_RTT_SINGLE);
379 feature_flag1 = RMI_REALM_FLAGS1_RTT_S2AP_ENCODING_INDIRECT;
380 }
381
382 for (i = 1U; i < rec_count; i++) {
383 rec_flag[i] = RMI_NOT_RUNNABLE;
384 }
385
386 if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Juan Pablo Condedc23fcd2025-04-05 14:26:13 -0500387 feature_flag0, feature_flag1, sl, rec_flag, rec_count, num_aux_planes,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100388 get_test_mecid())) {
Shruti Guptabd729192025-01-24 17:02:15 +0000389 return TEST_RESULT_FAIL;
390 }
391
392 is_secondary_cpu_on = 0U;
393 init_spinlock(&secondary_cpu_lock);
394 my_mpidr = read_mpidr_el1() & MPID_MASK;
395 host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG3_INDEX, rec_count);
396 host_shared_data_set_host_val(&realm, 1U, 0U, HOST_ARG3_INDEX, rec_count);
397
398 /* Set args for entering Plane 1 Rec0 */
399 host_realm_set_aux_plane_args(&realm, 1U, 0U);
400
401 /* CMD for Plane 1 */
402 host_shared_data_set_realm_cmd(&realm, REALM_PLANES_MULTIPLE_REC_MULTIPLE_CPU_CMD, 1U, 0U);
403
404 /* Enter P0, and then PN */
405 ret1 = host_enter_realm_execute(&realm, REALM_PLANES_MULTIPLE_REC_MULTIPLE_CPU_CMD,
406 RMI_EXIT_PSCI, 0U);
407
408 if (!ret1) {
409 ERROR("Host did not receive CPU ON request\n");
410
411 goto destroy_realm;
412 }
413 while (true) {
414 run = (struct rmi_rec_run *)realm.run[0];
415 if (run->exit.gprs[0] != SMC_PSCI_CPU_ON_AARCH64) {
416 ERROR("Host did not receive CPU ON request\n");
417 goto destroy_realm;
418 }
419 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
420 if (rec_num >= MAX_REC_COUNT) {
421 ERROR("Invalid mpidr requested\n");
422 goto destroy_realm;
423 }
424 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
425 (unsigned long)PSCI_E_SUCCESS);
426 if (ret == RMI_SUCCESS) {
427 /* Re-enter REC0 complete CPU_ON */
428 ret = host_realm_rec_enter(&realm, &exit_reason,
429 &host_call_result, 0U);
430 if (ret != RMI_SUCCESS || exit_reason != RMI_EXIT_PSCI) {
431 break;
432 }
433 } else {
434 ERROR("host_rmi_psci_complete failed\n");
435 goto destroy_realm;
436 }
437 }
438 if (exit_reason != RMI_EXIT_HOST_CALL || host_call_result != TEST_RESULT_SUCCESS) {
439 ERROR("Realm failed\n");
440 goto destroy_realm;
441 }
442
443 i = 0U;
444
445 /* Turn on all CPUs */
446 for_each_cpu(cpu_node) {
447 if (i == (rec_count - 1U)) {
448 break;
449 }
450 other_mpidr = tftf_get_mpidr_from_node(cpu_node);
451 if (other_mpidr == my_mpidr) {
452 continue;
453 }
454
455 /* Power on the other CPU */
456 ret = tftf_try_cpu_on(other_mpidr, (uintptr_t)plane_cpu_on_handler, 0);
457 if (ret != PSCI_E_SUCCESS) {
458 ERROR("TFTF CPU ON failed\n");
459 goto destroy_realm;
460 }
461 i++;
462 }
463
464 while (true) {
465 /* Re-enter REC0 complete PSCI_AFFINITY_INFO */
466 ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 0U);
467 if (ret != RMI_SUCCESS) {
468 ERROR("Rec0 re-enter failed\n");
469 goto destroy_realm;
470 }
471 if (run->exit.gprs[0] != SMC_PSCI_AFFINITY_INFO_AARCH64) {
472 break;
473 }
474 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
475 if (rec_num >= rec_count) {
476 ERROR("Invalid mpidr requested\n");
477 goto destroy_realm;
478 }
479 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
480 (unsigned long)PSCI_E_SUCCESS);
481
482 if (ret != RMI_SUCCESS) {
483 ERROR("host_rmi_psci_complete failed\n");
484 goto destroy_realm;
485 }
486 }
487
488 if (ret == RMI_SUCCESS && exit_reason == RMI_EXIT_HOST_CALL) {
489 ret3 = host_call_result;
490 }
491destroy_realm:
492 waitms(100U);
493 ret2 = host_destroy_realm(&realm);
494
495 if ((ret != RMI_SUCCESS) || !ret2) {
496 ERROR("%s(): enter=%d destroy=%d\n",
497 __func__, ret, ret2);
498 return TEST_RESULT_FAIL;
499 }
500
501 return ret3;
502}
503
Shruti Guptaaffbae82023-08-22 12:51:11 +0100504static test_result_t cpu_on_handler(void)
505{
506 bool ret;
507 struct rmi_rec_run *run;
508 unsigned int i;
509
510 spin_lock(&secondary_cpu_lock);
511 i = ++is_secondary_cpu_on;
512 spin_unlock(&secondary_cpu_lock);
513 ret = host_enter_realm_execute(&realm, REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
514 RMI_EXIT_PSCI, i);
515 if (ret) {
516 run = (struct rmi_rec_run *)realm.run[i];
517 if (run->exit.gprs[0] == SMC_PSCI_CPU_OFF) {
518 return TEST_RESULT_SUCCESS;
519 }
520 }
521 ERROR("Rec %d failed\n", i);
522 return TEST_RESULT_FAIL;
523}
524
525/*
526 * The test creates a realm with MAX recs
527 * On receiving PSCI_CPU_ON call from REC0 for all other recs,
528 * the test completes the PSCI call and re-enters REC0.
529 * Turn ON secondary CPUs upto a max of MAX_REC_COUNT.
530 * Each of the secondary then enters Realm with a different REC
531 * and executes the test REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD in Realm payload.
532 * It is expected that the REC will exit with PSCI_CPU_OFF as the exit reason.
AlexeiFedorov0db147a2024-10-03 16:46:35 +0100533 * REC0 checks if all other CPUs are off, via PSCI_AFFINITY_INFO.
Shruti Guptaaffbae82023-08-22 12:51:11 +0100534 * Host completes the PSCI requests.
535 */
536test_result_t host_realm_multi_rec_multiple_cpu(void)
537{
538 bool ret1, ret2;
539 test_result_t ret3 = TEST_RESULT_FAIL;
540 int ret = RMI_ERROR_INPUT;
541 u_register_t rec_num;
542 u_register_t other_mpidr, my_mpidr;
543 struct rmi_rec_run *run;
AlexeiFedorov0db147a2024-10-03 16:46:35 +0100544 unsigned int host_call_result, i;
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100545 u_register_t rec_flag[MAX_REC_COUNT] = {RMI_RUNNABLE};
Shruti Guptaaffbae82023-08-22 12:51:11 +0100546 u_register_t exit_reason;
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100547 unsigned int cpu_node, rec_count;
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100548 u_register_t feature_flag = 0U;
549 long sl = RTT_MIN_LEVEL;
Shruti Guptaaffbae82023-08-22 12:51:11 +0100550
551 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100552
553 rec_count = tftf_get_total_cpus_count();
554 assert(rec_count <= MAX_REC_COUNT);
Shruti Guptaaffbae82023-08-22 12:51:11 +0100555
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000556 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100557 feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
558 sl = RTT_MIN_LEVEL_LPA2;
559 }
560
AlexeiFedorov0db147a2024-10-03 16:46:35 +0100561 for (i = 1U; i < rec_count; i++) {
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100562 rec_flag[i] = RMI_NOT_RUNNABLE;
563 }
564
Shruti Guptaaffbae82023-08-22 12:51:11 +0100565 if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100566 feature_flag, 0U, sl, rec_flag, rec_count, 0U, get_test_mecid())) {
Shruti Guptaaffbae82023-08-22 12:51:11 +0100567 return TEST_RESULT_FAIL;
568 }
Shruti Guptaaffbae82023-08-22 12:51:11 +0100569
570 is_secondary_cpu_on = 0U;
571 init_spinlock(&secondary_cpu_lock);
572 my_mpidr = read_mpidr_el1() & MPID_MASK;
Shruti Gupta69cae792024-11-27 04:30:00 +0000573 host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, rec_count);
Shruti Guptaaffbae82023-08-22 12:51:11 +0100574 ret1 = host_enter_realm_execute(&realm, REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
575 RMI_EXIT_PSCI, 0U);
576 if (!ret1) {
577 ERROR("Host did not receive CPU ON request\n");
578 goto destroy_realm;
579 }
580 while (true) {
581 run = (struct rmi_rec_run *)realm.run[0];
582 if (run->exit.gprs[0] != SMC_PSCI_CPU_ON_AARCH64) {
583 ERROR("Host did not receive CPU ON request\n");
584 goto destroy_realm;
585 }
586 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
587 if (rec_num >= MAX_REC_COUNT) {
588 ERROR("Invalid mpidr requested\n");
589 goto destroy_realm;
590 }
591 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
592 (unsigned long)PSCI_E_SUCCESS);
593 if (ret == RMI_SUCCESS) {
594 /* Re-enter REC0 complete CPU_ON */
595 ret = host_realm_rec_enter(&realm, &exit_reason,
596 &host_call_result, 0U);
597 if (ret != RMI_SUCCESS || exit_reason != RMI_EXIT_PSCI) {
598 break;
599 }
600 } else {
601 ERROR("host_rmi_psci_complete failed\n");
602 goto destroy_realm;
603 }
604 }
605 if (exit_reason != RMI_EXIT_HOST_CALL || host_call_result != TEST_RESULT_SUCCESS) {
606 ERROR("Realm failed\n");
607 goto destroy_realm;
608 }
609
AlexeiFedorov0db147a2024-10-03 16:46:35 +0100610 i = 0U;
611
Shruti Guptaaffbae82023-08-22 12:51:11 +0100612 /* Turn on all CPUs */
613 for_each_cpu(cpu_node) {
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100614 if (i == (rec_count - 1U)) {
Shruti Guptaaffbae82023-08-22 12:51:11 +0100615 break;
616 }
617 other_mpidr = tftf_get_mpidr_from_node(cpu_node);
618 if (other_mpidr == my_mpidr) {
619 continue;
620 }
621
622 /* Power on the other CPU */
623 ret = tftf_try_cpu_on(other_mpidr, (uintptr_t)cpu_on_handler, 0);
624 if (ret != PSCI_E_SUCCESS) {
625 ERROR("TFTF CPU ON failed\n");
626 goto destroy_realm;
627 }
628 i++;
629 }
630
631 while (true) {
632 /* Re-enter REC0 complete PSCI_AFFINITY_INFO */
633 ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 0U);
634 if (ret != RMI_SUCCESS) {
635 ERROR("Rec0 re-enter failed\n");
636 goto destroy_realm;
637 }
638 if (run->exit.gprs[0] != SMC_PSCI_AFFINITY_INFO_AARCH64) {
639 break;
640 }
641 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100642 if (rec_num >= rec_count) {
Shruti Guptaaffbae82023-08-22 12:51:11 +0100643 ERROR("Invalid mpidr requested\n");
644 goto destroy_realm;
645 }
646 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
647 (unsigned long)PSCI_E_SUCCESS);
648
649 if (ret != RMI_SUCCESS) {
650 ERROR("host_rmi_psci_complete failed\n");
651 goto destroy_realm;
652 }
653 }
654
655 if (ret == RMI_SUCCESS && exit_reason == RMI_EXIT_HOST_CALL) {
656 ret3 = host_call_result;
657 }
658destroy_realm:
659 ret2 = host_destroy_realm(&realm);
660
661 if ((ret != RMI_SUCCESS) || !ret2) {
662 ERROR("%s(): enter=%d destroy=%d\n",
663 __func__, ret, ret2);
664 return TEST_RESULT_FAIL;
665 }
666
667 return ret3;
668}
669
Shruti Gupta86f312a2023-12-21 11:33:03 +0000670/*
671 * Test creates 2 realms with multiple recs
672 * realm1, rec1 requests CPU_ON for rec2
673 * Host calls PSCI_COMPLETE with wrong rec3, checks for error
674 * Host calls PSCI_COMPLETE with wrong rec from different realm, checks for error
675 * Host calls PSCI_COMPLETE with correct rec, checks for success
676 * Host attempts to execute rec which is NOT_RUNNABLE, checks for error
677 */
678test_result_t host_realm_multi_rec_multiple_cpu2(void)
679{
680 bool ret1, ret2;
681 test_result_t ret3 = TEST_RESULT_FAIL;
682 int ret = RMI_ERROR_INPUT;
683 u_register_t rec_num;
684 struct rmi_rec_run *run;
685 unsigned int host_call_result;
686 struct realm realm2;
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100687 u_register_t feature_flag = 0U;
688 long sl = RTT_MIN_LEVEL;
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100689 u_register_t rec_flag[MAX_REC_COUNT] = {RMI_RUNNABLE};
Shruti Gupta86f312a2023-12-21 11:33:03 +0000690 u_register_t exit_reason;
691
692 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
693
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000694 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100695 feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
696 sl = RTT_MIN_LEVEL_LPA2;
697 }
698
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100699 for (unsigned int i = 1U; i < MAX_REC_COUNT; i++) {
700 rec_flag[i] = RMI_NOT_RUNNABLE;
701 }
702
Shruti Gupta86f312a2023-12-21 11:33:03 +0000703 if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100704 feature_flag, 0UL, sl, rec_flag, MAX_REC_COUNT, 0U, get_test_mecid())) {
Shruti Gupta86f312a2023-12-21 11:33:03 +0000705 return TEST_RESULT_FAIL;
706 }
707
708 if (!host_create_activate_realm_payload(&realm2, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100709 feature_flag, 0U, sl, rec_flag, 1U, 0U, get_test_mecid())) {
Shruti Gupta86f312a2023-12-21 11:33:03 +0000710 ret2 = host_destroy_realm(&realm);
711 return TEST_RESULT_FAIL;
712 }
713
Shruti Gupta86f312a2023-12-21 11:33:03 +0000714 /* Realm to request CPU_ON for rec 2 */
Shruti Gupta69cae792024-11-27 04:30:00 +0000715 host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, 0U, HOST_ARG1_INDEX, 2U);
Shruti Gupta86f312a2023-12-21 11:33:03 +0000716 ret1 = host_enter_realm_execute(&realm, REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
717 RMI_EXIT_PSCI, 0U);
718 if (!ret1) {
719 ERROR("Host did not receive CPU ON request\n");
720 goto destroy_realm;
721 }
722 run = (struct rmi_rec_run *)realm.run[0];
723 if (run->exit.gprs[0] != SMC_PSCI_CPU_ON_AARCH64) {
724 ERROR("Host2 did not receive CPU ON request\n");
725 goto destroy_realm;
726 }
727 rec_num = host_realm_find_rec_by_mpidr(run->exit.gprs[1], &realm);
728 if (rec_num >= MAX_REC_COUNT) {
729 ERROR("Invalid mpidr requested\n");
730 goto destroy_realm;
731 }
732
733 /* pass wrong target_rec, expect error */
734 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num + 1U],
735 (unsigned long)PSCI_E_SUCCESS);
736 if (ret == RMI_SUCCESS) {
737 ERROR("host_rmi_psci_complete wrong target_rec didn't fail ret=%x\n",
738 ret);
739 goto destroy_realm;
740 }
741
742 /* pass wrong target_rec from different realm, expect error */
743 ret = host_rmi_psci_complete(realm.rec[0], realm2.rec[0U],
744 (unsigned long)PSCI_E_SUCCESS);
745 if (ret == RMI_SUCCESS) {
746 ERROR("host_rmi_psci_complete wrong target_rec didn't fail ret=%x\n",
747 ret);
748 goto destroy_realm;
749 }
750
751 ret = host_rmi_psci_complete(realm.rec[0], realm.rec[rec_num],
752 (unsigned long)PSCI_E_SUCCESS);
753
754 /* Try to run Rec3(CPU OFF/NOT_RUNNABLE), expect error */
755 ret = host_realm_rec_enter(&realm, &exit_reason,
756 &host_call_result, 3U);
757
758 if (ret == RMI_SUCCESS) {
759 ERROR("Expected error\n");
760 goto destroy_realm;
761 }
Shruti Gupta408a89d2024-08-06 12:33:29 +0100762
Shruti Gupta86f312a2023-12-21 11:33:03 +0000763 ret3 = TEST_RESULT_SUCCESS;
764
765destroy_realm:
766 ret1 = host_destroy_realm(&realm);
767 ret2 = host_destroy_realm(&realm2);
768
769 if (!ret1 || !ret2) {
770 ERROR("%s(): failed destroy=%d, %d\n",
771 __func__, ret1, ret2);
772 return TEST_RESULT_FAIL;
773 }
Shruti Gupta408a89d2024-08-06 12:33:29 +0100774
Shruti Gupta86f312a2023-12-21 11:33:03 +0000775 return ret3;
776}
Shruti Guptab1b37922024-01-13 21:49:04 +0000777
778/*
779 * Test PMU counters available to each REC matches that programmed by host
780 * Test PMU counters are preserved for each rec
781 */
782static test_result_t cpu_on_handler_pmu(void)
783{
784 bool ret1;
785 unsigned int i;
786
787 spin_lock(&secondary_cpu_lock);
788 i = is_secondary_cpu_on++;
789 spin_unlock(&secondary_cpu_lock);
Shruti Gupta47078f32025-01-16 18:54:24 +0000790
791 host_set_pmu_state(&pmu_state[i]);
792
Shruti Guptab1b37922024-01-13 21:49:04 +0000793 ret1 = host_enter_realm_execute(&realm, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, i);
794 if (!ret1) {
795 return TEST_RESULT_FAIL;
796 }
797 ret1 = host_enter_realm_execute(&realm1, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, i);
798 if (!ret1) {
799 return TEST_RESULT_FAIL;
800 }
801 ret1 = host_enter_realm_execute(&realm, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, i);
802 if (!ret1) {
803 return TEST_RESULT_FAIL;
804 }
Shruti Gupta47078f32025-01-16 18:54:24 +0000805
Shruti Guptab1b37922024-01-13 21:49:04 +0000806 ret1 = host_enter_realm_execute(&realm1, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, i);
Shruti Gupta47078f32025-01-16 18:54:24 +0000807 if (!ret1) {
808 return TEST_RESULT_FAIL;
809 }
810
811 if (host_check_pmu_state(&pmu_state[i])) {
Shruti Guptab1b37922024-01-13 21:49:04 +0000812 return TEST_RESULT_SUCCESS;
813 }
Shruti Gupta47078f32025-01-16 18:54:24 +0000814
Shruti Guptab1b37922024-01-13 21:49:04 +0000815 return TEST_RESULT_FAIL;
816}
817
818/*
819 * Test realm creation with more PMU counter than available, expect failure
820 * Test realm creation with 0 PMU counter
821 * expect failure if FEAT_HPMN0 is not supported
822 * expect success if FEAT_HPMN0 is supported
823 * Create 2 Realms first one with MAX PMU counters
824 * second realm with lesser PMU counter than available
825 * Schedule multiple rec on multiple CPU
826 * Test PMU counters available to each REC matches that programmed by host
827 * Test PMU counters are preserved for each rec
828 */
829test_result_t host_realm_pmuv3_mul_rec(void)
830{
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100831 u_register_t feature_flag = 0U;
Shruti Guptab1b37922024-01-13 21:49:04 +0000832 u_register_t rmm_feat_reg0;
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100833 u_register_t rec_flag[MAX_REC_COUNT];
834 bool ret1 = false, ret2;
Shruti Gupta47078f32025-01-16 18:54:24 +0000835 unsigned int rec_count, i, num_cnts;
Shruti Guptab1b37922024-01-13 21:49:04 +0000836 u_register_t other_mpidr, my_mpidr, ret;
837 int cpu_node;
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100838 long sl = RTT_MIN_LEVEL;
Shruti Guptab1b37922024-01-13 21:49:04 +0000839
840 SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
841
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000842 host_rmi_init_cmp_result();
843
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100844 rec_count = tftf_get_total_cpus_count();
845 assert(rec_count <= MAX_REC_COUNT);
846
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000847 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100848 feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
849 sl = RTT_MIN_LEVEL_LPA2;
850 }
851
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100852 for (i = 0U; i < rec_count; i++) {
853 rec_flag[i] = RMI_RUNNABLE;
854 }
855
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000856 /* Get number of PMU event counters implemented through RMI_FEATURES */
Shruti Guptab1b37922024-01-13 21:49:04 +0000857 if (host_rmi_features(0UL, &rmm_feat_reg0) != REALM_SUCCESS) {
858 ERROR("%s() failed\n", "host_rmi_features");
859 return TEST_RESULT_FAIL;
860 }
861
862 num_cnts = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, rmm_feat_reg0);
Shruti Gupta47078f32025-01-16 18:54:24 +0000863 host_set_pmu_state(&pmu_state[0U]);
864
Shruti Guptab1b37922024-01-13 21:49:04 +0000865 is_secondary_cpu_on = 0;
866 my_mpidr = read_mpidr_el1() & MPID_MASK;
867
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000868 if (num_cnts == 0) {
869 INFO("No event counters implemented\n");
870 } else {
871 INFO("Testing %u event counters\n", num_cnts);
Shruti Guptab1b37922024-01-13 21:49:04 +0000872 }
873
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000874 /*
875 * Check that number of event counters is less
876 * than maximum supported by architecture.
877 */
878 if (num_cnts < ((1U << RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS_WIDTH) - 1U)) {
879 feature_flag |= RMI_FEATURE_REGISTER_0_PMU_EN |
880 INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, num_cnts + 1U);
Shruti Guptab1b37922024-01-13 21:49:04 +0000881
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000882 if (is_feat_52b_on_4k_2_supported()) {
883 feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
884 }
885
886 /* Request more event counters than total, expect failure */
887 if (host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Juan Pablo Condedc23fcd2025-04-05 14:26:13 -0500888 feature_flag, 0UL, sl, rec_flag, 1U, 0U,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100889 get_test_mecid())) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000890 ERROR("Realm create should have failed\n");
891 host_destroy_realm(&realm);
892 return TEST_RESULT_FAIL;
893 }
Shruti Guptab1b37922024-01-13 21:49:04 +0000894 }
895
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000896 /* Request Cycle Counter with no event counters */
Shruti Guptab1b37922024-01-13 21:49:04 +0000897 feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000898 INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, 0U);
Shruti Guptab1b37922024-01-13 21:49:04 +0000899
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000900 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100901 feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
902 }
903
Shruti Guptab1b37922024-01-13 21:49:04 +0000904 ret1 = host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Juan Pablo Condedc23fcd2025-04-05 14:26:13 -0500905 feature_flag, 0U, sl, rec_flag, 1U, 0U,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100906 get_test_mecid());
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000907 host_destroy_realm(&realm);
Shruti Guptab1b37922024-01-13 21:49:04 +0000908
909 if (!get_feat_hpmn0_supported()) {
910 if (ret1) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000911 ERROR("Realm create with 0 event counters should have failed\n");
Shruti Guptab1b37922024-01-13 21:49:04 +0000912 return TEST_RESULT_FAIL;
913 }
914 } else {
915 if (!ret1) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000916 ERROR("Realm create with 0 event counters should not have failed\n");
Shruti Guptab1b37922024-01-13 21:49:04 +0000917 return TEST_RESULT_FAIL;
918 }
Shruti Guptab1b37922024-01-13 21:49:04 +0000919 }
920
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000921 /* Create first realm with number of PMU event counters */
Shruti Guptab1b37922024-01-13 21:49:04 +0000922 feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000923 INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, num_cnts);
Shruti Guptab1b37922024-01-13 21:49:04 +0000924
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000925 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100926 feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
927 }
928
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000929 /* Prepare realm, create recs later */
Shruti Guptab1b37922024-01-13 21:49:04 +0000930 if (!host_prepare_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100931 feature_flag, 0UL, sl, rec_flag, rec_count, 0U, get_test_mecid())) {
Shruti Guptab1b37922024-01-13 21:49:04 +0000932 return TEST_RESULT_FAIL;
933 }
Shruti Guptab1b37922024-01-13 21:49:04 +0000934
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000935 /*
936 * Second realm1 with less or equal number of event counters.
937 * When no event counters are implemented, only Cycle Counter
938 * will be tested.
939 */
Shruti Guptab1b37922024-01-13 21:49:04 +0000940 feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000941 INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS,
942 (num_cnts == 0U) ? num_cnts : num_cnts - 1U);
Shruti Guptab1b37922024-01-13 21:49:04 +0000943
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000944 if (is_feat_52b_on_4k_2_supported()) {
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100945 feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
946 }
947
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000948 ret1 = host_create_activate_realm_payload(&realm1, (u_register_t)REALM_IMAGE_BASE,
Juan Pablo Condedc23fcd2025-04-05 14:26:13 -0500949 feature_flag, 0U, sl, rec_flag, rec_count, 0U,
Soby Mathew5d7869f2025-07-21 00:02:52 +0100950 get_test_mecid());
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000951 if (!ret1) {
952 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +0000953 }
Shruti Guptab1b37922024-01-13 21:49:04 +0000954
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000955 /* Create realm recs, activate realm0 */
Shruti Guptab1b37922024-01-13 21:49:04 +0000956 if (host_realm_rec_create(&realm) != REALM_SUCCESS) {
957 ERROR("%s() failed\n", "host_realm_rec_create");
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000958 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +0000959 }
960
Javier Almansa Sobrino7efea192023-09-19 16:07:09 +0100961 if (host_realm_init_ipa_state(&realm, sl, 0U, 1ULL << 32)
Shruti Guptab1b37922024-01-13 21:49:04 +0000962 != RMI_SUCCESS) {
963 ERROR("%s() failed\n", "host_realm_init_ipa_state");
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000964 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +0000965 }
966
967 if (host_realm_activate(&realm) != REALM_SUCCESS) {
968 ERROR("%s() failed\n", "host_realm_activate");
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000969 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +0000970 }
Shruti Guptab1b37922024-01-13 21:49:04 +0000971
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000972 /* Pass number of event counters programmed to realms */
AlexeiFedorov93d4df52024-10-03 09:44:52 +0100973 for (unsigned int j = 0U; j < rec_count; j++) {
Shruti Gupta69cae792024-11-27 04:30:00 +0000974 host_shared_data_set_host_val(&realm, PRIMARY_PLANE_ID, j,
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000975 HOST_ARG1_INDEX, num_cnts);
Shruti Gupta69cae792024-11-27 04:30:00 +0000976 host_shared_data_set_host_val(&realm1, PRIMARY_PLANE_ID, j,
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000977 HOST_ARG1_INDEX,
978 (num_cnts == 0U) ? 0U : num_cnts - 1U);
Shruti Guptab1b37922024-01-13 21:49:04 +0000979 }
980
981 /*
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000982 * Enter realm rec0 test PMU counters available is same as that programmed by host.
983 * Validation is done by the Realm and will return error if the count does not match.
Shruti Guptab1b37922024-01-13 21:49:04 +0000984 */
985 ret1 = host_enter_realm_execute(&realm, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, 0U);
986 if (!ret1) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000987 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +0000988 }
989
990 /* Enter realm1 rec0 test PMU counters available is same as that programmed by host */
991 ret1 = host_enter_realm_execute(&realm1, REALM_PMU_COUNTER, RMI_EXIT_HOST_CALL, 0U);
992 if (!ret1) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000993 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +0000994 }
995
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000996 /* Test if realm rec0 entering/exiting preserves PMU state */
Shruti Guptab1b37922024-01-13 21:49:04 +0000997 ret1 = host_enter_realm_execute(&realm, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, 0U);
998 if (!ret1) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +0000999 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +00001000 }
1001
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00001002 /* Test if realm1 rec0 entering/exiting preserves PMU state */
Shruti Guptab1b37922024-01-13 21:49:04 +00001003 ret1 = host_enter_realm_execute(&realm1, REALM_PMU_PRESERVE, RMI_EXIT_HOST_CALL, 0U);
1004 if (!ret1) {
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00001005 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +00001006 }
1007
Shruti Gupta47078f32025-01-16 18:54:24 +00001008 if (!host_check_pmu_state(&pmu_state[0U])) {
1009 goto test_exit;
1010 }
1011
AlexeiFedorov93d4df52024-10-03 09:44:52 +01001012 i = 0U;
1013
Shruti Guptab1b37922024-01-13 21:49:04 +00001014 /* Turn on all CPUs */
1015 for_each_cpu(cpu_node) {
AlexeiFedorov93d4df52024-10-03 09:44:52 +01001016 if (i == (rec_count - 1U)) {
Shruti Guptab1b37922024-01-13 21:49:04 +00001017 break;
1018 }
1019 other_mpidr = tftf_get_mpidr_from_node(cpu_node);
1020 if (other_mpidr == my_mpidr) {
1021 continue;
1022 }
1023
1024 /* Power on the other CPU */
1025 ret = tftf_try_cpu_on(other_mpidr, (uintptr_t)cpu_on_handler_pmu, 0);
1026 if (ret != PSCI_E_SUCCESS) {
1027 ERROR("TFTF CPU ON failed\n");
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00001028 goto test_exit;
Shruti Guptab1b37922024-01-13 21:49:04 +00001029 }
1030 i++;
1031 }
1032
1033 /* Wait for all CPU to power up */
AlexeiFedorov93d4df52024-10-03 09:44:52 +01001034 while (is_secondary_cpu_on != (rec_count - 1U)) {
Shruti Guptab1b37922024-01-13 21:49:04 +00001035 waitms(100);
1036 }
1037
1038 /* Wait for all CPU to power down */
1039 for_each_cpu(cpu_node) {
1040 other_mpidr = tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
1041 if (other_mpidr == my_mpidr) {
1042 continue;
1043 }
1044 while (tftf_psci_affinity_info(other_mpidr, MPIDR_AFFLVL0) != PSCI_STATE_OFF) {
1045 continue;
1046 }
1047 }
1048
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00001049test_exit:
Shruti Guptab1b37922024-01-13 21:49:04 +00001050 ret2 = host_destroy_realm(&realm1);
1051 if (!ret1 || !ret2) {
1052 ERROR("%s() enter=%u destroy=%u\n", __func__, ret1, ret2);
1053 }
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00001054
Shruti Guptab1b37922024-01-13 21:49:04 +00001055 ret2 = host_destroy_realm(&realm);
1056 if (!ret1 || !ret2) {
1057 ERROR("%s() enter=%u destroy=%u\n", __func__, ret1, ret2);
1058 return TEST_RESULT_FAIL;
1059 }
1060
AlexeiFedorovc398c8f2025-01-16 14:35:48 +00001061 return host_cmp_result();
Shruti Guptab1b37922024-01-13 21:49:04 +00001062}