Skip to content

Commit 38c4810

Browse files
marcinszkudlinskilgirdwood
authored andcommitted
mem: use single cross-core virtual heap
In case of cross core buffers a buffer may be allocated and freed by different core, depending on which component is deleted second. As all control structures of virtual heaps are stored in uncached aliases, there's no technical problems with allowing virtual heaps to work cross core. The only consideration is that in case of cross core allocate/free the cache invalidation MUST be performed on the core that was storing data. It is up to the memory user to ensure this Signed-off-by: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
1 parent a2ac447 commit 38c4810

4 files changed

Lines changed: 23 additions & 175 deletions

File tree

zephyr/include/sof/lib/regions_mm.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,12 @@ struct vmh_heap_config {
7777
struct vmh_block_bundle_descriptor block_bundles_table[MAX_MEMORY_ALLOCATORS_COUNT];
7878
};
7979

80-
struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg,
81-
int memory_region_attribute, int core_id, bool allocating_continuously);
80+
struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocating_continuously);
8281
void *vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size);
8382
int vmh_free_heap(struct vmh_heap *heap);
8483
int vmh_free(struct vmh_heap *heap, void *ptr);
85-
struct vmh_heap *vmh_reconfigure_heap(struct vmh_heap *heap,
86-
struct vmh_heap_config *cfg, int core_id, bool allocating_continuously);
8784
void vmh_get_default_heap_config(const struct sys_mm_drv_region *region,
8885
struct vmh_heap_config *cfg);
89-
struct vmh_heap *vmh_get_heap_by_attribute(uint32_t attr, uint32_t core_id);
9086
/**
9187
* @brief Checks if ptr is in range of given memory range
9288
*

zephyr/lib/alloc.c

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <sof/lib/regions_mm.h>
2323

2424
struct vmh_heap;
25-
struct vmh_heap *virtual_buffers_heap[CONFIG_MP_MAX_NUM_CPUS];
25+
struct vmh_heap *virtual_buffers_heap;
2626
struct k_spinlock vmh_lock;
2727

2828
#undef HEAPMEM_SIZE
@@ -252,12 +252,11 @@ static bool is_virtual_heap_pointer(void *ptr)
252252

253253
static void virtual_heap_free(void *ptr)
254254
{
255-
struct vmh_heap *const heap = virtual_buffers_heap[cpu_get_id()];
256255
int ret;
257256

258257
ptr = (__sparse_force void *)sys_cache_cached_ptr_get(ptr);
259258

260-
ret = vmh_free(heap, ptr);
259+
ret = vmh_free(virtual_buffers_heap, ptr);
261260
if (ret) {
262261
tr_err(&zephyr_tr, "Unable to free %p! %d", ptr, ret);
263262
k_panic();
@@ -280,17 +279,12 @@ static const struct vmh_heap_config static_hp_buffers = {
280279

281280
static int virtual_heap_init(void)
282281
{
283-
int core;
284-
285282
k_spinlock_init(&vmh_lock);
286283

287-
for (core = 0; core < CONFIG_MP_MAX_NUM_CPUS; core++) {
288-
struct vmh_heap *heap = vmh_init_heap(&static_hp_buffers, MEM_REG_ATTR_CORE_HEAP,
289-
core, false);
290-
if (!heap)
291-
tr_err(&zephyr_tr, "Unable to init virtual heap for core %d!", core);
292-
293-
virtual_buffers_heap[core] = heap;
284+
virtual_buffers_heap = vmh_init_heap(&static_hp_buffers, false);
285+
if (!virtual_buffers_heap) {
286+
tr_err(&zephyr_tr, "Unable to init virtual heap");
287+
return -ENOMEM;
294288
}
295289

296290
return 0;
@@ -491,9 +485,6 @@ EXPORT_SYMBOL(rzalloc);
491485
void *rballoc_align(uint32_t flags, uint32_t caps, size_t bytes,
492486
uint32_t align)
493487
{
494-
#if CONFIG_VIRTUAL_HEAP
495-
struct vmh_heap *virtual_heap;
496-
#endif
497488
struct k_heap *heap;
498489

499490
/* choose a heap */
@@ -511,9 +502,8 @@ void *rballoc_align(uint32_t flags, uint32_t caps, size_t bytes,
511502

512503
#if CONFIG_VIRTUAL_HEAP
513504
/* Use virtual heap if it is available */
514-
virtual_heap = virtual_buffers_heap[cpu_get_id()];
515-
if (virtual_heap)
516-
return virtual_heap_alloc(virtual_heap, flags, caps, bytes, align);
505+
if (virtual_buffers_heap)
506+
return virtual_heap_alloc(virtual_buffers_heap, flags, caps, bytes, align);
517507
#endif /* CONFIG_VIRTUAL_HEAP */
518508

519509
if (flags & SOF_MEM_FLAG_COHERENT)

zephyr/lib/regions_mm.c

Lines changed: 7 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,27 @@
1010
#if defined(CONFIG_MM_DRV)
1111
#include <sof/lib/regions_mm.h>
1212

13-
/* list of vmh_heap objects created */
14-
static struct list_item vmh_list = LIST_INIT(vmh_list);
1513

1614
/** @struct vmh_heap
1715
*
1816
* @brief This structure holds all information about virtual memory heap
1917
* it aggregates information about its allocations and
2018
* physical mappings.
2119
*
22-
* @var node generic list member used for list operations
2320
* @var virtual_region pointer to virtual region information, it holds its
2421
* attributes size and beginning ptr provided by zephyr.
2522
* @var physical_blocks_allocators[] a table of block allocators
2623
* each representing a virtual regions part in blocks of a given size
2724
* governed by sys_mem_blocks API.
2825
* @var allocation_sizes[] a table of bit arrays representing sizes of allocations
2926
* made in physical_blocks_allocators directly related to physical_blocks_allocators
30-
* @var core_id id of the core that heap was created on
3127
* @var allocating_continuously configuration value deciding if heap allocations
3228
* will be contiguous or single block.
3329
*/
3430
struct vmh_heap {
35-
struct list_item node;
3631
const struct sys_mm_drv_region *virtual_region;
3732
struct sys_mem_blocks *physical_blocks_allocators[MAX_MEMORY_ALLOCATORS_COUNT];
3833
struct sys_bitarray *allocation_sizes[MAX_MEMORY_ALLOCATORS_COUNT];
39-
int core_id;
4034
bool allocating_continuously;
4135
};
4236

@@ -47,49 +41,32 @@ struct vmh_heap {
4741
* and config. The heap size overall must be aligned to physical page
4842
* size.
4943
* @param cfg Configuration structure with block structure for the heap
50-
* @param memory_region_attribute A zephyr defined virtual region identifier
51-
* @param core_id Core id of a heap that will be created
5244
* @param allocating_continuously Flag deciding if heap can do contiguous allocation.
5345
*
5446
* @retval ptr to a new heap if successful.
5547
* @retval NULL on creation failure.
5648
*/
57-
struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg,
58-
int memory_region_attribute, int core_id, bool allocating_continuously)
49+
struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocating_continuously)
5950
{
6051
const struct sys_mm_drv_region *virtual_memory_regions =
6152
sys_mm_drv_query_memory_regions();
6253
int i;
6354

64-
/* Check if we haven't created heap for this region already */
65-
if (vmh_get_heap_by_attribute(memory_region_attribute, core_id))
66-
return NULL;
67-
6855
struct vmh_heap *new_heap =
6956
rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*new_heap));
7057

