Skip to content

Commit 52198d1

Browse files
committed
ipc: make ipc_msg_reply and compound-message handlers syscalls
The IPC reply and compound-message completion entry points need to be callable from the IPC user-space thread. Declare ipc_msg_reply(), ipc_compound_pre_start(), ipc_compound_post_start() and ipc_wait_for_compound_msg() as Zephyr syscalls when CONFIG_SOF_USERSPACE_LL is enabled, renaming the implementations to z_impl_* and adding z_vrfy_* verification wrappers. A new ipc_reply.h carries the ipc_msg_reply declaration so it can be pulled in as a syscall header. Register the new syscall headers in CMakeLists.txt. No functional change for non-userspace builds, where the functions keep direct external linkage via z_impl_* defines. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Co-developed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent eecf32b commit 52198d1

6 files changed

Lines changed: 144 additions & 22 deletions

File tree

src/include/ipc4/handler.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,41 @@ int ipc4_user_process_glb_message(struct ipc4_message_request *ipc4, struct ipc_
6262
int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4);
6363

6464
/**
65-
* \brief Increment the IPC compound message pre-start counter.
65+
* \brief Complete the IPC compound message.
6666
* @param[in] msg_id IPC message ID.
67+
* @param[in] error Error code of the IPC command.
6768
*/
68-
void ipc_compound_pre_start(int msg_id);
69+
void ipc_compound_msg_done(uint32_t msg_id, int error);
6970

71+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
7072
/**
71-
* \brief Decrement the IPC compound message pre-start counter on return value status.
73+
* \brief Increment the IPC compound message pre-start counter.
7274
* @param[in] msg_id IPC message ID.
73-
* @param[in] ret Return value of the IPC command.
74-
* @param[in] delayed True if the reply is delayed.
7575
*/
76-
void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed);
76+
__syscall void ipc_compound_pre_start(int msg_id);
7777

7878
/**
79-
* \brief Complete the IPC compound message.
79+
* \brief Decrement the IPC compound message pre-start counter on return value status.
8080
* @param[in] msg_id IPC message ID.
81-
* @param[in] error Error code of the IPC command.
81+
* @param[in] ret Return value of the IPC command.
82+
* @param[in] delayed True if the reply is delayed.
8283
*/
83-
void ipc_compound_msg_done(uint32_t msg_id, int error);
84+
__syscall void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed);
8485

8586
/**
8687
* \brief Wait for the IPC compound message to complete.
8788
* @return 0 on success, error code otherwise on timeout.
8889
*/
89-
int ipc_wait_for_compound_msg(void);
90+
__syscall int ipc_wait_for_compound_msg(void);
91+
92+
#include <zephyr/syscalls/handler.h>
93+
#else
94+
void z_impl_ipc_compound_pre_start(int msg_id);
95+
#define ipc_compound_pre_start z_impl_ipc_compound_pre_start
96+
void z_impl_ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed);
97+
#define ipc_compound_post_start z_impl_ipc_compound_post_start
98+
int z_impl_ipc_wait_for_compound_msg(void);
99+
#define ipc_wait_for_compound_msg z_impl_ipc_wait_for_compound_msg
100+
#endif
90101

91102
#endif /* __SOF_IPC4_HANDLER_H__ */

src/include/sof/ipc/common.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
#include <user/trace.h>
1919
#include <ipc/header.h>
2020
#include <ipc/stream.h>
21+
#include <sof/ipc/ipc_reply.h>
2122

2223
#include <stdbool.h>
2324
#include <stdint.h>
2425

2526
struct comp_driver;
2627
struct dma_sg_elem_array;
2728
struct ipc_msg;
29+
struct ipc4_message_request;
2830

2931
/* validates internal non tail structures within IPC command structure */
3032
#define IPC_IS_SIZE_INVALID(object) \
@@ -211,6 +213,29 @@ struct dai_data;
211213
*/
212214
int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev);
213215

216+
/**
217+
* \brief Processes IPC4 userspace module message.
218+
* @param[in] ipc4 IPC4 message request.
219+
* @param[in] reply IPC message reply structure.
220+
* @return IPC4_SUCCESS on success, error code otherwise.
221+
*/
222+
int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, struct ipc_msg *reply);
223+
224+
/**
225+
* \brief Processes IPC4 userspace global message.
226+
* @param[in] ipc4 IPC4 message request.
227+
* @param[in] reply IPC message reply structure.
228+
* @return IPC4_SUCCESS on success, error code otherwise.
229+
*/
230+
int ipc4_user_process_glb_message(struct ipc4_message_request *ipc4, struct ipc_msg *reply);
231+
232+
/**
233+
* \brief Complete the IPC compound message.
234+
* @param[in] msg_id IPC message ID.
235+
* @param[in] error Error code of the IPC command.
236+
*/
237+
void ipc_compound_msg_done(uint32_t msg_id, int error);
238+
214239
/**
215240
* \brief create a IPC boot complete message.
216241
* @param[in] header header.
@@ -281,12 +306,6 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr);
281306
*/
282307
int ipc_process_on_core(uint32_t core, bool blocking);
283308

284-
/**
285-
* \brief reply to an IPC message.
286-
* @param[in] reply pointer to the reply structure.
287-
*/
288-
void ipc_msg_reply(struct sof_ipc_reply *reply);
289-
290309
/**
291310
* \brief Call platform-specific IPC completion function.
292311
*/

src/include/sof/ipc/ipc_reply.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause
2+
*
3+
* Copyright(c) 2026 Intel Corporation. All rights reserved.
4+
*/
5+
6+
#ifndef __SOF_IPC_IPC_REPLY_H__
7+
#define __SOF_IPC_IPC_REPLY_H__
8+
9+
#include <ipc/header.h>
10+
11+
struct sof_ipc_reply;
12+
13+
/**
14+
* \brief reply to an IPC message.
15+
* @param[in] reply pointer to the reply structure.
16+
*/
17+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
18+
__syscall void ipc_msg_reply(struct sof_ipc_reply *reply);
19+
20+
#include <zephyr/syscalls/ipc_reply.h>
21+
#else
22+
void z_impl_ipc_msg_reply(struct sof_ipc_reply *reply);
23+
#define ipc_msg_reply z_impl_ipc_msg_reply
24+
#endif
25+
26+
#endif /* __SOF_IPC_IPC_REPLY_H__ */

src/ipc/ipc3/helper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ int ipc_comp_new(struct ipc *ipc, ipc_comp *_comp)
727727
return 0;
728728
}
729729

730-
void ipc_msg_reply(struct sof_ipc_reply *reply)
730+
void z_impl_ipc_msg_reply(struct sof_ipc_reply *reply)
731731
{
732732
struct ipc *ipc = ipc_get();
733733
k_spinlock_key_t key;

src/ipc/ipc4/handler-kernel.c

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
#include <rtos/string.h>
4141
#include <sof/lib_manager.h>
4242

43+
#ifdef __ZEPHYR__
44+
#include <zephyr/kernel.h>
45+
#include <zephyr/internal/syscall_handler.h>
46+
#endif
47+
4348
#include <errno.h>
4449
#include <stdbool.h>
4550
#include <stddef.h>
@@ -128,15 +133,31 @@ __cold static bool is_any_ppl_active(void)
128133
return false;
129134
}
130135

131-
void ipc_compound_pre_start(int msg_id)
136+
void z_impl_ipc_compound_pre_start(int msg_id)
132137
{
133138
/* ipc thread will wait for all scheduled tasks to be complete
134139
* Use a reference count to check status of these tasks.
135140
*/
136141
atomic_add(&msg_data.delayed_reply, 1);
137142
}
138143

139-
void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed)
144+
#ifdef CONFIG_USERSPACE
145+
/**
146+
* \brief Userspace verification wrapper for ipc_compound_pre_start().
147+
*
148+
* Forwards the call to z_impl_ipc_compound_pre_start(). No pointer
149+
* validation is needed as only primitive types are passed.
150+
*
151+
* @param[in] msg_id IPC message ID.
152+
*/
153+
void z_vrfy_ipc_compound_pre_start(int msg_id)
154+
{
155+
z_impl_ipc_compound_pre_start(msg_id);
156+
}
157+
#include <zephyr/syscalls/ipc_compound_pre_start_mrsh.c>
158+
#endif
159+
160+
void z_impl_ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed)
140161
{
141162
if (ret) {
142163
ipc_cmd_err(&ipc_tr, "failed to process msg %d status %d", msg_id, ret);
@@ -149,6 +170,24 @@ void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed)
149170
atomic_sub(&msg_data.delayed_reply, 1);
150171
}
151172

