Skip to content

Phase 3 (part 1): split the mixed IPC files, kernel halves to src/kernel/ipc - #11422

Draft
lgirdwood wants to merge 10 commits into
thesofproject:mainfrom
lgirdwood:kernel-user/phase3a
Draft

lgirdwood wants to merge 10 commits into
thesofproject:mainfrom
lgirdwood:kernel-user/phase3a

Conversation

@lgirdwood

Copy link
Copy Markdown
Member

Phase 3 of #11306 (kernel / user-space partition), first part: split the three mixed IPC source files and move their kernel halves into src/kernel/ipc. Stacked on #11421 (trace removal), which is stacked on #11420; only the last three commits are new.

The kernel half of src/X/foo.c is src/kernel/X/foo-kernel.c, and each user half says where its kernel half is. Shared helpers that used to be static are now declared in the existing IPC headers.

Patches

  1. ipc/ipc-common.c → kernel/ipc/ipc-common-kernel.c:
    • Moves to the kernel half:
      • the IPC task, command completion and IDC forwarding;
      • the outgoing message queue and the kernel half of the ipc_msg_send() and ipc_msg_list_remove() system calls;
      • the setup of the user-space IPC threads and the command forwarding to them;
      • the user-space LL IPC context with ipc_get();
      • ipc_init().
    • Stays in ipc-common.c:
      • message allocation and the component lookups;
      • the user-space IPC thread function and its default dispatch. The thread entry point and its event bits are now in sof/ipc/common.h.
  2. ipc/ipc4/handler-user.c → kernel/ipc/ipc4/handler-user-kernel.c:
    • Moves to the kernel half: the global and module message routers, which run in the kernel IPC thread and forward commands to the user-space IPC thread, and everything only they use:
      • the reply message;
      • the target core lookup and the multicore SET_PIPELINE_STATE sequencing;
      • the MOD_INIT_INSTANCE driver lookup and module loading;
      • the CHAIN_DMA, IPC gateway and GDB commands;
      • kernel-mode module init;
      • the base firmware LARGE_CONFIG get and set;
      • the wrappers that the routers of builds without user-space LL call directly.
    • Stays in handler-user.c: the pipeline state handling, the module config and large config processing, and the user-space IPC thread dispatch.
    • Now shared: four helpers, declared in ipc4/handler.h.
  3. ipc/ipc4/helper.c → kernel/ipc/ipc4/helper-kernel.c:
    • Moves to the kernel half:
      • the component driver lookup, which reads the IMR manifest, registers loadable modules and walks the driver list;
      • comp_new_ipc4() and ipc4_user_module_load();
      • the IDC helpers ipc4_process_on_core() and ipc_comp_free_remote();
      • the chain DMA manager.
    • Stays in helper.c: pipeline and component management, binding and the DMA config parsing.
    • Includes: helper.c no longer includes the rimage manifest, platform memory map or library manager headers.

The 16 cmocka and 2 ztest unit test CMake files that build ipc-common.c also build its kernel half. No unit test builds the IPC4 files.

Some code in the user halves still calls the kernel (ipc4_process_on_core() and ipc_comp_free_remote() in builds without user-space LL, and the base firmware driver lookup). The issue tracks that as a Phase 5 item.

Functional change

None. The functions are moved, not changed. The per-function disassembly of every image (the builds listed under Testing) was compared before and after each commit. It differs only where the compiler can no longer inline or specialise a function across the split:

  • ipc-common.c: no such cases. Only Xtensa alignment padding and narrow/wide encodings differ, plus the line numbers passed to the assertion handler in qemu_xtensa, which has assertions enabled.
  • handler-user.c:
    • the callers of the shared helpers call them with the full argument list instead of GCC's constant-propagated clones;
    • ipc4_set_pipeline_state() only partially inlines ipc4_pipeline_id_get() (builds without user-space LL);
    • the routers' register allocation differs.
  • helper.c: the callers no longer inline the shared helpers:
    • ipc_pipeline_new(), ipc_pipeline_free(), ipc4_comp_connect() and ipc4_comp_disconnect() call ipc4_process_on_core() and ipc_comp_free_remote();
    • comp_new_ipc4(), ipc4_user_module_load() and ipc4_chain_manager_create() call the module config and component list helpers.

Symbols and SYS_INIT() order are otherwise unchanged, as are every build's .config and the generated rimage configurations.

