blob: 04c8fde5d52802c25b52c35ba064dcf1decf8b81 [file] [log] [blame]
J-Alves40618a32020-10-08 17:25:37 +01001/*
J-Alves3be0efa2023-10-02 19:11:11 +01002 * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
J-Alves40618a32020-10-08 17:25:37 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
J-Alves8083db22023-06-27 17:22:58 +01007#include "arch_features.h"
J-Alves3be0efa2023-10-02 19:11:11 +01008#include "arch_helpers.h"
9#include "ffa_helpers.h"
J-Alves8083db22023-06-27 17:22:58 +010010#include "ffa_svc.h"
J-Alves72f00292024-01-08 11:31:45 +000011#include "stdint.h"
J-Alves3be0efa2023-10-02 19:11:11 +010012#include "utils_def.h"
J-Alves40618a32020-10-08 17:25:37 +010013#include <debug.h>
Karl Meakin3d879b82023-06-16 10:32:08 +010014#include "ffa_helpers.h"
J-Alves8083db22023-06-27 17:22:58 +010015#include <sync.h>
Max Shvetsov103e0562021-02-04 16:58:31 +000016
17#include <cactus_test_cmds.h>
J-Alves40618a32020-10-08 17:25:37 +010018#include <ffa_endpoints.h>
J-Alves3be0efa2023-10-02 19:11:11 +010019#include <host_realm_rmi.h>
Daniel Boulby82bf3392023-07-28 18:32:27 +010020#include <spm_common.h>
21#include <spm_test_helpers.h>
J-Alves40618a32020-10-08 17:25:37 +010022#include <test_helpers.h>
23#include <tftf_lib.h>
24#include <xlat_tables_defs.h>
25
26#define MAILBOX_SIZE PAGE_SIZE
27
28#define SENDER HYP_ID
29#define RECEIVER SP_ID(1)
30
Karl Meakin0d4f5ff2023-10-13 20:03:16 +010031/*
32 * A number of pages that is large enough that it must take two fragments to
33 * share.
34 */
35#define FRAGMENTED_SHARE_PAGE_COUNT \
36 (sizeof(struct ffa_memory_region) / \
37 sizeof(struct ffa_memory_region_constituent))
38
J-Alves3106b072020-11-18 10:37:21 +000039static const struct ffa_uuid expected_sp_uuids[] = {
40 {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}
41 };
42
J-Alves27390fd2020-11-18 10:51:15 +000043/* Memory section to be used for memory share operations */
Karl Meakin0d4f5ff2023-10-13 20:03:16 +010044static __aligned(PAGE_SIZE) uint8_t
45 share_page[PAGE_SIZE * FRAGMENTED_SHARE_PAGE_COUNT];
J-Alves3be0efa2023-10-02 19:11:11 +010046static __aligned(PAGE_SIZE) uint8_t donate_page[PAGE_SIZE];
J-Alves36c9b072023-03-17 15:05:41 +000047static __aligned(PAGE_SIZE) uint8_t consecutive_donate_page[PAGE_SIZE];
J-Alves04fc4f22023-10-11 17:04:52 +010048static __aligned(PAGE_SIZE) uint8_t four_share_pages[PAGE_SIZE * 4];
J-Alves72f00292024-01-08 11:31:45 +000049
J-Alves8083db22023-06-27 17:22:58 +010050static bool gpc_abort_triggered;
J-Alves40618a32020-10-08 17:25:37 +010051
J-Alves807ce142021-12-14 15:24:11 +000052static bool check_written_words(uint32_t *ptr, uint32_t word, uint32_t wcount)
53{
54 VERBOSE("TFTF - Memory contents after SP use:\n");
55 for (unsigned int i = 0U; i < wcount; i++) {
56 VERBOSE(" %u: %x\n", i, ptr[i]);
57
58 /* Verify content of memory is as expected. */
59 if (ptr[i] != word) {
60 return false;
61 }
62 }
63 return true;
64}
65
J-Alves9c088902023-03-16 18:21:37 +000066static bool test_memory_send_expect_denied(uint32_t mem_func,
J-Alves7b8f5c02023-03-17 15:05:13 +000067 void *mem_ptr,
68 ffa_id_t borrower)
J-Alves9c088902023-03-16 18:21:37 +000069{
70 struct ffa_value ret;
71 struct mailbox_buffers mb;
72 struct ffa_memory_region_constituent constituents[] = {
73 {(void *)mem_ptr, 1, 0}
74 };
75 ffa_memory_handle_t handle;
76
77 const uint32_t constituents_count = sizeof(constituents) /
78 sizeof(struct ffa_memory_region_constituent);
Karl Meakin1331a8c2023-09-14 16:25:15 +010079
80 struct ffa_memory_access receiver =
81 ffa_memory_access_init_permissions_from_mem_func(borrower,
82 mem_func);
83
J-Alves9c088902023-03-16 18:21:37 +000084 GET_TFTF_MAILBOX(mb);
85
86 handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
Karl Meakin1331a8c2023-09-14 16:25:15 +010087 MAILBOX_SIZE, SENDER, &receiver, 1,
J-Alves9c088902023-03-16 18:21:37 +000088 constituents, constituents_count,
89 mem_func, &ret);
90
91 if (handle != FFA_MEMORY_HANDLE_INVALID) {
Karl Meakin0d4f5ff2023-10-13 20:03:16 +010092 ERROR("Received a valid FF-A memory handle, and that isn't "
93 "expected.\n");
J-Alves9c088902023-03-16 18:21:37 +000094 return false;
95 }
96
97 if (!is_expected_ffa_error(ret, FFA_ERROR_DENIED)) {
98 return false;
99 }
100
101 return true;
102}
103
J-Alves8083db22023-06-27 17:22:58 +0100104static bool data_abort_handler(void)
105{
106 uint64_t esr_elx = IS_IN_EL2() ? read_esr_el2() : read_esr_el1();
107
108 VERBOSE("%s esr_elx %llx\n", __func__, esr_elx);
109
110 if (EC_BITS(esr_elx) == EC_DABORT_CUR_EL) {
111 /* Synchronous data abort triggered by Granule protection */
112 if ((ISS_BITS(esr_elx) & ISS_DFSC_MASK) == DFSC_GPF_DABORT) {
J-Alves3be0efa2023-10-02 19:11:11 +0100113 VERBOSE("%s GPF Data Abort caught to address: %llx\n",
114 __func__, (uint64_t)read_far_el2());
J-Alves8083db22023-06-27 17:22:58 +0100115 gpc_abort_triggered = true;
116 return true;
117 }
118 }
119
120 return false;
121}
122
J-Alves3be0efa2023-10-02 19:11:11 +0100123static bool get_gpc_abort_triggered(void)
124{
125 bool ret = gpc_abort_triggered;
126
127 gpc_abort_triggered = false;
128
129 return ret;
130}
131
J-Alves9c088902023-03-16 18:21:37 +0000132/**
133 * Test invocation to FF-A memory sharing interfaces that should return in an
134 * error.
135 */
136test_result_t test_share_forbidden_ranges(void)
137{
138 const uintptr_t forbidden_address[] = {
139 /* Cactus SP memory. */
140 (uintptr_t)0x7200000,
141 /* SPMC Memory. */
142 (uintptr_t)0x6000000,
143 /* NS memory defined in cactus tertiary. */
144 (uintptr_t)0x0000880080001000,
145 };
146
Daniel Boulbyb34fe102024-01-17 15:10:52 +0000147 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
J-Alves9c088902023-03-16 18:21:37 +0000148
149 for (unsigned i = 0; i < 3; i++) {
150 if (!test_memory_send_expect_denied(
J-Alves8984e722024-05-07 22:21:54 +0100151 FFA_MEM_SHARE_SMC64, (void *)forbidden_address[i],
J-Alves7b8f5c02023-03-17 15:05:13 +0000152 RECEIVER)) {
J-Alves9c088902023-03-16 18:21:37 +0000153 return TEST_RESULT_FAIL;
154 }
155 }
156
157 return TEST_RESULT_SUCCESS;
158}
159
J-Alves3106b072020-11-18 10:37:21 +0000160/**
161 * Tests that it is possible to share memory with SWd from NWd.
162 * After calling the respective memory send API, it will expect a reply from
163 * cactus SP, at which point it will reclaim access to the memory region and
164 * check the memory region has been used by receiver SP.
165 *
166 * Accessing memory before a memory reclaim operation should only be possible
167 * in the context of a memory share operation.
168 * According to the FF-A spec, the owner is temporarily relinquishing
169 * access to the memory region on a memory lend operation, and on a
170 * memory donate operation the access is relinquished permanently.
171 * SPMC is positioned in S-EL2, and doesn't control stage-1 mapping for
172 * EL2. Therefore, it is impossible to enforce the expected access
173 * policy for a donate and lend operations within the SPMC.
174 * Current SPMC implementation is under the assumption of trust that
175 * Hypervisor (sitting in EL2) would relinquish access from EL1/EL0
176 * FF-A endpoint at relevant moment.
177 */
J-Alves7b8f5c02023-03-17 15:05:13 +0000178static test_result_t test_memory_send_sp(uint32_t mem_func, ffa_id_t borrower,
179 struct ffa_memory_region_constituent *constituents,
180 size_t constituents_count)
J-Alves40618a32020-10-08 17:25:37 +0100181{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100182 struct ffa_value ret;
J-Alves40618a32020-10-08 17:25:37 +0100183 ffa_memory_handle_t handle;
184 uint32_t *ptr;
J-Alvesf1126f22020-11-02 17:28:20 +0000185 struct mailbox_buffers mb;
J-Alves8083db22023-06-27 17:22:58 +0100186 unsigned int rme_supported = get_armv9_2_feat_rme_support();
187 const bool check_gpc_fault =
J-Alves8984e722024-05-07 22:21:54 +0100188 mem_func != FFA_MEM_SHARE_SMC64 &&
J-Alves8083db22023-06-27 17:22:58 +0100189 rme_supported != 0U;
J-Alves40618a32020-10-08 17:25:37 +0100190
J-Alves32ccd2b2021-12-14 14:59:51 +0000191 /* Arbitrarily write 5 words after using memory. */
192 const uint32_t nr_words_to_write = 5;
193
Karl Meakin1331a8c2023-09-14 16:25:15 +0100194 struct ffa_memory_access receiver =
195 ffa_memory_access_init_permissions_from_mem_func(borrower,
196 mem_func);
197
J-Alves3106b072020-11-18 10:37:21 +0000198 /***********************************************************************
199 * Check if SPMC has ffa_version and expected FFA endpoints are deployed.
J-Alves40618a32020-10-08 17:25:37 +0100200 **********************************************************************/
Daniel Boulbyb34fe102024-01-17 15:10:52 +0000201 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
J-Alves40618a32020-10-08 17:25:37 +0100202
J-Alves3106b072020-11-18 10:37:21 +0000203 GET_TFTF_MAILBOX(mb);
J-Alves40618a32020-10-08 17:25:37 +0100204
J-Alves8083db22023-06-27 17:22:58 +0100205 /*
J-Alves72f00292024-01-08 11:31:45 +0000206 * If the RME is enabled for the platform under test, check that the
207 * GPCs are working as expected, as such setup the exception handler.
J-Alves8083db22023-06-27 17:22:58 +0100208 */
209 if (check_gpc_fault) {
210 register_custom_sync_exception_handler(data_abort_handler);
211 }
212
J-Alvesc2e32ed2023-12-04 13:22:44 +0000213 for (size_t i = 0; i < constituents_count; i++) {
214 VERBOSE("Sharing Address: %p\n", constituents[i].address);
215 ptr = (uint32_t *)constituents[i].address;
216 for (size_t j = 0; j < nr_words_to_write; j++) {
217 ptr[j] = mem_func + 0xFFA;
218 }
219 }
220
J-Alvesbe1519a2021-02-19 14:33:54 +0000221 handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
Karl Meakin1331a8c2023-09-14 16:25:15 +0100222 MAILBOX_SIZE, SENDER, &receiver, 1,
J-Alves3106b072020-11-18 10:37:21 +0000223 constituents, constituents_count,
Maksims Svecovsa65a9072021-12-10 13:08:41 +0000224 mem_func, &ret);
J-Alves40618a32020-10-08 17:25:37 +0100225
J-Alves3106b072020-11-18 10:37:21 +0000226 if (handle == FFA_MEMORY_HANDLE_INVALID) {
J-Alves40618a32020-10-08 17:25:37 +0100227 return TEST_RESULT_FAIL;
228 }
229
J-Alvesff607a22023-03-16 15:42:21 +0000230 VERBOSE("TFTF - Handle: %llx\n", handle);
J-Alves40618a32020-10-08 17:25:37 +0100231
232 ptr = (uint32_t *)constituents[0].address;
233
J-Alves7b8f5c02023-03-17 15:05:13 +0000234 ret = cactus_mem_send_cmd(SENDER, borrower, mem_func, handle, 0,
J-Alvese742ba82024-01-11 10:38:29 +0000235 nr_words_to_write, false);
J-Alves40618a32020-10-08 17:25:37 +0100236
J-Alvesb122eea2023-10-11 16:59:46 +0100237 if (!is_ffa_direct_response(ret) ||
238 cactus_get_response(ret) != CACTUS_SUCCESS) {
239 ffa_mem_reclaim(handle, 0);
J-Alves3106b072020-11-18 10:37:21 +0000240 ERROR("Failed memory send operation!\n");
J-Alves40618a32020-10-08 17:25:37 +0100241 return TEST_RESULT_FAIL;
242 }
243
J-Alves8083db22023-06-27 17:22:58 +0100244 /*
J-Alves72f00292024-01-08 11:31:45 +0000245 * If there is RME support, look to trigger an exception as soon as the
J-Alves8083db22023-06-27 17:22:58 +0100246 * security state is update, due to GPC fault.
247 */
248 if (check_gpc_fault) {
249 *ptr = 0xBEEF;
250 }
251
J-Alves8984e722024-05-07 22:21:54 +0100252 if (mem_func != FFA_MEM_DONATE_SMC64) {
J-Alves40618a32020-10-08 17:25:37 +0100253
J-Alvesdbd5ac22023-05-05 19:47:24 +0100254 /* Reclaim memory entirely before checking its state. */
255 if (is_ffa_call_error(ffa_mem_reclaim(handle, 0))) {
J-Alves40618a32020-10-08 17:25:37 +0100256 tftf_testcase_printf("Couldn't reclaim memory\n");
257 return TEST_RESULT_FAIL;
J-Alvesdbd5ac22023-05-05 19:47:24 +0100258 }
259
J-Alves72f00292024-01-08 11:31:45 +0000260 for (uint32_t i = 0; i < constituents_count; i++) {
261 ptr = constituents[i].address;
262
263 /*
J-Alvesc2e32ed2023-12-04 13:22:44 +0000264 * Check that borrower used the memory as expected
265 * for FFA_MEM_SHARE test.
J-Alves72f00292024-01-08 11:31:45 +0000266 */
J-Alves8984e722024-05-07 22:21:54 +0100267 if (mem_func == FFA_MEM_SHARE_SMC64 &&
J-Alvesc2e32ed2023-12-04 13:22:44 +0000268 !check_written_words(ptr,
269 mem_func + 0xFFAU,
J-Alves72f00292024-01-08 11:31:45 +0000270 nr_words_to_write)) {
271 ERROR("Fail because of state of memory.\n");
272 return TEST_RESULT_FAIL;
273 }
J-Alvesdbd5ac22023-05-05 19:47:24 +0100274 }
J-Alves40618a32020-10-08 17:25:37 +0100275 }
276
J-Alves8083db22023-06-27 17:22:58 +0100277 if (check_gpc_fault) {
278 unregister_custom_sync_exception_handler();
J-Alves3be0efa2023-10-02 19:11:11 +0100279 if (!get_gpc_abort_triggered()) {
J-Alves8083db22023-06-27 17:22:58 +0100280 ERROR("No exception due to GPC for lend/donate with RME.\n");
281 return TEST_RESULT_FAIL;
282 }
283 }
284
J-Alves40618a32020-10-08 17:25:37 +0100285 return TEST_RESULT_SUCCESS;
286}
287
288test_result_t test_mem_share_sp(void)
289{
J-Alves7b8f5c02023-03-17 15:05:13 +0000290 struct ffa_memory_region_constituent constituents[] = {
291 {(void *)share_page, 1, 0}
292 };
293
294 const uint32_t constituents_count = sizeof(constituents) /
295 sizeof(struct ffa_memory_region_constituent);
296
J-Alves8984e722024-05-07 22:21:54 +0100297 return test_memory_send_sp(FFA_MEM_SHARE_SMC64, RECEIVER, constituents,
J-Alves7b8f5c02023-03-17 15:05:13 +0000298 constituents_count);
J-Alves40618a32020-10-08 17:25:37 +0100299}
300
301test_result_t test_mem_lend_sp(void)
302{
J-Alves7b8f5c02023-03-17 15:05:13 +0000303 struct ffa_memory_region_constituent constituents[] = {
J-Alves72f00292024-01-08 11:31:45 +0000304 {(void *)four_share_pages, 4, 0},
J-Alves7b8f5c02023-03-17 15:05:13 +0000305 {(void *)share_page, 1, 0}
306 };
307
308 const uint32_t constituents_count = sizeof(constituents) /
309 sizeof(struct ffa_memory_region_constituent);
310
J-Alves8984e722024-05-07 22:21:54 +0100311 return test_memory_send_sp(FFA_MEM_LEND_SMC64, RECEIVER, constituents,
J-Alves7b8f5c02023-03-17 15:05:13 +0000312 constituents_count);
J-Alves40618a32020-10-08 17:25:37 +0100313}
314
315test_result_t test_mem_donate_sp(void)
316{
J-Alves7b8f5c02023-03-17 15:05:13 +0000317 struct ffa_memory_region_constituent constituents[] = {
J-Alves3be0efa2023-10-02 19:11:11 +0100318 {(void *)donate_page, 1, 0}
J-Alves7b8f5c02023-03-17 15:05:13 +0000319 };
320 const uint32_t constituents_count = sizeof(constituents) /
321 sizeof(struct ffa_memory_region_constituent);
J-Alves8984e722024-05-07 22:21:54 +0100322 return test_memory_send_sp(FFA_MEM_DONATE_SMC64, RECEIVER, constituents,
J-Alves7b8f5c02023-03-17 15:05:13 +0000323 constituents_count);
J-Alves40618a32020-10-08 17:25:37 +0100324}
J-Alves27390fd2020-11-18 10:51:15 +0000325
J-Alves36c9b072023-03-17 15:05:41 +0000326test_result_t test_consecutive_donate(void)
327{
328 struct ffa_memory_region_constituent constituents[] = {
329 {(void *)consecutive_donate_page, 1, 0}
330 };
331 const uint32_t constituents_count = sizeof(constituents) /
332 sizeof(struct ffa_memory_region_constituent);
333
Daniel Boulbyb34fe102024-01-17 15:10:52 +0000334 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
J-Alves36c9b072023-03-17 15:05:41 +0000335
J-Alves8984e722024-05-07 22:21:54 +0100336 test_result_t ret = test_memory_send_sp(FFA_MEM_DONATE_SMC64, SP_ID(1),
J-Alves36c9b072023-03-17 15:05:41 +0000337 constituents,
338 constituents_count);
339
340 if (ret != TEST_RESULT_SUCCESS) {
341 ERROR("Failed at first attempting of sharing.\n");
342 return TEST_RESULT_FAIL;
343 }
344
J-Alves8984e722024-05-07 22:21:54 +0100345 if (!test_memory_send_expect_denied(FFA_MEM_DONATE_SMC64,
J-Alves36c9b072023-03-17 15:05:41 +0000346 consecutive_donate_page,
347 SP_ID(1))) {
348 ERROR("Memory was successfully donated again from the NWd, to "
349 "the same borrower.\n");
350 return TEST_RESULT_FAIL;
351 }
352
J-Alves8984e722024-05-07 22:21:54 +0100353 if (!test_memory_send_expect_denied(FFA_MEM_DONATE_SMC64,
J-Alves36c9b072023-03-17 15:05:41 +0000354 consecutive_donate_page,
355 SP_ID(2))) {
356 ERROR("Memory was successfully donated again from the NWd, to "
357 "another borrower.\n");
358 return TEST_RESULT_FAIL;
359 }
360
361 return TEST_RESULT_SUCCESS;
362}
363
J-Alves27390fd2020-11-18 10:51:15 +0000364/*
365 * Test requests a memory send operation between cactus SPs.
366 * Cactus SP should reply to TFTF on whether the test succeeded or not.
367 */
368static test_result_t test_req_mem_send_sp_to_sp(uint32_t mem_func,
Daniel Boulbye79d2072021-03-03 11:34:53 +0000369 ffa_id_t sender_sp,
Federico Recanati6328fb02022-01-14 15:48:16 +0100370 ffa_id_t receiver_sp,
371 bool non_secure)
J-Alves27390fd2020-11-18 10:51:15 +0000372{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100373 struct ffa_value ret;
J-Alves27390fd2020-11-18 10:51:15 +0000374
375 /***********************************************************************
376 * Check if SPMC's ffa_version and presence of expected FF-A endpoints.
377 **********************************************************************/
Daniel Boulbyb34fe102024-01-17 15:10:52 +0000378 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
J-Alves27390fd2020-11-18 10:51:15 +0000379
J-Alves53392012020-11-18 14:51:57 +0000380 ret = cactus_req_mem_send_send_cmd(HYP_ID, sender_sp, mem_func,
Federico Recanati6328fb02022-01-14 15:48:16 +0100381 receiver_sp, non_secure);
J-Alves27390fd2020-11-18 10:51:15 +0000382
J-Alves06373c52021-02-11 15:17:42 +0000383 if (!is_ffa_direct_response(ret)) {
J-Alves27390fd2020-11-18 10:51:15 +0000384 return TEST_RESULT_FAIL;
385 }
386
J-Alves53392012020-11-18 14:51:57 +0000387 if (cactus_get_response(ret) == CACTUS_ERROR) {
Maksims Svecovs61740652021-12-14 12:01:45 +0000388 ERROR("Failed sharing memory between SPs. Error code: %d\n",
389 cactus_error_code(ret));
J-Alves27390fd2020-11-18 10:51:15 +0000390 return TEST_RESULT_FAIL;
391 }
392
393 return TEST_RESULT_SUCCESS;
394}
395
Maksims Svecovs61740652021-12-14 12:01:45 +0000396/*
397 * Test requests a memory send operation from SP to VM.
398 * The tests expects cactus to reply CACTUS_ERROR, providing FF-A error code of
399 * the last memory send FF-A call that cactus performed.
400 */
401static test_result_t test_req_mem_send_sp_to_vm(uint32_t mem_func,
402 ffa_id_t sender_sp,
403 ffa_id_t receiver_vm)
404{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100405 struct ffa_value ret;
Maksims Svecovs61740652021-12-14 12:01:45 +0000406
407 /**********************************************************************
408 * Check if SPMC's ffa_version and presence of expected FF-A endpoints.
409 *********************************************************************/
Daniel Boulbyb34fe102024-01-17 15:10:52 +0000410 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
Maksims Svecovs61740652021-12-14 12:01:45 +0000411
412 ret = cactus_req_mem_send_send_cmd(HYP_ID, sender_sp, mem_func,
Federico Recanati6328fb02022-01-14 15:48:16 +0100413 receiver_vm, false);
Maksims Svecovs61740652021-12-14 12:01:45 +0000414
415 if (!is_ffa_direct_response(ret)) {
416 return TEST_RESULT_FAIL;
417 }
418
419 if (cactus_get_response(ret) == CACTUS_ERROR &&
420 cactus_error_code(ret) == FFA_ERROR_DENIED) {
421 return TEST_RESULT_SUCCESS;
422 }
423
424 tftf_testcase_printf("Did not get the expected error, "
425 "mem send returned with %d\n",
426 cactus_get_response(ret));
427 return TEST_RESULT_FAIL;
428}
429
J-Alves27390fd2020-11-18 10:51:15 +0000430test_result_t test_req_mem_share_sp_to_sp(void)
431{
J-Alves8984e722024-05-07 22:21:54 +0100432 return test_req_mem_send_sp_to_sp(FFA_MEM_SHARE_SMC64, SP_ID(3),
Federico Recanati6328fb02022-01-14 15:48:16 +0100433 SP_ID(2), false);
434}
435
436test_result_t test_req_ns_mem_share_sp_to_sp(void)
437{
Olivier Deprez728cc562022-06-09 11:37:46 +0200438 /*
439 * Skip the test when RME is enabled (for test setup reasons).
440 * For RME tests, the model specifies 48b physical address size
441 * at the PE, but misses allocating RAM and increasing the PA at
442 * the interconnect level.
443 */
444 if (get_armv9_2_feat_rme_support() != 0U) {
445 return TEST_RESULT_SKIPPED;
446 }
447
448 /* This test requires 48b physical address size capability. */
Federico Recanati6328fb02022-01-14 15:48:16 +0100449 SKIP_TEST_IF_PA_SIZE_LESS_THAN(48);
Olivier Deprez728cc562022-06-09 11:37:46 +0200450
J-Alves8984e722024-05-07 22:21:54 +0100451 return test_req_mem_send_sp_to_sp(FFA_MEM_SHARE_SMC64, SP_ID(3),
Federico Recanati6328fb02022-01-14 15:48:16 +0100452 SP_ID(2), true);
J-Alves27390fd2020-11-18 10:51:15 +0000453}
454
455test_result_t test_req_mem_lend_sp_to_sp(void)
456{
J-Alves8984e722024-05-07 22:21:54 +0100457 return test_req_mem_send_sp_to_sp(FFA_MEM_LEND_SMC64, SP_ID(3),
Federico Recanati6328fb02022-01-14 15:48:16 +0100458 SP_ID(2), false);
J-Alves27390fd2020-11-18 10:51:15 +0000459}
460
461test_result_t test_req_mem_donate_sp_to_sp(void)
462{
J-Alves8984e722024-05-07 22:21:54 +0100463 return test_req_mem_send_sp_to_sp(FFA_MEM_DONATE_SMC64, SP_ID(1),
Federico Recanati6328fb02022-01-14 15:48:16 +0100464 SP_ID(3), false);
J-Alves27390fd2020-11-18 10:51:15 +0000465}
Maksims Svecovs61740652021-12-14 12:01:45 +0000466
467test_result_t test_req_mem_share_sp_to_vm(void)
468{
J-Alves8984e722024-05-07 22:21:54 +0100469 return test_req_mem_send_sp_to_vm(FFA_MEM_SHARE_SMC64, SP_ID(1),
Maksims Svecovs61740652021-12-14 12:01:45 +0000470 HYP_ID);
471}
472
473test_result_t test_req_mem_lend_sp_to_vm(void)
474{
J-Alves8984e722024-05-07 22:21:54 +0100475 return test_req_mem_send_sp_to_vm(FFA_MEM_LEND_SMC64, SP_ID(2),
Maksims Svecovs61740652021-12-14 12:01:45 +0000476 HYP_ID);
477}
J-Alves807ce142021-12-14 15:24:11 +0000478
479test_result_t test_mem_share_to_sp_clear_memory(void)
480{
481 struct ffa_memory_region_constituent constituents[] = {
J-Alves04fc4f22023-10-11 17:04:52 +0100482 {(void *)four_share_pages, 4, 0},
483 {(void *)share_page, 1, 0}
484 };
485
J-Alves807ce142021-12-14 15:24:11 +0000486 const uint32_t constituents_count = sizeof(constituents) /
487 sizeof(struct ffa_memory_region_constituent);
488 struct mailbox_buffers mb;
489 uint32_t remaining_constituent_count;
490 uint32_t total_length;
491 uint32_t fragment_length;
492 ffa_memory_handle_t handle;
Daniel Boulbyce386b12022-03-29 18:36:36 +0100493 struct ffa_value ret;
J-Alves807ce142021-12-14 15:24:11 +0000494 /* Arbitrarily write 10 words after using shared memory. */
495 const uint32_t nr_words_to_write = 10U;
496
Karl Meakin1331a8c2023-09-14 16:25:15 +0100497 struct ffa_memory_access receiver =
498 ffa_memory_access_init_permissions_from_mem_func(
J-Alves8984e722024-05-07 22:21:54 +0100499 RECEIVER, FFA_MEM_LEND_SMC64);
Karl Meakin1331a8c2023-09-14 16:25:15 +0100500
Daniel Boulbyb34fe102024-01-17 15:10:52 +0000501 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
J-Alves807ce142021-12-14 15:24:11 +0000502
503 GET_TFTF_MAILBOX(mb);
504
505 remaining_constituent_count = ffa_memory_region_init(
506 (struct ffa_memory_region *)mb.send, MAILBOX_SIZE, SENDER,
Karl Meakin1331a8c2023-09-14 16:25:15 +0100507 &receiver, 1, constituents, constituents_count, 0,
508 FFA_MEMORY_REGION_FLAG_CLEAR,
J-Alves6656a772022-07-04 09:48:12 +0100509 FFA_MEMORY_NOT_SPECIFIED_MEM, 0, 0,
J-Alves807ce142021-12-14 15:24:11 +0000510 &total_length, &fragment_length);
511
512 if (remaining_constituent_count != 0) {
513 ERROR("Transaction descriptor initialization failed!\n");
514 return TEST_RESULT_FAIL;
515 }
516
J-Alves8984e722024-05-07 22:21:54 +0100517 handle = memory_send(mb.send, FFA_MEM_LEND_SMC64, constituents,
Karl Meakin0d4f5ff2023-10-13 20:03:16 +0100518 constituents_count, remaining_constituent_count,
519 fragment_length, total_length, &ret);
J-Alves807ce142021-12-14 15:24:11 +0000520
521 if (handle == FFA_MEMORY_HANDLE_INVALID) {
522 ERROR("Memory Share failed!\n");
523 return TEST_RESULT_FAIL;
524 }
525
526 VERBOSE("Memory has been shared!\n");
527
J-Alves8984e722024-05-07 22:21:54 +0100528 ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_LEND_SMC64, handle,
J-Alvese742ba82024-01-11 10:38:29 +0000529 FFA_MEMORY_REGION_FLAG_CLEAR,
530 nr_words_to_write, false);
J-Alves807ce142021-12-14 15:24:11 +0000531
532 if (!is_ffa_direct_response(ret)) {
533 return TEST_RESULT_FAIL;
534 }
535
536 if (cactus_get_response(ret) != CACTUS_SUCCESS) {
537 ERROR("Failed memory send operation!\n");
538 return TEST_RESULT_FAIL;
539 }
540
541 ret = ffa_mem_reclaim(handle, 0);
542
543 if (is_ffa_call_error(ret)) {
544 ERROR("Memory reclaim failed!\n");
545 return TEST_RESULT_FAIL;
546 }
547
J-Alves807ce142021-12-14 15:24:11 +0000548 return TEST_RESULT_SUCCESS;
549}
Karl Meakin3d879b82023-06-16 10:32:08 +0100550
551/**
552 * Print `region` if LOG_LEVEL >= LOG_LEVEL_VERBOSE
553 */
554static void print_memory_region(struct ffa_memory_region *region)
555{
556 VERBOSE("region.sender = %d\n", region->sender);
557 VERBOSE("region.attributes.shareability = %d\n",
558 region->attributes.shareability);
559 VERBOSE("region.attributes.cacheability = %d\n",
560 region->attributes.cacheability);
561 VERBOSE("region.attributes.type = %d\n", region->attributes.type);
562 VERBOSE("region.attributes.security = %d\n",
563 region->attributes.security);
564 VERBOSE("region.flags = %d\n", region->flags);
565 VERBOSE("region.handle = %lld\n", region->handle);
566 VERBOSE("region.tag = %lld\n", region->tag);
567 VERBOSE("region.memory_access_desc_size = %d\n",
568 region->memory_access_desc_size);
569 VERBOSE("region.receiver_count = %d\n", region->receiver_count);
570 VERBOSE("region.receivers_offset = %d\n", region->receivers_offset);
571}
572
573/**
574 * Used by hypervisor retrieve request test: validate descriptors provided by
575 * SPMC.
576 */
577static bool verify_retrieve_response(const struct ffa_memory_region *region1,
578 const struct ffa_memory_region *region2)
579{
580 if (region1->sender != region2->sender) {
581 ERROR("region1.sender=%d, expected %d\n", region1->sender,
582 region2->sender);
583 return false;
584 }
585 if (region1->attributes.shareability != region2->attributes.shareability) {
586 ERROR("region1.attributes.shareability=%d, expected %d\n",
587 region1->attributes.shareability,
588 region2->attributes.shareability);
589 return false;
590 }
591 if (region1->attributes.cacheability != region2->attributes.cacheability) {
592 ERROR("region1.attributes.cacheability=%d, expected %d\n",
593 region1->attributes.cacheability,
594 region2->attributes.cacheability);
595 return false;
596 }
597 if (region1->attributes.type != region2->attributes.type) {
598 ERROR("region1.attributes.type=%d, expected %d\n",
599 region1->attributes.type, region2->attributes.type);
600 return false;
601 }
602 if (region1->attributes.security != region2->attributes.security) {
603 ERROR("region1.attributes.security=%d, expected %d\n",
604 region1->attributes.security, region2->attributes.security);
605 return false;
606 }
607 if (region1->flags != region2->flags) {
608 ERROR("region1->flags=%d, expected %d\n", region1->flags,
609 region2->flags);
610 return false;
611 }
612 if (region1->handle != region2->handle) {
613 ERROR("region1.handle=%lld, expected %lld\n", region1->handle,
614 region2->handle);
615 return false;
616 }
617 if (region1->tag != region2->tag) {
618 ERROR("region1.tag=%lld, expected %lld\n", region1->tag, region2->tag);
619 return false;
620 }
621 if (region1->memory_access_desc_size != region2->memory_access_desc_size) {
622 ERROR("region1.memory_access_desc_size=%d, expected %d\n",
623 region1->memory_access_desc_size,
624 region2->memory_access_desc_size);
625 return false;
626 }
627 if (region1->receiver_count != region2->receiver_count) {
628 ERROR("region1.receiver_count=%d, expected %d\n",
629 region1->receiver_count, region2->receiver_count);
630 return false;
631 }
632 if (region1->receivers_offset != region2->receivers_offset) {
633 ERROR("region1.receivers_offset=%d, expected %d\n",
634 region1->receivers_offset, region2->receivers_offset);
635 return false;
636 }
637 for (uint32_t i = 0; i < 3; i++) {
638 if (region1->reserved[i] != 0) {
639 ERROR("region.reserved[%d]=%d, expected 0\n", i,
640 region1->reserved[i]);
641 return false;
642 }
643 }
644 return true;
645}
646
647/**
648 * Used by hypervisor retrieve request test: validate descriptors provided by
649 * SPMC.
650 */
651static bool
652verify_constituent(struct ffa_memory_region_constituent *constituent,
653 void *address, uint32_t page_count)
654{
655 if (constituent->address != address) {
656 ERROR("constituent.address=%p, expected %p\n",
657 constituent->address, address);
658 return false;
659 }
660 if (constituent->page_count != page_count) {
661 ERROR("constituent.page_count=%d, expected %d\n",
662 constituent->page_count, page_count);
663 return false;
664 }
665 if (constituent->reserved != 0) {
666 ERROR("constituent.reserved=%d, expected 0\n",
667 constituent->reserved);
668 return false;
669 }
670 return true;
671}
672
673/**
674 * Used by hypervisor retrieve request test: validate descriptors provided by
675 * SPMC.
676 */
677static bool verify_composite(struct ffa_composite_memory_region *composite,
678 struct ffa_memory_region_constituent *constituent,
679 uint32_t page_count, uint32_t constituent_count)
680{
681 if (composite->page_count != page_count) {
682 ERROR("composite.page_count=%d, expected %d\n",
683 composite->page_count, page_count);
684 return false;
685 }
686 if (composite->constituent_count != constituent_count) {
687 ERROR("composite.constituent_count=%d, expected %d\n",
688 composite->constituent_count, constituent_count);
689 return false;
690 }
691 if (composite->reserved_0 != 0) {
692 ERROR("composite.reserved_0=%llu, expected 0\n",
693 composite->reserved_0);
694 return false;
695 }
696 for (uint32_t j = 0; j < composite->constituent_count; j++) {
697 if (!verify_constituent(constituent, share_page, 1)) {
698 return false;
699 }
700 }
701 return true;
702}
703
J-Alvesb744c9b2024-01-18 17:03:47 +0000704static bool verify_receivers_impdef(struct ffa_memory_access_impdef impdef1,
705 struct ffa_memory_access_impdef impdef2)
706{
707 if (impdef1.val[0] != impdef2.val[0] ||
708 impdef1.val[1] != impdef2.val[1]) {
709 ERROR("ipmdef1.val[0]=%llu expected=%llu"
710 " ipmdef1.val[1]=%llu expected=%llu\n",
711 impdef1.val[0], impdef2.val[0],
712 impdef1.val[1], impdef2.val[1]);
713 return false;
714 }
715
716 return true;
717}
718
719static bool verify_permissions(
720 ffa_memory_access_permissions_t permissions1,
721 ffa_memory_access_permissions_t permissions2)
722{
723 uint8_t access1;
724 uint8_t access2;
725
726 access1 = permissions1.data_access;
727 access2 = permissions2.data_access;
728
729 if (access1 != access2) {
730 ERROR("permissions1.data_access=%u expected=%u\n",
731 access1, access2);
732 return false;
733 }
734
735 access1 = permissions1.instruction_access;
736 access2 = permissions2.instruction_access;
737
738 if (access1 != access2) {
739 ERROR("permissions1.instruction_access=%u expected=%u\n",
740 access1, access2);
741 return false;
742 }
743
744 return true;
745}
746
747/**
748 * Used by hypervisor retrieve request test: validate descriptors provided by
749 * SPMC.
750 */
751static bool verify_receivers(struct ffa_memory_access *receivers1,
752 struct ffa_memory_access *receivers2,
753 uint32_t receivers_count)
754{
755 for (uint32_t i = 0; i < receivers_count; i++) {
756 if (receivers1[i].receiver_permissions.receiver !=
757 receivers2[i].receiver_permissions.receiver) {
758 ERROR("receivers1[%u].receiver_permissions.receiver=%x"
759 " expected=%x\n", i,
760 receivers1[i].receiver_permissions.receiver,
761 receivers2[i].receiver_permissions.receiver);
762 return false;
763 }
764
765 if (receivers1[i].receiver_permissions.flags !=
766 receivers2[i].receiver_permissions.flags) {
767 ERROR("receivers1[%u].receiver_permissions.flags=%u"
768 " expected=%u\n", i,
769 receivers1[i].receiver_permissions.flags,
770 receivers2[i].receiver_permissions.flags);
771 return false;
772 }
773
774 if (!verify_permissions(
775 receivers1[i].receiver_permissions.permissions,
776 receivers2[i].receiver_permissions.permissions)) {
777 return false;
778 }
779
780 if (receivers1[i].composite_memory_region_offset !=
781 receivers2[i].composite_memory_region_offset) {
782 ERROR("receivers1[%u].composite_memory_region_offset=%u"
783 " expected %u\n",
784 i, receivers1[i].composite_memory_region_offset,
785 receivers2[i].composite_memory_region_offset);
786 return false;
787 }
788
789 if (!verify_receivers_impdef(receivers1[i].impdef,
790 receivers1[i].impdef)) {
791 return false;
792 }
793 }
794
795 return true;
796}
797
Karl Meakin3d879b82023-06-16 10:32:08 +0100798/**
799 * Helper for performing a hypervisor retrieve request test.
800 */
Karl Meakin028712b2023-12-06 15:50:33 +0000801static test_result_t hypervisor_retrieve_request_test_helper(
802 uint32_t mem_func, bool multiple_receivers, bool fragmented)
Karl Meakin3d879b82023-06-16 10:32:08 +0100803{
Karl Meakin0d4f5ff2023-10-13 20:03:16 +0100804 static struct ffa_memory_region_constituent
805 sent_constituents[FRAGMENTED_SHARE_PAGE_COUNT];
Karl Meakin3d879b82023-06-16 10:32:08 +0100806 __aligned(PAGE_SIZE) static uint8_t page[PAGE_SIZE * 2] = {0};
807 struct ffa_memory_region *hypervisor_retrieve_response =
808 (struct ffa_memory_region *)page;
809 struct ffa_memory_region expected_response;
810 struct mailbox_buffers mb;
811 ffa_memory_handle_t handle;
812 struct ffa_value ret;
J-Alvesb744c9b2024-01-18 17:03:47 +0000813 struct ffa_composite_memory_region *composite;
814 struct ffa_memory_access *retrvd_receivers;
Karl Meakin3d879b82023-06-16 10:32:08 +0100815 uint32_t expected_flags = 0;
816
817 ffa_memory_attributes_t expected_attrs = {
818 .cacheability = FFA_MEMORY_CACHE_WRITE_BACK,
819 .shareability = FFA_MEMORY_INNER_SHAREABLE,
820 .security = FFA_MEMORY_SECURITY_NON_SECURE,
J-Alves8984e722024-05-07 22:21:54 +0100821 .type = (!multiple_receivers && mem_func != FFA_MEM_SHARE_SMC64)
Karl Meakin3d879b82023-06-16 10:32:08 +0100822 ? FFA_MEMORY_NOT_SPECIFIED_MEM
823 : FFA_MEMORY_NORMAL_MEM,
824 };
825
Karl Meakin1f488922023-12-04 21:28:25 +0000826 struct ffa_memory_access receivers[2] = {
827 ffa_memory_access_init_permissions_from_mem_func(SP_ID(1),
828 mem_func),
829 ffa_memory_access_init_permissions_from_mem_func(SP_ID(2),
830 mem_func),
831 };
832
833 /*
834 * Only pass 1 receiver to `memory_init_and_send` if we are not testing
835 * the multiple-receivers functionality of the hypervisor retrieve
836 * request.
837 */
838 uint32_t receiver_count =
839 multiple_receivers ? ARRAY_SIZE(receivers) : 1;
Karl Meakin1331a8c2023-09-14 16:25:15 +0100840
Karl Meakin028712b2023-12-06 15:50:33 +0000841 uint32_t sent_constituents_count =
842 fragmented ? ARRAY_SIZE(sent_constituents) : 1;
843
J-Alvesb744c9b2024-01-18 17:03:47 +0000844 /* Prepare the composite offset for the comparison. */
845 for (uint32_t i = 0; i < receiver_count; i++) {
846 receivers[i].composite_memory_region_offset =
847 sizeof(struct ffa_memory_region) +
848 receiver_count *
849 sizeof(struct ffa_memory_access);
850 }
851
Karl Meakin0d4f5ff2023-10-13 20:03:16 +0100852 /* Add a page per constituent, so that we exhaust the size of a single
853 * fragment (for testing). In a real world scenario, the whole region
854 * could be described in a single constituent.
855 */
856 for (uint32_t i = 0; i < sent_constituents_count; i++) {
857 sent_constituents[i].address = share_page + i * PAGE_SIZE;
858 sent_constituents[i].page_count = 1;
859 sent_constituents[i].reserved = 0;
860 }
861
Karl Meakin3d879b82023-06-16 10:32:08 +0100862 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
863 GET_TFTF_MAILBOX(mb);
864
865 switch (mem_func) {
J-Alves8984e722024-05-07 22:21:54 +0100866 case FFA_MEM_SHARE_SMC64:
Karl Meakin3d879b82023-06-16 10:32:08 +0100867 expected_flags = FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE;
868 break;
J-Alves8984e722024-05-07 22:21:54 +0100869 case FFA_MEM_LEND_SMC64:
Karl Meakin3d879b82023-06-16 10:32:08 +0100870 expected_flags = FFA_MEMORY_REGION_TRANSACTION_TYPE_LEND;
871 break;
J-Alves8984e722024-05-07 22:21:54 +0100872 case FFA_MEM_DONATE_SMC64:
Karl Meakin3d879b82023-06-16 10:32:08 +0100873 expected_flags = FFA_MEMORY_REGION_TRANSACTION_TYPE_DONATE;
874 break;
875 default:
876 ERROR("Invalid mem_func: %d\n", mem_func);
877 panic();
878 }
879
J-Alvesb744c9b2024-01-18 17:03:47 +0000880 handle = memory_init_and_send(mb.send, MAILBOX_SIZE, SENDER, receivers,
881 receiver_count, sent_constituents,
Karl Meakin3d879b82023-06-16 10:32:08 +0100882 sent_constituents_count, mem_func, &ret);
883 if (handle == FFA_MEMORY_HANDLE_INVALID) {
884 ERROR("Memory share failed: %d\n", ffa_error_code(ret));
885 return TEST_RESULT_FAIL;
886 }
887
888 /*
889 * Send Hypervisor Retrieve request according to section 17.4.3 of FFA
890 * v1.2-REL0 specification.
891 */
892 if (!hypervisor_retrieve_request(&mb, handle, page, sizeof(page))) {
893 return TEST_RESULT_FAIL;
894 }
895
896 print_memory_region(hypervisor_retrieve_response);
897
898 /*
899 * Verify the received `FFA_MEM_RETRIEVE_RESP` aligns with
900 * transaction description sent above.
901 */
J-Alvesb744c9b2024-01-18 17:03:47 +0000902 expected_response = (struct ffa_memory_region) {
Karl Meakin3d879b82023-06-16 10:32:08 +0100903 .sender = SENDER,
904 .attributes = expected_attrs,
905 .flags = expected_flags,
906 .handle = handle,
907 .tag = 0,
908 .memory_access_desc_size = sizeof(struct ffa_memory_access),
J-Alvesb744c9b2024-01-18 17:03:47 +0000909 .receiver_count = receiver_count,
Karl Meakin3d879b82023-06-16 10:32:08 +0100910 .receivers_offset =
911 offsetof(struct ffa_memory_region, receivers),
912 };
J-Alvesb744c9b2024-01-18 17:03:47 +0000913
914 if (!verify_retrieve_response(hypervisor_retrieve_response,
915 &expected_response)) {
Karl Meakin3d879b82023-06-16 10:32:08 +0100916 return TEST_RESULT_FAIL;
917 }
918
J-Alvesb744c9b2024-01-18 17:03:47 +0000919 retrvd_receivers =
920 ffa_memory_region_get_receiver(hypervisor_retrieve_response, 0);
Karl Meakin3d879b82023-06-16 10:32:08 +0100921
J-Alvesb744c9b2024-01-18 17:03:47 +0000922 if (!verify_receivers(retrvd_receivers,
923 receivers, receiver_count)) {
924 return TEST_RESULT_FAIL;
925 }
926
927 composite = ffa_memory_region_get_composite(
928 hypervisor_retrieve_response, 0);
929
930 if (!verify_composite(composite, composite->constituents,
931 sent_constituents_count, sent_constituents_count)) {
932 return TEST_RESULT_FAIL;
Karl Meakin3d879b82023-06-16 10:32:08 +0100933 }
934
935 /*
936 * Reclaim for the SPMC to deallocate any data related to the handle.
937 */
938 ret = ffa_mem_reclaim(handle, 0);
939 if (is_ffa_call_error(ret)) {
940 ERROR("Memory reclaim failed: %d\n", ffa_error_code(ret));
941 return TEST_RESULT_FAIL;
942 }
943
Karl Meakin3d879b82023-06-16 10:32:08 +0100944 return TEST_RESULT_SUCCESS;
945}
946
947test_result_t test_hypervisor_share_retrieve(void)
948{
J-Alves8984e722024-05-07 22:21:54 +0100949 return hypervisor_retrieve_request_test_helper(FFA_MEM_SHARE_SMC64, false, false);
Karl Meakin3d879b82023-06-16 10:32:08 +0100950}
951
952test_result_t test_hypervisor_lend_retrieve(void)
953{
J-Alves8984e722024-05-07 22:21:54 +0100954 return hypervisor_retrieve_request_test_helper(FFA_MEM_LEND_SMC64, false, false);
Karl Meakin3d879b82023-06-16 10:32:08 +0100955}
956
957test_result_t test_hypervisor_donate_retrieve(void)
958{
J-Alves8984e722024-05-07 22:21:54 +0100959 return hypervisor_retrieve_request_test_helper(FFA_MEM_DONATE_SMC64, false, false);
Karl Meakin1f488922023-12-04 21:28:25 +0000960}
961
962test_result_t test_hypervisor_share_retrieve_multiple_receivers(void)
963{
J-Alves8984e722024-05-07 22:21:54 +0100964 return hypervisor_retrieve_request_test_helper(FFA_MEM_SHARE_SMC64, true, false);
Karl Meakin1f488922023-12-04 21:28:25 +0000965}
966
967test_result_t test_hypervisor_lend_retrieve_multiple_receivers(void)
968{
J-Alves8984e722024-05-07 22:21:54 +0100969 return hypervisor_retrieve_request_test_helper(FFA_MEM_LEND_SMC64, true, false);
Karl Meakin028712b2023-12-06 15:50:33 +0000970}
971
972test_result_t test_hypervisor_share_retrieve_fragmented(void)
973{
J-Alves8984e722024-05-07 22:21:54 +0100974 return hypervisor_retrieve_request_test_helper(FFA_MEM_SHARE_SMC64, false, true);
Karl Meakin028712b2023-12-06 15:50:33 +0000975}
976
977test_result_t test_hypervisor_lend_retrieve_fragmented(void)
978{
J-Alves8984e722024-05-07 22:21:54 +0100979 return hypervisor_retrieve_request_test_helper(FFA_MEM_LEND_SMC64, false, true);
Karl Meakin3d879b82023-06-16 10:32:08 +0100980}
J-Alves3be0efa2023-10-02 19:11:11 +0100981
982/**
983 * Test helper that performs memory sharing operation, and alters the PAS
984 * of the memory, to validate that SPM intersects the operation in case the PAS
985 * is not coherent with its use. Relevant for the functioning of FFA_MEM_LEND
986 * and FFA_MEM_DONATE from NWd to an SP.
987 *
988 * In cases the memory is not in NS state, the SPMC should intersect memory
989 * management call with an appropriate FFA_ERROR.
990 */
991static test_result_t test_ffa_mem_send_realm_expect_fail(
992 uint32_t mem_func, ffa_id_t borrower,
993 struct ffa_memory_region_constituent *constituents,
994 size_t constituents_count, uint64_t delegate_addr)
995{
996 struct ffa_value ret;
997 uint32_t remaining_constituent_count;
998 uint32_t total_length;
999 uint32_t fragment_length;
1000 struct mailbox_buffers mb;
1001 u_register_t ret_rmm;
1002 test_result_t result = TEST_RESULT_FAIL;
1003 struct ffa_memory_access receiver =
1004 ffa_memory_access_init_permissions_from_mem_func(borrower,
1005 mem_func);
1006
1007 if (get_armv9_2_feat_rme_support() == 0U) {
1008 return TEST_RESULT_SKIPPED;
1009 }
1010
1011 /***********************************************************************
1012 * Check if SPMC has ffa_version and expected FFA endpoints are deployed.
1013 **********************************************************************/
1014 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
1015
1016 GET_TFTF_MAILBOX(mb);
1017
1018 register_custom_sync_exception_handler(data_abort_handler);
1019
1020 /*
1021 * Delegate page to a realm. This should make memory sharing operation
1022 * fail.
1023 */
1024 ret_rmm = host_rmi_granule_delegate((u_register_t)delegate_addr);
1025
1026 if (ret_rmm != 0UL) {
1027 INFO("Delegate operation returns 0x%lx for address %llx\n",
1028 ret_rmm, delegate_addr);
1029 return TEST_RESULT_FAIL;
1030 }
1031
1032 remaining_constituent_count = ffa_memory_region_init(
1033 (struct ffa_memory_region *)mb.send, MAILBOX_SIZE, SENDER,
1034 &receiver, 1, constituents, constituents_count, 0,
1035 FFA_MEMORY_REGION_FLAG_CLEAR,
1036 FFA_MEMORY_NOT_SPECIFIED_MEM, 0, 0,
1037 &total_length, &fragment_length);
1038
1039 if (remaining_constituent_count != 0) {
1040 goto out;
1041 }
1042
1043 switch (mem_func) {
J-Alves8984e722024-05-07 22:21:54 +01001044 case FFA_MEM_LEND_SMC64:
J-Alves3be0efa2023-10-02 19:11:11 +01001045 ret = ffa_mem_lend(total_length, fragment_length);
1046 break;
J-Alves8984e722024-05-07 22:21:54 +01001047 case FFA_MEM_DONATE_SMC64:
J-Alves3be0efa2023-10-02 19:11:11 +01001048 ret = ffa_mem_donate(total_length, fragment_length);
1049 break;
1050 default:
1051 ERROR("Not expected for func name: %x\n", mem_func);
1052 return TEST_RESULT_FAIL;
1053 }
1054
1055 if (!is_expected_ffa_error(ret, FFA_ERROR_DENIED)) {
1056 goto out;
1057 }
1058
1059 /* Undelegate to reestablish the same security state for PAS. */
1060 ret_rmm = host_rmi_granule_undelegate((u_register_t)delegate_addr);
1061
1062 for (uint32_t i = 0; i < constituents_count; i++) {
1063 uint32_t *ptr = (uint32_t *)constituents[i].address;
1064
1065 *ptr = 0xFFA;
1066 }
1067
1068 if (get_gpc_abort_triggered()) {
1069 ERROR("Exception due to GPC for lend/donate with RME. Not"
1070 " expected for this case.\n");
1071 result = TEST_RESULT_FAIL;
1072 } else {
1073 result = TEST_RESULT_SUCCESS;
1074 }
1075out:
1076 unregister_custom_sync_exception_handler();
1077
1078 if (ret_rmm != 0UL) {
1079 INFO("Undelegate operation returns 0x%lx for address %llx\n",
1080 ret_rmm, (uint64_t)delegate_addr);
1081 return TEST_RESULT_FAIL;
1082 }
1083
1084 return result;
1085}
1086
1087/**
1088 * Memory to be shared between partitions is described in a composite, with
1089 * various constituents. In an RME system, the memory must be in NS PAS in
1090 * operations from NWd to an SP. In case the PAS is not following this
1091 * expectation memory lend/donate should fail, and all constituents must
1092 * remain in the NS PAS.
1093 *
1094 * This test validates that if one page in the middle of one of the constituents
1095 * is not in the NS PAS the operation fails.
1096 */
1097test_result_t test_ffa_mem_send_sp_realm_memory(void)
1098{
1099 test_result_t ret;
J-Alves8984e722024-05-07 22:21:54 +01001100 uint32_t mem_func[] = {FFA_MEM_LEND_SMC64, FFA_MEM_DONATE_SMC64};
J-Alves3be0efa2023-10-02 19:11:11 +01001101 struct ffa_memory_region_constituent constituents[] = {
1102 {(void *)four_share_pages, 4, 0},
1103 {(void *)share_page, 1, 0}
1104 };
1105
1106 const uint32_t constituents_count = sizeof(constituents) /
1107 sizeof(struct ffa_memory_region_constituent);
1108
J-Alvesb44b4752024-05-13 10:15:51 +01001109 /***********************************************************************
1110 * Check if SPMC has ffa_version and expected FFA endpoints are deployed.
1111 **********************************************************************/
1112 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
1113
J-Alves3be0efa2023-10-02 19:11:11 +01001114 for (unsigned j = 0; j < ARRAY_SIZE(mem_func); j++) {
1115 for (unsigned int i = 0; i < 4; i++) {
1116 /* Address to be delegated to Realm PAS. */
1117 uint64_t realm_addr =
1118 (uint64_t)&four_share_pages[i * PAGE_SIZE];
1119
1120 INFO("%s memory with realm addr: %llx\n",
J-Alves8984e722024-05-07 22:21:54 +01001121 mem_func[j] == FFA_MEM_LEND_SMC64
J-Alves3be0efa2023-10-02 19:11:11 +01001122 ? "Lend"
1123 : "Donate",
1124 realm_addr);
1125
1126 ret = test_ffa_mem_send_realm_expect_fail(
1127 mem_func[j], SP_ID(1), constituents,
1128 constituents_count, realm_addr);
1129
1130 if (ret != TEST_RESULT_SUCCESS) {
1131 break;
1132 }
1133 }
1134 }
1135
1136 return ret;
1137}
1138
1139/**
1140 * Memory to be shared between partitions is described in a composite, with
1141 * various constituents. In an RME system, the memory must be in NS PAS in
1142 * operations from NWd to an SP. In case the PAS is not following this
1143 * expectation memory lend/donate should fail, and all constituents must
1144 * remain in the NS PAS.
1145 *
1146 * This test validates the case in which the memory lend/donate fail in
1147 * case one of the constituents in the composite is not in the NS PAS.
1148 */
1149test_result_t test_ffa_mem_lend_sp_realm_memory_separate_constituent(void)
1150{
1151 test_result_t ret;
1152 struct ffa_memory_region_constituent constituents[] = {
1153 {(void *)four_share_pages, 4, 0},
1154 {(void *)share_page, 1, 0}
1155 };
1156 const uint32_t constituents_count = sizeof(constituents) /
1157 sizeof(struct ffa_memory_region_constituent);
1158 /* Address to be delegated to Realm PAS. */
1159 uint64_t realm_addr = (uint64_t)&share_page[0];
1160
1161 INFO("Sharing memory with realm addr: %llx\n", realm_addr);
1162
1163 ret = test_ffa_mem_send_realm_expect_fail(
J-Alves8984e722024-05-07 22:21:54 +01001164 FFA_MEM_LEND_SMC64, SP_ID(1), constituents,
J-Alves3be0efa2023-10-02 19:11:11 +01001165 constituents_count, realm_addr);
1166
1167 return ret;
1168}
J-Alvesd8e2fcd2024-03-28 15:53:51 +00001169
1170/**
1171 * Map the NS RXTX buffers to the SPM, change RX buffer PAS to realm,
1172 * invoke the FFA_MEM_SHARE interface, such that SPM does NS access
1173 * to realm region and triggers GPF.
1174 */
1175test_result_t test_ffa_mem_share_tx_realm_expect_fail(void)
1176{
1177 struct ffa_value ret;
1178 uint32_t total_length;
1179 uint32_t fragment_length;
1180 struct mailbox_buffers mb;
1181 u_register_t ret_rmm;
1182 struct ffa_memory_access receiver =
1183 ffa_memory_access_init_permissions_from_mem_func(SP_ID(1),
1184 FFA_MEM_SHARE_SMC64);
1185 size_t remaining_constituent_count;
1186 struct ffa_memory_region_constituent constituents[] = {
1187 {(void *)share_page, 1, 0}
1188 };
1189
1190 if (get_armv9_2_feat_rme_support() == 0U) {
1191 return TEST_RESULT_SKIPPED;
1192 }
1193
1194 /***********************************************************************
1195 * Check if SPMC has ffa_version and expected FFA endpoints are deployed.
1196 **********************************************************************/
1197 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
1198
1199 GET_TFTF_MAILBOX(mb);
1200
1201 remaining_constituent_count = ffa_memory_region_init(
1202 (struct ffa_memory_region *)mb.send, PAGE_SIZE, HYP_ID,
1203 &receiver, 1, constituents, 1, 0, 0,
1204 FFA_MEMORY_NOT_SPECIFIED_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
1205 FFA_MEMORY_INNER_SHAREABLE,
1206 &total_length, &fragment_length);
1207
1208 if (remaining_constituent_count != 0) {
1209 return TEST_RESULT_FAIL;
1210 }
1211
1212 /*
1213 * Delegate TX buffer to realm.
1214 */
1215 ret_rmm = host_rmi_granule_delegate((u_register_t)mb.send);
1216
1217 if (ret_rmm != 0UL) {
1218 INFO("Delegate operation returns %#lx for address %p\n",
1219 ret_rmm, mb.send);
1220 return TEST_RESULT_FAIL;
1221 }
1222
1223 ret = ffa_mem_share(total_length, fragment_length);
1224
1225 /* Access to Realm region from SPMC should return FFA_ERROR_ABORTED. */
1226 if (!is_expected_ffa_error(ret, FFA_ERROR_ABORTED)) {
1227 return TEST_RESULT_FAIL;
1228 }
1229
1230 /* Undelegate to reestablish the same security state for PAS. */
1231 ret_rmm = host_rmi_granule_undelegate((u_register_t)mb.send);
1232
1233 if (ret_rmm != 0UL) {
1234 INFO("Undelegate operation returns 0x%lx for address %p\n",
1235 ret_rmm, mb.send);
1236 return TEST_RESULT_FAIL;
1237 }
1238
1239 /* Retry but expect test to pass. */
1240 ret = ffa_mem_share(total_length, fragment_length);
1241
1242 if (is_ffa_call_error(ret)) {
1243 return TEST_RESULT_FAIL;
1244 }
1245
1246 /* Reclaim to clean-up. */
1247 ret = ffa_mem_reclaim(ffa_mem_success_handle(ret), 0);
1248
1249 if (is_ffa_call_error(ret)) {
1250 return TEST_RESULT_FAIL;
1251 }
1252
1253 return TEST_RESULT_SUCCESS;
1254}
J-Alves3aa08bc2024-04-24 22:20:23 +01001255
1256/**
1257 * Base helper to prepare for tests that need to retrieve memory from the SPMC
1258 * from a VM endpoint.
1259 */
1260static ffa_memory_handle_t base_memory_send_for_nwd_retrieve(struct mailbox_buffers *mb,
1261 struct ffa_memory_access receivers[],
1262 size_t receivers_count)
1263{
1264 ffa_memory_handle_t handle;
1265 struct ffa_memory_region_constituent constituents[] = {
1266 {(void *)four_share_pages, 4, 0},
1267 {(void *)share_page, 1, 0}
1268 };
1269 const uint32_t constituents_count = ARRAY_SIZE(constituents);
1270 struct ffa_value ret;
1271
1272 /* Prepare the composite offset for the comparison. */
1273 for (uint32_t i = 0; i < receivers_count; i++) {
1274 receivers[i].composite_memory_region_offset =
1275 sizeof(struct ffa_memory_region) +
1276 receivers_count *
1277 sizeof(struct ffa_memory_access);
1278 }
1279
1280 handle = memory_init_and_send(mb->send, MAILBOX_SIZE, SENDER, receivers,
1281 receivers_count, constituents,
1282 constituents_count, FFA_MEM_SHARE_SMC64, &ret);
1283 return handle;
1284}
1285
1286/**
1287 * Test FF-A memory retrieve request from a VM into the SPMC.
1288 * TFTF invokes all the FF-A calls expected from an hypervisor into the
1289 * SPMC, even those that would be initiated by a VM, and then forwarded
1290 * to the SPMC by the Hypervisor.
1291 */
1292test_result_t test_ffa_memory_retrieve_request_from_vm(void)
1293{
1294 struct mailbox_buffers mb;
1295 struct ffa_memory_region *m;
1296 struct ffa_memory_access receivers[2] = {
1297 ffa_memory_access_init_permissions_from_mem_func(VM_ID(1),
1298 FFA_MEM_SHARE_SMC64),
1299 ffa_memory_access_init_permissions_from_mem_func(SP_ID(2),
1300 FFA_MEM_SHARE_SMC64),
1301 };
1302 ffa_memory_handle_t handle;
1303
1304 GET_TFTF_MAILBOX(mb);
1305
1306 if (get_armv9_2_feat_rme_support() == 0U) {
1307 return TEST_RESULT_SKIPPED;
1308 }
1309
1310 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
1311
1312 handle = base_memory_send_for_nwd_retrieve(&mb, receivers, ARRAY_SIZE(receivers));
1313
1314 if (handle == FFA_MEMORY_HANDLE_INVALID) {
1315 return TEST_RESULT_FAIL;
1316 }
1317
1318 if (!memory_retrieve(&mb, &m, handle, 0, receivers, ARRAY_SIZE(receivers), 0)) {
1319 ERROR("Failed to retrieve the memory.\n");
1320 return TEST_RESULT_FAIL;
1321 }
1322
1323 ffa_rx_release();
1324
1325 if (!memory_relinquish(mb.send, handle, VM_ID(1))) {
1326 ERROR("%s: Failed to relinquish.\n", __func__);
1327 return TEST_RESULT_FAIL;
1328 }
1329
1330 if (is_ffa_call_error(ffa_mem_reclaim(handle, 0))) {
1331 ERROR("%s: Failed to reclaim memory.\n", __func__);
1332 return TEST_RESULT_FAIL;
1333 }
1334
1335 return TEST_RESULT_SUCCESS;
1336}
J-Alves14c4a322024-04-25 13:57:09 +01001337
J-Alves8d6843a2024-04-25 14:17:52 +01001338test_result_t base_ffa_memory_retrieve_request_fail_buffer_realm(bool delegate_rx)
J-Alves14c4a322024-04-25 13:57:09 +01001339{
1340 struct mailbox_buffers mb;
1341 struct ffa_memory_access receivers[2] = {
1342 ffa_memory_access_init_permissions_from_mem_func(VM_ID(1),
1343 FFA_MEM_SHARE_SMC64),
1344 ffa_memory_access_init_permissions_from_mem_func(SP_ID(2),
1345 FFA_MEM_SHARE_SMC64),
1346 };
1347 ffa_memory_handle_t handle;
1348 u_register_t ret_rmm;
1349 struct ffa_value ret;
1350 size_t descriptor_size;
J-Alves8d6843a2024-04-25 14:17:52 +01001351 void *to_delegate;
J-Alves14c4a322024-04-25 13:57:09 +01001352
1353 GET_TFTF_MAILBOX(mb);
1354
J-Alves8d6843a2024-04-25 14:17:52 +01001355 to_delegate = delegate_rx ? mb.recv : mb.send;
1356
J-Alves14c4a322024-04-25 13:57:09 +01001357 if (get_armv9_2_feat_rme_support() == 0U) {
1358 return TEST_RESULT_SKIPPED;
1359 }
1360
1361 CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
1362
1363 handle = base_memory_send_for_nwd_retrieve(&mb, receivers, ARRAY_SIZE(receivers));
1364
1365 if (handle == FFA_MEMORY_HANDLE_INVALID) {
1366 return TEST_RESULT_FAIL;
1367 }
1368
1369 /* Prepare the descriptor before delegating the TX buffer. */
1370 descriptor_size = ffa_memory_retrieve_request_init(
1371 mb.send, handle, SENDER, receivers, ARRAY_SIZE(receivers), 0, 0,
1372 FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
1373 FFA_MEMORY_INNER_SHAREABLE);
1374
J-Alves8d6843a2024-04-25 14:17:52 +01001375 /* Delegate buffer to realm. */
1376 ret_rmm = host_rmi_granule_delegate((u_register_t)to_delegate);
J-Alves14c4a322024-04-25 13:57:09 +01001377
1378 if (ret_rmm != 0UL) {
1379 ERROR("Delegate operation returns %#lx for address %p\n",
1380 ret_rmm, mb.send);
1381 return TEST_RESULT_FAIL;
1382 }
1383
1384 ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
1385
1386 if (!is_expected_ffa_error(ret, FFA_ERROR_ABORTED)) {
1387 return TEST_RESULT_FAIL;
1388 }
1389
1390 /* Undelegate to reestablish the same security state for PAS. */
J-Alves8d6843a2024-04-25 14:17:52 +01001391 ret_rmm = host_rmi_granule_undelegate((u_register_t)to_delegate);
J-Alves14c4a322024-04-25 13:57:09 +01001392
1393 if (ret_rmm != 0UL) {
1394 ERROR("Undelegate operation returns %#lx for address %p\n",
1395 ret_rmm, mb.send);
1396 return TEST_RESULT_FAIL;
1397 }
1398
1399 /* Retry the memory retrieve request, but this time expect success. */
1400 ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
1401
1402 if (is_ffa_call_error(ret)) {
1403 return TEST_RESULT_FAIL;
1404 }
1405
1406 ffa_rx_release();
1407
1408 if (!memory_relinquish(mb.send, handle, VM_ID(1))) {
1409 ERROR("%s: Failed to relinquish.\n", __func__);
1410 return TEST_RESULT_FAIL;
1411 }
1412
1413 if (is_ffa_call_error(ffa_mem_reclaim(handle, 0))) {
1414 ERROR("%s: Failed to reclaim memory.\n", __func__);
1415 return TEST_RESULT_FAIL;
1416 }
1417
1418 return TEST_RESULT_SUCCESS;
1419}
J-Alves8d6843a2024-04-25 14:17:52 +01001420
1421/**
1422 * Test that a retrieve request from the hypervisor would fail if the TX buffer
1423 * was in realm state. This is recreating the situation in which the Hyp doesn't
1424 * track the state of the operation, and it is forwarding the retrieve request
1425 * to the SPMC.
1426 */
1427test_result_t test_ffa_memory_retrieve_request_fail_tx_realm(void)
1428{
1429 return base_ffa_memory_retrieve_request_fail_buffer_realm(false);
1430}
1431
1432/**
1433 * Test that a retrieve request from the hypervisor would fail if the RX buffer
1434 * was in realm state. This is recreating the situation in which the Hyp doesn't
1435 * track the state of the operation, and it is forwarding the retrieve request
1436 * to the SPMC. The operation shall fail at the point at which the SPMC is
1437 * providing retrieve response. The SPMC should have reverted the change to any
1438 * of its share state tracking structures, such that the final reclaim would be
1439 * possible.
1440 */
1441test_result_t test_ffa_memory_retrieve_request_fail_rx_realm(void)
1442{
1443 return base_ffa_memory_retrieve_request_fail_buffer_realm(true);
1444}