7158
if (!new_heap)
7259
return NULL;
7360

74-
new_heap->core_id = core_id;
75-
list_init(&new_heap->node);
7661
struct vmh_heap_config new_config = {0};
7762

78-
/* Search for matching attribute so we place heap on right
79-
* virtual region.
80-
* In case of core heaps regions we count theme from 0 to max
81-
* available cores
82-
*/
83-
if (memory_region_attribute == MEM_REG_ATTR_CORE_HEAP) {
84-
new_heap->virtual_region = &virtual_memory_regions[core_id];
85-
} else {
86-
for (i = CONFIG_MP_MAX_NUM_CPUS;
87-
i < CONFIG_MP_MAX_NUM_CPUS + VIRTUAL_REGION_COUNT; i++) {
63+
/* Search for matching attribute so we place heap on shared virtual region */
64+
for (i = CONFIG_MP_MAX_NUM_CPUS;
65+
i < CONFIG_MP_MAX_NUM_CPUS + VIRTUAL_REGION_COUNT; i++) {
8866

89-
if (memory_region_attribute == virtual_memory_regions[i].attr) {
90-
new_heap->virtual_region = &virtual_memory_regions[i];
91-
break;
92-
}
67+
if (virtual_memory_regions[i].attr == MEM_REG_ATTR_SHARED_HEAP) {
68+
new_heap->virtual_region = &virtual_memory_regions[i];
69+
break;
9370
}
9471
}
9572

@@ -220,9 +197,6 @@ struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg,
220197

221198
new_heap->allocating_continuously = allocating_continuously;
222199

223-
/* Save the new heap pointer to a linked list */
224-
list_item_append(&vmh_list, &new_heap->node);
225-
226200
return new_heap;
227201
fail:
228202
for (i = 0; i < MAX_MEMORY_ALLOCATORS_COUNT; i++) {
@@ -419,9 +393,6 @@ void *vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size)
419393
{
420394
if (!alloc_size)
421395
return NULL;
422-
/* Only operations on the same core are allowed */
423-
if (heap->core_id != cpu_get_id())
424-
return NULL;
425396

426397
void *ptr = NULL;
427398
int mem_block_iterator, allocation_error_code = -ENOMEM;
@@ -566,7 +537,6 @@ int vmh_free_heap(struct vmh_heap *heap)
566537
rfree(heap->allocation_sizes[i]);
567538
}
568539
}
569-
list_item_del(&heap->node);
570540
rfree(heap);
571541
return 0;
572542
}
@@ -587,9 +557,6 @@ int vmh_free(struct vmh_heap *heap, void *ptr)
587557
{
588558
int retval;
589559

590-
if (heap->core_id != cpu_get_id())
591-
return -EINVAL;
592-
593560
size_t mem_block_iter, i, size_to_free, block_size, ptr_bit_array_offset,
594561
ptr_bit_array_position, blocks_to_free;
595562
bool ptr_range_found;
@@ -703,32 +670,6 @@ int vmh_free(struct vmh_heap *heap, void *ptr)
703670
size_to_free);
704671
}
705672

