Skip to content

userspace: DP: application: switch to vregion#10702

Merged
kv2019i merged 15 commits intothesofproject:mainfrom
lyakh:vreg
Apr 30, 2026
Merged

userspace: DP: application: switch to vregion#10702
kv2019i merged 15 commits intothesofproject:mainfrom
lyakh:vreg

Conversation

@lyakh
Copy link
Copy Markdown
Collaborator

@lyakh lyakh commented Apr 14, 2026

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_api through module resources, buffers, and IPC buffer creation.
  • Update Zephyr userspace config gating to require SOF_VREGIONS for 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() uses uintptr_t in 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.

Comment thread zephyr/lib/vregion.c
Comment thread zephyr/lib/vregion.c
Comment thread src/include/sof/audio/audio_buffer.h
Comment on lines 203 to 206
/* 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);

Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
* 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.
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
* to move to the lifetime buffer. Make it 1k for the beginning.
* to move to the lifetime buffer. Make it 4k for the beginning.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really cool to see this move forward! A couple of comments inline, please check.

Comment thread src/audio/module_adapter/module_adapter.c Outdated
Comment thread zephyr/lib/vregion.c
* 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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intentionally omitted?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this allocation hasn't been switched to the vregion so far

Copy link
Copy Markdown
Contributor

@jsarha jsarha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need separate is_shared flag when we have defined SOF_MEM_FLAG_COHERENT in the flags field?

Copy link
Copy Markdown
Collaborator Author

@lyakh lyakh Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsarha don't know, not my original implementation. Originally the is_shared argument was added in 4a03699

size_t *heap_size)
static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *config,
size_t *heap_size)
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here there will be some conflicts with and connections to do with my #10603

@lyakh lyakh force-pushed the vreg branch 3 times, most recently from 3de5c1c to 536c442 Compare April 17, 2026 13:35
@lyakh
Copy link
Copy Markdown
Collaborator Author

lyakh commented Apr 28, 2026

@lrudyX the single MTL failure seems unrelated?

@lrudyX
Copy link
Copy Markdown

lrudyX commented Apr 28, 2026

@lrudyX the single MTL failure seems unrelated?

Yes, that one is unrelated

@lyakh lyakh added DNM Do Not Merge tag and removed DNM Do Not Merge tag labels Apr 28, 2026
@lyakh
Copy link
Copy Markdown
Collaborator Author

lyakh commented Apr 28, 2026

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

@lyakh lyakh added the DNM Do Not Merge tag label Apr 28, 2026
@lyakh
Copy link
Copy Markdown
Collaborator Author

lyakh commented Apr 28, 2026

This last "DNM" is more serious - just discovered, that this PR is causing a regression - it makes aplay -r 8000 -D hw:0,2 on nocodec fail. A fix to follow shortly.

@lyakh lyakh marked this pull request as draft April 28, 2026 15:48
@lyakh lyakh marked this pull request as ready for review April 29, 2026 09:50
@lyakh lyakh removed DNM Do Not Merge tag labels Apr 29, 2026
@lyakh lyakh force-pushed the vreg branch 3 times, most recently from fd70d02 to 139f77c Compare April 29, 2026 14:44
lyakh added 5 commits April 29, 2026 19:03
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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() frees vr when 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.

Comment on lines 112 to 115
bool walking; /**< indicates if the buffer is being walked */

struct k_heap *heap;
struct mod_alloc_ctx *alloc;
};
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

propose to address in a follow-up

@kv2019i kv2019i merged commit 8d75e2c into thesofproject:main Apr 30, 2026
44 of 45 checks passed
@lyakh lyakh deleted the vreg branch April 30, 2026 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants