From f6ed14c6818817cd137bb99634cb448127b6ee17 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 16 Nov 2023 13:02:34 +0100 Subject: [PATCH 1/4] test: add boot-time ztest-based testing Add a ZTEST test-suite to run SOF boot-time self-tests at the time of the first FW_GEN_MSG IPC. Signed-off-by: Guennadi Liakhovetski --- app/debug_overlay.conf | 3 +++ app/src/main.c | 15 ++++++++++++++- src/include/sof/boot_test.h | 28 ++++++++++++++++++++++++++++ src/ipc/ipc4/handler.c | 16 ++++++++++++++++ zephyr/CMakeLists.txt | 4 ++++ zephyr/Kconfig | 10 ++++++++++ zephyr/boot_test.c | 12 ++++++++++++ 7 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/include/sof/boot_test.h create mode 100644 zephyr/boot_test.c diff --git a/app/debug_overlay.conf b/app/debug_overlay.conf index 439af1b67ea0..86cc10c745fe 100644 --- a/app/debug_overlay.conf +++ b/app/debug_overlay.conf @@ -1,6 +1,9 @@ CONFIG_DEBUG=y CONFIG_ASSERT=y +CONFIG_ZTEST=y +CONFIG_SOF_BOOT_TEST=y + # Following options can be enabled additionally, # but will incur a higher runtime cost, so are thus # disabled by default. diff --git a/app/src/main.c b/app/src/main.c index 7a622556b1ae..0f5c1f84fe0e 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -20,7 +20,7 @@ int sof_main(int argc, char *argv[]); * TODO: Here comes SOF initialization */ -int main(void) +static int sof_app_main(void) { int ret; @@ -49,3 +49,16 @@ int main(void) #endif return 0; } + +#if CONFIG_ZTEST +void test_main(void) +{ + sof_app_main(); + k_sleep(K_FOREVER); +} +#else +int main(void) +{ + return sof_app_main(); +} +#endif diff --git a/src/include/sof/boot_test.h b/src/include/sof/boot_test.h new file mode 100644 index 000000000000..965eec06a6a9 --- /dev/null +++ b/src/include/sof/boot_test.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_BOOT_TEST_H__ +#define __SOF_BOOT_TEST_H__ + +#include + +#define TEST_RUN_ONCE(fn, ...) do { \ + static bool once; \ + if (!once) { \ + once = true; \ + fn(__VA_ARGS__); \ + } \ +} while (0) + +#define TEST_CHECK_RET(ret, testname) do { \ + if ((ret) < 0) { \ + LOG_ERR(testname " failed: %d", (ret)); \ + ztest_test_fail(); \ + } else { \ + ztest_test_pass(); \ + } \ +} while (0) + +#endif diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index 1d92879b32d6..52b7f039a788 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,11 @@ #include #include +#if CONFIG_SOF_BOOT_TEST +/* CONFIG_SOF_BOOT_TEST depends on Zephyr */ +#include +#endif + #include #include #include @@ -1527,4 +1533,14 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr) ipc4_send_reply(&reply); } + +#if CONFIG_SOF_BOOT_TEST + /* + * When the first FW_GEN IPC has been processed we are in a stable + * running state, now if a test causes an exception, we have a good + * chance of capturing it. + */ + if (target == SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG) + TEST_RUN_ONCE(ztest_run_test_suite, sof_boot); +#endif } diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b4d729bada78..39e45ebd052d 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -810,6 +810,10 @@ zephyr_library_sources_ifdef(CONFIG_DW_DMA ${SOF_DRIVERS_PATH}/dw/dma.c ) +zephyr_library_sources_ifdef(CONFIG_SOF_BOOT_TEST + boot_test.c +) + zephyr_library_link_libraries(SOF) target_link_libraries(SOF INTERFACE zephyr_interface) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index ea8c1d6e809f..3d9a0b841231 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -67,4 +67,14 @@ config CROSS_CORE_STREAM can be processed on different cores, however, each stream is processed entirely on single core. +config SOF_BOOT_TEST + bool "enable SOF run-time testing" + depends on ZTEST + help + Run tests during boot. This enables an SOF boot-time self-test. When + enabled, the resulting image will run a number of self-tests when the + first global IPC command is received, i.e. when SOF is completely + initialized. After that SOF will continue running and be usable as + usual. + endif diff --git a/zephyr/boot_test.c b/zephyr/boot_test.c new file mode 100644 index 000000000000..bd1b22a95062 --- /dev/null +++ b/zephyr/boot_test.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include + +#include + +LOG_MODULE_REGISTER(sof_boot_test, LOG_LEVEL_DBG); + +ZTEST_SUITE(sof_boot, NULL, NULL, NULL, NULL, NULL); From 3e2f073d40d7397ae9c000d6dc7803f85fb3c762 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 6 Dec 2023 17:47:25 +0100 Subject: [PATCH 2/4] test: add a simple VMH test This adds an initial Virtual Memory Heap test. Signed-off-by: Guennadi Liakhovetski --- zephyr/CMakeLists.txt | 2 +- zephyr/test/CMakeLists.txt | 5 +++++ zephyr/test/vmh.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 zephyr/test/CMakeLists.txt create mode 100644 zephyr/test/vmh.c diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 39e45ebd052d..ccba83b4ab82 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -129,7 +129,7 @@ endmacro() add_subdirectory(../src/init/ init_unused_install/) add_subdirectory(../src/ipc/ ipc_unused_install/) - +add_subdirectory(test/) # Old way below: all .c files added by this giant CMake file. diff --git a/zephyr/test/CMakeLists.txt b/zephyr/test/CMakeLists.txt new file mode 100644 index 000000000000..e0718b8e0754 --- /dev/null +++ b/zephyr/test/CMakeLists.txt @@ -0,0 +1,5 @@ +if (CONFIG_ACE_VERSION_1_5) + zephyr_library_sources_ifdef(CONFIG_SOF_BOOT_TEST + vmh.c + ) +endif() diff --git a/zephyr/test/vmh.c b/zephyr/test/vmh.c new file mode 100644 index 000000000000..c2f3d4463697 --- /dev/null +++ b/zephyr/test/vmh.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Guennadi Liakhovetski + */ + +#include +#include + +#include +#include +#include + +#include +#include + +LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL); + +static int vmh_test(void) +{ + struct vmh_heap *h = vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, false); + + if (!h) + return -ENOMEM; + + return vmh_free_heap(h); +} + +ZTEST(sof_boot, virtual_memory_heap) +{ + int ret = vmh_test(); + + TEST_CHECK_RET(ret, "virtual_memory_heap"); +} From e94a99874a13f02c066b3ea9412e9fd4d8b2d09a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 26 Jul 2023 16:26:44 +0200 Subject: [PATCH 3/4] test: extend VMH testing with an allocation Add calls to vmh_alloc() and vmh_free() for testing. Signed-off-by: Guennadi Liakhovetski --- zephyr/test/vmh.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zephyr/test/vmh.c b/zephyr/test/vmh.c index c2f3d4463697..303a6a226a43 100644 --- a/zephyr/test/vmh.c +++ b/zephyr/test/vmh.c @@ -24,6 +24,16 @@ static int vmh_test(void) if (!h) return -ENOMEM; + char *buf = vmh_alloc(h, 1616); + + if (!buf) + return -ENOMEM; + + buf[0] = 0; + buf[1615] = 15; + + vmh_free(h, buf); + return vmh_free_heap(h); } From 06350f3efa54ed783d4b667afa3b91aa3be7907e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 27 Jul 2023 11:44:02 +0200 Subject: [PATCH 4/4] vmh test: extend test for spanning Test both cases - when spanning multiple blocks is allowed and when it isn't. Signed-off-by: Guennadi Liakhovetski --- zephyr/test/vmh.c | 70 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/zephyr/test/vmh.c b/zephyr/test/vmh.c index 303a6a226a43..038413607ce3 100644 --- a/zephyr/test/vmh.c +++ b/zephyr/test/vmh.c @@ -17,24 +17,76 @@ LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL); -static int vmh_test(void) +#define ALLOC_SIZE1 1616 +#define ALLOC_SIZE2 26 + +static int vmh_test_single(bool span) { - struct vmh_heap *h = vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, false); + struct vmh_heap *h = vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, span); if (!h) - return -ENOMEM; + return -EINVAL; + + char *buf = vmh_alloc(h, ALLOC_SIZE1); + int ret1; + + if (buf) { + buf[0] = 0; + buf[ALLOC_SIZE1 - 1] = 15; - char *buf = vmh_alloc(h, 1616); + ret1 = vmh_free(h, buf); + if (ret1 < 0) + goto out; + } else if (span) { + ret1 = -ENOMEM; + LOG_ERR("Failed to allocate %u in contiguous mode", ALLOC_SIZE1); + goto out; + } else { + LOG_WRN("Ignoring failure to allocate %u in non-contiguous mode", + ALLOC_SIZE1); + } - if (!buf) - return -ENOMEM; + buf = vmh_alloc(h, ALLOC_SIZE2); + + if (!buf) { + ret1 = -ENOMEM; + LOG_ERR("Failed to allocate %u", ALLOC_SIZE2); + goto out; + } buf[0] = 0; - buf[1615] = 15; + buf[ALLOC_SIZE2 - 1] = 15; + + ret1 = vmh_free(h, buf); + if (ret1 < 0) + LOG_ERR("Free error %d", ret1); + +out: + int ret2 = vmh_free_heap(h); + + if (ret2 < 0) + LOG_ERR("Free heap error %d", ret2); + + if (!ret1) + ret1 = ret2; + + return ret1; +} + +static int vmh_test(void) +{ + int ret = vmh_test_single(false); + + if (ret < 0) { + LOG_ERR("Non-contiguous test error %d", ret); + return ret; + } - vmh_free(h, buf); + ret = vmh_test_single(true); + if (ret < 0) + LOG_ERR("Contiguous test error %d", ret); - return vmh_free_heap(h); + return ret; } ZTEST(sof_boot, virtual_memory_heap)