Skip to content

Commit cc45308

Browse files
committed
ptl: mmu: Introduce driver heap for non-privileged modules
Non-privileged modules should be isolated each other. It means that module related data should be located in memory available for kernel and the owner module only. To manage access all such data should be allocated from single, separate region. This patch introduces private module system heap. It is allocated from regular heap, assigned to module thread and then used to allocate all infrastructure data associated with the module. Other non-privileged modules will not have access to this region. Currently it is arbitrary defined to use 5 pages, what could change. Signed-off-by: Jaroslaw Stelter <Jaroslaw.Stelter@intel.com> Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
1 parent d5b295e commit cc45308

8 files changed

Lines changed: 362 additions & 5 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause
2+
*
3+
* Copyright(c) 2025 Intel Corporation. All rights reserved.
4+
*
5+
* Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com>
6+
* Adrian Warecki <adrian.warecki@intel.com>
7+
*/
8+
9+
/**
10+
* \brief Userspace support functions.
11+
*/
12+
#ifndef __RTOS_USERSPACE_HELPER_H__
13+
#define __RTOS_USERSPACE_HELPER_H__
14+
15+
#include <stdint.h>
16+
#include <stddef.h>
17+
18+
#include <rtos/alloc.h>
19+
20+
struct sys_heap;
21+
22+
#ifdef CONFIG_USERSPACE
23+
/**
24+
* Initialize private processing module heap.
25+
* @param N/A.
26+
* @return pointer to the sys_heap structure.
27+
*
28+
* @note
29+
* Function used only when CONFIG_USERSPACE is set.
30+
* The private heap is used only for non-privileged modules
31+
* for all processing module allocations that should be isolated.
32+
* The heap helps to accumulate all dynamic allocations in single
33+
* memory region which is then added to modules memory domain.
34+
*/
35+
static inline struct sys_heap *drv_heap_init(void)
36+
{
37+
return NULL;
38+
}
39+
40+
#endif
41+
42+
/**
43+
* Allocates memory block from private module sys_heap if exists, otherwise call rballoc_align().
44+
* @param sys_heap - pointer to the sys_heap structure
45+
* @param flags - Flags, see SOF_MEM_FLAG_...
46+
* @param bytes - Size in bytes.
47+
* @param alignment - Alignment in bytes.
48+
* @return Pointer to the allocated memory or NULL if failed.
49+
*
50+
* @note When CONFIG_USERSPACE not set function calls rballoc_align()
51+
*/
52+
static inline void *drv_heap_aligned_alloc(struct sys_heap *drv_heap, uint32_t flags, size_t bytes,
53+
uint32_t align)
54+
{
55+
return rballoc_align(flags, bytes, align);
56+
}
57+
58+
/**
59+
* Allocates memory block from private module sys_heap if exists, otherwise call rmalloc.
60+
* @param sys_heap - pointer to the sys_heap structure
61+
* @param flags - Flags, see SOF_MEM_FLAG_...
62+
* @param bytes - Size in bytes.
63+
* @return - Pointer to the allocated memory or NULL if failed.
64+
*
65+
* * @note When CONFIG_USERSPACE not set function calls rmalloc()
66+
*/
67+
static inline void *drv_heap_rmalloc(struct sys_heap *drv_heap, uint32_t flags, size_t bytes)
68+
{
69+
return rmalloc(flags, bytes);
70+
}
71+
72+
/**
73+
* Similar to user_rmalloc(), guarantees that returned block is zeroed.
74+
*
75+
* @note When CONFIG_USERSPACE not set function calls rzalloc()
76+
*/
77+
static inline void *drv_heap_rzalloc(struct sys_heap *drv_heap, uint32_t flags, size_t bytes)
78+
{
79+
return rzalloc(flags, bytes);
80+
}
81+
82+
/**
83+
* Frees the memory block from private module sys_heap if exists.
84+
* otherwise call rfree.
85+
* @param ptr Pointer to the memory block.
86+
*
87+
* @note User should take care to not free memory allocated from sys_heap
88+
* with drv_heap set to NULL. It will cause exception.
89+
*
90+
* When CONFIG_USERSPACE not set function calls rfree()
91+
*/
92+
static inline void drv_heap_free(struct sys_heap *drv_heap, void *mem)
93+
{
94+
rfree(mem);
95+
}
96+
97+
/**
98+
* Free private processing module heap.
99+
* @param sys_heap pointer to the sys_heap structure.
100+
*
101+
* @note
102+
* Function used only when CONFIG_USERSPACE is set.
103+
* Frees private module heap.
104+
*/
105+
static inline void drv_heap_remove(struct sys_heap *drv_heap)
106+
{ }
107+
108+
#endif /* __RTOS_USERSPACE_HELPER_H__ */

