Skip to content

Commit 3de5c1c

Browse files
committed
userspace: application: move to vregion
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>
1 parent b845f97 commit 3de5c1c

9 files changed

Lines changed: 112 additions & 66 deletions

File tree

src/audio/buffers/comp_buffer.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,12 @@ static void comp_buffer_free(struct sof_audio_buffer *audio_buffer)
163163
struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc;
164164

165165
rfree(buffer->stream.addr);
166-
if (alloc && alloc->vreg)
166+
if (alloc && alloc->vreg) {
167167
vregion_free(alloc->vreg, buffer);
168-
else
168+
if (!vregion_put(alloc->vreg))
169+
rfree(alloc);
170+
} else {
169171
sof_heap_free(alloc ? alloc->heap : NULL, buffer);
170-
171-
if (alloc && !--alloc->client_count) {
172-
vregion_put(alloc->vreg);
173-
rfree(alloc);
174172
}
175173
}
176174

src/audio/module_adapter/module/generic.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <sof/audio/module_adapter/module/generic.h>
1818
#include <sof/audio/data_blob.h>
1919
#include <sof/lib/fast-get.h>
20+
#include <sof/lib/vregion.h>
2021
#include <sof/schedule/dp_schedule.h>
2122
#if CONFIG_IPC_MAJOR_4
2223
#include <ipc4/header.h>
@@ -87,6 +88,7 @@ void mod_resource_init(struct processing_module *mod)
8788
/* Init memory list */
8889
list_init(&res->objpool.list);
8990
res->objpool.heap = res->alloc->heap;
91+
res->objpool.vreg = res->alloc->vreg;
9092
res->heap_usage = 0;
9193
res->heap_high_water_mark = 0;
9294
}
@@ -158,11 +160,15 @@ void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start
158160
{
159161
struct module_resources *res = &mod->priv.resources;
160162

161-
if (size)
162-
*size = res->alloc->heap->heap.init_bytes;
163+
if (res->alloc->vreg) {
164+
vregion_mem_info(res->alloc->vreg, size, start);
165+
} else if (res->alloc->heap) {
166+
if (size)
167+
*size = res->alloc->heap->heap.init_bytes;
163168

164-
if (start)
165-
*start = (uintptr_t)res->alloc->heap;
169+
if (start)
170+
*start = (uintptr_t)res->alloc->heap->heap.init_mem;
171+
}
166172
}
167173
#endif
168174

@@ -246,7 +252,16 @@ void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t
246252
}
247253

248254
/* Allocate memory for module */
249-
void *ptr = sof_heap_alloc(res->alloc->heap, flags, size, alignment);
255+
void *ptr;
256+
257+
if (!res->alloc->vreg)
258+
ptr = sof_heap_alloc(res->alloc->heap, flags, size, alignment);
259+
else if (flags & SOF_MEM_FLAG_COHERENT)
260+
ptr = vregion_alloc_coherent_align(res->alloc->vreg, VREGION_MEM_TYPE_INTERIM,
261+
size, alignment);
262+
else
263+
ptr = vregion_alloc_align(res->alloc->vreg, VREGION_MEM_TYPE_INTERIM,
264+
size, alignment);
250265

251266
if (!ptr) {
252267
comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.",
@@ -347,7 +362,10 @@ static int free_contents(struct processing_module *mod, struct module_resource *
347362

348363
switch (container->type) {
349364
case MOD_RES_HEAP:
350-
sof_heap_free(res->alloc->heap, container->ptr);
365+
if (res->alloc->vreg)
366+
vregion_free(res->alloc->vreg, container->ptr);
367+
else
368+
sof_heap_free(res->alloc->heap, container->ptr);
351369
res->heap_usage -= container->size;
352370
return 0;
353371
#if CONFIG_COMP_BLOB
@@ -426,10 +444,13 @@ EXPORT_SYMBOL(z_impl_mod_free);
426444
const void *z_vrfy_mod_fast_get(struct processing_module *mod, const void * const dram_ptr,
427445
size_t size)
428446
{
429-
struct module_resources *res = &mod->priv.resources;
447+
size_t h_size = 0;
448+
uintptr_t h_start;
430449

431450
K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod)));
432-
K_OOPS(K_SYSCALL_MEMORY_WRITE(res->alloc->heap, sizeof(*res->alloc->heap)));
451+
mod_heap_info(mod, &h_size, &h_start);
452+
if (h_size)
453+
K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size));
433454
K_OOPS(K_SYSCALL_MEMORY_READ(dram_ptr, size));
434455

