blob: 032d2e2e326703086b0c560fe1d319e61f6b1f6e [file] [log] [blame]
J-Alves9f6f0142020-06-17 15:37:59 +01001/*
Max Shvetsov103e0562021-02-04 16:58:31 +00002 * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
J-Alves9f6f0142020-06-17 15:37:59 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <assert.h>
J-Alves9f6f0142020-06-17 15:37:59 +01007#include <debug.h>
Max Shvetsov40eb6a22020-06-08 11:15:30 +01008#include <errno.h>
Max Shvetsov103e0562021-02-04 16:58:31 +00009
Max Shvetsovc32f4782020-06-23 09:41:15 +010010#include <cactus_def.h>
Max Shvetsov103e0562021-02-04 16:58:31 +000011#include <cactus_platform_def.h>
J-Alves8f4a56f2020-10-28 10:29:05 +000012#include <ffa_endpoints.h>
J-Alves9f6f0142020-06-17 15:37:59 +010013#include <sp_helpers.h>
Max Shvetsov103e0562021-02-04 16:58:31 +000014#include <spm_common.h>
J-Alves9f6f0142020-06-17 15:37:59 +010015
J-Alves63cdaa72020-10-08 17:22:45 +010016#include <lib/libc/string.h>
17#include <lib/xlat_tables/xlat_tables_v2.h>
18
J-Alves9f6f0142020-06-17 15:37:59 +010019/* FFA version test helpers */
20#define FFA_MAJOR 1U
21#define FFA_MINOR 0U
22
Max Shvetsovc32f4782020-06-23 09:41:15 +010023static const uint32_t primary_uuid[4] = PRIMARY_UUID;
24static const uint32_t secondary_uuid[4] = SECONDARY_UUID;
Ruari Phippsd75596a2020-07-17 16:41:34 +010025static const uint32_t tertiary_uuid[4] = TERTIARY_UUID;
Max Shvetsovc32f4782020-06-23 09:41:15 +010026static const uint32_t null_uuid[4] = {0};
27
Max Shvetsov40eb6a22020-06-08 11:15:30 +010028/*
Olivier Deprez881b1992020-12-01 15:34:34 +010029 * Fill SIMD vectors from secure world side with a unique value.
30 * 0x22 is just a dummy value to be distinguished from the value
31 * in the normal world.
32 */
33void fill_simd_vectors(void)
34{
35 simd_vector_t simd_vectors[SIMD_NUM_VECTORS];
36
37 for (unsigned int num = 0U; num < SIMD_NUM_VECTORS; num++) {
38 memset(simd_vectors[num], 0x22 * num, sizeof(simd_vector_t));
39 }
40
41 fill_simd_vector_regs(simd_vectors);
42}
43
44/*
Max Shvetsov40eb6a22020-06-08 11:15:30 +010045 * Test FFA_FEATURES interface.
46 */
47static void ffa_features_test(void)
48{
49 const char *test_features = "FFA Features interface";
50 smc_ret_values ffa_ret;
Max Shvetsov103e0562021-02-04 16:58:31 +000051 const struct ffa_features_test *ffa_feature_test_target;
Max Shvetsov40eb6a22020-06-08 11:15:30 +010052 unsigned int i, test_target_size =
Max Shvetsov103e0562021-02-04 16:58:31 +000053 get_ffa_feature_test_target(&ffa_feature_test_target);
54
Max Shvetsov40eb6a22020-06-08 11:15:30 +010055
56 announce_test_section_start(test_features);
57
58 for (i = 0U; i < test_target_size; i++) {
Max Shvetsov103e0562021-02-04 16:58:31 +000059 announce_test_start(ffa_feature_test_target[i].test_name);
Max Shvetsov40eb6a22020-06-08 11:15:30 +010060
Max Shvetsov103e0562021-02-04 16:58:31 +000061 ffa_ret = ffa_features(ffa_feature_test_target[i].feature);
J-Alves6cb21d92021-01-07 15:18:12 +000062 expect(ffa_func_id(ffa_ret), ffa_feature_test_target[i].expected_ret);
Max Shvetsov103e0562021-02-04 16:58:31 +000063 if (ffa_feature_test_target[i].expected_ret == FFA_ERROR) {
J-Alves6cb21d92021-01-07 15:18:12 +000064 expect(ffa_error_code(ffa_ret), FFA_ERROR_NOT_SUPPORTED);
Max Shvetsov40eb6a22020-06-08 11:15:30 +010065 }
66
Max Shvetsov103e0562021-02-04 16:58:31 +000067 announce_test_end(ffa_feature_test_target[i].test_name);
Max Shvetsov40eb6a22020-06-08 11:15:30 +010068 }
69
70 announce_test_section_end(test_features);
71}
72
Max Shvetsovc32f4782020-06-23 09:41:15 +010073static void ffa_partition_info_helper(struct mailbox_buffers *mb, const uint32_t uuid[4],
74 const struct ffa_partition_info *expected,
75 const uint16_t expected_size)
76{
77 smc_ret_values ret = ffa_partition_info_get(uuid);
78 unsigned int i;
J-Alves6cb21d92021-01-07 15:18:12 +000079 expect(ffa_func_id(ret), FFA_SUCCESS_SMC32);
Max Shvetsovc32f4782020-06-23 09:41:15 +010080
81 struct ffa_partition_info *info = (struct ffa_partition_info *)(mb->recv);
82 for (i = 0U; i < expected_size; i++) {
83 expect(info[i].id, expected[i].id);
84 expect(info[i].exec_context, expected[i].exec_context);
85 expect(info[i].properties, expected[i].properties);
86 }
87
88 ret = ffa_rx_release();
J-Alves6cb21d92021-01-07 15:18:12 +000089 expect(ffa_func_id(ret), FFA_SUCCESS_SMC32);
Max Shvetsovc32f4782020-06-23 09:41:15 +010090}
91
92static void ffa_partition_info_wrong_test(void)
93{
94 const char *test_wrong_uuid = "Request wrong UUID";
95 uint32_t uuid[4] = {1};
96
97 announce_test_start(test_wrong_uuid);
98
99 smc_ret_values ret = ffa_partition_info_get(uuid);
J-Alves6cb21d92021-01-07 15:18:12 +0000100 expect(ffa_func_id(ret), FFA_ERROR);
101 expect(ffa_error_code(ret), FFA_ERROR_INVALID_PARAMETER);
Max Shvetsovc32f4782020-06-23 09:41:15 +0100102
103 announce_test_end(test_wrong_uuid);
104}
105
106static void ffa_partition_info_get_test(struct mailbox_buffers *mb)
107{
108 const char *test_partition_info = "FFA Partition info interface";
109 const char *test_primary = "Get primary partition info";
110 const char *test_secondary = "Get secondary partition info";
Ruari Phippsd75596a2020-07-17 16:41:34 +0100111 const char *test_tertiary = "Get tertiary partition info";
Max Shvetsovc32f4782020-06-23 09:41:15 +0100112 const char *test_all = "Get all partitions info";
113
114 const struct ffa_partition_info expected_info[] = {
Arunachalam Ganapathy51be1fe2020-09-22 13:25:21 +0100115 /* Primary partition info */
116 {
117 .id = SPM_VM_ID_FIRST,
118 .exec_context = CACTUS_PRIMARY_EC_COUNT,
Olivier Deprez6d274a42020-10-23 09:12:27 +0200119 /* Supports receipt of direct message requests. */
120 .properties = 1U
Arunachalam Ganapathy51be1fe2020-09-22 13:25:21 +0100121 },
122 /* Secondary partition info */
123 {
124 .id = SPM_VM_ID_FIRST + 1U,
125 .exec_context = CACTUS_SECONDARY_EC_COUNT,
Olivier Deprez6d274a42020-10-23 09:12:27 +0200126 .properties = 1U
Arunachalam Ganapathy51be1fe2020-09-22 13:25:21 +0100127 },
128 /* Tertiary partition info */
129 {
130 .id = SPM_VM_ID_FIRST + 2U,
131 .exec_context = CACTUS_TERTIARY_EC_COUNT,
Olivier Deprez6d274a42020-10-23 09:12:27 +0200132 .properties = 1U
Arunachalam Ganapathy51be1fe2020-09-22 13:25:21 +0100133 }
Max Shvetsovc32f4782020-06-23 09:41:15 +0100134 };
135
136 announce_test_section_start(test_partition_info);
137
Ruari Phippsd75596a2020-07-17 16:41:34 +0100138 announce_test_start(test_tertiary);
139 ffa_partition_info_helper(mb, tertiary_uuid, &expected_info[2], 1);
140 announce_test_end(test_tertiary);
141
Max Shvetsovc32f4782020-06-23 09:41:15 +0100142 announce_test_start(test_secondary);
143 ffa_partition_info_helper(mb, secondary_uuid, &expected_info[1], 1);
144 announce_test_end(test_secondary);
145
146 announce_test_start(test_primary);
147 ffa_partition_info_helper(mb, primary_uuid, &expected_info[0], 1);
148 announce_test_end(test_primary);
149
150 announce_test_start(test_all);
Ruari Phippsd75596a2020-07-17 16:41:34 +0100151 ffa_partition_info_helper(mb, null_uuid, expected_info, 3);
Max Shvetsovc32f4782020-06-23 09:41:15 +0100152 announce_test_end(test_all);
153
154 ffa_partition_info_wrong_test();
155
156 announce_test_section_end(test_partition_info);
157}
158
Max Shvetsov57c6ddb2020-07-01 14:09:48 +0100159void ffa_version_test(void)
J-Alves9f6f0142020-06-17 15:37:59 +0100160{
J-Alves9f6f0142020-06-17 15:37:59 +0100161 const char *test_ffa_version = "FFA Version interface";
162
J-Alves9f6f0142020-06-17 15:37:59 +0100163 announce_test_start(test_ffa_version);
164
165 smc_ret_values ret = ffa_version(MAKE_FFA_VERSION(FFA_MAJOR, FFA_MINOR));
Max Shvetsov57c6ddb2020-07-01 14:09:48 +0100166 uint32_t spm_version = (uint32_t)ret.ret0;
J-Alves9f6f0142020-06-17 15:37:59 +0100167
Max Shvetsov40eb6a22020-06-08 11:15:30 +0100168 bool ffa_version_compatible =
169 ((spm_version >> FFA_VERSION_MAJOR_SHIFT) == FFA_MAJOR &&
170 (spm_version & FFA_VERSION_MINOR_MASK) >= FFA_MINOR);
J-Alves9f6f0142020-06-17 15:37:59 +0100171
172 NOTICE("FFA_VERSION returned %u.%u; Compatible: %i\n",
173 spm_version >> FFA_VERSION_MAJOR_SHIFT,
174 spm_version & FFA_VERSION_MINOR_MASK,
175 (int)ffa_version_compatible);
176
177 expect((int)ffa_version_compatible, (int)true);
178
179 announce_test_end(test_ffa_version);
Max Shvetsov57c6ddb2020-07-01 14:09:48 +0100180}
181
J-Alves63cdaa72020-10-08 17:22:45 +0100182bool ffa_memory_retrieve_test(struct mailbox_buffers *mb,
J-Alves0435cae2020-11-06 10:49:56 +0000183 struct ffa_memory_region **retrieved,
J-Alves63cdaa72020-10-08 17:22:45 +0100184 uint64_t handle, ffa_vm_id_t sender,
185 ffa_vm_id_t receiver, uint32_t mem_func)
186{
187 smc_ret_values ret;
188 uint32_t fragment_size;
189 uint32_t total_size;
190 uint32_t descriptor_size;
191
192 if (retrieved == NULL || mb == NULL) {
193 ERROR("Invalid parameters!\n");
194 return false;
195 }
196
J-Alves63cdaa72020-10-08 17:22:45 +0100197 /*
198 * TODO: Revise shareability attribute in function call
199 * below.
200 * https://lists.trustedfirmware.org/pipermail/hafnium/2020-June/000023.html
201 */
202 descriptor_size = ffa_memory_retrieve_request_init(
J-Alves0435cae2020-11-06 10:49:56 +0000203 mb->send, handle, sender, receiver, 0, 0,
J-Alves63cdaa72020-10-08 17:22:45 +0100204 FFA_DATA_ACCESS_RW,
205 FFA_INSTRUCTION_ACCESS_NX,
206 FFA_MEMORY_NORMAL_MEM,
207 FFA_MEMORY_CACHE_WRITE_BACK,
208 FFA_MEMORY_OUTER_SHAREABLE);
209
210 ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
211
J-Alves6cb21d92021-01-07 15:18:12 +0000212 if (ffa_func_id(ret) != FFA_MEM_RETRIEVE_RESP) {
J-Alves0435cae2020-11-06 10:49:56 +0000213 ERROR("Couldn't retrieve the memory page. Error: %lx\n",
214 ret.ret2);
J-Alves63cdaa72020-10-08 17:22:45 +0100215 return false;
216 }
217
218 /*
219 * Following total_size and fragment_size are useful to keep track
220 * of the state of transaction. When the sum of all fragment_size of all
221 * fragments is equal to total_size, the memory transaction has been
222 * completed.
223 * This is a simple test with only one segment. As such, upon
224 * successful ffa_mem_retrieve_req, total_size must be equal to
225 * fragment_size.
226 */
227 total_size = ret.ret1;
228 fragment_size = ret.ret2;
229
230 if (total_size != fragment_size) {
231 ERROR("Only expect one memory segment to be sent!\n");
232 return false;
233 }
234
235 if (fragment_size > PAGE_SIZE) {
236 ERROR("Fragment should be smaller than RX buffer!\n");
237 return false;
238 }
239
J-Alves0435cae2020-11-06 10:49:56 +0000240 *retrieved = (struct ffa_memory_region *)mb->recv;
J-Alves63cdaa72020-10-08 17:22:45 +0100241
J-Alves0435cae2020-11-06 10:49:56 +0000242 if ((*retrieved)->receiver_count > MAX_MEM_SHARE_RECIPIENTS) {
243 VERBOSE("SPMC memory sharing operations support max of %u "
244 "receivers!\n", MAX_MEM_SHARE_RECIPIENTS);
J-Alves63cdaa72020-10-08 17:22:45 +0100245 return false;
246 }
247
Olivier Deprezaed7f082020-11-04 15:11:59 +0100248 VERBOSE("Memory Retrieved!\n");
J-Alves63cdaa72020-10-08 17:22:45 +0100249
250 return true;
251}
252
253bool ffa_memory_relinquish_test(struct ffa_mem_relinquish *m,
254 uint64_t handle,
255 ffa_vm_id_t id)
256{
J-Alves6cb21d92021-01-07 15:18:12 +0000257 smc_ret_values ret;
J-Alves63cdaa72020-10-08 17:22:45 +0100258
J-Alves6cb21d92021-01-07 15:18:12 +0000259 ffa_mem_relinquish_init(m, handle, 0, id);
260 ret = ffa_mem_relinquish();
261 if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
262 ERROR("%s failed to relinquish memory! error: %x\n",
263 __func__, ffa_error_code(ret));
J-Alves63cdaa72020-10-08 17:22:45 +0100264 return false;
265 }
266
Olivier Deprezaed7f082020-11-04 15:11:59 +0100267 VERBOSE("Memory Relinquished!\n");
J-Alves63cdaa72020-10-08 17:22:45 +0100268 return true;
269}
270
271void ffa_memory_management_test(struct mailbox_buffers *mb, ffa_vm_id_t vm_id,
272 ffa_vm_id_t sender, uint32_t mem_func,
273 uint64_t handle)
274{
275 const char *test_ffa = "Memory Management";
J-Alves0435cae2020-11-06 10:49:56 +0000276 struct ffa_memory_region *m;
J-Alves63cdaa72020-10-08 17:22:45 +0100277 struct ffa_composite_memory_region *composite;
278 int ret;
279 unsigned int mem_attrs;
280 uint32_t *ptr;
281
282 announce_test_section_start(test_ffa);
283
284 expect(ffa_memory_retrieve_test(
285 mb, &m, handle, sender, vm_id, mem_func),
286 true);
287
J-Alves0435cae2020-11-06 10:49:56 +0000288 composite = ffa_memory_region_get_composite(m, 0);
J-Alves63cdaa72020-10-08 17:22:45 +0100289
Olivier Deprezaed7f082020-11-04 15:11:59 +0100290 VERBOSE("Address: %p; page_count: %x %x\n",
J-Alves63cdaa72020-10-08 17:22:45 +0100291 composite->constituents[0].address,
292 composite->constituents[0].page_count, PAGE_SIZE);
293
294 /* This test is only concerned with RW permissions. */
295 expect(ffa_get_data_access_attr(
J-Alves0435cae2020-11-06 10:49:56 +0000296 m->receivers[0].receiver_permissions.permissions),
J-Alves63cdaa72020-10-08 17:22:45 +0100297 FFA_DATA_ACCESS_RW);
298
J-Alvesd8edeed2020-11-18 10:48:12 +0000299 mem_attrs = MT_RW_DATA | MT_EXECUTE_NEVER;
300
301 if (!IS_SP_ID(sender)) {
302 mem_attrs |= MT_NS;
303 }
J-Alves63cdaa72020-10-08 17:22:45 +0100304
305 ret = mmap_add_dynamic_region(
306 (uint64_t)composite->constituents[0].address,
307 (uint64_t)composite->constituents[0].address,
308 composite->constituents[0].page_count * PAGE_SIZE,
309 mem_attrs);
310 expect(ret, 0);
311
312 VERBOSE("Memory has been mapped\n");
313
314 ptr = (uint32_t *) composite->constituents[0].address;
315
316 /* Write mem_func to retrieved memory region for validation purposes. */
317 VERBOSE("Writing: %x\n", mem_func);
318 for (unsigned int i = 0U; i < 5U; i++)
319 ptr[i] = mem_func;
320
321 /*
322 * A FFA_MEM_DONATE changes the ownership of the page, as such no
323 * relinquish is needed.
324 */
325 if (mem_func != FFA_MEM_DONATE_SMC32) {
326 ret = mmap_remove_dynamic_region(
327 (uint64_t)composite->constituents[0].address,
328 composite->constituents[0].page_count * PAGE_SIZE);
329 expect(ret, 0);
330
331 expect(ffa_memory_relinquish_test(
332 (struct ffa_mem_relinquish *)mb->send,
J-Alves0435cae2020-11-06 10:49:56 +0000333 m->handle, vm_id),
J-Alves63cdaa72020-10-08 17:22:45 +0100334 true);
335 }
336
J-Alves6cb21d92021-01-07 15:18:12 +0000337 expect(ffa_func_id(ffa_rx_release()), FFA_SUCCESS_SMC32);
J-Alves0435cae2020-11-06 10:49:56 +0000338
J-Alves63cdaa72020-10-08 17:22:45 +0100339 announce_test_section_end(test_ffa);
340}
341
Max Shvetsov57c6ddb2020-07-01 14:09:48 +0100342void ffa_tests(struct mailbox_buffers *mb)
343{
344 const char *test_ffa = "FFA Interfaces";
345
346 announce_test_section_start(test_ffa);
J-Alves9f6f0142020-06-17 15:37:59 +0100347
Max Shvetsov40eb6a22020-06-08 11:15:30 +0100348 ffa_features_test();
Max Shvetsov57c6ddb2020-07-01 14:09:48 +0100349 ffa_version_test();
Max Shvetsovc32f4782020-06-23 09:41:15 +0100350 ffa_partition_info_get_test(mb);
Max Shvetsov40eb6a22020-06-08 11:15:30 +0100351
J-Alves9f6f0142020-06-17 15:37:59 +0100352 announce_test_section_end(test_ffa);
353}