706-
/**
707-
* @brief Reconfigure heap with given config
708-
*
709-
* This will destroy the heap from the pointer and recreate it
710-
* using provided config. Individual region attribute is the
711-
* "anchor" to the virtual space we use.
712-
*
713-
* @param heap Ptr to the heap that should be reconfigured
714-
* @param cfg heap blocks configuration
715-
* @param allocating_continuously allow contiguous on the reconfigured heap
716-
*
717-
* @retval heap_pointer Returns new heap pointer on success
718-
* @retval NULL when reconfiguration failed
719-
*/
720-
struct vmh_heap *vmh_reconfigure_heap(
721-
struct vmh_heap *heap, struct vmh_heap_config *cfg,
722-
int core_id, bool allocating_continuously)
723-
{
724-
uint32_t region_attribute = heap->virtual_region->attr;
725-
726-
if (vmh_free_heap(heap))
727-
return NULL;
728-
729-
return vmh_init_heap(cfg, region_attribute, core_id, allocating_continuously);
730-
}
731-
732673
/**
733674
* @brief Get default configuration for heap
734675
*
@@ -757,47 +698,4 @@ void vmh_get_default_heap_config(const struct sys_mm_drv_region *region,
757698
}
758699
}
759700

760-
/**
761-
* @brief Gets pointer to already created heap identified by
762-
* provided attribute.
763-
*
764-
* @param attr Virtual memory region attribute.
765-
* @param core_id id of the core that heap was created for (core heap specific).
766-
*
767-
* @retval heap ptr on success
768-
* @retval NULL if there was no heap created fitting the attr.
769-
*/
770-
struct vmh_heap *vmh_get_heap_by_attribute(uint32_t attr, uint32_t core_id)
771-
{
772-
struct list_item *vm_heaps_iterator;
773-
struct vmh_heap *retval;
774-
775-
if (attr == MEM_REG_ATTR_CORE_HEAP) {
776-
/* if we look up cpu heap we need to match its cpuid with addr
777-
* we know that regions keep cpu heaps from 0 to max so we match
778-
* the region of the cpu id with lists one to find match
779-
*/
780-
const struct sys_mm_drv_region *virtual_memory_region =
781-
sys_mm_drv_query_memory_regions();
782-
/* we move ptr to cpu vmr */
783-
virtual_memory_region = &virtual_memory_region[core_id];
784-
785-
list_for_item(vm_heaps_iterator, &vmh_list) {
786-
retval =
787-
CONTAINER_OF(vm_heaps_iterator, struct vmh_heap, node);
788-
789-
if (retval->virtual_region->addr == virtual_memory_region->addr)
790-
return retval;
791-
}
792-
} else {
793-
list_for_item(vm_heaps_iterator, &vmh_list) {
794-
retval =
795-
CONTAINER_OF(vm_heaps_iterator, struct vmh_heap, node);
796-
if (retval->virtual_region->attr == attr)
797-
return retval;
798-
}
799-
}
800-
return NULL;
801-
}
802-
803701
#endif /* if defined (CONFIG_MM_DRV) */

zephyr/test/vmh.c

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,11 @@ LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL);
2020
struct vmh_heap;
2121