435456
return z_impl_mod_fast_get(mod, dram_ptr, size);
@@ -440,21 +461,27 @@ const void *z_vrfy_mod_fast_get(struct processing_module *mod, const void * cons
440461
void *z_vrfy_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
441462
size_t alignment)
442463
{
443-
struct module_resources *res = &mod->priv.resources;
464+
size_t h_size = 0;
465+
uintptr_t h_start;
444466

445467
K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod)));
446-
K_OOPS(K_SYSCALL_MEMORY_WRITE(res->alloc->heap, sizeof(*res->alloc->heap)));
468+
mod_heap_info(mod, &h_size, &h_start);
469+
if (h_size)
470+
K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size));
447471

448472
return z_impl_mod_alloc_ext(mod, flags, size, alignment);
449473
}
450474
#include <zephyr/syscalls/mod_alloc_ext_mrsh.c>
451475

452476
int z_vrfy_mod_free(struct processing_module *mod, const void *ptr)
453477
{
454-
struct module_resources *res = &mod->priv.resources;
478+
size_t h_size = 0;
479+
uintptr_t h_start;
455480

456481
K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod)));
457-
K_OOPS(K_SYSCALL_MEMORY_WRITE(res->alloc->heap, sizeof(*res->alloc->heap)));
482+
mod_heap_info(mod, &h_size, &h_start);
483+
if (h_size)
484+
K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size));
458485

459486
return z_impl_mod_free(mod, ptr);
460487
}

src/audio/module_adapter/module_adapter.c

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <sof/audio/source_api.h>
1919
#include <sof/audio/audio_buffer.h>
2020
#include <sof/audio/pipeline.h>
21+
#include <sof/lib/vregion.h>
2122
#include <sof/schedule/dp_schedule.h>
2223
#include <sof/schedule/ll_schedule_domain.h>
2324
#include <sof/common.h>
@@ -57,38 +58,29 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
5758
#define PAGE_SZ HOST_PAGE_SIZE
5859
#endif
5960

60-
static struct k_heap *module_adapter_dp_heap_new(const struct comp_ipc_config *config,
61-
size_t *heap_size)
61+
static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *config,
62+
size_t *heap_size)
6263
{
6364
/* src-lite with 8 channels has been seen allocating 14k in one go */
6465
/* FIXME: the size will be derived from configuration */
6566
const size_t buf_size = 20 * 1024;
6667

67-
/* Keep uncached to match the default SOF heap! */
68-
uint8_t *mod_heap_mem = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT,
69-
buf_size, PAGE_SZ);
70-
71-
if (!mod_heap_mem)
72-
return NULL;
73-
74-
struct k_heap *mod_heap = (struct k_heap *)mod_heap_mem;
75-
const size_t heap_prefix_size = ALIGN_UP(sizeof(*mod_heap), 4);
76-
void *mod_heap_buf = mod_heap_mem + heap_prefix_size;
77-
78-
*heap_size = buf_size - heap_prefix_size;
79-
k_heap_init(mod_heap, mod_heap_buf, *heap_size);
80-
#ifdef __ZEPHYR__
81-
mod_heap->heap.init_mem = mod_heap_buf;
82-
mod_heap->heap.init_bytes = *heap_size;
83-
#endif
84-
85-
return mod_heap;
68+
/*
69+
* A 1-to-1 replacement of the original heap implementation would be to
70+
* have "lifetime size" equal to 0. But (1) this is invalid for
71+
* vregion_create() and (2) we gradually move objects, that are simple
72+
* to move to the lifetime buffer. Make it 1k for the beginning.
73+
*/
74+
return vregion_create(4096, buf_size - 4096);
8675
}
8776