Testing

  • Per commit:
    • Builds: tgl, tgl-h, mtl, lnl, ptl, wcl, nvl, imx8, imx8x, imx8m, imx8m_cm7, imx8ulp, imx95 and qemu_xtensa, and the extra CI configurations:
      • native_sim IPC3/IPC4 stub builds;
      • imx93 64-bit;
      • PTL with each userspace overlay;
      • PTL with CONFIG_SOF_USERSPACE_PROXY=n;
      • PTL and MTL with os_linux_overlay.conf;llext_relocatable.conf.
    • Comparisons: objects, LLEXT modules and firmware images (sections, symbols, SYS_INIT() order), plus the per-function disassembly comparison described above.
    • Signing: rimage runs for every Intel platform, and the generated configs are unchanged.
    • Cadence xt-clang (RI-2022.10): MTL, PTL and NVL compile.
    • ZTest: the unit tests pass, run as in CI (18 of 18 configurations).
    • Host: the host library and the cmocka unit tests build and pass for all nine defconfigs and the library config.
  • At the tip:
    • the testbench and the tools pass;
    • the platforms that already fail on main (acp_6_0, acp_7_0, acp_7_x, mt8186, mt8188, mt8195, mt8196, mt8365) have unchanged error sets.
  • Hardware: TGL (UP Xtreme i11), sof-hda-generic-cavs25-2ch.tplg, comparing the tip of Kernel/user partition: remove the SOF DMA trace #11421 and this branch. Both boot, play 5 s, and play again after runtime suspend, with no DSP errors.

🤖 Generated with Claude Code