2222
/* Test creating and freeing a virtual memory heap */
23-
static void test_vmh_init_and_free_heap(int memory_region_attribute,
24-
struct vmh_heap_config *config,
25-
int core_id,
23+
static void test_vmh_init_and_free_heap(struct vmh_heap_config *config,
2624
bool allocating_continuously,
2725
bool expect_success)
2826
{
29-
struct vmh_heap *heap = vmh_init_heap(config, memory_region_attribute,
30-
core_id, allocating_continuously);
27+
struct vmh_heap *heap = vmh_init_heap(config, allocating_continuously);
3128
if (expect_success) {
3229
zassert_not_null(heap,
3330
"Heap initialization expected to succeed but failed");
@@ -147,7 +144,7 @@ static void test_vmh_multiple_allocs(struct vmh_heap *heap, int num_allocs,
147144
static void test_vmh_alloc_multiple_times(bool allocating_continuously)
148145
{
149146
struct vmh_heap *heap =
150-
vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, allocating_continuously);
147+
vmh_init_heap(NULL, allocating_continuously);
151148

152149
zassert_not_null(heap, "Heap initialization failed");
153150

@@ -171,7 +168,7 @@ static void test_vmh_alloc_multiple_times(bool allocating_continuously)
171168
static void test_vmh_alloc_free(bool allocating_continuously)
172169
{
173170
struct vmh_heap *heap =
174-
vmh_init_heap(NULL, MEM_REG_ATTR_CORE_HEAP, 0, allocating_continuously);
171+
vmh_init_heap(NULL, allocating_continuously);
175172

176173
zassert_not_null(heap, "Heap initialization failed");
177174

@@ -195,7 +192,7 @@ static void test_vmh_alloc_free(bool allocating_continuously)
195192
/* Test case for vmh_alloc and vmh_free with and without config */
196193
static void test_heap_creation(void)
197194
{
198-
test_vmh_init_and_free_heap(MEM_REG_ATTR_CORE_HEAP, NULL, 0, false, true);
195+
test_vmh_init_and_free_heap(NULL, 0, false, true);
199196

200197
/* Try to setup with pre defined heap config */
201198
struct vmh_heap_config config = {0};
@@ -208,7 +205,7 @@ static void test_heap_creation(void)
208205

209206
config.block_bundles_table[1].number_of_blocks = 512;
210207

211-
test_vmh_init_and_free_heap(MEM_REG_ATTR_CORE_HEAP, &config, 0, false, true);
208+
test_vmh_init_and_free_heap(&config, 0, false, true);
212209
}
213210

214211
/* Test case for alloc/free on configured heap */
@@ -224,7 +221,7 @@ static void test_alloc_on_configured_heap(bool allocating_continuously)
224221

225222
/* Create continuous allocation heap for success test */
226223
struct vmh_heap *heap =
227-
vmh_init_heap(&config, MEM_REG_ATTR_CORE_HEAP, 0, allocating_continuously);
224+
vmh_init_heap(&config, allocating_continuously);
228225

229226
/* Will succeed on continuous and fail with single block alloc */
230227
test_vmh_alloc_free_check(heap, 512, allocating_continuously);
@@ -234,42 +231,9 @@ static void test_alloc_on_configured_heap(bool allocating_continuously)
234231
zassert_equal(ret, 0, "Failed to free heap");
235232
}
236233

237-
/* Test cases for initializing heaps on all available regions */
238-
static void test_vmh_init_all_heaps(void)
239-
{
240-
int num_regions = CONFIG_MP_MAX_NUM_CPUS + VIRTUAL_REGION_COUNT;
241-
int i;
242-
const struct sys_mm_drv_region *virtual_memory_region =
243-
sys_mm_drv_query_memory_regions();
244-
245-
/* Test initializing all types of heaps */
246-
for (i = 0; i < num_regions; i++) {
247-
248-
/* Zeroed size symbolizes end of regions table */
249-
if (!virtual_memory_region[i].size)
250-
break;
251-
252-
struct vmh_heap *heap = vmh_init_heap(NULL, virtual_memory_region[i].attr,
253-
i, true);
254-
255-
zassert_not_null(heap, "Heap initialization expected to succeed but failed");
256-
257-
/* Test if it fails when heap already exists */
258-
test_vmh_init_and_free_heap(virtual_memory_region[i].attr, NULL, i, true,
259-
false);
260-
261-
if (heap) {
262-
int ret = vmh_free_heap(heap);
263-
264-
zassert_equal(ret, 0, "Failed to free heap");
265-
}
266-
}
267-
}
268-
269234
ZTEST(sof_boot, virtual_memory_heap)
270235
{
271236
test_heap_creation();
272-
test_vmh_init_all_heaps();
273237
test_alloc_on_configured_heap(true);
274238
test_alloc_on_configured_heap(false);
275239
test_vmh_alloc_free(true);

0 commit comments

Comments
 (0)