Skip to content

Commit 776cbe8

Browse files
committed
ipc4: forward pipeline and module commands to the user thread
Route the IPC4 commands that operate on audio pipelines to the user-space IPC thread via ipc_user_forward_cmd() when CONFIG_SOF_USERSPACE_LL is enabled: create/delete/set-state pipeline, config get/set, large-config get/set, bind/unbind and init/delete instance. For MOD_INIT_INSTANCE the kernel still resolves the driver (needs IMR manifest access) and copies comp_driver + tr_ctx into the user-readable ipc_user buffer before forwarding; cross-core creation stays in kernel. LARGE_CONFIG get/set for base firmware (module_id 0) also stay in kernel because they touch the IMR manifest. CONFIG_GET / LARGE_CONFIG_GET copy the reply extension (and tx payload) back from the user thread. The now-unused ipc4_new_pipeline()/ipc4_delete_pipeline() kernel helpers are compiled out in the user-space configuration. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 81db0de commit 776cbe8

1 file changed

Lines changed: 142 additions & 0 deletions

File tree

src/ipc/ipc4/handler-user.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ static inline const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data(
9090
/*
9191
* Global IPC Operations.
9292
*/
93+
#ifndef CONFIG_SOF_USERSPACE_LL
9394
__cold static int ipc4_new_pipeline(struct ipc4_message_request *ipc4)
9495
{
9596
struct ipc *ipc = ipc_get();
@@ -98,7 +99,9 @@ __cold static int ipc4_new_pipeline(struct ipc4_message_request *ipc4)
9899

99100
return ipc_pipeline_new(ipc, (ipc_pipe_new *)ipc4);
100101
}
102+
#endif
101103

104+
#ifndef CONFIG_SOF_USERSPACE_LL
102105
__cold static int ipc4_delete_pipeline(struct ipc4_message_request *ipc4)
103106
{
104107
struct ipc4_pipeline_delete *pipe;
@@ -111,6 +114,7 @@ __cold static int ipc4_delete_pipeline(struct ipc4_message_request *ipc4)
111114

112115
return ipc_pipeline_free(ipc, pipe->primary.r.instance_id);
113116
}
117+
#endif
114118

115119
static int ipc4_pcm_params(struct ipc_comp_dev *pcm_dev)
116120
{
@@ -689,13 +693,25 @@ int ipc4_user_process_glb_message(struct ipc4_message_request *ipc4,
689693

690694
/* pipeline settings */
691695
case SOF_IPC4_GLB_CREATE_PIPELINE:
696+
#ifdef CONFIG_SOF_USERSPACE_LL
697+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
698+
#else
692699
ret = ipc4_new_pipeline(ipc4);
700+
#endif
693701
break;
694702
case SOF_IPC4_GLB_DELETE_PIPELINE:
703+
#ifdef CONFIG_SOF_USERSPACE_LL
704+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
705+
#else
695706
ret = ipc4_delete_pipeline(ipc4);
707+
#endif
696708
break;
697709
case SOF_IPC4_GLB_SET_PIPELINE_STATE:
710+
#ifdef CONFIG_SOF_USERSPACE_LL
711+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
712+
#else
698713
ret = ipc4_set_pipeline_state(ipc4);
714+
#endif
699715
break;
700716

701717
case SOF_IPC4_GLB_GET_PIPELINE_STATE:
@@ -1503,28 +1519,154 @@ __cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4,
15031519

15041520
switch (type) {
15051521
case SOF_IPC4_MOD_INIT_INSTANCE:
1522+
#ifdef CONFIG_SOF_USERSPACE_LL
1523+
{
1524+
/* User-space init: kernel does driver lookup only (requires
1525+
* access to IMR manifest and driver list in kernel memory).
1526+
* Component creation (drv->ops.create) runs in user thread
1527+
* so untrusted module code does not execute in kernel context.
1528+
* Cross-core creation stays fully in kernel.
1529+
*/
1530+
struct ipc4_module_init_instance mi;
1531+
1532+
BUILD_ASSERT(sizeof(struct comp_driver) + sizeof(struct tr_ctx) <=
1533+
sizeof(((struct ipc_user *)0)->init_drv_data),
1534+
"ipc_user.init_drv_data too small for driver copy");
1535+
1536+
memcpy_s(&mi, sizeof(mi), ipc4, sizeof(*ipc4));
1537+
if (!cpu_is_me(mi.extension.r.core_id)) {
1538+
ret = ipc4_init_module_instance(ipc4);
1539+
} else {
1540+
struct ipc *ipc = ipc_get();
1541+
uint32_t comp_id = IPC4_COMP_ID(mi.primary.r.module_id,
1542+
mi.primary.r.instance_id);
1543+
const struct comp_driver *drv = ipc4_get_comp_drv(
1544+
IPC4_MOD_ID(comp_id));
1545+
1546+
if (!drv) {
1547+
ret = IPC4_MOD_NOT_INITIALIZED;
1548+
} else {
1549+
struct ipc_user *pdata = ipc->ipc_user_pdata;
1550+
1551+
/* Copy comp_driver and tr_ctx into
1552+
* user-accessible ipc_user buffer —
1553+
* originals are in kernel .rodata/.data
1554+
* and not readable from user mode.
1555+
*/
1556+
struct comp_driver *drv_copy =
1557+
(struct comp_driver *)pdata->init_drv_data;
1558+
struct tr_ctx *tctx_copy =
1559+
(struct tr_ctx *)(pdata->init_drv_data +
1560+
sizeof(struct comp_driver));
1561+
1562+
memcpy_s(drv_copy, sizeof(*drv_copy),
1563+
drv, sizeof(*drv));
1564+
if (drv->tctx) {
1565+
memcpy_s(tctx_copy, sizeof(*tctx_copy),
1566+
drv->tctx, sizeof(*drv->tctx));
1567+
drv_copy->tctx = tctx_copy;
1568+
}
1569+
1570+
pdata->init_drv = drv;
1571+
ret = ipc_user_forward_cmd(ipc4->primary.dat,
1572+
ipc4->extension.dat);
1573+
}
1574+
}
1575+
}
1576+
#else
15061577
ret = ipc4_init_module_instance(ipc4);
1578+
#endif
15071579
break;
15081580
case SOF_IPC4_MOD_CONFIG_GET:
1581+
#ifdef CONFIG_SOF_USERSPACE_LL
1582+
/* Forward to user thread for privilege-separated execution */
1583+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1584+
if (!ret) {
1585+
struct ipc *ipc = ipc_get();
1586+
struct ipc_user *pdata = ipc->ipc_user_pdata;
1587+
1588+
msg_reply->extension = pdata->reply_ext;
1589+
}
1590+
#else
15091591
ret = ipc4_set_get_config_module_instance(ipc4, false);
1592+
#endif
15101593
break;
15111594
case SOF_IPC4_MOD_CONFIG_SET:
1595+
#ifdef CONFIG_SOF_USERSPACE_LL
1596+
/* Forward to user thread for privilege-separated execution */
1597+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1598+
#else
15121599
ret = ipc4_set_get_config_module_instance(ipc4, true);
1600+
#endif
15131601
break;
15141602
case SOF_IPC4_MOD_LARGE_CONFIG_GET:
1603+
#ifdef CONFIG_SOF_USERSPACE_LL
1604+
{
1605+
struct ipc4_module_large_config config;
1606+
1607+
memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4));
1608+
if (config.primary.r.module_id) {
1609+
/* Module case: forward to user thread */
1610+
ret = ipc_user_forward_cmd(ipc4->primary.dat,
1611+
ipc4->extension.dat);
1612+
if (!ret) {
1613+
struct ipc *ipc = ipc_get();
1614+
struct ipc_user *pdata = ipc->ipc_user_pdata;
1615+
1616+
msg_reply->extension = pdata->reply_ext;
1617+
msg_reply->tx_size = pdata->reply_tx_size;
1618+
msg_reply->tx_data = pdata->reply_tx_data;
1619+
}
1620+
} else {
1621+
/* Base firmware (module_id==0): keep in kernel —
1622+
* ipc4_get_comp_drv() accesses IMR manifest which
1623+
* has no user-space partition.
1624+
*/
1625+
ret = ipc4_get_large_config_module_instance(ipc4);
1626+
}
1627+
}
1628+
#else
15151629
ret = ipc4_get_large_config_module_instance(ipc4);
1630+
#endif
15161631
break;
15171632
case SOF_IPC4_MOD_LARGE_CONFIG_SET:
1633+
#ifdef CONFIG_SOF_USERSPACE_LL
1634+
{
1635+
struct ipc4_module_large_config config;
1636+
1637+
memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4));
1638+
if (config.primary.r.module_id) {
1639+
ret = ipc_user_forward_cmd(ipc4->primary.dat,
1640+
ipc4->extension.dat);
1641+
} else {
1642+
/* Base firmware: keep in kernel (IMR access) */
1643+
ret = ipc4_set_large_config_module_instance(ipc4);
1644+
}
1645+
}
1646+
#else
15181647
ret = ipc4_set_large_config_module_instance(ipc4);
1648+
#endif
15191649
break;
15201650
case SOF_IPC4_MOD_BIND:
1651+
#ifdef CONFIG_SOF_USERSPACE_LL
1652+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1653+
#else
15211654
ret = ipc4_bind_module_instance(ipc4);
1655+
#endif
15221656
break;
15231657
case SOF_IPC4_MOD_UNBIND:
1658+
#ifdef CONFIG_SOF_USERSPACE_LL
1659+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1660+
#else
15241661
ret = ipc4_unbind_module_instance(ipc4);
1662+
#endif
15251663
break;
15261664
case SOF_IPC4_MOD_DELETE_INSTANCE:
1665+
#ifdef CONFIG_SOF_USERSPACE_LL
1666+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1667+
#else
15271668
ret = ipc4_delete_module_instance(ipc4);
1669+
#endif
15281670
break;
15291671
case SOF_IPC4_MOD_ENTER_MODULE_RESTORE:
15301672
case SOF_IPC4_MOD_EXIT_MODULE_RESTORE:

0 commit comments

Comments
 (0)