1 /*
2  * Copyright 2021 The Hafnium Authors.
3  *
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/BSD-3-Clause.
7  */
8 
9 #include "hf/ffa.h"
10 
11 #include <stdint.h>
12 
13 #include "hf/arch/irq.h"
14 #include "hf/arch/vm/interrupts.h"
15 #include "hf/arch/vm/timer.h"
16 
17 #include "hf/std.h"
18 
19 #include "vmapi/hf/call.h"
20 
21 #include "primary_with_secondary.h"
22 #include "test/hftest.h"
23 #include "test/vmapi/ffa.h"
24 
TEAR_DOWN(ffa)25 TEAR_DOWN(ffa)
26 {
27 	EXPECT_FFA_ERROR(ffa_rx_release(), FFA_DENIED);
28 }
29 
30 /**
31  * Send a message to a secondary VM which checks the validity of the received
32  * header.
33  */
TEST(ffa,msg_send)34 TEST(ffa, msg_send)
35 {
36 	const char message[] = "ffa_msg_send";
37 	struct ffa_value run_res;
38 	struct mailbox_buffers mb = set_up_mailbox();
39 
40 	SERVICE_SELECT(SERVICE_VM1, "ffa_check", mb.send);
41 
42 	/* Set the payload, init the message header and send the message. */
43 	memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
44 	EXPECT_EQ(
45 		ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
46 			.func,
47 		FFA_SUCCESS_32);
48 
49 	run_res = ffa_run(SERVICE_VM1, 0);
50 	EXPECT_EQ(run_res.func, FFA_YIELD_32);
51 }
52 
53 /**
54  * Send a message to a secondary VM spoofing the source VM id.
55  */
TEST(ffa,msg_send_spoof)56 TEST(ffa, msg_send_spoof)
57 {
58 	const char message[] = "ffa_msg_send";
59 	struct mailbox_buffers mb = set_up_mailbox();
60 
61 	SERVICE_SELECT(SERVICE_VM1, "ffa_check", mb.send);
62 
63 	/* Set the payload, init the message header and send the message. */
64 	memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
65 	EXPECT_FFA_ERROR(
66 		ffa_msg_send(SERVICE_VM2, SERVICE_VM1, sizeof(message), 0),
67 		FFA_INVALID_PARAMETERS);
68 }
69 
70 /**
71  * Send a message to a secondary VM with incorrect destination id.
72  */
TEST(ffa,ffa_invalid_destination_id)73 TEST(ffa, ffa_invalid_destination_id)
74 {
75 	const char message[] = "fail to send";
76 	struct mailbox_buffers mb = set_up_mailbox();
77 
78 	SERVICE_SELECT(SERVICE_VM1, "ffa_check", mb.send);
79 	/* Set the payload, init the message header and send the message. */
80 	memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
81 	EXPECT_FFA_ERROR(ffa_msg_send(HF_PRIMARY_VM_ID, -1, sizeof(message), 0),
82 			 FFA_INVALID_PARAMETERS);
83 }
84 
85 /**
86  * Ensure that the length parameter is respected when sending messages.
87  */
TEST(ffa,ffa_incorrect_length)88 TEST(ffa, ffa_incorrect_length)
89 {
90 	const char message[] = "this should be truncated";
91 	struct ffa_value run_res;
92 	struct mailbox_buffers mb = set_up_mailbox();
93 
94 	SERVICE_SELECT(SERVICE_VM1, "ffa_length", mb.send);
95 
96 	/* Send the message and compare if truncated. */
97 	memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
98 	/* Hard code incorrect length. */
99 	EXPECT_EQ(ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, 16, 0).func,
100 		  FFA_SUCCESS_32);
101 	run_res = ffa_run(SERVICE_VM1, 0);
102 	EXPECT_EQ(run_res.func, FFA_YIELD_32);
103 }
104 
105 /**
106  * Attempt to send a message larger than what is supported.
107  */
TEST(ffa,ffa_large_message)108 TEST(ffa, ffa_large_message)
109 {
110 	const char message[] = "fail to send";
111 	struct mailbox_buffers mb = set_up_mailbox();
112 
113 	memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
114 	/* Send a message that is larger than the mailbox supports (4KB). */
115 	EXPECT_FFA_ERROR(
116 		ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, 4 * 1024 + 1, 0),
117 		FFA_INVALID_PARAMETERS);
118 }
119 
120 /**
121  * Verify secondary VM non blocking recv.
122  */
TEST(ffa,ffa_recv_non_blocking)123 TEST(ffa, ffa_recv_non_blocking)
124 {
125 	struct mailbox_buffers mb = set_up_mailbox();
126 	struct ffa_value run_res;
127 
128 	/* Check is performed in secondary VM. */
129 	SERVICE_SELECT(SERVICE_VM1, "ffa_recv_non_blocking", mb.send);
130 	run_res = ffa_run(SERVICE_VM1, 0);
131 	EXPECT_EQ(run_res.func, FFA_YIELD_32);
132 }
133 
134 /**
135  * Verify that FFA_MSG_WAIT responds correctly to wrong parameters.
136  */
TEST(ffa,ffa_msg_wait_fail)137 TEST(ffa, ffa_msg_wait_fail)
138 {
139 	struct ffa_value ret;
140 	ret = ffa_call((struct ffa_value){.func = FFA_MSG_WAIT_32,
141 					  .arg1 = 1,
142 					  .arg2 = 2,
143 					  .arg3 = 3,
144 					  .arg4 = 4,
145 					  .arg5 = 5,
146 					  .arg6 = 6,
147 					  .arg7 = 7});
148 	EXPECT_FFA_ERROR(ret, FFA_INVALID_PARAMETERS);
149 }
150 
151 /**
152  * Verify that partition discovery via the FFA_PARTITION_INFO interface
153  * returns the expected information on the VMs in the system.
154  */
TEST(ffa,ffa_partition_info)155 TEST(ffa, ffa_partition_info)
156 {
157 	struct mailbox_buffers mb = set_up_mailbox();
158 	struct ffa_value ret;
159 	const struct ffa_partition_info *partitions = mb.recv;
160 	struct ffa_uuid uuid;
161 	ffa_vm_count_t vm_count;
162 
163 	/* A Null UUID requests information for all partitions. */
164 	ffa_uuid_init(0, 0, 0, 0, &uuid);
165 
166 	ret = ffa_partition_info_get(&uuid, 0);
167 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
168 	vm_count = ret.arg2;
169 	EXPECT_EQ(vm_count, 4);
170 
171 	for (uint16_t index = 0; index < vm_count; ++index) {
172 		ffa_vm_id_t vm_id = partitions[index].vm_id;
173 		EXPECT_GE(vm_id, (ffa_vm_id_t)HF_PRIMARY_VM_ID);
174 		EXPECT_LE(vm_id, (ffa_vm_id_t)SERVICE_VM3);
175 
176 		/*
177 		 * NOTE: The ordering is NOT specified by the spec, but is an
178 		 * artifact of how it's implemented in Hafnium. If that changes
179 		 * the following EXPECT could fail.
180 		 */
181 		EXPECT_EQ(vm_id, index + 1);
182 
183 		EXPECT_GE(partitions[index].vcpu_count, 1);
184 	}
185 
186 	ret = ffa_rx_release();
187 	EXPECT_EQ(ret.func, FFA_SUCCESS_32);
188 }
189 
190 /**
191  * Trying to run a partition which is waiting for a message should not actually
192  * run it, but return FFA_MSG_WAIT again.
193  */
TEST(ffa,run_waiting)194 TEST(ffa, run_waiting)
195 {
196 	struct mailbox_buffers mb = set_up_mailbox();
197 	struct ffa_value run_res;
198 
199 	SERVICE_SELECT(SERVICE_VM1, "run_waiting", mb.send);
200 
201 	/* Let the secondary get started and wait for a message. */
202 	run_res = ffa_run(SERVICE_VM1, 0);
203 	EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
204 	EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
205 
206 	/*
207 	 * Trying to run it again should return the same value, and not actually
208 	 * run it.
209 	 */
210 	run_res = ffa_run(SERVICE_VM1, 0);
211 	EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
212 	EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
213 }
214 
215 /**
216  * Send direct message, verify that sent info is echoed back.
217  */
TEST(ffa,ffa_send_direct_message_req_echo)218 TEST(ffa, ffa_send_direct_message_req_echo)
219 {
220 	const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
221 				0x88889999};
222 	struct mailbox_buffers mb = set_up_mailbox();
223 	struct ffa_value res;
224 
225 	SERVICE_SELECT(SERVICE_VM1, "ffa_direct_message_resp_echo", mb.send);
226 	ffa_run(SERVICE_VM1, 0);
227 
228 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, msg[0],
229 				      msg[1], msg[2], msg[3], msg[4]);
230 
231 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
232 
233 	EXPECT_EQ(res.arg3, msg[0]);
234 	EXPECT_EQ(res.arg4, msg[1]);
235 	EXPECT_EQ(res.arg5, msg[2]);
236 	EXPECT_EQ(res.arg6, msg[3]);
237 	EXPECT_EQ(res.arg7, msg[4]);
238 }
239 
240 /**
241  * Send direct message, secondary verifies disallowed SMC invocations while
242  * ffa_msg_send_direct_req is being serviced.
243  */
TEST(ffa,ffa_send_direct_message_req_disallowed_smc)244 TEST(ffa, ffa_send_direct_message_req_disallowed_smc)
245 {
246 	const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
247 				0x88889999};
248 	struct mailbox_buffers mb = set_up_mailbox();
249 	struct ffa_value res;
250 
251 	SERVICE_SELECT(SERVICE_VM1, "ffa_direct_msg_req_disallowed_smc",
252 		       mb.send);
253 	ffa_run(SERVICE_VM1, 0);
254 
255 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, msg[0],
256 				      msg[1], msg[2], msg[3], msg[4]);
257 
258 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
259 }
260 
261 /**
262  * Send direct message to invalid destination.
263  */
TEST(ffa,ffa_send_direct_message_req_invalid_dst)264 TEST(ffa, ffa_send_direct_message_req_invalid_dst)
265 {
266 	const uint32_t msg[] = {0x00001111, 0x22223333, 0x44445555, 0x66667777,
267 				0x88889999};
268 	struct ffa_value res;
269 
270 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, HF_PRIMARY_VM_ID,
271 				      msg[0], msg[1], msg[2], msg[3], msg[4]);
272 
273 	EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
274 }
275 
276 /**
277  * Verify that the primary VM can't send direct message responses.
278  */
TEST(ffa,ffa_send_direct_message_resp_invalid)279 TEST(ffa, ffa_send_direct_message_resp_invalid)
280 {
281 	struct ffa_value res;
282 	struct mailbox_buffers mb = set_up_mailbox();
283 
284 	SERVICE_SELECT(SERVICE_VM1, "ffa_direct_message_resp_echo", mb.send);
285 	ffa_run(SERVICE_VM1, 0);
286 
287 	res = ffa_msg_send_direct_resp(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0,
288 				       0, 0);
289 	EXPECT_FFA_ERROR(res, FFA_INVALID_PARAMETERS);
290 }
291 
292 /**
293  * Run secondary VM through ffa_run and check it cannot invoke
294  * a direct message request.
295  */
TEST(ffa,ffa_secondary_direct_msg_req_invalid)296 TEST(ffa, ffa_secondary_direct_msg_req_invalid)
297 {
298 	struct mailbox_buffers mb = set_up_mailbox();
299 	struct ffa_value res;
300 
301 	SERVICE_SELECT(SERVICE_VM1, "ffa_disallowed_direct_msg_req", mb.send);
302 	ffa_run(SERVICE_VM1, 0);
303 
304 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0, 0,
305 				      0);
306 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
307 }
308 
309 /**
310  * Run secondary VM without sending a direct message request beforehand.
311  * Secondary VM must fail sending a direct message response.
312  */
TEST(ffa,ffa_secondary_direct_msg_resp_invalid)313 TEST(ffa, ffa_secondary_direct_msg_resp_invalid)
314 {
315 	struct mailbox_buffers mb = set_up_mailbox();
316 	struct ffa_value res;
317 
318 	SERVICE_SELECT(SERVICE_VM1, "ffa_disallowed_direct_msg_resp", mb.send);
319 	ffa_run(SERVICE_VM1, 0);
320 
321 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0, 0,
322 				      0);
323 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
324 }
325 
326 /**
327  * Run secondary VM and send a direct message request. Secondary VM attempts
328  * altering the sender and receiver in its direct message responses, and must
329  * fail to do so.
330  */
TEST(ffa,ffa_secondary_spoofed_response)331 TEST(ffa, ffa_secondary_spoofed_response)
332 {
333 	struct mailbox_buffers mb = set_up_mailbox();
334 	struct ffa_value res;
335 
336 	SERVICE_SELECT(SERVICE_VM1,
337 		       "ffa_direct_msg_resp_invalid_sender_receiver", mb.send);
338 	ffa_run(SERVICE_VM1, 0);
339 
340 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0, 0, 0,
341 				      0);
342 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
343 }
344 
345 /*
346  * The secondary vCPU is waiting for a direct request, but the primary instead
347  * calls `FFA_RUN`. This should return immediately to the primary without the
348  * secondary ever actually being run.
349  */
TEST(ffa,ffa_secondary_run)350 TEST(ffa, ffa_secondary_run)
351 {
352 	struct mailbox_buffers mb = set_up_mailbox();
353 	struct ffa_value res;
354 
355 	SERVICE_SELECT(SERVICE_VM1, "ffa_direct_msg_run", mb.send);
356 	res = ffa_run(SERVICE_VM1, 0);
357 	EXPECT_EQ(res.func, FFA_MSG_WAIT_32);
358 	EXPECT_EQ(res.arg2, FFA_SLEEP_INDEFINITE);
359 
360 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 1, 0, 0, 0,
361 				      0);
362 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
363 	EXPECT_EQ(res.arg3, 2);
364 
365 	res = ffa_run(SERVICE_VM1, 0);
366 	EXPECT_EQ(res.func, FFA_MSG_WAIT_32);
367 	EXPECT_EQ(res.arg2, FFA_SLEEP_INDEFINITE);
368 
369 	res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 3, 0, 0, 0,
370 				      0);
371 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
372 	EXPECT_EQ(res.arg3, 4);
373 }
374