@@ -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
115119static 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
887906static 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