blob: 6d248428e48536ac7cc7dfec7d5d84ef8d4f20bd [file] [log] [blame]
Antonio Nino Diaza1497e32018-11-08 11:45:13 +00001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <cactus_def.h>
9#include <debug.h>
10#include <events.h>
11#include <ivy_def.h>
12#include <plat_topology.h>
13#include <platform.h>
14#include <power_management.h>
15#include <smccc.h>
16#include <spci_helpers.h>
17#include <spci_svc.h>
18#include <test_helpers.h>
19#include <tftf_lib.h>
20
21#define TEST_NUM_ITERATIONS 1000U
22
23static event_t cpu_has_entered_test[PLATFORM_CORE_COUNT];
24
25static test_result_t test_spci_blocking_multicore_fn(void)
26{
27 int ret;
28 uint16_t handle_cactus, handle_ivy;
29 u_register_t rx1, rx2, rx3;
30 test_result_t result = TEST_RESULT_SUCCESS;
31
32 u_register_t cpu_mpid = read_mpidr_el1() & MPID_MASK;
33 unsigned int core_pos = platform_get_core_pos(cpu_mpid);
34
35 tftf_send_event(&cpu_has_entered_test[core_pos]);
36
37 /* Open handles. */
38
39 ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_cactus,
40 CACTUS_SERVICE1_UUID);
41 if (ret != SPCI_SUCCESS) {
42 tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: 0x%x\n",
43 __LINE__, (uint32_t)ret);
44 result = TEST_RESULT_FAIL;
45 goto exit_none;
46 }
47
48 ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_ivy,
49 IVY_SERVICE1_UUID);
50 if (ret != SPCI_SUCCESS) {
51 tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: 0x%x\n",
52 __LINE__, (uint32_t)ret);
53 result = TEST_RESULT_FAIL;
54 goto exit_cactus;
55 }
56
57 /* Request services. */
58
59 for (unsigned int i = 0U; i < TEST_NUM_ITERATIONS; i++) {
60
61 /* Send request to Cactus */
62
63 ret = spci_service_request_blocking(CACTUS_GET_MAGIC,
64 0, 0, 0, 0, 0,
65 TFTF_SPCI_CLIENT_ID,
66 handle_cactus,
67 &rx1, &rx2, &rx3);
68
69 if (ret == SPCI_BUSY) {
70 /*
71 * Another CPU is already using Cactus, this is not a
72 * failure.
73 */
74 } else if (ret == SPCI_SUCCESS) {
75 if (rx1 != CACTUS_MAGIC_NUMBER) {
76 tftf_testcase_printf("%d: Cactus returned 0x%x 0x%lx 0x%lx 0x%lx\n",
77 __LINE__, (uint32_t)ret, rx1, rx2, rx3);
78 result = TEST_RESULT_FAIL;
79 break;
80 }
81 } else {
82 tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: 0x%x\n",
83 __LINE__, (uint32_t)ret);
84 result = TEST_RESULT_FAIL;
85 break;
86 }
87
88 /* Send request to Ivy */
89
90 ret = spci_service_request_blocking(IVY_GET_MAGIC,
91 0, 0, 0, 0, 0,
92 TFTF_SPCI_CLIENT_ID,
93 handle_ivy,
94 &rx1, &rx2, &rx3);
95 if (ret == SPCI_BUSY) {
96 /*
97 * Another CPU is already using Ivy, this is not a
98 * failure.
99 */
100 } else if (ret == SPCI_SUCCESS) {
101 if (rx1 != IVY_MAGIC_NUMBER) {
102 tftf_testcase_printf("%d: Ivy returned 0x%x 0x%lx 0x%lx 0x%lx\n",
103 __LINE__, (uint32_t)ret, rx1, rx2, rx3);
104 result = TEST_RESULT_FAIL;
105 break;
106 }
107 } else {
108 tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: 0x%x\n",
109 __LINE__, (uint32_t)ret);
110 result = TEST_RESULT_FAIL;
111 break;
112 }
113
114 }
115
116 /* Close handles. */
117
118 ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_ivy);
119 if (ret != SPCI_SUCCESS) {
120 tftf_testcase_printf("%d: SPM failed to close the handle. Returned: 0x%x\n",
121 __LINE__, (uint32_t)ret);
122 result = TEST_RESULT_FAIL;
123 }
124
125exit_cactus:
126 ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_cactus);
127 if (ret != SPCI_SUCCESS) {
128 tftf_testcase_printf("%d: SPM failed to close the handle. Returned: 0x%x\n",
129 __LINE__, (uint32_t)ret);
130 result = TEST_RESULT_FAIL;
131 }
132
133 /* All tests finished. */
134exit_none:
135 return result;
136}
137
138/*
139 * @Test_Aim@ This tests opens a Secure Service handle and performs many simple
140 * blocking requests to Cactus and Ivy from multiple cores
141 */
142test_result_t test_spci_blocking_request_multicore(void)
143{
144 unsigned int cpu_node, core_pos;
145 int psci_ret;
146 u_register_t cpu_mpid;
147 u_register_t lead_mpid = read_mpidr_el1() & MPID_MASK;
148
149 SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 1);
150
151 for (int i = 0; i < PLATFORM_CORE_COUNT; i++) {
152 tftf_init_event(&cpu_has_entered_test[i]);
153 }
154
155 /* Power on all CPUs */
156 for_each_cpu(cpu_node) {
157 cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
158 /* Skip lead CPU as it is already powered on */
159 if (cpu_mpid == lead_mpid) {
160 continue;
161 }
162
163 psci_ret = tftf_cpu_on(cpu_mpid,
164 (uintptr_t)test_spci_blocking_multicore_fn, 0);
165 if (psci_ret != PSCI_E_SUCCESS) {
166 core_pos = platform_get_core_pos(cpu_mpid);
167
168 tftf_testcase_printf(
169 "Failed to power on CPU %d (rc = %d)\n",
170 core_pos, psci_ret);
171 return TEST_RESULT_FAIL;
172 }
173 }
174
175 /* Wait until all CPUs have started the test. */
176 for_each_cpu(cpu_node) {
177 cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
178 /* Skip lead CPU */
179 if (cpu_mpid == lead_mpid) {
180 continue;
181 }
182
183 core_pos = platform_get_core_pos(cpu_mpid);
184 tftf_wait_for_event(&cpu_has_entered_test[core_pos]);
185 }
186
187 /* Enter the test on lead CPU and return the result. */
188 return test_spci_blocking_multicore_fn();
189}