1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved.
4  */
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <sys/ioctl.h>
10 #include <unistd.h>
11 #include "include/uapi/linux/arm_ffa_user.h"
12 #include "xtest_helpers.h"
13 #include "xtest_test.h"
14 
15 #define FFA_DRIVER_FS_PATH	"/sys/kernel/debug/arm_ffa_user"
16 #define SPMC_TEST_OK 0xaa
17 #define INCORRECT_ENDPOINT_ID 0xffff
18 #define NORMAL_WORLD_ENDPOINT_ID	0
19 
20 #define FFA_USER_REQ_VER_MAJOR 5
21 #define FFA_USER_REQ_VER_MINOR 0
22 #define FFA_USER_REQ_VER_PATCH 1
23 
24 /* Get the 32 least significant bits of a handle.*/
25 #define MEM_SHARE_HANDLE_LOW(x) ((x) & 0xffffffff)
26 /* Get the 32 most significant bits of a handle.*/
27 #define MEM_SHARE_HANDLE_HIGH(x) (((x) >> 32) & 0xffffffff)
28 
29 #define MEM_SHARE_HANDLE_LOW_INDEX	1
30 #define MEM_SHARE_HANDLE_HIGH_INDEX	2
31 #define MEM_SHARE_HANDLE_ENDPOINT_INDEX	3
32 
33 enum sp_tests {
34 	EP_TEST_SP,
35 	EP_TEST_SP_COMMUNICATION,
36 	EP_TEST_SP_INCREASE,
37 	EP_TRY_R_ACCESS,
38 	EP_TRY_W_ACCESS,
39 	EP_RETRIEVE,
40 	EP_RELINQUISH,
41 	EP_SP_MEM_SHARING,
42 	EP_SP_MEM_SHARING_MULTI,
43 	EP_SP_MEM_SHARING_EXC,
44 	EP_SP_MEM_INCORRECT_ACCESS,
45 	EP_SP_NOP
46 };
47 
48 static int ffa_fd = -1;
49 
50 static const char test_endpoint1_uuid[] =
51 	"5c9edbc3-7b3a-4367-9f83-7c191ae86a37";
52 static const char test_endpoint2_uuid[] =
53 	"7817164c-c40c-4d1a-867a-9bb2278cf41a";
54 static const char test_endpoint3_uuid[] =
55 	"23eb0100-e32a-4497-9052-2f11e584afa6";
56 
57 static struct ffa_ioctl_ep_desc test_endpoint1 = {
58 	.uuid_ptr = (uint64_t)test_endpoint1_uuid,
59 };
60 
61 static struct ffa_ioctl_ep_desc test_endpoint2 = {
62 	.uuid_ptr = (uint64_t)test_endpoint2_uuid,
63 };
64 
65 static struct ffa_ioctl_ep_desc test_endpoint3 = {
66 	.uuid_ptr = (uint64_t)test_endpoint3_uuid,
67 };
68 
check_ffa_user_version(void)69 static bool check_ffa_user_version(void)
70 {
71 	FILE *f = NULL;
72 	int ver_major = -1;
73 	int ver_minor = -1;
74 	int ver_patch = -1;
75 	int scan_cnt = 0;
76 
77 	f = fopen("/sys/module/arm_ffa_user/version", "r");
78 	if (f) {
79 		scan_cnt = fscanf(f, "%d.%d.%d",
80 				  &ver_major, &ver_minor, &ver_patch);
81 		fclose(f);
82 		if (scan_cnt != 3) {
83 			printf("error: failed to parse arm_ffa_user version\n");
84 			return false;
85 		}
86 	} else {
87 		printf("error: failed to read arm_ffa_user module info - %s\n",
88 		       strerror(errno));
89 		return false;
90 	}
91 
92 	if (ver_major != FFA_USER_REQ_VER_MAJOR)
93 		goto err;
94 
95 	if (ver_minor < FFA_USER_REQ_VER_MINOR)
96 		goto err;
97 
98 	if (ver_minor == FFA_USER_REQ_VER_MINOR)
99 		if (ver_patch < FFA_USER_REQ_VER_PATCH)
100 			goto err;
101 
102 	return true;
103 
104 err:
105 	printf("error: Incompatible arm_ffa_user driver detected.");
106 	printf("Found v%d.%d.%d wanted >= v%d.%d.%d)\n",
107 	       ver_major, ver_minor, ver_patch, FFA_USER_REQ_VER_MAJOR,
108 		   FFA_USER_REQ_VER_MINOR, FFA_USER_REQ_VER_PATCH);
109 
110 	return false;
111 }
112 
close_debugfs(void)113 static void close_debugfs(void)
114 {
115 	int err = 0;
116 
117 	if (ffa_fd >= 0) {
118 		err = close(ffa_fd);
119 		if (err < 0)
120 			Do_ADBG_Log("Error: Could not close the FF-A driver");
121 	}
122 	ffa_fd = -1;
123 }
124 
init_sp_xtest(ADBG_Case_t * c)125 static bool init_sp_xtest(ADBG_Case_t *c)
126 {
127 	if (!check_ffa_user_version())
128 		return false;
129 
130 	if (ffa_fd < 0) {
131 		ffa_fd = open(FFA_DRIVER_FS_PATH, O_RDWR);
132 		if (ffa_fd < 0) {
133 			Do_ADBG_Log("Error: Could not open the FF-A driver");
134 			return false;
135 		}
136 	}
137 
138 	return true;
139 }
140 
start_sp_test(uint16_t endpoint,enum sp_tests test,struct ffa_ioctl_msg_args * args)141 static int start_sp_test(uint16_t endpoint, enum sp_tests test,
142 			 struct ffa_ioctl_msg_args *args)
143 {
144 	args->dst_id = endpoint;
145 	args->args[0] = test;
146 	return ioctl(ffa_fd, FFA_IOC_MSG_SEND, args);
147 }
148 
get_endpoint_id(uint64_t endp)149 static uint16_t get_endpoint_id(uint64_t endp)
150 {
151 	struct ffa_ioctl_ep_desc sid = { .uuid_ptr = endp };
152 
153 	/* Get ID of destination SP based on UUID */
154 	if (ioctl(ffa_fd, FFA_IOC_GET_PART_ID, &sid))
155 		return INCORRECT_ENDPOINT_ID;
156 
157 	return sid.id;
158 }
159 
xtest_ffa_spmc_test_1001(ADBG_Case_t * c)160 static void xtest_ffa_spmc_test_1001(ADBG_Case_t *c)
161 {
162 	struct ffa_ioctl_msg_args args = { 0 };
163 	uint16_t endpoint1_id = 0;
164 	uint16_t endpoint2_id = 0;
165 	int rc = 0;
166 
167 	Do_ADBG_BeginSubCase(c, "SP1 comms check");
168 	if (!init_sp_xtest(c)) {
169 		Do_ADBG_Log("Failed to initialise test, skipping SP test");
170 		goto out;
171 	}
172 
173 	endpoint1_id = get_endpoint_id(test_endpoint1.uuid_ptr);
174 	if (endpoint1_id == INCORRECT_ENDPOINT_ID) {
175 		Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test");
176 		Do_ADBG_Log("Add xtest_1 sp to the image to enable tests");
177 		goto out;
178 	}
179 
180 	memset(&args, 0, sizeof(args));
181 	rc = start_sp_test(endpoint1_id, EP_TEST_SP, &args);
182 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0))
183 		goto out;
184 
185 	if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK))
186 		goto out;
187 	Do_ADBG_EndSubCase(c, "SP1 comms check");
188 
189 	Do_ADBG_BeginSubCase(c, "Sp2 comms check");
190 	endpoint2_id = get_endpoint_id(test_endpoint2.uuid_ptr);
191 	if (endpoint2_id == INCORRECT_ENDPOINT_ID) {
192 		Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test");
193 		Do_ADBG_Log("Add xtest_2 sp to the image to enable tests");
194 		goto out;
195 	}
196 
197 	memset(&args, 0, sizeof(args));
198 	rc = start_sp_test(endpoint2_id, EP_TEST_SP, &args);
199 	if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0))
200 		goto out;
201 
202 	if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK))
203 		goto out;
204 	Do_ADBG_EndSubCase(c, "Sp2 comms check");
205 
206 	/* Test SP to SP messaging. */
207 	Do_ADBG_BeginSubCase(c, "SP to SP messaging check");
208 	memset(&args, 0, sizeof(args));
209 	args.args[1] = endpoint2_id;
210 
211 	rc = start_sp_test(endpoint1_id, EP_TEST_SP_COMMUNICATION, &args);
212 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
213 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
214 
215 	memset(&args, 0, sizeof(args));
216 	args.args[1] = endpoint1_id;
217 
218 	rc = start_sp_test(endpoint2_id, EP_TEST_SP_COMMUNICATION, &args);
219 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
220 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
221 
222 out:
223 	Do_ADBG_EndSubCase(c, NULL);
224 	close_debugfs();
225 }
226 
227 ADBG_CASE_DEFINE(ffa_spmc, 1001, xtest_ffa_spmc_test_1001,
228 		 "Test FF-A communication");
229 
check_alive(ADBG_Case_t * c,uint16_t endpoint)230 static void check_alive(ADBG_Case_t *c, uint16_t endpoint)
231 {
232 	struct ffa_ioctl_msg_args args = {};
233 	int rc = 0;
234 
235 	args.dst_id = endpoint;
236 	rc = start_sp_test(endpoint, EP_SP_NOP, &args);
237 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
238 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
239 }
240 
share_mem(uint16_t endpoint,uint64_t * handle)241 static int share_mem(uint16_t endpoint, uint64_t *handle)
242 {
243 	int status = false;
244 	struct ffa_ioctl_shm_desc shm_desc = { .dst_id = endpoint,
245 					      .size = 0x1000 };
246 
247 	status = ioctl(ffa_fd, FFA_IOC_SHM_INIT, &shm_desc);
248 
249 	if (!status)
250 		*handle = shm_desc.handle;
251 
252 	return status;
253 }
254 
set_up_mem(struct ffa_ioctl_ep_desc * endp,struct ffa_ioctl_msg_args * args,uint64_t * handle,ADBG_Case_t * c)255 static int set_up_mem(struct ffa_ioctl_ep_desc *endp,
256 		      struct ffa_ioctl_msg_args *args,
257 		      uint64_t *handle, ADBG_Case_t *c)
258 {
259 	uint16_t endpoint = 0;
260 	int rc = 0;
261 
262 	endpoint = get_endpoint_id(endp->uuid_ptr);
263 	*handle = 0;
264 	/* Share memory with SP*/
265 	rc = share_mem(endpoint, handle);
266 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
267 
268 	if (!ADBG_EXPECT_NOT_NULL(c, handle))
269 		return TEEC_ERROR_GENERIC;
270 
271 	/* SP will retrieve the memory region. */
272 	memset(args, 0, sizeof(*args));
273 	args->dst_id = endpoint;
274 	args->args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(*handle);
275 	args->args[MEM_SHARE_HANDLE_HIGH_INDEX] =
276 		MEM_SHARE_HANDLE_HIGH(*handle);
277 	args->args[MEM_SHARE_HANDLE_ENDPOINT_INDEX] = NORMAL_WORLD_ENDPOINT_ID;
278 
279 	rc = start_sp_test(endpoint, EP_RETRIEVE, args);
280 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
281 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args->args[0], ==, SPMC_TEST_OK);
282 
283 	return TEEC_SUCCESS;
284 }
285 
xtest_ffa_spmc_test_1002(ADBG_Case_t * c)286 static void xtest_ffa_spmc_test_1002(ADBG_Case_t *c)
287 {
288 	struct ffa_ioctl_msg_args args = { 0 };
289 	uint64_t handle = 0;
290 	uint16_t endpoint1_id = 0;
291 	int rc = 0;
292 	struct ffa_ioctl_shm_desc shm_desc = { 0 };
293 
294 	if (!init_sp_xtest(c)) {
295 		Do_ADBG_Log("Failed to initialise test, skipping SP test");
296 		goto out;
297 	}
298 
299 	endpoint1_id = get_endpoint_id(test_endpoint1.uuid_ptr);
300 	if (endpoint1_id == INCORRECT_ENDPOINT_ID) {
301 		Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test");
302 		Do_ADBG_Log("Add xtest_1 sp to the image to enable tests");
303 		goto out;
304 	}
305 
306 	memset(&args, 0, sizeof(args));
307 	rc = start_sp_test(endpoint1_id, EP_TEST_SP, &args);
308 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
309 	if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK))
310 		goto out;
311 
312 	/* Set up memory and have the SP retrieve it. */
313 	Do_ADBG_BeginSubCase(c, "Test memory set-up");
314 	memset(&args, 0, sizeof(args));
315 	if (set_up_mem(&test_endpoint1, &args, &handle, c)) {
316 		Do_ADBG_EndSubCase(c, "Test memory set-up");
317 		goto out;
318 	}
319 	Do_ADBG_EndSubCase(c, "Test memory set-up");
320 
321 	/* Retrieve it again. */
322 	Do_ADBG_BeginSubCase(c, "Test retrieve memory second time");
323 	memset(&args, 0, sizeof(args));
324 	args.dst_id = endpoint1_id;
325 	args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle);
326 	args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle);
327 	args.args[MEM_SHARE_HANDLE_ENDPOINT_INDEX] = NORMAL_WORLD_ENDPOINT_ID;
328 	rc = start_sp_test(endpoint1_id, EP_RETRIEVE, &args);
329 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
330 	Do_ADBG_EndSubCase(c, "Test retrieve memory second time");
331 
332 	/*Access it. */
333 	Do_ADBG_BeginSubCase(c, "Test accessing memory");
334 	memset(&args, 0, sizeof(args));
335 	rc = start_sp_test(endpoint1_id, EP_TRY_R_ACCESS, &args);
336 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
337 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
338 	Do_ADBG_EndSubCase(c, "Test accessing memory");
339 
340 	/*RELINQUISH the memory area.*/
341 	Do_ADBG_BeginSubCase(c, "Test relinquish memory");
342 	memset(&args, 0, sizeof(args));
343 	args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle);
344 	args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle);
345 	rc = start_sp_test(endpoint1_id, EP_RELINQUISH, &args);
346 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
347 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
348 	check_alive(c, endpoint1_id);
349 	Do_ADBG_EndSubCase(c, "Test relinquish memory");
350 
351 	/* Try to reclaim the mem with the SP still having access to it. */
352 	Do_ADBG_BeginSubCase(c, "Test incorrect reclaim");
353 	shm_desc.handle = handle;
354 	shm_desc.dst_id = endpoint1_id;
355 	rc = ioctl(ffa_fd, FFA_IOC_SHM_DEINIT, &shm_desc);
356 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, <, 0);
357 	Do_ADBG_EndSubCase(c, "Test incorrect reclaim");
358 
359 	/*RELINQUISH the memory area.*/
360 	Do_ADBG_BeginSubCase(c, "Test relinquish memory second time");
361 	memset(&args, 0, sizeof(args));
362 	args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle);
363 	args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle);
364 	rc = start_sp_test(endpoint1_id, EP_RELINQUISH, &args);
365 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
366 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
367 	check_alive(c, endpoint1_id);
368 	Do_ADBG_EndSubCase(c, "Test relinquish memory second time");
369 
370 	/* Try to reclaim again this time it should work. */
371 	Do_ADBG_BeginSubCase(c, "Test correct reclaim");
372 	shm_desc.handle = handle;
373 	shm_desc.dst_id = endpoint1_id;
374 	rc = ioctl(ffa_fd, FFA_IOC_SHM_DEINIT, &shm_desc);
375 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, >=, 0);
376 	check_alive(c, endpoint1_id);
377 	Do_ADBG_EndSubCase(c, "Test correct reclaim");
378 
379 	/* SP will try to retrieve invalid memory region. */
380 	Do_ADBG_BeginSubCase(c, "Test retrieve invalid memory region");
381 	memset(&args, 0, sizeof(args));
382 	args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle);
383 	args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle);
384 	args.args[MEM_SHARE_HANDLE_ENDPOINT_INDEX] = NORMAL_WORLD_ENDPOINT_ID;
385 	rc = start_sp_test(endpoint1_id, EP_RETRIEVE, &args);
386 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
387 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], !=, SPMC_TEST_OK);
388 	check_alive(c, endpoint1_id);
389 
390 	Do_ADBG_EndSubCase(c, "Test retrieve invalid memory region");
391 out:
392 	close_debugfs();
393 }
394 
395 ADBG_CASE_DEFINE(ffa_spmc, 1002, xtest_ffa_spmc_test_1002,
396 		 "Test FF-A memory: share memory from Normal World to SP");
397 
xtest_ffa_spmc_test_1003(ADBG_Case_t * c)398 static void xtest_ffa_spmc_test_1003(ADBG_Case_t *c)
399 {
400 	struct ffa_ioctl_msg_args args = { 0 };
401 	uint16_t endpoint1 = 0;
402 	uint16_t endpoint2 = 0;
403 	int rc = 0;
404 
405 	if (!init_sp_xtest(c)) {
406 		Do_ADBG_Log("Failed to initialise test, skipping SP test");
407 		goto out;
408 	}
409 
410 	endpoint1 = get_endpoint_id(test_endpoint1.uuid_ptr);
411 	if (endpoint1 == INCORRECT_ENDPOINT_ID) {
412 		Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test");
413 		Do_ADBG_Log("Add xtest_1 sp to the image to enable tests");
414 		goto out;
415 	}
416 
417 	/* Test SP to SP memory sharing. */
418 	endpoint2 = get_endpoint_id(test_endpoint2.uuid_ptr);
419 	if (endpoint2 == INCORRECT_ENDPOINT_ID) {
420 		Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test");
421 		Do_ADBG_Log("Add xtest_2 sp to the image to enable tests");
422 		goto out;
423 	}
424 
425 	memset(&args, 0, sizeof(args));
426 	args.args[1] = endpoint2;
427 	rc = start_sp_test(endpoint1, EP_SP_MEM_SHARING, &args);
428 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
429 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
430 
431 out:
432 	close_debugfs();
433 }
434 
435 ADBG_CASE_DEFINE(ffa_spmc, 1003, xtest_ffa_spmc_test_1003,
436 		 "Test FF-A memory: SP to SP");
437 
xtest_ffa_spmc_test_1004(ADBG_Case_t * c)438 static void xtest_ffa_spmc_test_1004(ADBG_Case_t *c)
439 {
440 	struct ffa_ioctl_msg_args args = { 0 };
441 	uint16_t endpoint1 = 0;
442 	uint16_t endpoint2 = 0;
443 	int rc = 0;
444 
445 	if (!init_sp_xtest(c)) {
446 		Do_ADBG_Log("Failed to initialise test, skipping SP test");
447 		goto out;
448 	}
449 
450 	endpoint1 = get_endpoint_id(test_endpoint1.uuid_ptr);
451 	if (endpoint1 == INCORRECT_ENDPOINT_ID) {
452 		Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test");
453 		Do_ADBG_Log("Add xtest_1 sp to the image to enable tests");
454 		goto out;
455 	}
456 
457 	/* Test SP to SP memory sharing. */
458 	endpoint2 = get_endpoint_id(test_endpoint2.uuid_ptr);
459 	if (endpoint2 == INCORRECT_ENDPOINT_ID) {
460 		Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test");
461 		Do_ADBG_Log("Add xtest_2 sp to the image to enable tests");
462 		goto out;
463 	}
464 
465 	Do_ADBG_BeginSubCase(c, "Test sharing with exc access");
466 	memset(&args, 0, sizeof(args));
467 	args.args[1] = endpoint2;
468 	rc = start_sp_test(endpoint1, EP_SP_MEM_SHARING_EXC, &args);
469 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
470 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
471 	Do_ADBG_EndSubCase(c, "Test sharing with exc access");
472 
473 	Do_ADBG_BeginSubCase(c, "Test sharing with incorrect access");
474 	memset(&args, 0, sizeof(args));
475 	args.args[1] = endpoint2;
476 	rc = start_sp_test(endpoint1, EP_SP_MEM_INCORRECT_ACCESS, &args);
477 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
478 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
479 	Do_ADBG_EndSubCase(c, "Test sharing with incorrect access");
480 
481 out:
482 	close_debugfs();
483 }
484 
485 ADBG_CASE_DEFINE(ffa_spmc, 1004, xtest_ffa_spmc_test_1004,
486 		 "Test FF-A memory: Access and flags");
487 
xtest_ffa_spmc_test_1005(ADBG_Case_t * c)488 static void xtest_ffa_spmc_test_1005(ADBG_Case_t *c)
489 {
490 	struct ffa_ioctl_msg_args args = { 0 };
491 	uint16_t endpoint1 = 0;
492 	uint16_t endpoint2 = 0;
493 	uint16_t endpoint3 = 0;
494 	int rc = 0;
495 
496 	if (!init_sp_xtest(c)) {
497 		Do_ADBG_Log("Failed to initialise test, skipping SP test");
498 		goto out;
499 	}
500 
501 	endpoint1 = get_endpoint_id(test_endpoint1.uuid_ptr);
502 	if (endpoint1 == INCORRECT_ENDPOINT_ID) {
503 		Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test");
504 		Do_ADBG_Log("Add xtest_1 sp to the image to enable tests");
505 		goto out;
506 	}
507 
508 	endpoint2 = get_endpoint_id(test_endpoint2.uuid_ptr);
509 	if (endpoint2 == INCORRECT_ENDPOINT_ID) {
510 		Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test");
511 		Do_ADBG_Log("Add xtest_2 sp to the image to enable tests");
512 		goto out;
513 	}
514 
515 	endpoint3 = get_endpoint_id(test_endpoint3.uuid_ptr);
516 	if (endpoint3 == INCORRECT_ENDPOINT_ID) {
517 		Do_ADBG_Log("Could not contact xtest_3 sp, skipping SP test");
518 		Do_ADBG_Log("Add xtest_3 sp to the image to enable tests");
519 		goto out;
520 	}
521 
522 	memset(&args, 0, sizeof(args));
523 	args.args[1] = endpoint2;
524 	args.args[2] = endpoint3;
525 	rc = start_sp_test(endpoint1, EP_SP_MEM_SHARING_MULTI, &args);
526 	ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0);
527 	ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK);
528 
529 out:
530 	close_debugfs();
531 }
532 
533 ADBG_CASE_DEFINE(regression, 1005, xtest_ffa_spmc_test_1005,
534 		 "Test FF-A memory: multiple receiver");
535