@@ -1537,3 +1537,148 @@ __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+ result = memcpy_s (& bu , sizeof (bu ), & msg , sizeof (msg ));
1572+ if (result < 0 )
1573+ break ;
1574+
1575+ result = ipc_comp_connect (ipc_user -> ipc ,
1576+ (ipc_pipe_comp_connect * )& bu );
1577+ break ;
1578+ }
1579+ case SOF_IPC4_MOD_UNBIND : {
1580+ struct ipc4_module_bind_unbind bu ;
1581+
1582+ result = memcpy_s (& bu , sizeof (bu ), & msg , sizeof (msg ));
1583+ if (result < 0 )
1584+ break ;
1585+
1586+ result = ipc_comp_disconnect (ipc_user -> ipc ,
1587+ (ipc_pipe_comp_connect * )& bu );
1588+ break ;
1589+ }
1590+ case SOF_IPC4_MOD_INIT_INSTANCE : {
1591+ /* User thread creates the component —
1592+ * drv->ops.create() runs in user-space so untrusted
1593+ * module code does not execute with kernel privileges.
1594+ *
1595+ * init_drv = original kernel pointer
1596+ * init_drv_data = user-accessible copy
1597+ */
1598+ const struct comp_driver * orig_drv = ipc_user -> init_drv ;
1599+ const struct comp_driver * drv_copy =
1600+ (const struct comp_driver * )ipc_user -> init_drv_data ;
1601+ struct comp_dev * dev ;
1602+
1603+ ipc_user -> init_drv = NULL ;
1604+ if (!orig_drv ) {
1605+ result = IPC4_MOD_NOT_INITIALIZED ;
1606+ break ;
1607+ }
1608+
1609+ dev = comp_new_ipc4_user (& msg , drv_copy );
1610+ if (!dev ) {
1611+ result = IPC4_MOD_NOT_INITIALIZED ;
1612+ break ;
1613+ }
1614+
1615+ /* Restore original kernel driver pointer. comp_init()
1616+ * set dev->drv to the copy; runtime code expects the
1617+ * canonical kernel address.
1618+ */
1619+ dev -> drv = orig_drv ;
1620+
1621+ result = ipc4_add_comp_dev (dev );
1622+ if (result != IPC4_SUCCESS )
1623+ break ;
1624+
1625+ comp_update_ibs_obs_cpc (dev );
1626+ result = 0 ;
1627+ break ;
1628+ }
1629+ case SOF_IPC4_MOD_DELETE_INSTANCE : {
1630+ struct ipc4_module_delete_instance module ;
1631+ uint32_t comp_id ;
1632+
1633+ memcpy_s (& module , sizeof (module ), & msg , sizeof (msg ));
1634+ comp_id = IPC4_COMP_ID (module .primary .r .module_id ,
1635+ module .primary .r .instance_id );
1636+ result = ipc_comp_free (ipc_user -> ipc , comp_id );
1637+ if (result < 0 )
1638+ result = IPC4_INVALID_RESOURCE_ID ;
1639+ break ;
1640+ }
1641+ case SOF_IPC4_MOD_LARGE_CONFIG_GET :
1642+ result = ipc4_process_large_config_get (& msg ,
1643+ & ipc_user -> reply_ext ,
1644+ & ipc_user -> reply_tx_size ,
1645+ & ipc_user -> reply_tx_data );
1646+ break ;
1647+ case SOF_IPC4_MOD_LARGE_CONFIG_SET :
1648+ result = ipc4_process_large_config_set (& msg );
1649+ break ;
1650+ default :
1651+ LOG_ERR ("IPC user: unsupported module cmd type %d" ,
1652+ msg .primary .r .type );
1653+ result = - EINVAL ;
1654+ break ;
1655+ }
1656+ } else {
1657+ /* Global message dispatch */
1658+ switch (msg .primary .r .type ) {
1659+ case SOF_IPC4_GLB_CREATE_PIPELINE :
1660+ result = ipc_pipeline_new (ipc_user -> ipc ,
1661+ (ipc_pipe_new * )& msg );
1662+ break ;
1663+ case SOF_IPC4_GLB_DELETE_PIPELINE : {
1664+ struct ipc4_pipeline_delete * pipe =
1665+ (struct ipc4_pipeline_delete * )& msg ;
1666+
1667+ result = ipc_pipeline_free (ipc_user -> ipc ,
1668+ pipe -> primary .r .instance_id );
1669+ break ;
1670+ }
1671+ case SOF_IPC4_GLB_SET_PIPELINE_STATE :
1672+ result = ipc4_set_pipeline_state (& msg );
1673+ break ;
1674+ default :
1675+ LOG_ERR ("IPC user: unsupported glb cmd type %d" ,
1676+ msg .primary .r .type );
1677+ result = - EINVAL ;
1678+ break ;
1679+ }
1680+ }
1681+
1682+ return result ;
1683+ }
1684+ #endif /* CONFIG_SOF_USERSPACE_LL */
0 commit comments