Skip to content

Commit 9528058

Browse files
committed
userspace LL: WIP basic ztest runs with some WAs for qemu.
Starting point. Other patches to be merged etc. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
1 parent b4135b1 commit 9528058

10 files changed

Lines changed: 169 additions & 33 deletions

File tree

app/boards/qemu_xtensa_dc233c_mmu.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CONFIG_ZTEST=y
55
CONFIG_TEST_USERSPACE=y
66
CONFIG_MM_DRV=y
77
CONFIG_ZEPHYR_NATIVE_DRIVERS=y
8+
CONFIG_SOF_USERSPACE_LL=y
9+
CONFIG_SOF_BOOT_TEST_STANDALONE=y
810

911
# Ensure the kernel can exit QEMU on shutdown/panic
1012
CONFIG_REBOOT=y

app/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ CONFIG_SCHED_CPU_MASK=y
5050
CONFIG_SYS_CLOCK_TICKS_PER_SEC=15000
5151
CONFIG_DAI=y
5252
CONFIG_HEAP_MEM_POOL_SIZE=2048
53+
CONFIG_SPIN_VALIDATE=n

src/include/ipc4/pipeline.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,4 +453,9 @@ struct ipc4_chain_dma {
453453
} extension;
454454
} __attribute__((packed, aligned(4)));
455455

456+
struct ipc4_message_request;
457+
458+
int ipc4_new_pipeline(struct ipc4_message_request *ipc4);
459+
int ipc4_delete_pipeline(struct ipc4_message_request *ipc4);
460+
456461
#endif

src/ipc/ipc4/handler.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static inline const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data(
127127
/*
128128
* Global IPC Operations.
129129
*/
130-
__cold static int ipc4_new_pipeline(struct ipc4_message_request *ipc4)
130+
__cold int ipc4_new_pipeline(struct ipc4_message_request *ipc4)
131131
{
132132
struct ipc *ipc = ipc_get();
133133

@@ -136,7 +136,7 @@ __cold static int ipc4_new_pipeline(struct ipc4_message_request *ipc4)
136136
return ipc_pipeline_new(ipc, (ipc_pipe_new *)ipc4);
137137
}
138138

139-
__cold static int ipc4_delete_pipeline(struct ipc4_message_request *ipc4)
139+
__cold int ipc4_delete_pipeline(struct ipc4_message_request *ipc4)
140140
{
141141
struct ipc4_pipeline_delete *pipe;
142142
struct ipc *ipc = ipc_get();

src/platform/qemu_xtensa/platform.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//
55
#include <sof/lib/mailbox.h>
66
#include <sof/ipc/common.h>
7+
#include <sof/ipc/driver.h>
78
#include <rtos/sof.h>
89

910
void ipc_platform_complete_cmd(struct ipc *ipc)
@@ -16,6 +17,17 @@ int platform_boot_complete(uint32_t boot_message)
1617
}
1718

1819
int platform_init(struct sof *sof)
20+
{
21+
ipc_init(sof);
22+
return 0;
23+
}
24+
25+
int platform_ipc_init(struct ipc *ipc)
26+
{
27+
return 0;
28+
}
29+
30+
int ipc_platform_send_msg(const struct ipc_msg *msg)
1931
{
2032
return 0;
2133
}

src/schedule/zephyr_ll_user.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ static struct k_heap *zephyr_ll_heap_init(void)
4242
k_panic();
4343
}
4444

45+
uintptr_t cached_ptr = (uintptr_t)sys_cache_cached_ptr_get(heap->heap.init_mem);
46+
uintptr_t uncached_ptr = (uintptr_t)sys_cache_uncached_ptr_get(heap->heap.init_mem);
47+
4548
/* Create memory partition for sch_data array */
46-
mem_partition.start = (uintptr_t)sys_cache_cached_ptr_get(heap->heap.init_mem);
49+
mem_partition.start = cached_ptr;
4750
mem_partition.size = heap->heap.init_bytes;
4851
mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB;
4952

@@ -53,13 +56,15 @@ static struct k_heap *zephyr_ll_heap_init(void)
5356
if (ret)
5457
k_panic();
5558

