From 444d49051cb596abf5af8e8beafbc62bd12aef39 Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Mon, 22 Jun 2026 15:11:26 +0200 Subject: [PATCH] audio: comp_buffer: make allocations from the passed memory context To ensure the buffer is not left outside the module's memory domain, the payload allocation must be made from the supplied context instead of always calling rballoc_align(). This fixes a crash during bind processing when running a test with a userspace DP module on a secondary core. Signed-off-by: Serhiy Katsyuba --- src/audio/buffers/comp_buffer.c | 111 +++++++++++++++----------------- 1 file changed, 53 insertions(+), 58 deletions(-) diff --git a/src/audio/buffers/comp_buffer.c b/src/audio/buffers/comp_buffer.c index 9aa5c0f0ab10..9dfde7b7f33a 100644 --- a/src/audio/buffers/comp_buffer.c +++ b/src/audio/buffers/comp_buffer.c @@ -156,12 +156,12 @@ static void comp_buffer_free(struct sof_audio_buffer *audio_buffer) struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc; -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - sof_ctx_free(alloc, buffer->stream.addr); -#else - rfree(buffer->stream.addr); -#endif + assert(!IS_ENABLED(CONFIG_SOF_USERSPACE_LL) || alloc); + + if (alloc) + sof_ctx_free(alloc, buffer->stream.addr); + else + rfree(buffer->stream.addr); if (alloc && alloc->vreg) { vregion_free(alloc->vreg, buffer); @@ -255,12 +255,13 @@ struct comp_buffer *buffer_alloc(struct mod_alloc_ctx *alloc, size_t size, uint3 return NULL; } -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - stream_addr = sof_ctx_alloc(alloc, flags, size, align); -#else - stream_addr = rballoc_align(flags, size, align); -#endif + assert(!IS_ENABLED(CONFIG_SOF_USERSPACE_LL) || alloc); + + if (alloc) + stream_addr = sof_ctx_alloc(alloc, flags, size, align); + else + stream_addr = rballoc_align(flags, size, align); + if (!stream_addr) { tr_err(&buffer_tr, "could not alloc size = %zu bytes of flags = 0x%x", size, flags); @@ -270,12 +271,11 @@ struct comp_buffer *buffer_alloc(struct mod_alloc_ctx *alloc, size_t size, uint3 buffer = buffer_alloc_struct(alloc, stream_addr, size, flags, is_shared); if (!buffer) { tr_err(&buffer_tr, "could not alloc buffer structure"); -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - sof_ctx_free(alloc, stream_addr); -#else - rfree(stream_addr); -#endif + + if (alloc) + sof_ctx_free(alloc, stream_addr); + else + rfree(stream_addr); } return buffer; @@ -302,13 +302,14 @@ struct comp_buffer *buffer_alloc_range(struct mod_alloc_ctx *alloc, size_t prefe if (preferred_size % minimum_size) preferred_size += minimum_size - preferred_size % minimum_size; + assert(!IS_ENABLED(CONFIG_SOF_USERSPACE_LL) || alloc); + for (size = preferred_size; size >= minimum_size; size -= minimum_size) { -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - stream_addr = sof_ctx_alloc(alloc, flags, size, align); -#else - stream_addr = rballoc_align(flags, size, align); -#endif + if (alloc) + stream_addr = sof_ctx_alloc(alloc, flags, size, align); + else + stream_addr = rballoc_align(flags, size, align); + if (stream_addr) break; } @@ -324,12 +325,11 @@ struct comp_buffer *buffer_alloc_range(struct mod_alloc_ctx *alloc, size_t prefe buffer = buffer_alloc_struct(alloc, stream_addr, size, flags, is_shared); if (!buffer) { tr_err(&buffer_tr, "could not alloc buffer structure"); -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - sof_ctx_free(alloc, stream_addr); -#else - rfree(stream_addr); -#endif + + if (alloc) + sof_ctx_free(alloc, stream_addr); + else + rfree(stream_addr); } return buffer; @@ -350,9 +350,7 @@ void buffer_zero(struct comp_buffer *buffer) int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignment) { void *new_ptr = NULL; -#ifdef CONFIG_SOF_USERSPACE_LL struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc; -#endif CORE_CHECK_STRUCT(&buffer->audio_buffer); @@ -365,12 +363,12 @@ int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignmen if (size == audio_stream_get_size(&buffer->stream)) return 0; -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - new_ptr = sof_ctx_alloc(alloc, buffer->flags, size, alignment); -#else - new_ptr = rballoc_align(buffer->flags, size, alignment); -#endif + assert(!IS_ENABLED(CONFIG_SOF_USERSPACE_LL) || alloc); + + if (alloc) + new_ptr = sof_ctx_alloc(alloc, buffer->flags, size, alignment); + else + new_ptr = rballoc_align(buffer->flags, size, alignment); /* we couldn't allocate bigger chunk */ if (!new_ptr && size > audio_stream_get_size(&buffer->stream)) { @@ -381,12 +379,11 @@ int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignmen /* use bigger chunk, else just use the old chunk but set smaller */ if (new_ptr) { -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - sof_ctx_free(alloc, audio_stream_get_addr(&buffer->stream)); -#else - rfree(audio_stream_get_addr(&buffer->stream)); -#endif + if (alloc) + sof_ctx_free(alloc, audio_stream_get_addr(&buffer->stream)); + else + rfree(audio_stream_get_addr(&buffer->stream)); + audio_stream_set_addr(&buffer->stream, new_ptr); } @@ -401,9 +398,7 @@ int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, siz const size_t actual_size = audio_stream_get_size(&buffer->stream); void *new_ptr = NULL; size_t new_size; -#ifdef CONFIG_SOF_USERSPACE_LL struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc; -#endif CORE_CHECK_STRUCT(&buffer->audio_buffer); @@ -421,14 +416,15 @@ int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, siz if (preferred_size == actual_size) return 0; + assert(!IS_ENABLED(CONFIG_SOF_USERSPACE_LL) || alloc); + for (new_size = preferred_size; new_size >= minimum_size; new_size -= minimum_size) { -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - new_ptr = sof_ctx_alloc(alloc, buffer->flags, new_size, alignment); -#else - new_ptr = rballoc_align(buffer->flags, new_size, alignment); -#endif + if (alloc) + new_ptr = sof_ctx_alloc(alloc, buffer->flags, new_size, alignment); + else + new_ptr = rballoc_align(buffer->flags, new_size, alignment); + if (new_ptr) break; } @@ -442,12 +438,11 @@ int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, siz /* use bigger chunk, else just use the old chunk but set smaller */ if (new_ptr) { -#ifdef CONFIG_SOF_USERSPACE_LL - assert(alloc); - sof_ctx_free(alloc, audio_stream_get_addr(&buffer->stream)); -#else - rfree(audio_stream_get_addr(&buffer->stream)); -#endif + if (alloc) + sof_ctx_free(alloc, audio_stream_get_addr(&buffer->stream)); + else + rfree(audio_stream_get_addr(&buffer->stream)); + audio_stream_set_addr(&buffer->stream, new_ptr); }