1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/*
* Copyright (c) 2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <cactus_test_cmds.h>
#include <debug.h>
#include <ffa_endpoints.h>
#include <ffa_helpers.h>
#include <test_helpers.h>
#include <tftf_lib.h>
#include <xlat_tables_defs.h>
#define MAILBOX_SIZE PAGE_SIZE
#define SENDER HYP_ID
#define RECEIVER SP_ID(1)
static const struct ffa_uuid expected_sp_uuids[] = {
{PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}
};
/* Memory section to be sent over mem management ABIs */
static __aligned(PAGE_SIZE) uint8_t share_page[PAGE_SIZE];
/**
* Tests that it is possible to share memory with SWd from NWd.
* After calling the respective memory send API, it will expect a reply from
* cactus SP, at which point it will reclaim access to the memory region and
* check the memory region has been used by receiver SP.
*
* Accessing memory before a memory reclaim operation should only be possible
* in the context of a memory share operation.
* According to the FF-A spec, the owner is temporarily relinquishing
* access to the memory region on a memory lend operation, and on a
* memory donate operation the access is relinquished permanently.
* SPMC is positioned in S-EL2, and doesn't control stage-1 mapping for
* EL2. Therefore, it is impossible to enforce the expected access
* policy for a donate and lend operations within the SPMC.
* Current SPMC implementation is under the assumption of trust that
* Hypervisor (sitting in EL2) would relinquish access from EL1/EL0
* FF-A endpoint at relevant moment.
*/
static test_result_t test_memory_send_sp(uint32_t mem_func)
{
smc_ret_values ret;
ffa_memory_handle_t handle;
uint32_t *ptr;
struct mailbox_buffers mb;
/***********************************************************************
* Check if SPMC has ffa_version and expected FFA endpoints are deployed.
**********************************************************************/
CHECK_HAFNIUM_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids);
GET_TFTF_MAILBOX(mb);
struct ffa_memory_region_constituent constituents[] = {
{(void *)share_page, 1, 0}
};
const uint32_t constituents_count = sizeof(constituents) /
sizeof(struct ffa_memory_region_constituent);
handle = ffa_memory_init_and_send((struct ffa_memory_region *)mb.send,
MAILBOX_SIZE, SENDER, RECEIVER,
constituents, constituents_count,
mem_func);
if (handle == FFA_MEMORY_HANDLE_INVALID) {
return TEST_RESULT_FAIL;
}
VERBOSE("TFTF - Handle: %llx\nTFTF - Address: %p\n",
handle, constituents[0].address);
ptr = (uint32_t *)constituents[0].address;
ret = CACTUS_MEM_SEND_CMD(SENDER, RECEIVER, mem_func, handle);
if (ret.ret0 != FFA_MSG_SEND_DIRECT_RESP_SMC32) {
ERROR("Failed to send message. error: %lx\n",
ret.ret2);
return TEST_RESULT_FAIL;
}
if (CACTUS_GET_RESPONSE(ret) != CACTUS_SUCCESS) {
ERROR("Failed memory send operation!\n");
return TEST_RESULT_FAIL;
}
/*
* Print 5 words from the memory region to validate SP wrote to the
* memory region.
*/
VERBOSE("TFTF - Memory contents after SP use:\n");
for (unsigned int i = 0U; i < 5U; i++)
VERBOSE(" %u: %x\n", i, ptr[i]);
/* To make the compiler happy in case it is not a verbose build */
if (LOG_LEVEL < LOG_LEVEL_VERBOSE)
(void)ptr;
if (mem_func != FFA_MEM_DONATE_SMC32 &&
ffa_mem_reclaim(handle, 0).ret0 == FFA_ERROR) {
tftf_testcase_printf("Couldn't reclaim memory\n");
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
}
test_result_t test_mem_share_sp(void)
{
return test_memory_send_sp(FFA_MEM_SHARE_SMC32);
}
test_result_t test_mem_lend_sp(void)
{
return test_memory_send_sp(FFA_MEM_LEND_SMC32);
}
test_result_t test_mem_donate_sp(void)
{
return test_memory_send_sp(FFA_MEM_DONATE_SMC32);
}
|