Skip to content

Commit 8d75e2c

Browse files
lyakhkv2019i
authored andcommitted
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 5316c6e commit 8d75e2c

9 files changed

Lines changed: 111 additions & 68 deletions

File tree

src/audio/buffers/comp_buffer.c

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

159159
rfree(buffer->stream.addr);
160-
if (alloc && alloc->vreg)
160+
if (alloc && alloc->vreg) {
161161
vregion_free(alloc->vreg, buffer);
162-
else
162+
if (!vregion_put(alloc->vreg))
163+
rfree(alloc);
164+
} else {
163165
sof_heap_free(alloc ? alloc->heap : NULL, buffer);
164-
165-
if (alloc && !--alloc->client_count) {
166-
vregion_put(alloc->vreg);
167-
rfree(alloc);
168166
}
169167
}
170168

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: 43 additions & 43 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");
@@ -126,8 +125,7 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
126125

127126
memset(mod, 0, sizeof(*mod));
128127
alloc->heap = mod_heap;
129-
alloc->vreg = NULL;
130-
alloc->client_count = 0;
128+
alloc->vreg = mod_vreg;
131129
mod->priv.resources.alloc = alloc;
132130
mod_resource_init(mod);
133131

@@ -137,7 +135,10 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
137135
* then it can be cached. Effectively it can be only cached in
138136
* single-core configurations.
139137
*/
140-
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);
141142

142143
if (!dev) {
143144
comp_cl_err(drv, "failed to allocate memory for comp_dev");
@@ -150,17 +151,17 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
150151
mod->dev = dev;
151152
dev->mod = mod;
152153

153-
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP)
154-
alloc->client_count++;
155-
156154
return mod;
157155

158156
edev:
159157
rfree(alloc);
160158
ealloc:
161-
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);
162163
emod:
163-
rfree(mod_heap);
164+
vregion_put(mod_vreg);
164165

165166
return NULL;
166167
}
@@ -169,7 +170,6 @@ static void module_adapter_mem_free(struct processing_module *mod)
169170
{
170171
struct mod_alloc_ctx *alloc = mod->priv.resources.alloc;
171172
struct k_heap *mod_heap = alloc->heap;
172-
unsigned int domain = mod->dev->ipc_config.proc_domain;
173173

174174
/*
175175
* In principle it shouldn't even be needed to free individual objects
@@ -178,14 +178,16 @@ static void module_adapter_mem_free(struct processing_module *mod)
178178
#if CONFIG_IPC_MAJOR_4
179179
sof_heap_free(mod_heap, mod->priv.cfg.input_pins);
180180
#endif
181-
sof_heap_free(mod_heap, mod->dev);
182-
sof_heap_free(mod_heap, mod);
183-
if (domain == COMP_PROCESSING_DOMAIN_DP) {
184-
if (!IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP))
185-
rfree(mod_heap);
186-
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))
187187
rfree(alloc);
188188
} else {
189+
sof_heap_free(mod_heap, mod->dev);
190+
sof_heap_free(mod_heap, mod);
189191
rfree(alloc);
190192
}
191193
}
@@ -631,9 +633,7 @@ int module_adapter_prepare(struct comp_dev *dev)
631633
goto free;
632634
}
633635

634-
if (md->resources.alloc->heap &&
635-
md->resources.alloc->heap != dev->drv->user_heap)
636-
md->resources.alloc->client_count++;
636+
vregion_get(md->resources.alloc->vreg);
637637

638638
irq_local_disable(flags);
639639
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);
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)