Skip to content

Commit d9ba1bc

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 efdd322 commit d9ba1bc

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

src/ipc/ipc4/handler-user.c

Lines changed: 149 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:
@@ -775,6 +791,7 @@ __cold static int ipc4_init_module_instance(struct ipc4_message_request *ipc4)
775791
return 0;
776792
}
777793

794+
#ifndef CONFIG_SOF_USERSPACE_LL
778795
__cold static int ipc4_bind_module_instance(struct ipc4_message_request *ipc4)
779796
{
780797
struct ipc4_module_bind_unbind bu;
@@ -812,6 +829,7 @@ __cold static int ipc4_unbind_module_instance(struct ipc4_message_request *ipc4)
812829

813830
return ipc_comp_disconnect(ipc, (ipc_pipe_comp_connect *)&bu);
814831
}
832+
#endif /* !CONFIG_SOF_USERSPACE_LL */
815833

816834
/**
817835
* @brief Process MOD_CONFIG_GET or MOD_CONFIG_SET in any execution context.
@@ -884,6 +902,7 @@ __cold int ipc4_process_module_config(struct ipc4_message_request *ipc4,
884902
return ret;
885903
}
886904

905+
#ifndef CONFIG_SOF_USERSPACE_LL
887906
static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4, bool set)
888907
{
889908
uint32_t reply_ext;
@@ -896,6 +915,7 @@ static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4
896915

897916
return ret;
898917
}
918+
#endif /* !CONFIG_SOF_USERSPACE_LL */
899919

900920
__cold static void ipc4_prepare_for_kcontrol_get(struct comp_dev *dev, uint8_t param_id,
901921
char *data_out, uint32_t data_size)
@@ -1462,6 +1482,7 @@ __cold static int ipc4_set_large_config_module_instance(struct ipc4_message_requ
14621482
return ret;
14631483
}
14641484

1485+
#ifndef CONFIG_SOF_USERSPACE_LL
14651486
__cold static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4)
14661487
{
14671488
struct ipc4_module_delete_instance module;
@@ -1489,6 +1510,7 @@ __cold static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4)
14891510

14901511
return ret;
14911512
}
1513+
#endif /* !CONFIG_SOF_USERSPACE_LL */
14921514

14931515
__cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4,
14941516
struct ipc_msg *reply)
@@ -1503,28 +1525,155 @@ __cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4,
15031525

