@@ -1537,3 +1537,142 @@ __cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4,
15371537
15381538 return ret ;
15391539}
1540+
1541+ #ifdef CONFIG_SOF_USERSPACE_LL
1542+ /*
1543+ * IPC4 implementation of the user-thread dispatch hook. Runs in the
1544+ * user-space IPC thread; reconstructs the IPC4 message from the forwarded
1545+ * words and executes the privilege-separated part of each command.
1546+ */
1547+ int ipc_user_thread_dispatch (struct ipc_user * ipc_user )
1548+ {
1549+ struct ipc4_message_request msg ;
1550+ int result = - EINVAL ;
1551+
1552+ /* Reconstruct the IPC4 message from copied words */
1553+ msg .primary .dat = ipc_user -> ipc_msg_pri ;
1554+ msg .extension .dat = ipc_user -> ipc_msg_ext ;
1555+
1556+ ipc_user -> reply_ext = 0 ;
1557+
1558+ if (msg .primary .r .msg_tgt == SOF_IPC4_MESSAGE_TARGET_MODULE_MSG ) {
1559+ /* Module message dispatch */
1560+ switch (msg .primary .r .type ) {
1561+ case SOF_IPC4_MOD_CONFIG_GET :
1562+ result = ipc4_process_module_config (& msg , false,
1563+ & ipc_user -> reply_ext );
1564+ break ;
1565+ case SOF_IPC4_MOD_CONFIG_SET :
1566+ result = ipc4_process_module_config (& msg , true, NULL );
1567+ break ;
1568+ case SOF_IPC4_MOD_BIND : {
1569+ struct ipc4_module_bind_unbind bu ;
1570+
1571+ memcpy_s (& bu , sizeof (bu ), & msg , sizeof (msg ));
1572+ result = ipc_comp_connect (ipc_user -> ipc ,
1573+ (ipc_pipe_comp_connect * )& bu );
1574+ break ;
1575+ }
1576+ case SOF_IPC4_MOD_UNBIND : {
1577+ struct ipc4_module_bind_unbind bu ;
1578+
1579+ memcpy_s (& bu , sizeof (bu ), & msg , sizeof (msg ));
1580+ result = ipc_comp_disconnect (ipc_user -> ipc ,
1581+ (ipc_pipe_comp_connect * )& bu );
1582+ break ;
1583+ }
1584+ case SOF_IPC4_MOD_INIT_INSTANCE : {
1585+ /* User thread creates the component —
1586+ * drv->ops.create() runs in user-space so untrusted
1587+ * module code does not execute with kernel privileges.
1588+ *
1589+ * init_drv = original kernel pointer
1590+ * init_drv_data = user-accessible copy
1591+ */
1592+ const struct comp_driver * orig_drv = ipc_user -> init_drv ;
1593+ const struct comp_driver * drv_copy =
1594+ (const struct comp_driver * )ipc_user -> init_drv_data ;
1595+ struct comp_dev * dev ;
1596+
1597+ ipc_user -> init_drv = NULL ;
1598+ if (!orig_drv ) {
1599+ result = IPC4_MOD_NOT_INITIALIZED ;
1600+ break ;
1601+ }
1602+
1603+ dev = comp_new_ipc4_user (& msg , drv_copy );
1604+ if (!dev ) {
1605+ result = IPC4_MOD_NOT_INITIALIZED ;
1606+ break ;
1607+ }
1608+
1609+ /* Restore original kernel driver pointer. comp_init()
1610+ * set dev->drv to the copy; runtime code expects the
1611+ * canonical kernel address.
1612+ */
1613+ dev -> drv = orig_drv ;
1614+
1615+ result = ipc4_add_comp_dev (dev );
1616+ if (result != IPC4_SUCCESS )
1617+ break ;
1618+
1619+ comp_update_ibs_obs_cpc (dev );
1620+ result = 0 ;
1621+ break ;
1622+ }
1623+ case SOF_IPC4_MOD_DELETE_INSTANCE : {
1624+ struct ipc4_module_delete_instance module ;
1625+ uint32_t comp_id ;
1626+
1627+ memcpy_s (& module , sizeof (module ), & msg , sizeof (msg ));
1628+ comp_id = IPC4_COMP_ID (module .primary .r .module_id ,
1629+ module .primary .r .instance_id );
1630+ result = ipc_comp_free (ipc_user -> ipc , comp_id );
1631+ if (result < 0 )
1632+ result = IPC4_INVALID_RESOURCE_ID ;
1633+ break ;
1634+ }
1635+ case SOF_IPC4_MOD_LARGE_CONFIG_GET :
1636+ result = ipc4_process_large_config_get (& msg ,
1637+ & ipc_user -> reply_ext ,
1638+ & ipc_user -> reply_tx_size ,
1639+ & ipc_user -> reply_tx_data );
1640+ break ;
1641+ case SOF_IPC4_MOD_LARGE_CONFIG_SET :
1642+ result = ipc4_process_large_config_set (& msg );
1643+ break ;
1644+ default :
1645+ LOG_ERR ("IPC user: unsupported module cmd type %d" ,
1646+ msg .primary .r .type );
1647+ result = - EINVAL ;
1648+ break ;
1649+ }
1650+ } else {
1651+ /* Global message dispatch */
1652+ switch (msg .primary .r .type ) {
1653+ case SOF_IPC4_GLB_CREATE_PIPELINE :
1654+ result = ipc_pipeline_new (ipc_user -> ipc ,
1655+ (ipc_pipe_new * )& msg );
1656+ break ;
1657+ case SOF_IPC4_GLB_DELETE_PIPELINE : {
1658+ struct ipc4_pipeline_delete * pipe =
1659+ (struct ipc4_pipeline_delete * )& msg ;
1660+
1661+ result = ipc_pipeline_free (ipc_user -> ipc ,
1662+ pipe -> primary .r .instance_id );
1663+ break ;
1664+ }
1665+ case SOF_IPC4_GLB_SET_PIPELINE_STATE :
1666+ result = ipc4_set_pipeline_state (& msg );
1667+ break ;
1668+ default :
1669+ LOG_ERR ("IPC user: unsupported glb cmd type %d" ,
1670+ msg .primary .r .type );
1671+ result = - EINVAL ;
1672+ break ;
1673+ }
1674+ }
1675+
1676+ return result ;
1677+ }
1678+ #endif /* CONFIG_SOF_USERSPACE_LL */
0 commit comments