src/audio/module_adapter/module_adapter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
7171
int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
7272
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;
7373

74-
mod = rzalloc(flags, sizeof(*mod));
74+
mod = drv_heap_rzalloc(drv->drv_heap, flags, sizeof(*mod));
7575
if (!mod) {
7676
comp_err(dev, "module_adapter_new(), failed to allocate memory for module");
7777
goto err;

src/audio/module_adapter/module_adapter_ipc4.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ int module_adapter_init_data(struct comp_dev *dev,
136136
if (cfgsz == (sizeof(*cfg) + pinsz)) {
137137
dst->nb_input_pins = n_in;
138138
dst->nb_output_pins = n_out;
139-
dst->input_pins = rmalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, pinsz);
139+
dst->input_pins = drv_heap_rmalloc(dev->drv->drv_heap, SOF_MEM_FLAG_USER |
140+
SOF_MEM_FLAG_COHERENT, pinsz);
140141
if (!dst->input_pins)
141142
return -ENOMEM;
142143

src/include/sof/audio/component.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <sof/audio/pipeline.h>
2222
#include <sof/debug/telemetry/telemetry.h>
2323
#include <rtos/idc.h>
24+
#include <rtos/userspace_helper.h>
2425
#include <sof/lib/dai.h>
2526
#include <sof/schedule/schedule.h>
2627
#include <ipc/control.h>
@@ -590,6 +591,7 @@ struct comp_driver {
590591
* Intended to replace the ops field.
591592
* Currently used by module_adapter.
592593
*/
594+
struct sys_heap *drv_heap; /**< Userspace heap */
593595
};
594596

595597
/** \brief Holds constant pointer to component driver */
@@ -853,16 +855,15 @@ static inline enum sof_comp_type dev_comp_type(const struct comp_dev *dev)
853855
* @param bytes Size of the component device in bytes.
854856
* @return Pointer to the component device.
855857
*/
856-
static inline struct comp_dev *comp_alloc(const struct comp_driver *drv,
857-
size_t bytes)
858+
static inline struct comp_dev *comp_alloc(const struct comp_driver *drv, size_t bytes)
858859
{
859860
struct comp_dev *dev = NULL;
860861

861862
/*
862863
* Use uncached address everywhere to access components to rule out
863864
* multi-core failures. TODO: verify if cached alias may be used in some cases
864865
*/
865-
dev = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, bytes);
866+
dev = drv_heap_rzalloc(drv->drv_heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, bytes);
866867
if (!dev)
867868
return NULL;
868869
dev->size = bytes;

zephyr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ zephyr_library_sources(
474474
lib/alloc.c
475475
lib/cpu.c
476476
lib/pm_runtime.c
477+
lib/userspace_helper.c
477478

478479
# Common library functions - Will be moved to Zephyr over time
479480
lib.c

zephyr/Kconfig

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

65+
config SOF_ZEPHYR_USERSPACE_MODULE_HEAP_SIZE
66+
hex "Size of the private heap created for each userspace module"
67+
default 0x1000
68+
help
69+
The size of the private heap created for each userspace module. Each userspace
70+
module has its own independent heap to which only it has access. This heap is
71+
shared between instances of the same module.
72+
6573
config ZEPHYR_NATIVE_DRIVERS
6674
bool "Use Zephyr native drivers"
6775
default n
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause
2+
*
3+
* Copyright(c) 2025 Intel Corporation. All rights reserved.
4+
*
5+
* Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com>
6+
* Adrian Warecki <adrian.warecki@intel.com>
7+
*/
8+
9+
/**
10+
* \brief Userspace support functions.
11+
*/
12+
#ifndef __ZEPHYR_LIB_USERSPACE_HELPER_H__
13+
#define __ZEPHYR_LIB_USERSPACE_HELPER_H__
14+
15+
#ifdef CONFIG_USERSPACE
16+
#define DRV_HEAP_SIZE ALIGN_UP(CONFIG_SOF_ZEPHYR_USERSPACE_MODULE_HEAP_SIZE, \
17+
CONFIG_MM_DRV_PAGE_SIZE)
18+
19+
/**
20+
* Initialize private processing module heap.
21+
* @param N/A.
22+
* @return pointer to the sys_heap structure.
23+
*
24+
* @note
25+
* Function used only when CONFIG_USERSPACE is set.
26+
* The private heap is used only for non-privileged modules
27+
* for all processing module allocations that should be isolated.
28+
* The heap helps to accumulate all dynamic allocations in single
29+
* memory region which is then added to modules memory domain.
30+
*/
31+
struct sys_heap *drv_heap_init(void);
32+
33+
#endif
34+
35+
/**
36+
* Allocates memory block from private module sys_heap if exists, otherwise call rballoc_align().
37+
* @param sys_heap - pointer to the sys_heap structure
38+
* @param flags - Flags, see SOF_MEM_FLAG_...
39+
* @param bytes - Size in bytes.
40+
* @param alignment - Alignment in bytes.
41+
* @return Pointer to the allocated memory or NULL if failed.
42+
*
43+
* @note When CONFIG_USERSPACE not set function calls rballoc_align()
44+
*/
45+
void *drv_heap_aligned_alloc(struct sys_heap *drv_heap, uint32_t flags, size_t bytes,
46+
uint32_t align);
47+
48+
/**
49+
* Allocates memory block from private module sys_heap if exists, otherwise call rmalloc.
50+
* @param sys_heap - pointer to the sys_heap structure
51+
* @param flags - Flags, see SOF_MEM_FLAG_...
52+
* @param bytes - Size in bytes.
53+
* @return - Pointer to the allocated memory or NULL if failed.
54+
*
55+
* * @note When CONFIG_USERSPACE not set function calls rmalloc()
56+
*/
57+
void *drv_heap_rmalloc(struct sys_heap *drv_heap, uint32_t flags, size_t bytes);
58+
59+
/**
60+
* Similar to user_rmalloc(), guarantees that returned block is zeroed.
61+
*
62+
* @note When CONFIG_USERSPACE not set function calls rzalloc()
63+
*/
64+
void *drv_heap_rzalloc(struct sys_heap *drv_heap, uint32_t flags, size_t bytes);
65+
66+
/**
67+
* Frees the memory block from private module sys_heap if exists.
68+
* otherwise call rfree.
69+
* @param ptr Pointer to the memory block.
70+
*
71+
* @note User should take care to not free memory allocated from sys_heap
72+
* with drv_heap set to NULL. It will cause exception.
73+
*
74+
* When CONFIG_USERSPACE not set function calls rfree()
75+
*/
76+
void drv_heap_free(struct sys_heap *drv_heap, void *mem);
77+
78+
/**
79+
* Free private processing module heap.
80+
* @param sys_heap pointer to the sys_heap structure.
81+
*
82+
* @note
83+
* Function used only when CONFIG_USERSPACE is set.
84+
* Frees private module heap.
85+
*/
86+
void drv_heap_remove(struct sys_heap *drv_heap);
87+
88+
#endif /* __ZEPHYR_LIB_USERSPACE_HELPER_H__ */

0 commit comments

Comments
 (0)