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