Skip to content

Commit c4d7ce7

Browse files
committed
zephyr: lib: make vregion_alloc/free system calls
Make vregion_alloc(), vregion_alloc_coherent(), vregion_alloc_align(), vregion_alloc_coherent_align(), and vregion_free() available as Zephyr system calls for user-space threads. Add K_SYSCALL_MEMORY_WRITE verification to all syscall handlers to validate the calling thread has access to the vregion's managed memory area. Add CONFIG_SOF_USERSPACE_INTERFACE_VREGION Kconfig option to control the feature. It is auto-selected by SOF_USERSPACE_LL when SOF_VREGIONS is enabled. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 5721fdf commit c4d7ce7

5 files changed

Lines changed: 129 additions & 20 deletions

File tree

src/include/sof/lib/vregion.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#define __SOF_LIB_VREGION_H__
77

88
#include <stddef.h>
9+
#include <stdint.h>
10+
#include <zephyr/toolchain.h>
911

1012
#ifdef __cplusplus
1113
extern "C" {
@@ -70,12 +72,16 @@ struct vregion *vregion_put(struct vregion *vr);
7072
* @param[in] size Size of memory to allocate in bytes.
7173
* @return void* Pointer to the allocated memory, or NULL on failure.
7274
*/
73-
void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size);
75+
__syscall void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size);
76+
77+
void *z_impl_vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size);
7478

7579
/**
7680
* @brief like vregion_alloc() but allocates coherent memory
7781
*/
78-
void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size);
82+
__syscall void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size);
83+
84+
void *z_impl_vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size);
7985

8086
/**
8187
* @brief Allocate aligned memory from the specified virtual region.
@@ -88,14 +94,20 @@ void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, siz
8894
* @param[in] alignment Alignment of memory to allocate in bytes.
8995
* @return void* Pointer to the allocated memory, or NULL on failure.
9096
*/
91-
void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
92-
size_t size, size_t alignment);
97+
__syscall void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
98+
size_t size, size_t alignment);
99+
100+
void *z_impl_vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
101+
size_t size, size_t alignment);
93102

94103
/**
95104
* @brief like vregion_alloc_align() but allocates coherent memory
96105
*/
97-
void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
98-
size_t size, size_t alignment);
106+
__syscall void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
107+
size_t size, size_t alignment);
108+
109+
void *z_impl_vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
110+
size_t size, size_t alignment);
99111

100112
/**
101113
* @brief Free memory allocated from the specified virtual region.
@@ -105,7 +117,9 @@ void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type typ
105117
* @param[in] vr Pointer to the virtual region instance.
106118
* @param[in] ptr Pointer to the memory to free.
107119
*/
108-
void vregion_free(struct vregion *vr, void *ptr);
120+
__syscall void vregion_free(struct vregion *vr, void *ptr);
121+
122+
void z_impl_vregion_free(struct vregion *vr, void *ptr);
109123

110124
/**
111125
* @brief Log virtual region memory usage.
@@ -183,4 +197,8 @@ static inline void vregion_mem_info(struct vregion *vr, size_t *size, uintptr_t
183197
}
184198
#endif
185199

200+
#if CONFIG_SOF_VREGIONS
201+
#include <zephyr/syscalls/vregion.h>
202+
#endif
203+
186204
#endif /* __SOF_LIB_VREGION_H__ */

zephyr/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,8 @@ zephyr_syscall_header(${SOF_SRC_PATH}/include/ipc4/handler.h)
631631
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/ipc/ipc_msg_send.h)
632632
zephyr_syscall_header(include/rtos/alloc.h)
633633
zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_INTERFACE_ALLOC syscall/alloc.c)
634+
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/vregion.h)
635+
zephyr_library_sources(syscall/vregion.c)
634636
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/dai-zephyr.h)
635637
zephyr_library_sources(syscall/dai.c)
636638