8877
static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
8978
const struct comp_ipc_config *config)
9079
{
9180
struct k_heap *mod_heap;
81+
struct vregion *mod_vreg;
82+
struct processing_module *mod;
83+
struct comp_dev *dev;
9284
/*
9385
* For DP shared modules the struct processing_module object must be
9486
* accessible from all cores. Unfortunately at this point there's no
@@ -102,17 +94,24 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
10294

10395
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_USERSPACE) &&
10496
!IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) {
105-
mod_heap = module_adapter_dp_heap_new(config, &heap_size);
106-
if (!mod_heap) {
107-
comp_cl_err(drv, "Failed to allocate DP module heap");
97+
mod_vreg = module_adapter_dp_heap_new(config, &heap_size);
98+
if (!mod_vreg) {
99+
comp_cl_err(drv, "Failed to allocate DP module heap / vregion");
108100
return NULL;
109101
}
102+
mod_heap = NULL;
110103
} else {
111104
mod_heap = drv->user_heap;
112105
heap_size = 0;
106+
mod_vreg = NULL;
113107
}
114108

115-
struct processing_module *mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);
109+
if (!mod_vreg)
110+
mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);
111+
else if (flags & SOF_MEM_FLAG_COHERENT)
112+
mod = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod));
113+
else
114+
mod = vregion_alloc(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod));
116115

117116
if (!mod) {
118117
comp_cl_err(drv, "failed to allocate memory for module");
@@ -127,6 +126,7 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
127126
memset(mod, 0, sizeof(*mod));
128127
mod->priv.resources.alloc = alloc;
129128
alloc->heap = mod_heap;
129+
alloc->vreg = mod_vreg;
130130
mod_resource_init(mod);
131131

132132
/*
@@ -135,7 +135,10 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
135135
* then it can be cached. Effectively it can be only cached in
136136
* single-core configurations.
137137
*/
138-
struct comp_dev *dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0);
138+
if (mod_vreg)
139+
dev = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*dev));
140+
else
141+
dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0);
139142

140143
if (!dev) {
141144
comp_cl_err(drv, "failed to allocate memory for comp_dev");
@@ -148,17 +151,17 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
148151
mod->dev = dev;
149152
dev->mod = mod;
150153

151-
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP)
152-
alloc->client_count++;
153-
154154
return mod;
155155

156156
edev:
157157
rfree(alloc);
158158
ealloc:
159-
sof_heap_free(mod_heap, mod);
159+
if (mod_vreg)
160+
vregion_free(mod_vreg, mod);
161+
else
162+
sof_heap_free(mod_heap, mod);
160163
emod:
161-
rfree(mod_heap);
164+
vregion_put(mod_vreg);
162165

