Skip to content

userspace: doc: document the overall approach how SOF utilizes Zephyr user-space - #11247

Open
kv2019i wants to merge 3 commits into
thesofproject:mainfrom
kv2019i:202609-userll-doc-update
Open

kv2019i wants to merge 3 commits into
thesofproject:mainfrom
kv2019i:202609-userll-doc-update

Conversation

@kv2019i

@kv2019i kv2019i commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

Series of documentation patches to document the overall approach to user-space usage in SOF. This covers the main build options, adds a new central syscalls.h header for documentation and updates agent guardrails for new code.

Moving source files around was considered, but this is not yet done in this PR. As SOF supports multiple approaches: all-kernel (no MMU/MPU), mixed (single audio modules isolated) and app-code-all-in-user, for most source code files, the user/kernel split is not always the same. Starting with a documentation framework seems like the best approach to get started.

SOF audio application logic now runs in Zephyr user-space on userspace
configurations (e.g. Intel PTL with CONFIG_SOF_USERSPACE_LL), but the
source layout gives no indication of which code runs in kernel vs user
context or where the privilege boundary is crossed.

Add a canonical reference under src/include/sof/userspace/:

- README.md documents the execution model, a four-tier directory taxonomy
  (kernel-only / boundary / application / shared-library), the syscall
  boundary, the memory-partition markers and their usage rule, the
  SOF_USERSPACE* Kconfig hierarchy, and rules for placing new code. The
  taxonomy is grep-verifiable.
- syscalls.h is a documentation-only map of the complete syscall surface,
  grouping every SOF __syscall by subsystem and pointing to its z_vrfy_
  validator and z_impl_ logic. It notes that zephyr/syscall/ already
  centralizes the lib-level validators and that the remaining scattered
  validators are the migration target.

No functional change; documentation only.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Make the user/kernel split evident at the point of use: each top-level
src/ directory README now opens with a "Runs in:" banner declaring its tier
(kernel-only / boundary / application / shared-library) and linking to the
canonical reference in src/include/sof/userspace/README.md.

Add banners to existing READMEs (schedule, ipc, ipc4, module_adapter, init,
module) and add short new READMEs for directories that lacked one (audio,
drivers, platform, arch, idc, lib, math). lib/ is flagged as shared-library
with a boundary exception, since dma.c and dai.c host syscall implementations.

No functional change; documentation only.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add a "User/kernel boundary" subsection under Development Standards that
points contributors to src/include/sof/userspace/README.md and states the
requirements for new code: place it in the correct directory tier, cross the
boundary only via a validated syscall, and mark any globals shared with user
threads with a partition marker.

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.

Copilot review overview

🟡 Changes recommended

Several central architecture claims, file classifications, and syscall signatures do not match the current source and configuration.

Review effort: Balanced
Findings: 9 Medium severity

Open (9)
What changed in this PR

Documents SOF’s Zephyr user/kernel boundary and adds contributor guidance for preserving it.

Changes:

  • Defines execution tiers, userspace configuration, memory partitions, and placement rules.
  • Adds a centralized syscall-boundary index.
  • Adds “Runs in” banners and agent guardrails across subsystems.
