aboutsummaryrefslogtreecommitdiff
path: root/spm/cactus/cactus_test_cmds.h
blob: f814ba560837ca748590deb957340836d53bd1bc (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
 * Copyright (c) 2021, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef CACTUS_TEST_CMDS
#define CACTUS_TEST_CMDS

#include <debug.h>
#include <ffa_helpers.h>

/**
 * Success and error return to be sent over a msg response.
 */
#define CACTUS_SUCCESS	 U(0)
#define CACTUS_ERROR	 U(-1)

/**
 * Get command from struct smc_ret_values.
 */
static inline uint64_t cactus_get_cmd(smc_ret_values ret)
{
	return (uint64_t)ret.ret3;
}

/**
 * Template for commands to be sent to CACTUS partitions over direct
 * messages interfaces.
 */
static inline smc_ret_values cactus_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t cmd, uint64_t val0,
	uint64_t val1, uint64_t val2, uint64_t val3)
{
	return 	ffa_msg_send_direct_req64_5args(source, dest, cmd, val0, val1,
						val2, val3);
}

/**
 * Template for responses to Cactus commands.
 * 'cactus_send_response' is the template for custom responses, in case there is
 * a need to propagate more than one value in the response of a command.
 */
static inline smc_ret_values cactus_send_response(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t resp, uint32_t val0,
	uint64_t val1, uint64_t val2, uint64_t val3)
{
	return ffa_msg_send_direct_resp64_5args(source, dest, resp, val0, val1,
						val2, val3);
}

/**
 * For responses of one value only.
 */
static inline smc_ret_values cactus_response(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t response)
{
	return ffa_msg_send_direct_resp(source, dest, response);
}

static inline uint32_t cactus_get_response(smc_ret_values ret)
{
	return (uint32_t)ret.ret3;
}

/**
 * In a successful test, in case the SP needs to propagate an extra value
 * to conclude the test.
 * If more arguments are needed, a custom response should be defined for the
 * specific test.
 */
static inline smc_ret_values cactus_success_resp(
		ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t value)
{
	return cactus_send_response(source, dest, CACTUS_SUCCESS, value,
				    0, 0, 0);
}

/**
 * In case the test fails on the SP side, the 'error_code' should help specify
 * the reason, which can be specific to the test, or general ones as defined
 * in the error code list.
 */
static inline smc_ret_values cactus_error_resp(
		ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t error_code)
{
	return cactus_send_response(source, dest, CACTUS_ERROR, error_code,
				    0, 0, 0);
}

static inline uint32_t cactus_error_code(smc_ret_values ret)
{
	return (uint32_t) ret.ret4;
}

#define PRINT_CMD(smc_ret)						\
	VERBOSE("cmd %lx; args: %lx, %lx, %lx, %lx\n",	 		\
		smc_ret.ret3, smc_ret.ret4, smc_ret.ret5, 		\
		smc_ret.ret6, smc_ret.ret7)

/**
 * With this test command the sender transmits a 64-bit value that it then
 * expects to receive on the respective command response.
 *
 * The id is the hex representation of the string 'echo'.
 */
#define CACTUS_ECHO_CMD U(0x6563686f)

static inline smc_ret_values cactus_echo_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t echo_val)
{
	return cactus_send_cmd(source, dest, CACTUS_ECHO_CMD, echo_val, 0, 0,
			       0);
}

static inline uint64_t cactus_echo_get_val(smc_ret_values ret)
{
	return (uint64_t)ret.ret4;
}

/**
 * Command to request a cactus secure partition to send an echo command to
 * another partition.
 *
 * The sender of this command expects to receive CACTUS_SUCCESS if the requested
 * echo interaction happened successfully, or CACTUS_ERROR otherwise.
 */
#define CACTUS_REQ_ECHO_CMD (CACTUS_ECHO_CMD + 1)

static inline smc_ret_values cactus_req_echo_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t echo_dest,
	uint64_t echo_val)
{
	return cactus_send_cmd(source, dest, CACTUS_REQ_ECHO_CMD, echo_val,
			       echo_dest, 0, 0);
}

