Skip to content

Commit

Permalink
boot tests: add vmh testing
Browse files Browse the repository at this point in the history
Add/enchance existing virtual memory heap testing.
Change boot test trigger.

Signed-off-by: Jakub Dabek <[email protected]>
  • Loading branch information
dabekjakub committed Jan 15, 2024
1 parent f6baccc commit f6aa027
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 67 deletions.
10 changes: 0 additions & 10 deletions src/ipc/ipc4/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1544,14 +1544,4 @@ 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
}
10 changes: 10 additions & 0 deletions zephyr/boot_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*/

#include <sof\boot_test.h>
#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);

#if CONFIG_SOF_BOOT_TEST
void sys_run_boot_tests(void)
{
TEST_RUN_ONCE(ztest_run_test_suite, sof_boot);
}
SYS_INIT(sys_run_boot_tests, APPLICATION, 99);

#endif
298 changes: 241 additions & 57 deletions zephyr/test/vmh.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*
* Author: Guennadi Liakhovetski <[email protected]>
*/
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*
* Author: Guennadi Liakhovetski <[email protected]>
*/

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

#include <adsp_memory_regions.h>
#include <sof/boot_test.h>
Expand All @@ -17,81 +18,264 @@

LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL);

#define ALLOC_SIZE1 1616
#define ALLOC_SIZE2 26
/* Test function creating and freeing a vmh from given parameters */
static void test_vmh_init_and_free_heap(int memory_region_attribute,
struct vmh_heap_config *config,
int core_id,
bool allocating_continuously,
bool expect_success)
{
struct vmh_heap *heap = vmh_init_heap(config, memory_region_attribute,
core_id, allocating_continuously);
if (expect_success) {
zassert_not_null(heap,
"Heap initialization expected to succeed but failed");
}
else
zassert_is_null(heap, "Heap initialization expected to fail but succeeded");

if (heap) {
int ret = vmh_free_heap(heap);

zassert_equal(ret, 0, "Failed to free heap");
}
}

static int vmh_test_single(bool span)
/* Parametrized test function for vmh_alloc and vmh_free */
static void test_vmh_alloc_free_no_check(struct vmh_heap *heap,
uint32_t alloc_size,
bool expect_success)
{
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);
void *ptr = vmh_alloc(heap, alloc_size);

if (expect_success)
zassert_not_null(ptr, "Allocation expected to succeed but failed");
else
zassert_is_null(ptr, "Allocation expected to fail but succeeded");

if (ptr) {
int ret = vmh_free(heap, ptr);

zassert_equal(ret, 0, "Failed to free allocated memory");
}
}

