aboutsummaryrefslogtreecommitdiff
path: root/include/runtime_services/cactus_test_cmds.h
blob: d03a97fcb00d2628324e98ad8859205eddb5a16f (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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/*
 * Copyright (c) 2021, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef CACTUS_TEST_CMDS
#define CACTUS_TEST_CMDS

#include <ffa_helpers.h>
#include <spm_common.h>

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

/**
 * Error codes.
 */
#define CACTUS_ERROR_INVALID		U(1)
#define CACTUS_ERROR_TEST		U(2)
#define CACTUS_ERROR_FFA_CALL		U(3)
#define CACTUS_ERROR_UNHANDLED		U(4)

/**
 * 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(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(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_resp64(source, dest, response, 0, 0, 0, 0);
}

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;
}

/**
 * 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);
}

/**
 * Command to request cactus to sleep for the given time in ms
 *
 * The command id is the hex representation of string "sleep"
 */
#define CACTUS_SLEEP_CMD U(0x736c656570)

static inline smc_ret_values cactus_sleep_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t sleep_time)
{
	return cactus_send_cmd(source, dest, CACTUS_SLEEP_CMD, sleep_time, 0, 0,
			       0);
}

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

/**
 * Command to request cactus to enable/disable an interrupt
 *
 * The command id is the hex representation of string "intr"
 */
#define CACTUS_INTERRUPT_CMD U(0x696e7472)

static inline smc_ret_values cactus_interrupt_cmd(
	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t interrupt_id,
	bool enable, uint32_t pin)
{
	return cactus_send_cmd(source, dest, CACTUS_INTERRUPT_CMD, interrupt_id,
			       enable, pin, 0);
}

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

static inline bool cactus_get_interrupt_enable(smc_ret_values ret)
{
	return (bool)ret.ret5;
}

static inline enum interrupt_pin cactus_get_interrupt_pin(smc_ret_values ret)
{
	return (enum interrupt_pin)ret.ret6;
}

#endif