56-
mem_partition.start = (uintptr_t)sys_cache_uncached_ptr_get(heap->heap.init_mem);
57-
mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW;
58-
ret = k_mem_domain_add_partition(&ll_mem_resources.mem_domain, &mem_partition);
59-
tr_dbg(&ll_tr, "init ll heap %p, size %u (uncached), ret %d",
60-
(void *)mem_partition.start, heap->heap.init_bytes, ret);
61-
if (ret)
62-
k_panic();
59+
if (cached_ptr != uncached_ptr) {
60+
mem_partition.start = uncached_ptr;
61+
mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW;
62+
ret = k_mem_domain_add_partition(&ll_mem_resources.mem_domain, &mem_partition);
63+
tr_dbg(&ll_tr, "init ll heap %p, size %u (uncached), ret %d",
64+
(void *)mem_partition.start, heap->heap.init_bytes, ret);
65+
if (ret)
66+
k_panic();
67+
}
6368

6469
return heap;
6570
}

zephyr/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ endif()
2222

2323
if(CONFIG_SOF_BOOT_TEST_STANDALONE AND CONFIG_SOF_USERSPACE_LL)
2424
zephyr_library_sources(userspace/test_ll_task.c)
25+
zephyr_library_sources(userspace/test_ipc4_pipeline.c)
2526
endif()
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/*
3+
* Copyright(c) 2026 Intel Corporation.
4+
*/
5+
6+
/*
7+
* Test case for creation and destruction of IPC4 pipelines.
8+
*/
9+
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/ztest.h>
12+
#include <zephyr/logging/log.h>
13+
#include <sof/ipc/topology.h>
14+
#include <ipc4/pipeline.h>
15+
#include <sof/ipc/msg.h>
16+
#include <rtos/alloc.h>
17+
#include <rtos/sof.h>
18+
19+
LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG);
20+
21+
ZTEST(userspace_ipc4_pipeline, test_pipeline_create_destroy_helpers)
22+
{
23+
struct ipc *ipc = ipc_get();
24+
struct ipc4_pipeline_create msg = { 0 };
25+
struct ipc_comp_dev *ipc_pipe;
26+
int ret;
27+
28+
LOG_INF("Starting IPC4 pipeline test (helpers)");
29+
30+
/* 1. Setup msg */
31+
msg.primary.r.instance_id = 1;
32+
msg.primary.r.ppl_priority = SOF_IPC4_PIPELINE_PRIORITY_0;
33+
msg.primary.r.ppl_mem_size = 1;
34+
msg.primary.r.type = SOF_IPC4_GLB_CREATE_PIPELINE;
35+
msg.extension.r.core_id = 0;
36+
37+
/* 2. Create pipeline */
38+
ret = ipc_pipeline_new(ipc, (ipc_pipe_new *)&msg);
39+
zassert_equal(ret, 0, "ipc_pipeline_new failed with %d", ret);
40+
41+
/* 3. Validate pipeline exists */
42+
ipc_pipe = ipc_get_pipeline_by_id(ipc, 1);
43+
zassert_not_null(ipc_pipe, "pipeline 1 not found after creation");
44+
45+
/* 4. Destroy pipeline */
46+
ret = ipc_pipeline_free(ipc, 1);
47+
zassert_equal(ret, 0, "ipc_pipeline_free failed with %d", ret);
48+
49+
/* 5. Validate pipeline is destroyed */
50+
ipc_pipe = ipc_get_pipeline_by_id(ipc, 1);
51+
zassert_is_null(ipc_pipe, "pipeline 1 still exists after destruction");
52+
53+
LOG_INF("IPC4 pipeline test (helpers) complete");
54+
}
55+
56+
ZTEST(userspace_ipc4_pipeline, test_pipeline_create_destroy_handlers)
57+
{
58+
struct ipc *ipc = ipc_get();
59+
struct ipc4_pipeline_create create_msg = { 0 };
60+
struct ipc4_message_request req = { 0 };
61+
struct ipc_comp_dev *ipc_pipe;
62+
int ret;
63+
64+
LOG_INF("Starting IPC4 pipeline test (handlers)");
65+
66+
/* 1. Setup create message */
67+
create_msg.primary.r.instance_id = 2;
68+
create_msg.primary.r.ppl_priority = SOF_IPC4_PIPELINE_PRIORITY_0;
69+
create_msg.primary.r.ppl_mem_size = 1;
70+
create_msg.primary.r.type = SOF_IPC4_GLB_CREATE_PIPELINE;
71+
create_msg.extension.r.core_id = 0;
72+
73+
/* Pack the create message into a generic request */
74+
req.primary.dat = create_msg.primary.dat;
75+
req.extension.dat = create_msg.extension.dat;
76+
77+
/* 2. Create pipeline using handler */
78+
ret = ipc4_new_pipeline(&req);
79+
zassert_equal(ret, 0, "ipc4_new_pipeline failed with %d", ret);
80+
81+
/* 3. Validate pipeline exists */
82+
ipc_pipe = ipc_get_pipeline_by_id(ipc, 2);
83+
zassert_not_null(ipc_pipe, "pipeline 2 not found after creation");
84+
85+
/* 4. Setup delete message */
86+
struct ipc4_pipeline_delete delete_msg = { 0 };
87+
88+
delete_msg.primary.r.instance_id = 2;
89+
delete_msg.primary.r.type = SOF_IPC4_GLB_DELETE_PIPELINE;
90+
91+
/* Pack the delete message into a generic request */
92+
req.primary.dat = delete_msg.primary.dat;
93+
req.extension.dat = delete_msg.extension.dat;
94+
95+
/* Destroy pipeline using handler */
96+
ret = ipc4_delete_pipeline(&req);
97+
zassert_equal(ret, 0, "ipc4_delete_pipeline failed with %d", ret);
98+
99+
/* 5. Validate pipeline is destroyed */
100+
ipc_pipe = ipc_get_pipeline_by_id(ipc, 2);
101+
zassert_is_null(ipc_pipe, "pipeline 2 still exists after destruction");
102+
103+
LOG_INF("IPC4 pipeline test (handlers) complete");
104+
}
105+
106+
static void *ipc4_pipeline_setup(void)
107+
{
108+
struct sof *sof = sof_get();
109+
110+
/* SOF_BOOT_TEST_STANDALONE skips IPC init. We must allocate it manually for testing. */
111+
if (!sof->ipc) {
112+
sof->ipc = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*sof->ipc));
113+
sof->ipc->comp_data = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT,
114+
SOF_IPC_MSG_MAX_SIZE);
115+
k_spinlock_init(&sof->ipc->lock);
116+
list_init(&sof->ipc->msg_list);
117+
list_init(&sof->ipc->comp_list);
118+
}
119+
120+
return NULL;
121+
}
122+
123+
ZTEST_SUITE(userspace_ipc4_pipeline, NULL, ipc4_pipeline_setup, NULL, NULL, NULL);
124+
125+