static inline ffa_vm_id_t cactus_req_echo_get_echo_dest(smc_ret_values ret)
{
	return (ffa_vm_id_t)ret.ret5;
}

/**
 * Command to create a cyclic dependency between SPs, which could result in
 * a deadlock. This aims at proving such scenario cannot happen.
 * If the deadlock happens, the system will just hang.
 * If the deadlock is prevented, the last partition to use the command will
 * send response CACTUS_SUCCESS.
 *
 * The id is the hex representation of the string 'dead'.
 */
#define CACTUS_DEADLOCK_CMD U(0x64656164)

static inline smc_ret_values cactus_deadlock_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t next_dest)
{
	return cactus_send_cmd(source, dest, CACTUS_DEADLOCK_CMD, next_dest, 0,
			       0, 0);
}

static inline ffa_vm_id_t cactus_deadlock_get_next_dest(smc_ret_values ret)
{
	return (ffa_vm_id_t)ret.ret4;
}

/**
 * Command to request a sequence CACTUS_DEADLOCK_CMD between the partitions
 * of specified IDs.
 */
#define CACTUS_REQ_DEADLOCK_CMD (CACTUS_DEADLOCK_CMD + 1)

static inline smc_ret_values cactus_req_deadlock_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t next_dest1,
	ffa_vm_id_t next_dest2)
{
	return cactus_send_cmd(source, dest, CACTUS_REQ_DEADLOCK_CMD,
			       next_dest1, next_dest2, 0, 0);
}

/* To get next_dest1 use CACTUS_DEADLOCK_GET_NEXT_DEST */
static inline ffa_vm_id_t cactus_deadlock_get_next_dest2(smc_ret_values ret)
{
	return (ffa_vm_id_t)ret.ret5;
}

/**
 * Command to notify cactus of a memory management operation. The cmd value
 * should be the memory management smc function id.
 *
 * The id is the hex representation of the string "mem"
 */
#define CACTUS_MEM_SEND_CMD U(0x6d656d)

static inline smc_ret_values cactus_mem_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t mem_func,
	ffa_memory_handle_t handle)
{
	return cactus_send_cmd(source, dest, CACTUS_MEM_SEND_CMD, mem_func,
			       handle, 0, 0);
}

static inline ffa_memory_handle_t cactus_mem_send_get_handle(smc_ret_values ret)
{
	return (ffa_memory_handle_t)ret.ret5;
}

/**
 * Command to request a memory management operation. The 'mem_func' argument
 * identifies the operation that is to be performend, and 'receiver' is the id
 * of the partition to receive the memory region.
 *
 * The command id is the hex representation of the string "memory".
 */
#define CACTUS_REQ_MEM_SEND_CMD U(0x6d656d6f7279)

static inline smc_ret_values cactus_req_mem_send_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t mem_func,
	ffa_vm_id_t receiver)
{
	return cactus_send_cmd(source, dest, CACTUS_REQ_MEM_SEND_CMD, mem_func,
			       receiver, 0, 0);
}

static inline uint32_t cactus_req_mem_send_get_mem_func(smc_ret_values ret)
{
	return (uint32_t)ret.ret4;
}

static inline ffa_vm_id_t cactus_req_mem_send_get_receiver(smc_ret_values ret)
{
	return (ffa_vm_id_t)ret.ret5;
}

/**
 * Request to fill SIMD vectors with dummy values with purpose to check a
 * save/restore routine during the context switches between secure world and
 * normal world.
 *
 * The command id is the hex representation of the string "SIMD"
 */
#define CACTUS_REQ_SIMD_FILL_CMD U(0x53494d44)

static inline smc_ret_values cactus_req_simd_fill_send_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest)
{
	return cactus_send_cmd(source, dest, CACTUS_REQ_SIMD_FILL_CMD, 0, 0, 0, 0);
}

#endif