Skip to content

Commit f8c9377

Browse files
committed
userspace: add a userspace heap
Add a userspace heap, memory type and associated helper APIs. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
1 parent 70ad318 commit f8c9377

4 files changed

Lines changed: 101 additions & 1 deletion

File tree

src/include/ipc/topology.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct sof_ipc_comp {
8989
#define SOF_MEM_CAPS_L3 BIT(8) /**< L3 memory */
9090
/* Don't forget to update when adding a new bit to the ABI. */
9191
#define SOF_MEM_CAPS_LOWEST_INVALID BIT(9) /**< Used for input validation */
92+
#define SOF_MEM_CAPS_MMU_SHD BIT(10) /**< MMU shared memory */
9293

9394
/*
9495
* overrun will cause ring buffer overwrite, instead of XRUN.

zephyr/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ config SOF_ZEPHYR_VIRTUAL_HEAP_SIZE
5151
NOTE: Keep in mind that the heap size should not be greater than the physical
5252
memory size of the system defined in DT (and this includes baseFW text/data).
5353

54+
config SOF_ZEPHYR_USER_HEAP_SIZE
55+
hex "Size of the Zephyr userspace heap for SOF"
56+
depends on SOF_STAGING
57+
depends on SOF_USERSPACE
58+
default 0x20000 if SOC_INTEL_ACE30
59+
default 0x0
60+
help
61+
Support scaling of the userspace address heap size for different platforms.
62+
NOTE: Keep in mind that the heap size should not be greater than the physical
63+
memory size of the system defined in DT (and this includes baseFW text/data
64+
alongside the default SOF heap size).
65+
5466
config ZEPHYR_NATIVE_DRIVERS
5567
bool "Use Zephyr native drivers"
5668
default n

zephyr/include/rtos/alloc.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,46 @@ void rfree(void *ptr);
139139
/* TODO: remove - debug only - only needed for linking */
140140
static inline void heap_trace_all(int force) {}
141141

142+
#if CONFIG_SOF_USERSPACE
143+
144+
/**
145+
* Returns whether pointer is in userspace heap.
146+
* @return True is userspace pointer.
147+
*/
148+
bool s_heap_user_is_pointer(void *ptr);
149+
150+
/**
151+
* Returns the start of user memory heap.
152+
* @return Pointer to the user memory heap start address.
153+
*/
154+
uintptr_t s_heap_user_get_start(void);
155+
156+
/**
157+
* Returns the size of user memory heap.
158+
* @return Size of the user memory region which can be used for user heap.
159+
*/
160+
static inline size_t s_get_heap_get_user_size(void)
161+
{
162+
return ROUND_DOWN(CONFIG_SOF_ZEPHYR_USER_HEAP_SIZE, CONFIG_MMU_PAGE_SIZE);
163+
}
164+
#else
165+
166+
static inline bool s_heap_user_is_pointer(void *ptr)
167+
{
168+
return false;
169+
}
170+
171+
static inline uintptr_t s_heap_user_get_start(void)
172+
{
173+
return 0;
174+
}
175+
176+
static inline size_t s_get_heap_get_user_size(void)
177+
{
178+
return 0;
179+
}
180+
#endif
181+
142182
/** @}*/
143183

144184
#endif /* __ZEPHYR_RTOS_ALLOC_H__ */

zephyr/lib/alloc.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ static uint8_t __aligned(PLATFORM_DCACHE_ALIGN) heapmem[HEAPMEM_SIZE];
9898
* to allow memory management driver to control unused
9999
* memory pages.
100100
*/
101-
__section(".heap_mem") static uint8_t __aligned(PLATFORM_DCACHE_ALIGN) heapmem[HEAPMEM_SIZE];
101+
102+
__section(".heap_mem") static uint8_t __aligned(HOST_PAGE_SIZE) heapmem[HEAPMEM_SIZE];
103+
104+
#if CONFIG_SOF_USERSPACE
105+
#define USER_HEAP_MEM_SIZE CONFIG_SOF_ZEPHYR_USER_HEAP_SIZE
106+
__section(".heap_mem") static uint8_t __aligned(HOST_PAGE_SIZE) user_heapmem[USER_HEAP_MEM_SIZE];
107+
#endif
102108

103109
#elif defined(CONFIG_ARCH_POSIX)
104110

@@ -125,6 +131,35 @@ extern char _end[], _heap_sentry[];
125131

126132
static struct k_heap sof_heap;
127133

134+
#if CONFIG_SOF_USERSPACE
135+
static struct k_heap sof_user_heap;
136+
137+
/**
138+
* Returns the start of user memory heap.
139+
* @return Pointer to the user memory heap start address.
140+
*/
141+
bool s_heap_user_is_pointer(void *ptr)
142+
{
143+
if (is_cached(ptr))
144+
ptr = sys_cache_uncached_ptr_get((__sparse_force void __sparse_cache *)ptr);
145+
146+
if ((POINTER_TO_UINT(ptr) >= (uintptr_t)&user_heapmem[0]) &&
147+
(POINTER_TO_UINT(ptr) < (uintptr_t)&user_heapmem[CONFIG_SOF_ZEPHYR_USER_HEAP_SIZE]))
148+
return true;
149+
150+
return false;
151+
}
152+
153+
/**
154+
* Returns the start of user memory heap.
155+
* @return Pointer to the user memory heap start address.
156+
*/
157+
uintptr_t s_heap_user_get_start(void)
158+
{
159+
return (uintptr_t)ROUND_UP(&user_heapmem[0], CONFIG_MMU_PAGE_SIZE);
160+
}
161+
#endif
162+
128163
#if CONFIG_L3_HEAP
129164
static struct k_heap l3_heap;
130165

@@ -401,6 +436,10 @@ void *rmalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes)
401436
return ptr;
402437
#else
403438
k_panic();
439+
#endif
440+
#if CONFIG_USERSPACE
441+
} else if (caps & SOF_MEM_CAPS_MMU_SHD) {
442+
heap = &sof_user_heap;
404443
#endif
405444
} else {
406445
heap = &sof_heap;
@@ -504,6 +543,11 @@ void *rballoc_align(uint32_t flags, uint32_t caps, size_t bytes,
504543
return virtual_heap_alloc(virtual_buffers_heap, flags, caps, bytes, align);
505544
#endif /* CONFIG_VIRTUAL_HEAP */
506545

546+
#if CONFIG_SOF_USERSPACE
547+
if (caps & SOF_MEM_CAPS_MMU_SHD)
548+
heap = &sof_user_heap;
549+
#endif
550+
507551
if (flags & SOF_MEM_FLAG_COHERENT)
508552
return heap_alloc_aligned(heap, align, bytes);
509553

@@ -541,6 +585,9 @@ static int heap_init(void)
541585
{
542586
sys_heap_init(&sof_heap.heap, heapmem, HEAPMEM_SIZE);
543587

588+
#if CONFIG_SOF_USERSPACE
589+
sys_heap_init(&sof_user_heap.heap, user_heapmem, USER_HEAP_MEM_SIZE);
590+
#endif
544591
#if CONFIG_L3_HEAP
545592
sys_heap_init(&l3_heap.heap, UINT_TO_POINTER(get_l3_heap_start()), get_l3_heap_size());
546593
#endif

0 commit comments

Comments
 (0)