zephyr/test/userspace/test_ll_task.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ static void ll_task_test(void)
5959
task = zephyr_ll_task_alloc();
6060
zassert_not_null(task, "task allocation failed");
6161

62-
/* allow user space to report status via 'test_runs' */
63-
k_mem_domain_add_partition(zephyr_ll_mem_domain(), &userspace_ll_part);
64-
6562
/* work in progress, see pipeline-schedule.c */
6663
ret = schedule_task_init_ll(task, SOF_UUID(test_task_uuid), SOF_SCHEDULE_LL_TIMER,
6764
priority, task_callback,
@@ -92,7 +89,11 @@ static void ll_task_test(void)
9289

9390
ZTEST(userspace_ll, ll_task_test)
9491
{
92+
#ifndef CONFIG_QEMU_TARGET
9593
ll_task_test();
94+
#else
95+
ztest_test_skip();
96+
#endif
9697
}
9798

9899
static void pipeline_check(void)
@@ -131,14 +132,4 @@ ZTEST(userspace_ll, pipeline_check)
131132

132133
ZTEST_SUITE(userspace_ll, NULL, NULL, NULL, NULL, NULL);
133134

134-
/**
135-
* SOF main has booted up and IPC handling is stopped.
136-
* Run test suites with ztest_run_all.
137-
*/
138-
static int run_tests(void)
139-
{
140-
ztest_run_test_suite(userspace_ll, false, 1, 1, NULL);
141-
return 0;
142-
}
143135

144-
SYS_INIT(run_tests, APPLICATION, 99);

zephyr/test/userspace/test_mailbox.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,25 +79,19 @@ static void mailbox_test(void)
7979

8080
ZTEST(userspace_mailbox, mailbox_test)
8181
{
82+
#ifndef CONFIG_QEMU_TARGET
8283
/* first test from kernel */
8384
mailbox_write_to_pipeline_regs();
8485

8586
/* then full test in userspace */
8687
mailbox_test();
8788

8889
ztest_test_pass();
90+
#else
91+
ztest_test_skip();
92+
#endif
8993
}
9094

9195
ZTEST_SUITE(userspace_mailbox, NULL, NULL, NULL, NULL, NULL);
9296

93-
/**
94-
* SOF main has booted up and IPC handling is stopped.
95-
* Run test suites with ztest_run_all.
96-
*/
97-
static int run_tests(void)
98-
{
99-
ztest_run_test_suite(userspace_mailbox, false, 1, 1, NULL);
100-
return 0;
101-
}
10297

103-
SYS_INIT(run_tests, APPLICATION, 99);

0 commit comments

Comments
 (0)