aboutsummaryrefslogtreecommitdiff
path: root/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
blob: 25cc77b1d8af1e93206b4041260dd39277377dca (plain)
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);
}