15041526
switch (type) {
15051527
case SOF_IPC4_MOD_INIT_INSTANCE:
1528+
#ifdef CONFIG_SOF_USERSPACE_LL
1529+
{
1530+
/* User-space init: kernel does driver lookup only (requires
1531+
* access to IMR manifest and driver list in kernel memory).
1532+
* Component creation (drv->ops.create) runs in user thread
1533+
* so untrusted module code does not execute in kernel context.
1534+
* Cross-core creation stays fully in kernel.
1535+
*/
1536+
struct ipc4_module_init_instance mi;
1537+
1538+
BUILD_ASSERT(sizeof(struct comp_driver) + sizeof(struct tr_ctx) <=
1539+
sizeof(((struct ipc_user *)0)->init_drv_data),
1540+
"ipc_user.init_drv_data too small for driver copy");
1541+
1542+
ret = memcpy_s(&mi, sizeof(mi), ipc4, sizeof(*ipc4));
1543+
if (ret < 0)
1544+
break;
1545+
1546+
if (!cpu_is_me(mi.extension.r.core_id)) {
1547+
ret = ipc4_init_module_instance(ipc4);
1548+
} else {
1549+
struct ipc *ipc = ipc_get();
1550+
uint32_t comp_id = IPC4_COMP_ID(mi.primary.r.module_id,
1551+
mi.primary.r.instance_id);
1552+
const struct comp_driver *drv = ipc4_get_comp_drv(
1553+
IPC4_MOD_ID(comp_id));
1554+
struct ipc_user *pdata = ipc->ipc_user_pdata;
1555+
1556+
if (!drv) {
1557+
ret = IPC4_MOD_NOT_INITIALIZED;
1558+
break;
1559+
}
1560+
1561+
/* Copy comp_driver and tr_ctx into user-accessible ipc_user buffer
1562+
* originals are in kernel .rodata/.data and not readable from user mode.
1563+
*/
1564+
struct comp_driver *drv_copy = (struct comp_driver *)pdata->init_drv_data;
1565+
struct tr_ctx *tctx_copy =
1566+
(struct tr_ctx *)(pdata->init_drv_data +
1567+
sizeof(struct comp_driver));
1568+
1569+
ret = memcpy_s(drv_copy, sizeof(*drv_copy), drv, sizeof(*drv));
1570+
if (!ret && drv->tctx) {
1571+
ret = memcpy_s(tctx_copy, sizeof(*tctx_copy),
1572+
drv->tctx, sizeof(*drv->tctx));
1573+
drv_copy->tctx = tctx_copy;
1574+
}
1575+
1576+
if (ret < 0)
1577+
break;
1578+
1579+
pdata->init_drv = drv;
1580+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1581+
}
1582+
}
1583+
#else
15061584
ret = ipc4_init_module_instance(ipc4);
1585+
#endif
15071586
break;
15081587
case SOF_IPC4_MOD_CONFIG_GET:
1588+
#ifdef CONFIG_SOF_USERSPACE_LL
1589+
/* Forward to user thread for privilege-separated execution */
1590+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1591+
if (!ret) {
1592+
struct ipc *ipc = ipc_get();
1593+
struct ipc_user *pdata = ipc->ipc_user_pdata;
1594+
1595+
msg_reply->extension = pdata->reply_ext;
1596+
}
1597+
#else
15091598
ret = ipc4_set_get_config_module_instance(ipc4, false);
1599+
#endif
15101600
break;
15111601
case SOF_IPC4_MOD_CONFIG_SET:
1602+
#ifdef CONFIG_SOF_USERSPACE_LL
1603+
/* Forward to user thread for privilege-separated execution */
1604+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1605+
#else
15121606
ret = ipc4_set_get_config_module_instance(ipc4, true);
1607+
#endif
15131608
break;
15141609
case SOF_IPC4_MOD_LARGE_CONFIG_GET:
1610+
#ifdef CONFIG_SOF_USERSPACE_LL
1611+
{
1612+
struct ipc4_module_large_config config;
1613+
1614+
memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4));
1615+
if (config.primary.r.module_id) {
1616+
/* Module case: forward to user thread */
1617+
ret = ipc_user_forward_cmd(ipc4->primary.dat,
1618+
ipc4->extension.dat);
1619+
if (!ret) {
1620+
struct ipc *ipc = ipc_get();
1621+
struct ipc_user *pdata = ipc->ipc_user_pdata;
1622+
1623+
msg_reply->extension = pdata->reply_ext;
1624+
msg_reply->tx_size = pdata->reply_tx_size;
1625+
msg_reply->tx_data = pdata->reply_tx_data;
1626+
}
1627+
} else {
1628+
/* Base firmware (module_id==0): keep in kernel —
1629+
* ipc4_get_comp_drv() accesses IMR manifest which
1630+
* has no user-space partition.
1631+
*/
1632+
ret = ipc4_get_large_config_module_instance(ipc4);
1633+
}
1634+
}
1635+
#else
15151636
ret = ipc4_get_large_config_module_instance(ipc4);
1637+
#endif
15161638
break;
15171639
case SOF_IPC4_MOD_LARGE_CONFIG_SET:
1640+
#ifdef CONFIG_SOF_USERSPACE_LL
1641+
{
1642+
struct ipc4_module_large_config config;
1643+
1644+
memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4));
1645+
if (config.primary.r.module_id) {
1646+
ret = ipc_user_forward_cmd(ipc4->primary.dat,
1647+
ipc4->extension.dat);
1648+
} else {
1649+
/* Base firmware: keep in kernel (IMR access) */
1650+
ret = ipc4_set_large_config_module_instance(ipc4);
1651+
}
1652+
}
1653+
#else
15181654
ret = ipc4_set_large_config_module_instance(ipc4);
1655+
#endif
15191656
break;
15201657
case SOF_IPC4_MOD_BIND:
1658+
#ifdef CONFIG_SOF_USERSPACE_LL
1659+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1660+
#else
15211661
ret = ipc4_bind_module_instance(ipc4);
1662+
#endif
15221663
break;
15231664
case SOF_IPC4_MOD_UNBIND:
1665+
#ifdef CONFIG_SOF_USERSPACE_LL
1666+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1667+
#else
15241668
ret = ipc4_unbind_module_instance(ipc4);
1669+
#endif
15251670
break;
15261671
case SOF_IPC4_MOD_DELETE_INSTANCE:
1672+
#ifdef CONFIG_SOF_USERSPACE_LL
1673+
ret = ipc_user_forward_cmd(ipc4->primary.dat, ipc4->extension.dat);
1674+
#else
15271675
ret = ipc4_delete_module_instance(ipc4);
1676+
#endif
15281677
break;
15291678
case SOF_IPC4_MOD_ENTER_MODULE_RESTORE:
15301679
case SOF_IPC4_MOD_EXIT_MODULE_RESTORE:

0 commit comments

Comments
 (0)