lrgirdwo and others added 10 commits November 7, 2026 19:07
The architecture code (Xtensa cache and interrupt support, the host
build's architecture layer and its library defconfig) is kernel-only.
Move it to src/kernel/arch.

Zephyr only uses it through include directories and the Xtensa cache
attribute source listed in zephyr/CMakeLists.txt; update those paths.
The host builds now add it from src/kernel. Update the configuration
search paths in kconfig.cmake and defconfigs.cmake, the testbench,
tplg_parser and app CMake, the MediaTek tools script and the docs.

Its Kconfig is sourced from the same place in src/Kconfig as before,
so the Kconfig definition order does not change. References to the
removed XTOS build output (build_<plat>_gcc/src/arch/xtensa) in old
scripts and .gitignore are left as they are. No functional change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The platform code (memory maps, clocks, interrupts, platform init and
the host library and posix platform layers) is kernel-only. Move it to
src/kernel/platform.

Point SOF_PLATFORM_PATH in zephyr/CMakeLists.txt to the new location;
the two i.MX linker snippets now use it as well. The host builds now
add it from src/kernel. Update the include directories of the cmocka
and ztest unit tests, the testbench and tplg_parser, the platform
header patterns in the include checker's manifest, CODEOWNERS, the
MediaTek tools script and the docs.

Its Kconfig is sourced from the same place in src/Kconfig as before,
so the Kconfig definition order does not change. No functional change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
zephyr/CMakeLists.txt lists the platform, driver and Xtensa cache
attribute sources itself, mixed with the Zephyr integration sources in
zephyr/lib, so they are built into modules_sof although they now live
under src/kernel.

After all sources have been added, move every source under src/kernel
from modules_sof to sof_kernel, so that sof_kernel holds exactly the
code in src/kernel however it was added. Both libraries are created in
the same directory and link the same SOF interface library, so the
compile flags do not change. No functional change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The Kconfig options of the SOF probe log backend
(CONFIG_LOG_BACKEND_SOF_PROBE*) are defined in src/trace/Kconfig,
which is otherwise only about the SOF DMA trace. Move them to a Kconfig
file next to the backend, in src/kernel/logging, sourced from
src/kernel/Kconfig. The option values are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The host builds (testbench, host library) print their traces to stderr
through the CONFIG_LIBRARY part of trace-soflogger.h, which is only
included when CONFIG_TRACE is set. CONFIG_TRACE also builds the SOF DMA
trace, which the host builds do not need.

Move the host printing to a header of its own, trace-host.h, and use it
for CONFIG_LIBRARY builds. It maps tr_err(), tr_warn(), tr_info(),
tr_dbg() and the component trace macros to the same levels and output
as before, which is what the host library got with CONFIG_TRACEV and
CONFIG_TRACEE set. Disable CONFIG_TRACE for the host library, build the
host trace support unconditionally, and drop CONFIG_TRACEV from
library_defconfig.

The host library code is unchanged; only the trace contexts move from
the .trace_ctx section, which only the firmware dictionary logger uses,
to normal data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The SOF DMA trace (CONFIG_TRACE) sends dictionary-encoded traces for
the sof-logger tool over a host DMA channel. Zephyr builds use Zephyr
logging instead and cannot enable it at all: zephyr/include/sof/trace/
preproc.h stops the build if CONFIG_TRACE is set. Since the previous
patch the host builds do not use it either, so nothing builds it any
more.

Remove it:
- src/trace with its Kconfig (CONFIG_TRACE, CONFIG_TRACEV, CONFIG_TRACEE,
  CONFIG_TRACEM and the trace filtering options), trace-soflogger.h and
  dma-trace.h;
- the IPC DMA copy helper (src/ipc/dma-copy.c) and
  CONFIG_TRACE_CHANNEL, used only by the DMA trace;
- the code under CONFIG_TRACE in the IPC3 handler (the DMA trace and
  trace filter commands; the stub that accepts trace commands without
  a DMA trace stays), the i.MX and AMD platform init, the system init,
  the panic handler and the cmocka mocks, and the DMA trace calls in
  the IPC3 PM gate handler;
- the trace position helpers ipc_build_trace_posn() and
  ipc_trigger_trace_xfer(), the trace and DMA trace fields of struct
  sof, and dump_hex() with the two CONFIG_TRACEV blocks in the Waves
  module that used it;
- the CONFIG_TRACE=n settings in the board and application configs,
  and the CONFIG_TRACE_CHANNEL settings in the cmocka defconfigs.

trace.h keeps the Zephyr logging, host and no-op trace macros. The IPC
trace structures in include/ipc/trace.h are host ABI and stay. The
dma_copy_*() declarations and DMA_TRACE_CHANNEL are still referenced
by the legacy (non-native driver) probe and AMD DMA code and are left
for the removal of that code.

No firmware build compiled the DMA trace itself. The firmware does
change in two ways: the unused ipc_build_trace_posn() and
ipc_trigger_trace_xfer() are no longer built, and struct sof is two
pointers smaller, which changes the field offsets in the code that
uses it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
With src/trace removed, src/kernel holds all directories of kernel-only
code. Update AGENTS.md and the user-space README, which listed the
directories not yet moved there, and the init README, which still
described the DMA trace initialization.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
ipc-common.c mixes code that only runs in kernel mode with code that
also runs in the user-space IPC thread. Move the kernel part to
src/kernel/ipc/ipc-common-kernel.c:
- the IPC context and ipc_get() of user-space LL builds;
- the IPC task, command completion and IDC forwarding to other cores;
- the outgoing message queue and its work queue, and the kernel half
  of the ipc_msg_send() and ipc_msg_list_remove() system calls;
- the setup of the user-space IPC threads, their kernel-only object
  copies and command forwarding to them;
- ipc_init().

ipc-common.c keeps message allocation, the component lookups and, for
user-space LL builds, the user-space IPC thread function and the
default command dispatch. The user thread entry point and its event
bits are now shared through sof/ipc/common.h. The unit tests that build
ipc-common.c also build the kernel part.

The code is unchanged. Only the Xtensa assembler's alignment padding
and its choice between narrow and wide encodings of the same
instructions differ in a few functions, as do the line numbers the
moved functions pass to the assertion handler in builds with
assertions (qemu_xtensa).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
handler-user.c mixes the IPC4 global and module message routers, which
run in the kernel IPC thread, with the handlers that also run in the
user-space IPC thread. Move the kernel part to
src/kernel/ipc/ipc4/handler-user-kernel.c:
- the global and module message routers and the reply message they
  fill in;
- the forwarding to the user-space IPC thread: the target core lookup,
  the multicore SET_PIPELINE_STATE sequencing and the MOD_INIT_INSTANCE
  driver lookup and module loading;
- the CHAIN_DMA, IPC gateway and GDB commands;
- the module init that runs in the kernel (DP modules and builds
  without user-space LL) and the base firmware LARGE_CONFIG get and set,
  which use IDC and the IMR manifest;
- the thin wrappers that the routers of builds without user-space LL
  call directly.

handler-user.c keeps the pipeline state handling, the module config and
large config processing and the user-space IPC thread dispatch. The
pipeline ID lookup and the vendor config and kcontrol helpers, which
both parts use, are no longer static and are declared in ipc4/handler.h.
handler-user.c no longer needs the IPC gateway copier header.

The code is unchanged, but the compiler can no longer inline or
specialise the shared helpers in the callers on the other side of the
split. Their callers now pass the full argument list instead of calling
GCC's constant-propagated clones, ipc4_set_pipeline_state() only
partially inlines ipc4_pipeline_id_get() in builds without user-space
LL, and the register allocation of the routers differs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
helper.c mixes the IPC4 topology helpers, which also run in the
user-space IPC thread, with code that needs kernel mode. Move the kernel
part to src/kernel/ipc/ipc4/helper-kernel.c:
- the component driver lookup, which reads the IMR manifest, registers
  loadable modules with the library manager and walks the driver list;
- comp_new_ipc4(), the module creation of the kernel IPC thread (DP
  modules and builds without user-space LL), and the privileged part of
  the user-space module creation, ipc4_user_module_load();
- the IDC helpers, ipc4_process_on_core() and ipc_comp_free_remote();
- the chain DMA manager, which only the kernel CHAIN_DMA command uses.

helper.c keeps the pipeline and component management, binding and the
DMA config parsing. The module config parsing and the module init payload
lookup, which both parts use, are no longer static and are declared in
sof/ipc/topology.h, as is ipc_comp_free_remote(). helper.c no longer
includes the rimage manifest, platform memory map and library manager
headers.

The code is unchanged, but the functions that now call across the split
can no longer inline their callees: ipc_pipeline_new(),
ipc_pipeline_free(), ipc4_comp_connect() and ipc4_comp_disconnect() call
ipc4_process_on_core() and ipc_comp_free_remote(), and comp_new_ipc4(),
ipc4_user_module_load() and ipc4_chain_manager_create() call the module
config and component list helpers, instead of inlining them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
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.

2 participants