163166
return NULL;
164167
}
@@ -167,7 +170,6 @@ static void module_adapter_mem_free(struct processing_module *mod)
167170
{
168171
struct mod_alloc_ctx *alloc = mod->priv.resources.alloc;
169172
struct k_heap *mod_heap = alloc->heap;
170-
unsigned int domain = mod->dev->ipc_config.proc_domain;
171173

172174
/*
173175
* In principle it shouldn't even be needed to free individual objects
@@ -176,13 +178,16 @@ static void module_adapter_mem_free(struct processing_module *mod)
176178
#if CONFIG_IPC_MAJOR_4
177179
sof_heap_free(mod_heap, mod->priv.cfg.input_pins);
178180
#endif
179-
sof_heap_free(mod_heap, mod->dev);
180-
sof_heap_free(mod_heap, mod);
181-
if (domain == COMP_PROCESSING_DOMAIN_DP) {
182-
if (!IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP))
183-
rfree(mod_heap);
184-
if (!--alloc->client_count)
181+
if (alloc->vreg) {
182+
struct vregion *mod_vreg = alloc->vreg;
183+
184+
vregion_free(mod_vreg, mod->dev);
185+
vregion_free(mod_vreg, mod);
186+
if (!vregion_put(mod_vreg))
185187
rfree(alloc);
188+
} else {
189+
sof_heap_free(mod_heap, mod->dev);
190+
sof_heap_free(mod_heap, mod);
186191
}
187192
}
188193

@@ -627,9 +632,7 @@ int module_adapter_prepare(struct comp_dev *dev)
627632
goto free;
628633
}
629634

630-
if (md->resources.alloc->heap &&
631-
md->resources.alloc->heap != dev->drv->user_heap)
632-
md->resources.alloc->client_count++;
635+
vregion_get(md->resources.alloc->vreg);
633636

634637
irq_local_disable(flags);
635638
list_item_prepend(&buffer->buffers_list, &mod->raw_data_buffers_list);

src/include/sof/audio/component.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,6 @@ struct vregion;
583583
struct mod_alloc_ctx {
584584
struct k_heap *heap;
585585
struct vregion *vreg;
586-
unsigned int client_count;
587586
};
588587

589588
/**

src/include/sof/objpool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
#include <stddef.h>
1313
#include <stdint.h>
1414

15+
struct vregion;
1516
struct k_heap;
1617
struct objpool_head {
1718
struct list_item list;
19+
struct vregion *vreg;
1820
struct k_heap *heap;
1921
uint32_t flags;
2022
};

src/ipc/ipc4/helper.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <sof/ipc/msg.h>
2222
#include <sof/lib/mailbox.h>
2323
#include <sof/lib/memory.h>
24+
#include <sof/lib/vregion.h>
2425
#include <sof/list.h>
2526
#include <sof/platform.h>
2627
#include <sof/schedule/dp_schedule.h>
@@ -739,7 +740,7 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
739740

740741
#if CONFIG_ZEPHYR_DP_SCHEDULER
741742
if (alloc)
742-
alloc->client_count++;
743+
vregion_get(alloc->vreg/*, NULL*/);
743744
#endif
744745

745746
/*

src/lib/objpool.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <sof/objpool.h>
88
#include <sof/common.h>
99
#include <sof/list.h>
10+
#include <sof/lib/vregion.h>
1011

1112
#include <errno.h>
1213
#include <limits.h>
@@ -37,8 +38,17 @@ static int objpool_add(struct objpool_head *head, unsigned int n, size_t size, u
3738
if (!head->heap)
3839
head->heap = sof_sys_heap_get();
3940

40-
struct objpool *pobjpool = sof_heap_alloc(head->heap, flags,
41-
aligned_size + sizeof(*pobjpool), 0);
41+
struct objpool *pobjpool;
42+
43+
if (!head->vreg)
44+
pobjpool = sof_heap_alloc(head->heap, flags,
45+
aligned_size + sizeof(*pobjpool), 0);
46+
else if (flags & SOF_MEM_FLAG_COHERENT)
47+
pobjpool = vregion_alloc_coherent(head->vreg, VREGION_MEM_TYPE_INTERIM,
48+
aligned_size + sizeof(*pobjpool));
49+
else
50+
pobjpool = vregion_alloc(head->vreg, VREGION_MEM_TYPE_INTERIM,
51+
aligned_size + sizeof(*pobjpool));
4252

4353
if (!pobjpool)
4454
return -ENOMEM;
@@ -150,8 +160,13 @@ void objpool_prune(struct objpool_head *head)
150160
struct list_item *next, *tmp;
151161

152162
list_for_item_safe(next, tmp, &head->list) {
163+
struct objpool *pool = container_of(next, struct objpool, list);
164+
153165
list_item_del(next);
154-
sof_heap_free(head->heap, container_of(next, struct objpool, list));
166+
if (head->vreg)
167+
vregion_free(head->vreg, pool);
168+
else
169+
sof_heap_free(head->heap, pool);
155170
}
156171
}
157172

0 commit comments

Comments
 (0)