zephyr/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,21 @@ config SOF_USERSPACE_INTERFACE_MUTEX
4343
Enables the sof_umutex API for dynamically-allocated
4444
user-space accessible mutexes backed by k_object_alloc.
4545

46+
config SOF_USERSPACE_INTERFACE_VREGION
47+
bool "Enable SOF vregion interface to userspace threads"
48+
depends on USERSPACE
49+
depends on SOF_VREGIONS
50+
help
51+
Allow user-space threads to use vregion_alloc/vregion_free
52+
and their variants as Zephyr system calls.
53+
4654
config SOF_USERSPACE_LL
4755
bool "Run Low-Latency pipelines in userspace threads"
4856
depends on USERSPACE
4957
select SOF_USERSPACE_INTERFACE_ALLOC
5058
select SOF_USERSPACE_INTERFACE_DMA
5159
select SOF_USERSPACE_INTERFACE_MUTEX
60+
select SOF_USERSPACE_INTERFACE_VREGION if SOF_VREGIONS
5261
help
5362
Run Low-Latency (LL) pipelines in userspace threads. This adds
5463
memory protection between operating system resources and

zephyr/lib/vregion.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ static void lifetime_free(struct vlinear_heap *heap, void *ptr)
305305
* @param vr Pointer to the virtual region instance.
306306
* @param ptr Pointer to the memory to free.
307307
*/
308-
void vregion_free(struct vregion *vr, void *ptr)
308+
void z_impl_vregion_free(struct vregion *vr, void *ptr)
309309
{
310310
if (!vr || !ptr)
311311
return;
@@ -329,7 +329,7 @@ void vregion_free(struct vregion *vr, void *ptr)
329329

330330
k_mutex_unlock(&vr->lock);
331331
}
332-
EXPORT_SYMBOL(vregion_free);
332+
EXPORT_SYMBOL(z_impl_vregion_free);
333333

334334
/**
335335
* @brief Allocate memory type from the virtual region.
@@ -341,8 +341,8 @@ EXPORT_SYMBOL(vregion_free);
341341
*
342342
* @return void* Pointer to the allocated memory, or NULL on failure.
343343
*/
344-
void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
345-
size_t size, size_t alignment)
344+
void *z_impl_vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
345+
size_t size, size_t alignment)
346346
{
347347
void *p;
348348

@@ -370,7 +370,7 @@ void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type,
370370

371371
return p;
372372
}
373-
EXPORT_SYMBOL(vregion_alloc_align);
373+
EXPORT_SYMBOL(z_impl_vregion_alloc_align);
374374

375375
/**
376376
* @brief Allocate memory from the virtual region.
@@ -379,17 +379,17 @@ EXPORT_SYMBOL(vregion_alloc_align);
379379
* @param[in] size Size of the allocation.
380380
* @return void* Pointer to the allocated memory, or NULL on failure.
381381
*/
382-
void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size)
382+
void *z_impl_vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size)
383383
{
384-
return vregion_alloc_align(vr, type, size, 0);
384+
return z_impl_vregion_alloc_align(vr, type, size, 0);
385385
}
386-
EXPORT_SYMBOL(vregion_alloc);
386+
EXPORT_SYMBOL(z_impl_vregion_alloc);
387387

388-
void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size)
388+
void *z_impl_vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size)
389389
{
390390
size = ALIGN_UP(size, CONFIG_DCACHE_LINE_SIZE);
391391

392-
void *p = vregion_alloc_align(vr, type, size, CONFIG_DCACHE_LINE_SIZE);
392+
void *p = z_impl_vregion_alloc_align(vr, type, size, CONFIG_DCACHE_LINE_SIZE);
393393

394394
if (!p)
395395
return NULL;
@@ -398,15 +398,16 @@ void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, siz
398398

399399
return sys_cache_uncached_ptr_get(p);
400400
}
401+
EXPORT_SYMBOL(z_impl_vregion_alloc_coherent);
401402

