userspace: DP: application: switch to vregion#10702
userspace: DP: application: switch to vregion#10702kv2019i merged 15 commits intothesofproject:mainfrom
Conversation
ab93282 to
f84a925
Compare
There was a problem hiding this comment.
Pull request overview
Switches userspace DP module-private allocations from a per-module k_heap to vregions, and introduces a unified sof_alloc_api handle (heap/vregion + refcount) that is threaded through buffer and module allocation paths.
Changes:
- Add vregion “coherent” allocation APIs and vregion metadata query, and adjust vregion free/alignment behavior.
- Replace DP module heap usage with vregion-backed allocations; propagate
sof_alloc_apithrough module resources, buffers, and IPC buffer creation. - Update Zephyr userspace config gating to require
SOF_VREGIONSfor the userspace application.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| zephyr/lib/vregion.c | Adds coherent alloc helpers, adjusts free() for uncached aliases, changes default alignment, adds vregion_mem_info(). |
| zephyr/Kconfig | Makes SOF_USERSPACE_APPLICATION depend on SOF_VREGIONS. |
| src/schedule/zephyr_dp_schedule_application.c | Updates mem partitions to use cached/uncached aliases for module heap region start. |
| src/lib/objpool.c | Allocates objpool backing storage from vregion when available (incl. coherent). |
| src/ipc/ipc4/helper.c | Threads sof_alloc_api into IPC4 buffer creation and client refcounting. |
| src/ipc/ipc-helper.c | Updates buffer_new() signature to take sof_alloc_api. |
| src/include/sof/schedule/dp_schedule.h | Removes obsolete dp_heap_user struct. |
| src/include/sof/objpool.h | Adds optional vregion pointer to objpool head. |
| src/include/sof/lib/vregion.h | Moves enum definition, adds coherent alloc APIs + mem_info, adds CONFIG stubs. |
| src/include/sof/audio/module_adapter/module/generic.h | Replaces module resources’ heap pointer with sof_alloc_api. |
| src/include/sof/audio/component.h | Introduces struct sof_alloc_api (heap/vreg/client_count). |
| src/include/sof/audio/buffer.h | Updates buffer allocation APIs to take sof_alloc_api. |
| src/include/sof/audio/audio_buffer.h | Replaces heap pointer with alloc pointer in sof_audio_buffer. |
| src/audio/module_adapter/module_adapter_ipc4.c | Uses alloc.heap for module adapter IPC4 init allocations. |
| src/audio/module_adapter/module_adapter.c | Replaces DP per-module heap with vregion creation and vregion-backed allocations; refcounts via alloc API. |
| src/audio/module_adapter/module/generic.c | Routes module alloc/free paths through vregion when present; updates syscall verification checks. |
| src/audio/dai-zephyr.c | Switches a DMA config allocation call from rballoc() to rmalloc(). |
| src/audio/buffers/ring_buffer.c | Uses vregion allocations for ring buffer objects/data when available; switches to alloc API. |
| src/audio/buffers/comp_buffer.c | Uses vregion allocations for buffer objects when available; switches to alloc API and refcount-based vregion lifetime. |
| src/audio/base_fw_intel.c | Makes UAOL helper(s) __cold, adds cold assertions, and config-guards one helper. |
Comments suppressed due to low confidence (1)
src/include/sof/lib/vregion.h:11
vregion_mem_info()usesuintptr_tin its signature, but this header no longer includes a header that defines it. Add#include <stdint.h>(or equivalent) near the top so this header is self-contained and doesn’t rely on transitive includes.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /* Allocate buffer memory for module */ | ||
| void *ptr = sof_heap_alloc(res->heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_LARGE_BUFFER, | ||
| void *ptr = sof_heap_alloc(res->alloc.heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_LARGE_BUFFER, | ||
| size, alignment); | ||
|
|
There was a problem hiding this comment.
mod_balloc_align() always allocates from res->alloc.heap, but when a module is backed by a vregion, alloc.heap is NULL and the allocation will fall back to the global SOF heap. Later, MOD_RES_HEAP frees go through vregion_free() when res->alloc.vreg is set, which will free a pointer that was not allocated from that vregion. Update mod_balloc_align() to allocate from the vregion when res->alloc.vreg is non-NULL (or ensure heap/vreg pairing is consistent) so allocation and free paths match.
| * A 1-to-1 replacement of the original heap implementation would be to | ||
| * have "lifetime size" equal to 0. But (1) this is invalid for | ||
| * vregion_create() and (2) we gradually move objects, that are simple | ||
| * to move to the lifetime buffer. Make it 1k for the beginning. |
There was a problem hiding this comment.
The comment says “Make it 1k for the beginning.” but the code uses 4096 bytes for the lifetime partition. Please either update the comment or change the value so they match (otherwise it’s unclear what the intended sizing is).
| * to move to the lifetime buffer. Make it 1k for the beginning. | |
| * to move to the lifetime buffer. Make it 4k for the beginning. |
kv2019i
left a comment
There was a problem hiding this comment.
Really cool to see this move forward! A couple of comments inline, please check.
| * vregion_create() and (2) we gradually move objects, that are simple | ||
| * to move to the lifetime buffer. Make it 1k for the beginning. | ||
| */ | ||
| return vregion_create(4096, buf_size - 4096); |
There was a problem hiding this comment.
Cosmetics: I would just declare two constants instead of magic number subtraction:
const size_t lifetime_size = 4 * 1024
const size_t interim_size = 16 * 1024
|
|
||
| static struct k_heap *module_adapter_dp_heap_new(const struct comp_ipc_config *config, | ||
| size_t *heap_size) | ||
| static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *config, |
There was a problem hiding this comment.
module_adapter_dp_heap_new -> module_adapter_dp_vreg_new
| /** | ||
| * @brief like vregion_alloc_align() but allocates coherent memory | ||
| */ | ||
| void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type, |
There was a problem hiding this comment.
Wouldn't be better to have a single function for both coherent and normal allocations? Function sof_heap_alloc already does this. You could just replace enum vregion_mem_type with enum vregion_alloc_flags or something similar.
There was a problem hiding this comment.
@wjablon1 you mean using flags like all other SOF allocation functions do. I thought about that. Personally I'm not a big fan of "flags"-like argument when they most often called with those flags constant. If the caller already knows which functionality it needs, why should it use a flag and have the called function check which flag was used? The caller can call the required functionality directly. And in this case the common functionality is easily enough implemented by a separate function, so I think this is a better fit. If however we decide that we want to continue using flags, we can switch too - now or later.
There was a problem hiding this comment.
I agree with you in principle provided that callers know the right function at compile time, i.e. it doesn’t have to be determined by means of repeating if-else pattern. Also, in this case the flags values are already determined for the legacy allocation method. So I guess it all depends on how long we are going to maintain both solutions.
| @@ -170,10 +176,17 @@ static void module_adapter_mem_free(struct processing_module *mod) | |||
| #if CONFIG_IPC_MAJOR_4 | |||
| sof_heap_free(mod_heap, mod->priv.cfg.input_pins); | |||
There was a problem hiding this comment.
Is this intentionally omitted?
There was a problem hiding this comment.
yes, this allocation hasn't been switched to the vregion so far
jsarha
left a comment
There was a problem hiding this comment.
Did this a bit hastily, but I did not find anything wrong. Just one question/suggestion.
| static struct comp_buffer *buffer_alloc_struct(struct k_heap *heap, | ||
| static struct comp_buffer *buffer_alloc_struct(struct sof_alloc_api *alloc, | ||
| void *stream_addr, size_t size, | ||
| uint32_t flags, bool is_shared) |
There was a problem hiding this comment.
Why do we need separate is_shared flag when we have defined SOF_MEM_FLAG_COHERENT in the flags field?
| size_t *heap_size) | ||
| static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *config, | ||
| size_t *heap_size) | ||
| { |
There was a problem hiding this comment.
Here there will be some conflicts with and connections to do with my #10603
3de5c1c to
536c442
Compare
|
@lrudyX the single MTL failure seems unrelated? |
Yes, that one is unrelated |
|
the short-lived "DNM" was due to a suspected bug in the PR, which, however, turned out to be an unrelated regression, fixed in #10731 |
|
This last "DNM" is more serious - just discovered, that this PR is causing a regression - it makes |
fd70d02 to
139f77c
Compare
uuid.h isn't needed in buffer.h. However just removing it from there breaks compilation because of multiple trace context definitions like DECLARE_TR_CTX(comp_tr, SOF_UUID(component_uuid), LOG_LEVEL_INFO); in files, not explicitly including uuid.h. To make a simple fix move the header to trace.h because that is anyway needed for all such lines. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
sof_dma.h is only used when actually building SOF. Put it under a proprocessor conditional to fix including the header in twister builds. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
fast-get has to choose which allocation method to use, it needs access to the full module allocation context. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When userspace modules use fast-get to access smaller buffers, their copies should be allocated on module's vregion, if available, not on the global SOF heap. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Modules, running in userspace while using the "application" DP implementation, are moved to vregion for all their private allocations. This has the advantage of not depending on build-time configured VMH buffers and of faster lifetime allocations. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/include/sof/lib/vregion.h:152
- In the
#else /* CONFIG_SOF_VREGIONS */stub implementation,vregion_put()freesvrwhen the refcount reaches 0 but still returns the (now freed) pointer. Callers in this PR treat a NULL return value as "destroyed" (e.g.if (!vregion_put(mod_vreg)) ...), so this causes both leaks and potential use-after-free. Make the stub return NULL when the refcount hits 0, matching the real implementation’s contract.
| bool walking; /**< indicates if the buffer is being walked */ | ||
|
|
||
| struct k_heap *heap; | ||
| struct mod_alloc_ctx *alloc; | ||
| }; |
There was a problem hiding this comment.
propose to address in a follow-up
| * A 1-to-1 replacement of the original heap implementation would be to | ||
| * have "lifetime size" equal to 0. But (1) this is invalid for | ||
| * vregion_create() and (2) we gradually move objects, that are simple | ||
| * to move to the lifetime buffer. Make it 1k for the beginning. |
There was a problem hiding this comment.
propose to address in a follow-up
Switch to using vregions for private module allocations with userspace DP.
Currently seems to be causing a regression, therefore a draft, debugging.Update: With the updated Zephyr the regression cannot be reproduced any more.