buf = vmh_alloc(h, ALLOC_SIZE2);
/* Parametrized test function for vmh_alloc and vmh_free with memory read/write */
static void test_vmh_alloc_free_check(struct vmh_heap *heap,
uint32_t alloc_size,
bool expect_success)
{
void *ptr = vmh_alloc(heap, alloc_size);

if (!buf) {
ret1 = -ENOMEM;
LOG_ERR("Failed to allocate %u", ALLOC_SIZE2);
goto out;
if (expect_success)
zassert_not_null(ptr, "Allocation expected to succeed but failed");
else {
zassert_is_null(ptr, "Allocation expected to fail but succeeded");
return; // No need to proceed if allocation was expected to fail
}

buf[0] = 0;
buf[ALLOC_SIZE2 - 1] = 15;
if (ptr) {
// Write test pattern to the allocated memory
memset(ptr, 0xAA, alloc_size);

// Verify the written test pattern at the start of the memory
uint8_t start_val = *((uint8_t *)ptr);

zassert_equal(start_val, 0xAA,
"Memory content verification failed at the start");

ret1 = vmh_free(h, buf);
if (ret1 < 0)
LOG_ERR("Free error %d", ret1);
// Verify the written test pattern at the end of the memory
uint8_t end_val = *((uint8_t *)ptr + alloc_size - 1);

out:
int ret2 = vmh_free_heap(h);
zassert_equal(end_val, 0xAA,
"Memory content verification failed at the end");

if (ret2 < 0)
LOG_ERR("Free heap error %d", ret2);
// Verify the written test pattern at a random position within the memory
if (alloc_size > 2) {
uint32_t middle_pos = alloc_size / 2; // Example position in the middle
uint8_t middle_val = *((uint8_t *)ptr + middle_pos);

if (!ret1)
ret1 = ret2;
zassert_equal(middle_val, 0xAA,
"Memory content verification failed in the middle");
}

// Free the allocated memory
int ret = vmh_free(heap, ptr);

return ret1;
zassert_equal(ret, 0, "Failed to free allocated memory");
}
}

static int vmh_test(void)
/* Parametrized test function for multiple allocations on the same heap */
static void test_vmh_multiple_allocs(struct vmh_heap *heap, int num_allocs,
uint32_t min_alloc_size,
uint32_t max_alloc_size)
{
int ret = vmh_test_single(false);
void *ptrs[num_allocs];
uint32_t alloc_size;
bool success;
int ret;

/* Perform multiple allocations */
for (int i = 0; i < num_allocs; i++) {
/* Generate a random allocation size between min_alloc_size and max_alloc_size */
alloc_size = min_alloc_size +
k_cycle_get_32() % (max_alloc_size - min_alloc_size + 1);

if (ret < 0) {
LOG_ERR("Non-contiguous test error %d", ret);
return ret;
/* Attempt to allocate memory */
ptrs[i] = vmh_alloc(heap, alloc_size);

/* Check if allocation was expected to succeed */
zassert_true(ptrs[i] != NULL,
"Allocation of size %u expected to succeed but failed",
alloc_size);

if (ptrs[i] != NULL) {
LOG_INF("Test allocation size: %d", alloc_size);
/* Example test pattern */
memset(ptrs[i], 0xAA, alloc_size);

/* Verify the written test pattern */
uint8_t *byte_ptr = (uint8_t *)ptrs[i];

for (uint32_t j = 0; j < alloc_size; j++) {
zassert_equal(byte_ptr[j], 0xAA,
"Memory content verification failed at position %u", j);
}
}
}

/* Free the allocated memory */
for (int i = 0; i < num_allocs; i++) {
if (ptrs[i]) {
ret = vmh_free(heap, ptrs[i]);
zassert_equal(ret, 0, "Failed to free allocated memory");
}
}
}

ret = vmh_test_single(true);
if (ret < 0)
LOG_ERR("Contiguous test error %d", ret);
/* Test case that uses the parametrized function for multiple allocations */
static void test_vmh_alloc_multiple_times(bool allocating_continuously)
{
struct vmh_heap *heap =
vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, allocating_continuously);

zassert_not_null(heap, "Heap initialization failed");

/* Test multiple allocations with small sizes */
test_vmh_multiple_allocs(heap, 64, 4, 8);
test_vmh_multiple_allocs(heap, 64, 4, 8);
test_vmh_multiple_allocs(heap, 64, 4, 8);
test_vmh_multiple_allocs(heap, 16, 4, 1024);
test_vmh_multiple_allocs(heap, 16, 4, 1024);
test_vmh_multiple_allocs(heap, 64, 1024, 4096);
test_vmh_multiple_allocs(heap, 64, 4096, 8192);
test_vmh_multiple_allocs(heap, 16, 1024, 4096);
test_vmh_multiple_allocs(heap, 16, 4096, 8192);

/* Clean up the heap after testing */
int ret = vmh_free_heap(heap);

zassert_equal(ret, 0, "Failed to free heap after multiple allocations");
}

/* Test function that calls parametrized tests for vmh_alloc and vmh_free */
static void test_vmh_alloc_free(bool allocating_continuously)
{
struct vmh_heap *heap =
vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, allocating_continuously);

return ret;
zassert_not_null(heap, "Heap initialization failed");

test_vmh_alloc_free_no_check(heap, 512, true);
test_vmh_alloc_free_no_check(heap, 2048, true);
test_vmh_alloc_free_no_check(heap, sizeof(int), false);
test_vmh_alloc_free_no_check(heap, 0, false);

test_vmh_alloc_free_check(heap, 512, true);
test_vmh_alloc_free_check(heap, 2048, true);
test_vmh_alloc_free_check(heap, sizeof(int), false);
test_vmh_alloc_free_check(heap, 0, false);

int ret = vmh_free_heap(heap);

zassert_equal(ret, 0, "Failed to free heap");

/* Could add tests with configs for heaps*/
}

/* Test function that calls parametrized tests for vmh_alloc and vmh_free */
static void test_heap_creation(void)
{
test_vmh_init_and_free_heap(MEM_REG_ATTR_CORE_HEAP, NULL, 0, false, true);

/* Try to setup with pre defined heap config */
struct vmh_heap_config config;

config.block_bundles_table[0].block_size = 4;

config.block_bundles_table[0].number_of_blocks = 80;

config.block_bundles_table[1].block_size = 4;

config.block_bundles_table[1].number_of_blocks = 80;

test_vmh_init_and_free_heap(MEM_REG_ATTR_CORE_HEAP, &config, 0, false, true);
}

static void test_alloc_on_configured_heap(bool allocating_continuously)
{

/* Try to setup with pre defined heap config */
struct vmh_heap_config config;

config.block_bundles_table[0].block_size = 20;

config.block_bundles_table[0].number_of_blocks = 80;

/* Create continuous allocation heap for success test */
struct vmh_heap *heap =
vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, allocating_continuously);

/* Will succeed on continuous and fail with single block alloc */
test_vmh_alloc_free_check(heap, 512, allocating_continuously);

int ret = vmh_free_heap(heap);

zassert_equal(ret, 0, "Failed to free heap");
}

/* Test cases for initializing heaps on all available regions */
static void test_vmh_init_all_heaps(void)
{
int num_regions = CONFIG_MP_MAX_NUM_CPUS + VIRTUAL_REGION_COUNT;
int i;
const struct sys_mm_drv_region *virtual_memory_region =
sys_mm_drv_query_memory_regions();

/* Test initializing all types of heaps */
for (i = 0; i < num_regions; i++) {

/* Test without continuous allocation */
test_vmh_init_and_free_heap(virtual_memory_region[i].attr, NULL, 0, false,
true);

/* Test if it fails when heap already exists */
test_vmh_init_and_free_heap(virtual_memory_region[i].attr, NULL, 0, true,
false);
}
}

ZTEST(sof_boot, virtual_memory_heap)
{
int ret = vmh_test();
test_heap_creation();
test_vmh_init_all_heaps();
test_alloc_on_configured_heap(true);
test_alloc_on_configured_heap(false);
test_vmh_alloc_free(true);
test_vmh_alloc_free(false);
test_vmh_alloc_multiple_times(true);
test_vmh_alloc_multiple_times(false);

TEST_CHECK_RET(ret, "virtual_memory_heap");
TEST_CHECK_RET(true, "virtual_memory_heap");
}

0 comments on commit f6aa027

Please sign in to comment.