402-
void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
403-
size_t size, size_t alignment)
403+
void *z_impl_vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type,
404+
size_t size, size_t alignment)
404405
{
405406
if (alignment < CONFIG_DCACHE_LINE_SIZE)
406407
alignment = CONFIG_DCACHE_LINE_SIZE;
407408
size = ALIGN_UP(size, CONFIG_DCACHE_LINE_SIZE);
408409

409-
void *p = vregion_alloc_align(vr, type, size, alignment);
410+
void *p = z_impl_vregion_alloc_align(vr, type, size, alignment);
410411

411412
if (!p)
412413
return NULL;
@@ -415,6 +416,7 @@ void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type typ
415416

416417
return sys_cache_uncached_ptr_get(p);
417418
}
419+
EXPORT_SYMBOL(z_impl_vregion_alloc_coherent_align);
418420

419421
/**
420422
* @brief Log virtual region memory usage.

zephyr/syscall/vregion.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2026 Intel Corporation.
4+
5+
#include <sof/lib/vregion.h>
6+
#include <zephyr/kernel.h>
7+
#include <zephyr/internal/syscall_handler.h>
8+
9+
static inline void *z_vrfy_vregion_alloc(struct vregion *vr,
10+
enum vregion_mem_type type, size_t size)
11+
{
12+
size_t vr_size = 0;
13+
uintptr_t vr_start;
14+
15+
vregion_mem_info(vr, &vr_size, &vr_start);
16+
if (vr_size)
17+
K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)vr_start, vr_size));
18+
19+
return z_impl_vregion_alloc(vr, type, size);
20+
}
21+
#include <zephyr/syscalls/vregion_alloc_mrsh.c>
22+
23+
static inline void *z_vrfy_vregion_alloc_coherent(struct vregion *vr,
24+
enum vregion_mem_type type, size_t size)
25+
{
26+
size_t vr_size = 0;
27+
uintptr_t vr_start;
28+
29+
vregion_mem_info(vr, &vr_size, &vr_start);
30+
if (vr_size)
31+
K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)vr_start, vr_size));
32+
33+
return z_impl_vregion_alloc_coherent(vr, type, size);
34+
}
35+
#include <zephyr/syscalls/vregion_alloc_coherent_mrsh.c>
36+
37+
static inline void *z_vrfy_vregion_alloc_align(struct vregion *vr,
38+
enum vregion_mem_type type,
39+
size_t size, size_t alignment)
40+
{
41+
size_t vr_size = 0;
42+
uintptr_t vr_start;
43+
44+
vregion_mem_info(vr, &vr_size, &vr_start);
45+
if (vr_size)
46+
K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)vr_start, vr_size));
47+
48+
return z_impl_vregion_alloc_align(vr, type, size, alignment);
49+
}
50+
#include <zephyr/syscalls/vregion_alloc_align_mrsh.c>
51+
52+
static inline void *z_vrfy_vregion_alloc_coherent_align(struct vregion *vr,
53+
enum vregion_mem_type type,
54+
size_t size, size_t alignment)
55+
{
56+
size_t vr_size = 0;
57+
uintptr_t vr_start;
58+
59+
vregion_mem_info(vr, &vr_size, &vr_start);
60+
if (vr_size)
61+
K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)vr_start, vr_size));
62+
63+
return z_impl_vregion_alloc_coherent_align(vr, type, size, alignment);
64+
}
65+
#include <zephyr/syscalls/vregion_alloc_coherent_align_mrsh.c>
66+
67+
static inline void z_vrfy_vregion_free(struct vregion *vr, void *ptr)
68+
{
69+
size_t vr_size = 0;
70+
uintptr_t vr_start;
71+
72+
vregion_mem_info(vr, &vr_size, &vr_start);
73+
if (vr_size)
74+
K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)vr_start, vr_size));
75+
76+
z_impl_vregion_free(vr, ptr);
77+
}
78+
#include <zephyr/syscalls/vregion_free_mrsh.c>

0 commit comments

Comments
 (0)