blob: edc5ed60e9354d4cf8b2085ed77ef03ea1ce369a [file] [log] [blame]
Patrick Williams8dd68482022-10-04 07:57:18 -05001From dbc51066367481b5a45ce24f91571f83a022576e Mon Sep 17 00:00:00 2001
2From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
3Date: Mon, 6 Jun 2022 17:26:06 +0100
4Subject: [PATCH 12/26] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
5
6Add functional test cases for the FF-A core driver
7
8These tests rely on the FF-A Sandbox driver which helps in
9 inspecting the FF-A core driver.
10
11Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
12Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/]
13---
14
15Changelog:
16===============
17
18v4: align sandbox tests with the new FF-A driver interfaces
19 and new way of error handling
20
21v1: introduce sandbox tests
22
23 MAINTAINERS | 1 +
24 test/dm/Makefile | 1 +
25 test/dm/ffa.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++
26 3 files changed, 396 insertions(+)
27 create mode 100644 test/dm/ffa.c
28
29diff --git a/MAINTAINERS b/MAINTAINERS
30index 96157db6b6..e5b71b0ade 100644
31--- a/MAINTAINERS
32+++ b/MAINTAINERS
33@@ -252,6 +252,7 @@ F: doc/README.ffa.drv
34 F: drivers/firmware/arm-ffa/
35 F: include/arm_ffa.h
36 F: include/sandbox_arm_ffa.h
37+F: test/dm/ffa.c
38
39 ARM FREESCALE IMX
40 M: Stefano Babic <sbabic@denx.de>
41diff --git a/test/dm/Makefile b/test/dm/Makefile
42index f0a7c97e3d..f96f848046 100644
43--- a/test/dm/Makefile
44+++ b/test/dm/Makefile
45@@ -79,6 +79,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
46 obj-$(CONFIG_ACPI_PMC) += pmc.o
47 obj-$(CONFIG_DM_PMIC) += pmic.o
48 obj-$(CONFIG_DM_PWM) += pwm.o
49+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
50 obj-$(CONFIG_QFW) += qfw.o
51 obj-$(CONFIG_RAM) += ram.o
52 obj-y += regmap.o
53diff --git a/test/dm/ffa.c b/test/dm/ffa.c
54new file mode 100644
55index 0000000000..052d5fc3f4
56--- /dev/null
57+++ b/test/dm/ffa.c
58@@ -0,0 +1,394 @@
59+// SPDX-License-Identifier: GPL-2.0+
60+/*
61+ * Functional tests for UCLASS_FFA class
62+ *
63+ * (C) Copyright 2022 ARM Limited
64+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
65+ */
66+
67+#include <common.h>
68+#include <console.h>
69+#include <dm.h>
70+#include <dm/test.h>
71+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
72+#include <sandbox_arm_ffa.h>
73+#include <test/test.h>
74+#include <test/ut.h>
75+
76+/* Macros */
77+
78+#define LOG_MSG_SZ (100)
79+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
80+
81+/* Functional tests for the UCLASS_FFA */
82+
83+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
84+{
85+ char cmd[LOG_CMD_SZ] = {0};
86+
87+ console_record_reset();
88+
89+ snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
90+ run_command(cmd, 0);
91+
92+ ut_assert_console_end();
93+
94+ return CMD_RET_SUCCESS;
95+}
96+
97+static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
98+ struct unit_test_state *uts)
99+{
100+ if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
101+ char msg[LOG_MSG_SZ] = {0};
102+
103+ snprintf(msg, LOG_MSG_SZ,
104+ "[%s]: Error: framework version: core = 0x%x , sandbox = 0x%x", __func__,
105+ prvdata->fwk_version,
106+ sdx_prvdata->fwk_version);
107+
108+ dm_test_ffa_log(uts, msg);
109+ return CMD_RET_FAILURE;
110+ }
111+ return CMD_RET_SUCCESS;
112+}
113+
114+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
115+{
116+ if (prvdata->id) {
117+ char msg[LOG_MSG_SZ] = {0};
118+
119+ snprintf(msg, LOG_MSG_SZ,
120+ "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
121+ dm_test_ffa_log(uts, msg);
122+ return CMD_RET_FAILURE;
123+ }
124+ return CMD_RET_SUCCESS;
125+}
126+
127+static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
128+{
129+ if (!prvdata->dev) {
130+ char msg[LOG_MSG_SZ] = {0};
131+
132+ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
133+ dm_test_ffa_log(uts, msg);
134+ return CMD_RET_FAILURE;
135+ }
136+ return CMD_RET_SUCCESS;
137+}
138+
139+static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
140+{
141+ if (!sdx_prvdata->dev) {
142+ char msg[LOG_MSG_SZ] = {0};
143+
144+ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
145+ dm_test_ffa_log(uts, msg);
146+ return CMD_RET_FAILURE;
147+ }
148+ return CMD_RET_SUCCESS;
149+}
150+
151+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
152+{
153+ if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
154+ char msg[LOG_MSG_SZ] = {0};
155+
156+ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
157+ prvdata->pair.rxbuf,
158+ prvdata->pair.txbuf);
159+ dm_test_ffa_log(uts, msg);
160+ return CMD_RET_FAILURE;
161+ }
162+ return CMD_RET_SUCCESS;
163+}
164+
165+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
166+{
167+ char msg[LOG_MSG_SZ] = {0};
168+
169+ if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
170+ prvdata->pair.rxtx_min_pages != RXTX_16K &&
171+ prvdata->pair.rxtx_min_pages != RXTX_64K) {
172+ snprintf(msg,
173+ LOG_MSG_SZ,
174+ "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
175+ __func__,
176+ prvdata->pair.rxtx_min_pages);
177+ dm_test_ffa_log(uts, msg);
178+ return CMD_RET_FAILURE;
179+ }
180+
181+ return CMD_RET_SUCCESS;
182+}
183+
184+static int check_rxbuf_mapped_flag(u32 queried_func_id,
185+ u8 rxbuf_mapped,
186+ struct unit_test_state *uts)
187+{
188+ char msg[LOG_MSG_SZ] = {0};
189+
190+ switch (queried_func_id) {
191+ case FFA_RXTX_MAP:
192+ {
193+ if (rxbuf_mapped)
194+ return CMD_RET_SUCCESS;
195+ break;
196+ }
197+ case FFA_RXTX_UNMAP:
198+ {
199+ if (!rxbuf_mapped)
200+ return CMD_RET_SUCCESS;
201+ break;
202+ }
203+ default:
204+ return CMD_RET_FAILURE;
205+ }
206+
207+ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
208+ (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
209+ dm_test_ffa_log(uts, msg);
210+
211+ return CMD_RET_FAILURE;
212+}
213+
214+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
215+{
216+ if (rxbuf_owned) {
217+ char msg[LOG_MSG_SZ] = {0};
218+
219+ snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
220+ dm_test_ffa_log(uts, msg);
221+ return CMD_RET_FAILURE;
222+ }
223+ return CMD_RET_SUCCESS;
224+}
225+
226+static int test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
227+{
228+ struct ffa_send_direct_data msg = {0};
229+ u8 cnt;
230+
231+ ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg));
232+
233+ for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
234+ ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
235+
236+ return CMD_RET_SUCCESS;
237+}
238+
239+static int test_partitions_and_comms(const char *service_uuid,
240+ struct sandbox_ffa_prvdata *sdx_prvdata,
241+ struct unit_test_state *uts)
242+{
243+ u32 count = 0, size = 0;
244+ struct ffa_partition_info *parts_info;
245+ u32 info_idx, exp_info_idx;
246+ int ret;
247+
248+ /*
249+ * get from the driver the count of the SPs matching the UUID
250+ */
251+ ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
252+ /* make sure partitions are detected */
253+ ut_assertok(ret != 0);
254+ ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
255+
256+ /*
257+ * pre-allocate a buffer to be filled by the driver
258+ * with ffa_partition_info structs
259+ */
260+
261+ parts_info = calloc(count, sizeof(struct ffa_partition_info));
262+ ut_assertok(!parts_info);
263+
264+ size = count * sizeof(struct ffa_partition_info);
265+
266+ /*
267+ * ask the driver to fill the buffer with the SPs info
268+ */
269+ ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
270+ if (ret != 0) {
271+ free(parts_info);
272+ ut_assertok(ret != 0);
273+ }
274+
275+ /*
276+ * SPs found , verify the partitions information
277+ */
278+
279+ ret = CMD_RET_FAILURE;
280+
281+ for (info_idx = 0; info_idx < count ; info_idx++) {
282+ for (exp_info_idx = 0;
283+ exp_info_idx < sdx_prvdata->partitions.count;
284+ exp_info_idx++) {
285+ if (parts_info[info_idx].id ==
286+ sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
287+ ret = memcmp(&parts_info[info_idx],
288+ &sdx_prvdata->partitions.descs[exp_info_idx]
289+ .info,
290+ sizeof(struct ffa_partition_info));
291+ if (ret)
292+ free(parts_info);
293+ ut_assertok(ret != 0);
294+ /* send and receive data from the current partition */
295+ test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
296+ }
297+ ret = CMD_RET_SUCCESS;
298+ }
299+ }
300+
301+ free(parts_info);
302+
303+ /* Verify expected partitions found in the emulated secure world*/
304+ ut_assertok(ret != CMD_RET_SUCCESS);
305+
306+ return CMD_RET_SUCCESS;
307+}
308+
309+static int dm_test_ffa_ack(struct unit_test_state *uts)
310+{
311+ struct ffa_prvdata *prvdata = NULL;
312+ struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
313+ struct ffa_sandbox_data func_data = {0};
314+ u8 rxbuf_flag = 0;
315+ const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
316+ const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
317+ int ret;
318+
319+ /* test probing FF-A devices */
320+ ut_assertok(ffa_bus_discover());
321+
322+ /* get a pointer to the FF-A core and sandbox drivers private data */
323+ func_data.data0 = &prvdata;
324+ func_data.data0_size = sizeof(prvdata);
325+ func_data.data1 = &sdx_prvdata;
326+ func_data.data1_size = sizeof(sdx_prvdata);
327+
328+ ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
329+
330+ /* make sure private data pointers are retrieved */
331+ ut_assertok(prvdata == 0);
332+ ut_assertok(sdx_prvdata == 0);
333+
334+ /* make sure dev devices created */
335+ ut_assertok(check_core_dev(prvdata, uts));
336+ ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
337+
338+ /* test FFA_VERSION */
339+ ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
340+
341+ /* test FFA_ID_GET */
342+ ut_assertok(check_endpoint_id(prvdata, uts));
343+
344+ /* test FFA_FEATURES */
345+ ut_assertok(check_features(prvdata, uts));
346+
347+ /* test core RX/TX buffers */
348+ ut_assertok(check_rxtxbuf(prvdata, uts));
349+
350+ /* test FFA_RXTX_MAP */
351+ func_data.data0 = &rxbuf_flag;
352+ func_data.data0_size = sizeof(rxbuf_flag);
353+
354+ rxbuf_flag = 0;
355+ ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
356+ ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
357+
358+ /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
359+ ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
360+ ut_assertok(ret != CMD_RET_SUCCESS);
361+
362+ /* test FFA_RX_RELEASE */
363+ rxbuf_flag = 1;
364+ ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
365+ ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
366+
367+ /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
368+ ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
369+ ut_assertok(ret != CMD_RET_SUCCESS);
370+
371+ /* test FFA_RX_RELEASE */
372+ rxbuf_flag = 1;
373+ ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
374+ ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
375+
376+ /* test FFA_RXTX_UNMAP */
377+ ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
378+
379+ rxbuf_flag = 1;
380+ ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
381+ ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
382+
383+ return CMD_RET_SUCCESS;
384+}
385+
386+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
387+
388+static int dm_test_ffa_nack(struct unit_test_state *uts)
389+{
390+ struct ffa_prvdata *prvdata = NULL;
391+ struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
392+ struct ffa_sandbox_data func_data = {0};
393+ const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
394+ const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
395+ const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
396+ struct ffa_send_direct_data msg = {0};
397+ int ret;
398+ u32 count = 0;
399+ u16 part_id = 0;
400+
401+ /* test probing FF-A devices */
402+ ut_assertok(ffa_bus_discover());
403+
404+ /* get a pointer to the FF-A core and sandbox drivers private data */
405+ func_data.data0 = &prvdata;
406+ func_data.data0_size = sizeof(prvdata);
407+ func_data.data1 = &sdx_prvdata;
408+ func_data.data1_size = sizeof(sdx_prvdata);
409+
410+ ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
411+
412+ /* make sure private data pointers are retrieved */
413+ ut_assertok(prvdata == 0);
414+ ut_assertok(sdx_prvdata == 0);
415+
416+ /* make sure dev devices created */
417+ ut_assertok(check_core_dev(prvdata, uts));
418+ ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
419+
420+ /* query partitions count using invalid arguments */
421+ ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
422+ ut_assertok(ret != -EINVAL);
423+
424+ /* query partitions count using an invalid UUID string */
425+ ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
426+ ut_assertok(ret != -EINVAL);
427+
428+ /* query partitions count using an invalid UUID (no matching SP) */
429+ count = 0;
430+ ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
431+ ut_assertok(count != 0);
432+
433+ /* query partitions count using a valid UUID */
434+ count = 0;
435+ ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
436+ /* make sure partitions are detected */
437+ ut_assertok(ret != 0);
438+ ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
439+
440+ /* send data to an invalid partition */
441+ ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
442+ ut_assertok(ret != -EINVAL);
443+
444+ /* send data to a valid partition */
445+ part_id = prvdata->partitions.descs[0].info.id;
446+ ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
447+ ut_assertok(ret != 0);
448+
449+ return CMD_RET_SUCCESS;
450+}
451+
452+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
453--
4542.17.1
455