173+
#ifdef CONFIG_USERSPACE
174+
/**
175+
* \brief Userspace verification wrapper for ipc_compound_post_start().
176+
*
177+
* Forwards the call to z_impl_ipc_compound_post_start(). No pointer
178+
* validation is needed as only primitive types are passed.
179+
*
180+
* @param[in] msg_id IPC message ID.
181+
* @param[in] ret Return value of the IPC command.
182+
* @param[in] delayed True if the reply is delayed.
183+
*/
184+
void z_vrfy_ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed)
185+
{
186+
z_impl_ipc_compound_post_start(msg_id, ret, delayed);
187+
}
188+
#include <zephyr/syscalls/ipc_compound_post_start_mrsh.c>
189+
#endif
190+
152191
void ipc_compound_msg_done(uint32_t msg_id, int error)
153192
{
154193
if (!atomic_read(&msg_data.delayed_reply)) {
@@ -170,13 +209,13 @@ void ipc_compound_msg_done(uint32_t msg_id, int error)
170209
* be always IPC4_FAILURE. Therefore the compound messages handling is simplified. The pipeline
171210
* triggers will require an explicit scheduler call to get the components to desired state.
172211
*/
173-
int ipc_wait_for_compound_msg(void)
212+
int z_impl_ipc_wait_for_compound_msg(void)
174213
{
175214
atomic_set(&msg_data.delayed_reply, 0);
176215
return IPC4_SUCCESS;
177216
}
178217
#else
179-
int ipc_wait_for_compound_msg(void)
218+
int z_impl_ipc_wait_for_compound_msg(void)
180219
{
181220
int try_count = 30;
182221

@@ -192,6 +231,22 @@ int ipc_wait_for_compound_msg(void)
192231

193232
return IPC4_SUCCESS;
194233
}
234+
235+
#ifdef CONFIG_USERSPACE
236+
/**
237+
* \brief Userspace verification wrapper for ipc_wait_for_compound_msg().
238+
*
239+
* Forwards the call to z_impl_ipc_wait_for_compound_msg(). No pointer
240+
* validation is needed as no pointers are passed.
241+
*
242+
* @return IPC4_SUCCESS on success, IPC4_FAILURE on timeout.
243+
*/
244+
int z_vrfy_ipc_wait_for_compound_msg(void)
245+
{
246+
return z_impl_ipc_wait_for_compound_msg();
247+
}
248+
#include <zephyr/syscalls/ipc_wait_for_compound_msg_mrsh.c>
249+
#endif
195250
#endif
196251

197252
#if CONFIG_LIBRARY_MANAGER
@@ -509,14 +564,23 @@ void ipc_send_buffer_status_notify(void)
509564
}
510565
#endif
511566

512-
void ipc_msg_reply(struct sof_ipc_reply *reply)
567+
void z_impl_ipc_msg_reply(struct sof_ipc_reply *reply)
513568
{
514569
struct ipc4_message_request in;
515570

516571
in.primary.dat = msg_data.msg_in.pri;
517572
ipc_compound_msg_done(in.primary.r.type, reply->error);
518573
}
519574

575+
#ifdef CONFIG_USERSPACE
576+
void z_vrfy_ipc_msg_reply(struct sof_ipc_reply *reply)
577+
{
578+
K_OOPS(K_SYSCALL_MEMORY_READ(reply, sizeof(*reply)));
579+
z_impl_ipc_msg_reply(reply);
580+
}
581+
#include <zephyr/syscalls/ipc_msg_reply_mrsh.c>
582+
#endif
583+
520584
void ipc_cmd(struct ipc_cmd_hdr *_hdr)
521585
{
522586
struct ipc4_message_request *in = ipc4_get_message_request();

zephyr/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ zephyr_library_sources_ifdef(CONFIG_SHELL
622622

623623
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/audio/module_adapter/module/generic.h)
624624
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/fast-get.h)
625+
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/ipc/ipc_reply.h)
626+
zephyr_syscall_header(${SOF_SRC_PATH}/include/ipc4/handler.h)
625627
zephyr_syscall_header(include/rtos/alloc.h)
626628
zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_INTERFACE_ALLOC syscall/alloc.c)
627629
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/dai-zephyr.h)

0 commit comments

Comments
 (0)