Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boot test and virtual heap testing #7688

Merged
merged 4 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/debug_overlay.conf
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
15 changes: 14 additions & 1 deletion app/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
28 changes: 28 additions & 0 deletions src/include/sof/boot_test.h
Original file line number Diff line number Diff line change
@@ -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 <stdbool.h>

#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
16 changes: 16 additions & 0 deletions src/ipc/ipc4/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <sof/audio/buffer.h>
#include <sof/audio/component_ext.h>
#include <sof/audio/pipeline.h>
#include <sof/boot_test.h>
#include <sof/common.h>
#include <sof/ipc/topology.h>
#include <sof/ipc/common.h>
Expand All @@ -37,6 +38,11 @@
#include <sof/trace/dma-trace.h>
#include <sof/lib_manager.h>

#if CONFIG_SOF_BOOT_TEST
/* CONFIG_SOF_BOOT_TEST depends on Zephyr */
#include <zephyr/ztest.h>
#endif

#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
Expand Down Expand Up @@ -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
}
6 changes: 5 additions & 1 deletion zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)

Expand Down
10 changes: 10 additions & 0 deletions zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions zephyr/boot_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*/

#include <zephyr/logging/log.h>

#include <zephyr/ztest.h>

LOG_MODULE_REGISTER(sof_boot_test, LOG_LEVEL_DBG);

ZTEST_SUITE(sof_boot, NULL, NULL, NULL, NULL, NULL);
5 changes: 5 additions & 0 deletions zephyr/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (CONFIG_ACE_VERSION_1_5)
zephyr_library_sources_ifdef(CONFIG_SOF_BOOT_TEST
vmh.c
)
endif()
97 changes: 97 additions & 0 deletions zephyr/test/vmh.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*
* Author: Guennadi Liakhovetski <[email protected]>
*/

#include <errno.h>
#include <stdbool.h>

#include <adsp_memory_regions.h>
#include <sof/boot_test.h>
#include <sof/lib/regions_mm.h>

#include <zephyr/logging/log.h>
#include <zephyr/ztest.h>

LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL);

#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, span);

if (!h)
return -EINVAL;

char *buf = vmh_alloc(h, ALLOC_SIZE1);
int ret1;

if (buf) {
buf[0] = 0;
buf[ALLOC_SIZE1 - 1] = 15;

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);
}

buf = vmh_alloc(h, ALLOC_SIZE2);

if (!buf) {
ret1 = -ENOMEM;
LOG_ERR("Failed to allocate %u", ALLOC_SIZE2);
goto out;
}

buf[0] = 0;
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;
}

ret = vmh_test_single(true);
if (ret < 0)
LOG_ERR("Contiguous test error %d", ret);

return ret;
}

ZTEST(sof_boot, virtual_memory_heap)
{
int ret = vmh_test();

TEST_CHECK_RET(ret, "virtual_memory_heap");
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in fact, thinking about this now, this code would probably be common for all SOF boot tests, so we can have a macro to be called in this case something like SOF_ZTEST_BOOT(vmh, vmh_test); I can try to do this now or we can try to switch to one like this later when we get at least a second such boot test

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Loading