File Description
AGENTS.md Adds user/kernel contribution rules.
src/​arch/​README.md Classifies architecture support.
src/​audio/​README.md Describes application-tier audio code.
src/​audio/​module_adapter/​README.md Classifies the module adapter boundary.
src/​drivers/​README.md Documents driver privilege requirements.
src/​idc/​README.md Classifies inter-core communication.
src/​include/​sof/​userspace/​README.md Defines the overall userspace architecture.
src/​include/​sof/​userspace/​syscalls.h Indexes SOF syscalls.
src/​init/​README.md Classifies initialization code.
src/​ipc/​README.md Documents IPC boundary behavior.
src/​ipc/​ipc4/​README.md Documents the IPC4 split.
src/​lib/​README.md Classifies common-library code.
src/​math/​README.md Documents user-safe math routines.
src/​module/​README.md Classifies the module API.
src/​platform/​README.md Classifies platform integration.
src/​schedule/​README.md Documents scheduler execution contexts.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +15 to +20
On PTL (`intel_adsp_ace30_ptl`) builds, audio application logic runs in Zephyr **user-space**
by default. The board config enables `CONFIG_USERSPACE`, and
`app/overlays/ptl/ll_userspace_overlay.conf` enables `CONFIG_SOF_USERSPACE_LL`, so the
low-latency (LL) pipeline, the data-processing (DP) modules, and the module-facing IPC all
execute in MMU-protected user threads. The kernel keeps the OS/HAL, boot, drivers, and the
syscall validators.
Comment on lines +56 to +57
- The **only sanctioned crossings** between the two are Zephyr syscalls (see
[The boundary is the syscall set](#the-boundary-is-the-syscall-set)).
Comment on lines +61 to +64
Every `src/` subdirectory falls into one of four tiers. This is the primary mechanism for
making the split evident: the tier tells you where a directory's code runs before you read a
line of it. Each top-level directory's own `README.md` repeats its tier in a **"Runs in:"**
banner.
| IPC | `ipc_msg_send`, `ipc_msg_list_remove`, `ipc_msg_reply`, `ipc_compound_pre_start`, `ipc_compound_post_start`, `ipc_wait_for_compound_msg`, `send_resource_notif` | `sof/ipc/msg.h`, `sof/ipc/ipc_reply.h`, `ipc4/handler.h`, `ipc4/notification.h` | scattered: `ipc/ipc-common.c`, `ipc/ipc3/helper.c`, `ipc/ipc4/handler-kernel.c`, `ipc/ipc4/notification.c` |
| Heap alloc | `sof_heap_alloc`, `sof_heap_free` | `rtos/alloc.h` | `zephyr/syscall/alloc.c` / `zephyr/lib/alloc.c` |
| Virtual regions | `vregion_create_map`, `vregion_set_interim`, `vregion_get`, `vregion_put`, `vregion_alloc_align`, `vregion_alloc_coherent_align`, `vregion_free` | `sof/lib/vregion.h` | `zephyr/syscall/vregion.c` / `zephyr/lib/vregion.c` |
| DMA | `sof_dma_get`, `sof_dma_put`, `sof_dma_get_attribute`, `sof_dma_request_channel`, `sof_dma_release_channel`, `sof_dma_config`, `sof_dma_start`, `sof_dma_stop`, `sof_dma_get_status`, `sof_dma_reload`, `sof_dma_suspend`, `sof_dma_resume` | `sof/lib/sof_dma.h` | `zephyr/syscall/sof_dma.c` / `lib/dma.c` |
Comment on lines +57 to +58
* bool send_resource_notif(uint32_t resource_id, uint32_t event_type,
* uint32_t data);
*
* ## DMA
* Declared: sof/lib/sof_dma.h
* Kernel side: zephyr/syscall/sof_dma.c (z_vrfy_) / src/lib/dma.c (z_impl_)
Comment thread src/init/README.md
Comment on lines +3 to +4
> **Runs in:** Kernel-only — boot and early bring-up run in supervisor context before any user
> thread exists; this code never executes in a user thread. See
Comment thread src/lib/README.md
Comment on lines +3 to +5
> **Runs in:** Shared library — **with a boundary exception.** Most of this directory
> (`lib.c`, `notifier.c`, `objpool.c`, `clk.c`, `agent.c`, `ams.c`, `cpu-clk-manager.c`) is
> context-agnostic helper code linked into whichever thread calls it and must stay user-safe.
Comment thread src/schedule/README.md
Comment on lines +4 to +6
> memory-domain setup. It is split internally between kernel-side files (`zephyr_ll.c`,
> `zephyr_domain.c`, `zephyr_dp_schedule_thread.c`) and user-side files (`zephyr_ll_user.c`,
> `zephyr_ll_app.c`, `zephyr_dp_schedule_application.c`), and it hosts the
**scattered** keep their `z_vrfy_` next to the kernel logic and are the migration targets.

Most syscall declarations are gated by `#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)`; outside that, the same name is a plain inline that calls `z_impl_*` directly (the non-userspace / host-test build).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

non-userspace Zephyr SOF builds still use __syscall declarations, only non-Zephyr builds and ztest builds use inline defines

the validator when the call originates in user space.

**These pairs are the entire user/kernel API surface.** The full, authoritative map lives in
[`syscalls.h`](syscalls.h) in this directory. Summary by subsystem:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

a C header that is never included and is only used for documentation? Not sure I'm a fan... :)


| Marker | Partition | Availability | Use for |
|--------|-----------|--------------|---------|
| `APP_TASK_DATA` / `APP_TASK_BSS` | `common_partition` | `CONFIG_USERSPACE` | Data shared with all user-space modules/tasks |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

so far this partition isn't accessible to DP modules in "application" mode AFAIK

| Marker | Partition | Availability | Use for |
|--------|-----------|--------------|---------|
| `APP_TASK_DATA` / `APP_TASK_BSS` | `common_partition` | `CONFIG_USERSPACE` | Data shared with all user-space modules/tasks |
| `APP_SYSUSER_DATA` / `APP_SYSUSER_BSS` | `sysuser_partition` | `CONFIG_SOF_USERSPACE_LL` | Data shared with the system LL user thread |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

and userspace IPC too?

|--------|-----------|--------------|---------|
| `APP_TASK_DATA` / `APP_TASK_BSS` | `common_partition` | `CONFIG_USERSPACE` | Data shared with all user-space modules/tasks |
| `APP_SYSUSER_DATA` / `APP_SYSUSER_BSS` | `sysuser_partition` | `CONFIG_SOF_USERSPACE_LL` | Data shared with the system LL user thread |
| `K_APP_DMEM(part)` / `K_APP_BMEM(part)` | caller-defined | `CONFIG_USERSPACE` | A component's own partition (e.g. `ipc_context_part`) |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not sure what is meant by this? Which component would want this? Is there an API for a component to call to map a partition to it? Not sure I understand. I see one use example with ipc_context_part but there the kernel-mode IPC part adds it to the userspace IPC domain. A "normal" user component won't have a kernel mode part to do that.

alongside the existing ones — validate every argument, and list the new call in
[`syscalls.h`](syscalls.h).
3. **Mark shared globals.** Any global a user thread reads/writes gets `APP_TASK_*`,
`APP_SYSUSER_*`, or a `K_APP_*` partition marker — and the kernel re-validates it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(not for DP modules)


# User threads / object grants / domains
grep -rl 'K_USER\|_access_grant\|mem_domain' src/<dir>
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

hmmm... in other words "Use the Source, Luke!" ;-)

[`ipc/README.md`](../../../ipc/README.md),
[`audio/module_adapter/README.md`](../../../audio/module_adapter/README.md) — boundary
subsystems.
- [`AGENTS.md`](../../../../AGENTS.md) — contributor rules that reference this document.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what does this mean? Are only AI contributions allowed to this document? ;-)


/**
* \file
* \brief Map of the SOF user/kernel system-call boundary.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not a fan of this file, sorry

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.

3 participants