blob: 80497bd328beffc76ac119fa0d2e2ba7b488da2d [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Max Shvetsov103e0562021-02-04 16:58:31 +00002 * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <plat_topology.h>
9#include <platform.h>
10#include <power_management.h>
11#include <test_helpers.h>
12#include <tftf_lib.h>
13
J-Alvesf1126f22020-11-02 17:28:20 +000014static struct mailbox_buffers test_mb = {.send = NULL, .recv = NULL};
15
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020016int is_sys_suspend_state_ready(void)
17{
18 int aff_info;
19 unsigned int target_node;
20 u_register_t target_mpid;
21 u_register_t current_mpid = read_mpidr_el1() & MPID_MASK;
22
23 for_each_cpu(target_node) {
24 target_mpid = tftf_get_mpidr_from_node(target_node);
25
26 /* Skip current CPU, as it is powered on */
27 if (target_mpid == current_mpid)
28 continue;
29
30 aff_info = tftf_psci_affinity_info(target_mpid, MPIDR_AFFLVL0);
31 if (aff_info != PSCI_STATE_OFF)
32 return 0;
33 }
34
35 return 1;
36}
37
38void psci_system_reset(void)
39{
40 smc_args args = { SMC_PSCI_SYSTEM_RESET };
41 smc_ret_values ret;
42
43 ret = tftf_smc(&args);
44
45 /* The PSCI SYSTEM_RESET call is not supposed to return */
46 tftf_testcase_printf("System didn't reboot properly (%d)\n",
47 (unsigned int)ret.ret0);
48}
49
50int psci_mem_protect(int val)
51{
52 smc_args args = { SMC_PSCI_MEM_PROTECT};
53 smc_ret_values ret;
54
55 args.arg1 = val;
56 ret = tftf_smc(&args);
57
58 return ret.ret0;
59}
60
61int psci_mem_protect_check(uintptr_t addr, size_t size)
62{
63 smc_args args = { SMC_PSCI_MEM_PROTECT_CHECK };
64 smc_ret_values ret;
65
66 args.arg1 = addr;
67 args.arg2 = size;
68 ret = tftf_smc(&args);
69 return ret.ret0;
70}
71
72/*
73 * This function returns an address that can be used as
74 * sentinel for mem_protect functions. The logic behind
75 * it is that it has to search one region that doesn't intersect
76 * with the memory used by TFTF.
77 */
78unsigned char *psci_mem_prot_get_sentinel(void)
79{
80 const mem_region_t *ranges, *rp, *lim;
81 int nranges;
82 IMPORT_SYM(uintptr_t, __TFTF_BASE__, tftf_base);
83 IMPORT_SYM(uintptr_t, __TFTF_END__, tftf_end);
84 uintptr_t p = 0;
85
86 ranges = plat_get_prot_regions(&nranges);
87 if (!ranges)
88 return NULL;
89
90 lim = &ranges[nranges];
91 for (rp = ranges ; rp < lim; rp++) {
92 p = rp->addr;
93 if (p < tftf_base || p > tftf_end)
94 break;
95 p = p + (rp->size - 1);
96 if (p < tftf_base || p > tftf_end)
97 break;
98 }
99
100 return (rp == lim) ? NULL : (unsigned char *) p;
101}
102
103/*
104 * This function maps the memory region before the
105 * test and unmap it after the test is run
106 */
107test_result_t map_test_unmap(const map_args_unmap_t *args,
108 test_function_arg_t test)
109{
110 int mmap_ret;
111 test_result_t test_ret;
112
113 mmap_ret = mmap_add_dynamic_region(args->addr, args->addr,
114 args->size, args->attr);
115
116 if (mmap_ret != 0) {
117 tftf_testcase_printf("Couldn't map memory (ret = %d)\n",
118 mmap_ret);
119 return TEST_RESULT_FAIL;
120 }
121
122 test_ret = (*test)(args->arg);
123
124 mmap_ret = mmap_remove_dynamic_region(args->addr, args->size);
125 if (mmap_ret != 0) {
126 tftf_testcase_printf("Couldn't unmap memory (ret = %d)\n",
127 mmap_ret);
128 return TEST_RESULT_FAIL;
129 }
130
131 return test_ret;
132}
J-Alvesf1126f22020-11-02 17:28:20 +0000133
134void set_tftf_mailbox(const struct mailbox_buffers *mb)
135{
136 if (mb != NULL) {
137 test_mb = *mb;
138 }
139}
140
141bool get_tftf_mailbox(struct mailbox_buffers *mb)
142{
143 if ((test_mb.recv != NULL) && (test_mb.send != NULL)) {
144 *mb = test_mb;
145 return true;
146 }
147 return false;
148}
J-Alvesd708c032020-11-19 12:14:21 +0000149
J-Alves04469302021-01-21 14:48:13 +0000150test_result_t check_spmc_testing_set_up(
J-Alvesd708c032020-11-19 12:14:21 +0000151 uint32_t ffa_version_major, uint32_t ffa_version_minor,
152 const struct ffa_uuid *ffa_uuids, size_t ffa_uuids_size)
153{
154 struct mailbox_buffers mb;
155
156 if (ffa_uuids == NULL) {
157 ERROR("Invalid parameter ffa_uuids!\n");
158 return TEST_RESULT_FAIL;
159 }
160
161 SKIP_TEST_IF_FFA_VERSION_LESS_THAN(ffa_version_major,
162 ffa_version_minor);
163
164 /**********************************************************************
165 * If OP-TEE is SPMC skip the current test.
166 **********************************************************************/
167 if (check_spmc_execution_level()) {
168 VERBOSE("OPTEE as SPMC at S-EL1. Skipping test!\n");
169 return TEST_RESULT_SKIPPED;
170 }
171
172 GET_TFTF_MAILBOX(mb);
173
174 for (unsigned int i = 0U; i < ffa_uuids_size; i++)
Max Shvetsov0b7d25f2021-03-05 13:46:42 +0000175 SKIP_TEST_IF_FFA_ENDPOINT_NOT_DEPLOYED(*mb, ffa_uuids[i]);
J-Alvesd708c032020-11-19 12:14:21 +0000176
177 return TEST_RESULT_SUCCESS;
178}
J-Alvesd56c53c2021-07-01 16:32:16 +0100179
180test_result_t spm_run_multi_core_test(uintptr_t cpu_on_handler,
181 event_t *cpu_done)
182{
183 unsigned int lead_mpid = read_mpidr_el1() & MPID_MASK;
184 unsigned int core_pos, cpu_node, mpidr;
185 int32_t ret;
186
187 VERBOSE("Powering on all cpus.\n");
188
189 for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
190 tftf_init_event(&cpu_done[i]);
191 }
192
193 for_each_cpu(cpu_node) {
194 mpidr = tftf_get_mpidr_from_node(cpu_node);
195 if (mpidr == lead_mpid) {
196 continue;
197 }
198
199 ret = tftf_cpu_on(mpidr, cpu_on_handler, 0U);
200 if (ret != 0) {
201 ERROR("tftf_cpu_on mpidr 0x%x returns %d\n",
202 mpidr, ret);
203 }
204 }
205
206 VERBOSE("Waiting secondary CPUs to turn off ...\n");
207
208 for_each_cpu(cpu_node) {
209 mpidr = tftf_get_mpidr_from_node(cpu_node);
210 if (mpidr == lead_mpid) {
211 continue;
212 }
213
214 core_pos = platform_get_core_pos(mpidr);
215 tftf_wait_for_event(&cpu_done[core_pos]);
216 }
217
218 VERBOSE("Done exiting.\n");
219
220 return TEST_RESULT_SUCCESS;
221}