-
Notifications
You must be signed in to change notification settings - Fork 8.4k
drivers: dai: add ability to use dai.h from user threads #99811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
drivers: dai: add ability to use dai.h from user threads #99811
Conversation
|
Draft for now, thesofproject/sof#10373 shall go in first. I'll rebase on top of that before converting to ready for review. |
drivers/dai/dai_handlers.c
Outdated
| * merge with Adrian's PR to add bespoke_cfg size */ | ||
| K_OOPS(K_SYSCALL_MEMORY_READ(bespoke_cfg, CONFIG_MMU_PAGE_SIZE)); | ||
|
|
||
| /* TODO: shall a kernel copy made of cfg */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, not sure what this comment means?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lyakh So basicly, can we trust to pass an object that sits in user-space accessible memory to a kernel function. In Linux this is a no-no as another user-space thread could be active (on another CPU) and modify the data while kernel is accessing it (on another).
On a resource constrained device, this is a bit harder pill to swallow as some of these objects are rather big. But I'm thinking it we want to merge this in Zephyr, we need to do a copy of all input data to kernel, validate and run the function. In SOF side (the application using Zephyr), we could optimize this as we know there will not be other user-space threads (enforced by system design).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kv2019i ah, so the typo is "a kernel copy be made" - that's what I couldn't guess, sorry :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to deeply copy this (nothing referring to user mode accessible memory), then validate it. This will be rather troublesome with a void * at an API level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack @teburd , will at deep copies to next version. @abonislawski is added a size field in a separate PR, so that allows to handle the bespoke data objects in a sane fashion. I'll be adding a new variant of get_properties() that can be used from user-space.
|
Can we wrap these changes into a more detailed config than |
Good question. This is a generic capability in Zephyr, so it's not really tied to any particular use (and not related to SOF). Currently user-space is a boolean build option in Zephyr, if you enable user-space, all interfaces that have a syscall interface (semaphores, cache.h, mutexes, now dai.h) , are exposed. I'd prefer to use some standard Zephyr option if user wants to build Zephyr with a subset of all possible syscalls-enables interfaces (e.g. have semaphore syscall impelemntation built in, but noth dma.h or dai.h). Let me study this a bit (and please chime in if anyone knows how to do this the Zephyr way). Functionally this is not a problem. Even if you enable Zephyr CONFIG_USERSPACE, but you call dai.h from kernel, nothing changes. And user threads cannot access dai.h unless permission is explicitly given, so just having dai.h syscalls built-in does not mean user threads can use this functionality. But this does add code to the binary, so a valid question for sure. Same problem should apply for other interfaces as well. Let's see if there's a solution already. |
kv2019i
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks all to reviewers so far!
drivers/dai/dai_handlers.c
Outdated
| * merge with Adrian's PR to add bespoke_cfg size */ | ||
| K_OOPS(K_SYSCALL_MEMORY_READ(bespoke_cfg, CONFIG_MMU_PAGE_SIZE)); | ||
|
|
||
| /* TODO: shall a kernel copy made of cfg */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack @teburd , will at deep copies to next version. @abonislawski is added a size field in a separate PR, so that allows to handle the bespoke data objects in a sane fashion. I'll be adding a new variant of get_properties() that can be used from user-space.
c16628a to
716366c
Compare
|
V2 pushed:
|
Add user-space support to the dai.h interface. No functional impact to builds when CONFIG_USERSPACE is not set. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a variant of get_properties() method that writes the properties to a caller provided pointer. Unlike the old variant, this copy variant can be exported to user-space in a safe way. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
The DAI interface is not used from user-space in all configurations where Zephyr user-space is enabled, so it is beneficial to have a build option to contorl whether the DAI syscalls are included or not. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add support for new get_properties_copy() method. This allows to use ssp driver from user-space threads. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
716366c to
3c5607b
Compare
|
V3:
|
|
|
@lyakh @softwarecki @lgirdwood @nashif can you take a look? |
softwarecki
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job wrapping zephyr_syscall_header in if(CONFIG_DAI_USERSPACE).
This was missing in thesofproject/sof#10341, so it's great to see it addressed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds user-space support to the DAI (Digital Audio Interface) driver interface by converting inline functions to syscalls and adding appropriate validation handlers.
Key changes:
- Converted 10 DAI API functions to syscalls with
__syscalldeclarations andz_impl_*implementations - Added new
dai_get_properties_copyAPI function for user-space safe property retrieval - Implemented syscall validation handlers in
dai_handlers.cwith memory access checks and parameter validation
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
include/zephyr/drivers/dai.h |
Converts inline functions to syscalls, adds get_properties_copy API and callback, includes syscall header |
drivers/dai/dai_handlers.c |
New file implementing syscall verification handlers with memory validation and bespoke config size limits |
drivers/dai/intel/ssp/ssp.c |
Implements dai_ssp_get_properties_copy callback for SSP driver |
drivers/dai/Kconfig |
Adds DAI_USERSPACE configuration option dependent on USERSPACE |
drivers/dai/CMakeLists.txt |
Conditionally includes syscall generation and handlers compilation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!prop) { | ||
| return -EINVAL; | ||
| } | ||
|
|
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing NULL check for kernel_prop before dereferencing it in memcpy. While dai_ssp_get_properties currently never returns NULL, defensive programming requires checking the return value. If it were NULL, line 2560 would cause a crash. Add a check: if (!kernel_prop) { return -ENODATA; } after line 2554.
| if (!kernel_prop) { | |
| return -ENODATA; | |
| } |
| * @brief Fetch properties of a DAI driver | ||
| * | ||
| * @param dev Pointer to the device structure for the driver instance | ||
| * @param dir Stream direction: RX or TX as defined by DAI_DIR_* | ||
| * @param stream_id Stream id: some drivers may have stream specific | ||
| * properties, this id specifies the stream. | ||
| * @param dst address where to write properties to | ||
| * @retval Zero on success |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation for dai_get_properties_copy is incomplete. It should specify the expected error return codes (e.g., -EINVAL for invalid parameters, -ENODATA if properties are unavailable). Additionally, it should clarify the relationship between this function and dai_get_properties, explaining that this is the user-space-safe variant.
| * @brief Fetch properties of a DAI driver | |
| * | |
| * @param dev Pointer to the device structure for the driver instance | |
| * @param dir Stream direction: RX or TX as defined by DAI_DIR_* | |
| * @param stream_id Stream id: some drivers may have stream specific | |
| * properties, this id specifies the stream. | |
| * @param dst address where to write properties to | |
| * @retval Zero on success | |
| * @brief Fetch properties of a DAI driver (user-space-safe variant) | |
| * | |
| * This function is the user-space-safe variant of @ref dai_get_properties. | |
| * It copies the properties into the provided destination buffer, allowing | |
| * safe access from user space. | |
| * | |
| * @param dev Pointer to the device structure for the driver instance | |
| * @param dir Stream direction: RX or TX as defined by DAI_DIR_* | |
| * @param stream_id Stream id: some drivers may have stream specific | |
| * properties, this id specifies the stream. | |
| * @param dst Address where to write properties to | |
| * | |
| * @retval 0 On success. | |
| * @retval -EINVAL Invalid parameters (e.g., null pointer, invalid stream id). | |
| * @retval -ENODATA Properties are unavailable for the specified stream. |
| struct dai_properties *dst) | ||
| { | ||
| const struct dai_driver_api *api = (const struct dai_driver_api *)dev->api; | ||
|
|
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing NULL check for the get_properties_copy API callback before calling it. If a driver doesn't implement this callback (like alh, dmic, hda, esai, micfil, and sai drivers), this will cause a NULL pointer dereference. Add a check: if (!api->get_properties_copy) { return -ENOSYS; } before the function call.
| if (!api->get_properties_copy) { | |
| return -ENOSYS; | |
| } |
| return -EINVAL; | ||
| } | ||
|
|
||
| K_OOPS(K_SYSCALL_DRIVER_DAI(dev, config_set)); |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing validation for the cfg parameter. The syscall handler should validate that userspace has read access to the dai_config structure before passing it to the kernel implementation. Add K_OOPS(K_SYSCALL_MEMORY_READ(cfg, sizeof(*cfg))); after the driver validation check.
| K_OOPS(K_SYSCALL_DRIVER_DAI(dev, config_set)); | |
| K_OOPS(K_SYSCALL_DRIVER_DAI(dev, config_set)); | |
| K_OOPS(K_SYSCALL_MEMORY_READ(cfg, sizeof(*cfg))); |
| K_OOPS(k_usermode_from_copy(bespoke_cfg_kernel, bespoke_cfg, size)); | ||
|
|
||
| return z_impl_dai_config_set(dev, cfg, bespoke_cfg_kernel, size); | ||
| } |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing validation for NULL or zero-size bespoke_cfg. If size is 0 and bespoke_cfg is NULL, the k_usermode_from_copy will fail. Consider checking if size is 0 and handling it appropriately, potentially skipping the copy when size == 0. This pattern should also be applied to z_vrfy_dai_config_update.
| K_OOPS(k_usermode_from_copy(bespoke_cfg_kernel, bespoke_cfg, size)); | |
| return z_impl_dai_config_set(dev, cfg, bespoke_cfg_kernel, size); | |
| } | |
| if (size > 0) { | |
| K_OOPS(k_usermode_from_copy(bespoke_cfg_kernel, bespoke_cfg, size)); | |
| return z_impl_dai_config_set(dev, cfg, bespoke_cfg_kernel, size); | |
| } else { | |
| /* No bespoke config to copy, pass NULL */ | |
| return z_impl_dai_config_set(dev, cfg, NULL, 0); | |
| } |



Add user-space support to the dai.h interface. No functional impact to builds when CONFIG_USERSPACE is not set.