Skip to content

zephyr: ll_user: carve out separate heap for LL data that kernel needs to access - #11450

Merged
lgirdwood merged 5 commits into
thesofproject:mainfrom
kv2019i:202611-ll-heap-areas
Nov 13, 2026
Merged

lgirdwood merged 5 commits into
thesofproject:mainfrom
kv2019i:202611-ll-heap-areas

Conversation

@kv2019i

@kv2019i kv2019i commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

As part of work to harden the syscall interface, this PR adds infra to manage memory that needs to be accessed from code runnin in kernel space (mostly in system calls called by LL scheduler).

The kernel areas are for objects that kernel code creates and LL user threads access. Their
allocator is a bump allocator with kernel-only state and no free, so use it for objects that
live until the firmware is reset. The Xtensa MMU has one write permission for both rings, so
the RO area is also read-only to kernel code running in the LL memory domain, such as system
calls from LL threads: only kernel threads can write objects there.

The LL user heap is a k_heap whose sys_heap metadata is in memory that
the LL and IPC user threads can write, while kernel code allocates and
frees from it. A user thread can therefore forge the metadata that the
kernel allocator follows.

As a first step towards keeping the kernel out of that heap, reserve two
page-aligned areas at the start of the LL memory region: one mapped
read-write and one mapped read-only into the LL memory domain. Kernel
code will allocate the objects that LL user threads must access from
these areas, with allocator state kept in kernel memory.

The sizes are set with CONFIG_SOF_ZEPHYR_LL_KAREA_RW_SIZE and
CONFIG_SOF_ZEPHYR_LL_KAREA_RO_SIZE. They are taken from the region size
CONFIG_SOF_ZEPHYR_SYS_USER_HEAP_SIZE, so the kernel heap, from which the
region is allocated, is not affected. The LL user heap gets the rest.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add zephyr_ll_karea_alloc() for kernel code that creates objects in the
LL memory region. It is a bump allocator whose state is in kernel-only
memory, so nothing that user threads write can affect it. Allocations
are cache line aligned and sized, and return the cached alias unless
SOF_MEM_FLAG_COHERENT is given, like sof_heap_alloc().

Memory is never freed, which suits the objects created at boot and at
secondary core bring-up that live until the firmware is reset. Add
zephyr_ll_karea_contains() for checking that memory lies in an area.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Kernel code is to stop allocating from the LL user heap, whose metadata
user threads can write. Add CONFIG_SOF_ZEPHYR_LL_HEAP_KERNEL_TRACE to
log each allocation from and free to that heap made by a kernel thread,
with size and caller address, for finding the remaining callers on
target. Calls by user threads, including those that enter the kernel
through system calls, are not logged.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Check that an LL user thread can write objects allocated from the
kernel RW area, can read objects in the kernel RO area and faults when
writing them, and that the area bounds checks and oversized requests
behave as expected.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Describe the kernel RO and RW areas of the LL memory region, their
allocator and the restriction on writing the RO area, and the option
for tracing LL heap use by kernel threads.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The Xtensa MMU permission split still needs target validation across cached and uncached aliases, including supervisor writes from LL-domain syscalls, since the added tests cover only cached-alias user access.

No open issues 🎉

What changed in this PR

Adds kernel-managed memory areas alongside the low-latency (LL) user heap to support syscall hardening. Persistent shared objects can use a separate allocator whose state remains inaccessible to user threads.

Changes:

  • Splits the LL memory region into read-only and read-write kernel-managed areas plus the remaining user heap.
  • Adds configurable area sizes, allocation and containment APIs, and optional tracing of kernel-thread use of the LL heap.
  • Documents memory permissions and lifetime constraints, and adds standalone userspace tests.
File Description
zephyr/​test/​userspace/​test_ll_karea.c Adds tests for access permissions, containment, and allocation limits.
zephyr/​test/​CMakeLists.txt Includes the new tests in standalone LL userspace builds.
zephyr/​lib/​alloc.c Adds optional tracing of kernel-thread LL heap allocations and frees.
zephyr/​Kconfig Defines kernel-area sizes and the heap tracing option.
src/​kernel/​schedule/​zephyr_ll_user.c Partitions and maps the region; implements the locked bump allocator and containment checks.
src/​include/​sof/​userspace/​README.md Documents the region layout, permissions, and persistent object lifetime.
src/​include/​sof/​schedule/​ll_schedule_domain.h Declares and documents the kernel-area APIs.

Review effort: Balanced

@intel-sofci

intel-sofci commented Nov 12, 2026 •

Copy link
Copy Markdown

PR 11450: test results

Run date: 2026-11-13 09:20 UTC

Tested commit: 6dfcc277ec3777367aa8b3a5511366c70dc0edfd

mtl pass rate lnl pass rate ptl pass rate wcl pass rate nvl pass rate

@lgirdwood
lgirdwood merged commit 407ff7e into thesofproject:main Nov 13, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants