ADR-0013: BTF on Every Architecture¶
Date: 2026-10-16
Status¶
Accepted (2026-10-18)
Supersedes the riscv64 debug information consequence of ADR-0009 ("riscv64 kernels carry no debug information and so no BTF: kconfig/riscv64.config does not request DEBUG_INFO_BTF, unlike the x86_64 and arm64 fragments"). The rest of ADR-0009 stands.
Context¶
Compile Once – Run Everywhere (CO-RE) eBPF programs require runtime type information exported by the kernel via /sys/kernel/btf/vmlinux.
When multi-architecture kernel compilation was standardized in ADR-0009, kconfig/x86_64.config and kconfig/arm64.config declared the BPF Type Format (BTF) dependency chain (CONFIG_DEBUG_KERNEL=y, CONFIG_DEBUG_INFO_DWARF5=y, and CONFIG_DEBUG_INFO_BTF=y), but kconfig/riscv64.config omitted debug information and BTF. Consequently, riscv64 kernels lacked /sys/kernel/btf/vmlinux, preventing modern CO-RE eBPF tools from loading on riscv64 nodes.
Because riscv64 lacked BTF, BTF presence could not be enforced as an architectural invariant across the repository's entire compilation matrix: the resolved configuration checks (scripts/check_required_config.py) and the artifact gate (scripts/check_kernel_artifacts.py) could not mandate BTF on all architectures without failing riscv64 builds.
Decision¶
- Every Architecture Fragment Declares the BTF Chain:
All architecture fragments under
kconfig/*.config(x86_64.config,arm64.config,riscv64.config) declare the full BTF dependency chain:
In kconfig/riscv64.config, the default kernel configuration (defconfig) does not enable CONFIG_DEBUG_INFO_REDUCED, so unlike arm64.config, no explicit unsetting is required.
- Repository-Wide BTF Claim in Required Configuration:
Add a
btfclaim tokconfig/required-config.jsoncovering all streams and all architectures:
{
"id": "btf",
"claim": "BTF in vmlinux for CO-RE eBPF (docs/streams.md, issue #112)",
"streams": "all",
"architectures": "all",
"symbols": {
"CONFIG_DEBUG_INFO_BTF": "y"
}
}
During configuration resolution (scripts/merge-config.sh --source-tree), scripts/check_required_config.py evaluates this claim against the generated .config. Any stream or architecture leg where CONFIG_DEBUG_INFO_BTF=y fails to survive olddefconfig is refused, and merge-config.sh exits non-zero.
-
Artifact Gate Enforces BTF in Kernel Packages: In
scripts/check_kernel_artifacts.py, addcheck_kernel_config(data, exp)withincheck_image. The gate extracts/boot/config-<kernelrelease>from thelinux-imageDebian package usingdpkg-deband asserts thatCONFIG_DEBUG_INFO_BTF=yis present. Any kernel package lacking BTF in its packaged configuration is refused before artifacts can be checksummed, attested, or published. -
Automated Verification Suites: Enforce the decision through dedicated unit and integration tests:
tests/test_kconfig.py::test_every_architecture_fragment_declares_btf: verifies that every fragment inkconfig/*.configdeclaresCONFIG_DEBUG_INFO_BTF=y.tests/test_check_kernel_artifacts.py::test_kernel_config_must_carry_btf: verifiescheck_kernel_configrejects configurations lacking BTF across all architectures (x86_64,arm64,riscv64).tests/test_check_kernel_artifacts.py::test_check_image_refuses_config_without_btf: verifiescheck_imagerejects Debian image packages whose internal configuration lacks BTF.tests/test_check_kernel_artifacts.py::test_a_release_whose_config_lacks_btf_is_refused: end-to-end CLI gate test refusing a release whose configuration lacks BTF.
This decision landed in pull request #159 (addressing issue #112), merged in commit 5b25755cb.
Evidence¶
The changes were compiled, resolved, and verified in GitHub Actions workflow build-matrix.yml run 38829455519 with dry_run=false across all twelve stream and architecture legs (4 streams x 3 architectures):
- Compilation and Gating: All twelve legs compiled and passed
scripts/check_kernel_artifacts.py. The cross-compiled riscv64 legs took 23 to 39 minutes each, including runner setup. - Resolved Configuration: Inspection of the resolved
.configartifacts for riscv64 (mainstream7.2.10 andlts6.18.56) verified thatCONFIG_PAHOLE_VERSION=131was detected andCONFIG_DEBUG_INFO_BTF=ysurvivedolddefconfig. - Artifact Sizes: Measured artifact sizes for riscv64 packages in run 38829455519:
linux-imageDebian package: 30,110,494 bytes (lts) and 31,559,200 bytes (mainstream).vmlinuzkernel image: 12,868,774 bytes (lts) and 13,189,948 bytes (mainstream). All generated artifacts remain well under the 512 MiB per-artifact ceiling enforced bycordanaLLM/imagoandscripts/check_kernel_artifacts.py.
Consequences¶
Positive¶
- Full CO-RE eBPF Capability: riscv64 kernels generate
/sys/kernel/btf/vmlinux, allowing eBPF instrumentation, tracing tools, and observability agents to load without kernel headers. - Uniform Architectural Contract: BTF is a mandatory requirement across all four streams (
bleeding,mainstream,lts,realtime) and all three architectures (x86_64,arm64,riscv64). - Two-Barrier Gate Enforcement: Missing BTF is refused declaratively at configuration resolution time via
kconfig/required-config.jsonand artifactually at packaging time viascripts/check_kernel_artifacts.py.
Negative¶
- Larger Package and Image Sizes: the riscv64 image package grows from 16.8 MB and
vmlinuzfrom 11.0 MB (mainstream, local build of 2026-09-29, the size table in Packaging) to 30.1 to 31.6 MB and 12.9 to 13.2 MB (run 38829455519). - Longer Builds: DWARF5 debug information and the
paholeBTF pass add compile time to every riscv64 leg; this record has no like-for-like measurement of the increase. - Toolchain Dependency: Kernel builds require
pahole1.22 or newer; theubuntu:26.04builder resolvedCONFIG_PAHOLE_VERSION=131.
Neutral¶
- sched-ext on riscv64: with BTF in place,
kconfig/riscv64.configdeclaresCONFIG_SCHED_CLASS_EXT=yand thesched-extclaim covers every architecture (issue #160). - Cross-Compilation Headers: riscv64 builds continue to be cross-compiled and omit
linux-headerspackages.
Compliance¶
kconfig/required-config.json: Thebtfclaim is validated for every stream and architecture byscripts/check_required_config.pyduring source tree configuration merging (scripts/merge-config.sh --source-tree).scripts/check_kernel_artifacts.py: Thecheck_kernel_configroutine rejects anylinux-imageDebian package lackingCONFIG_DEBUG_INFO_BTF=yin its/boot/config-<kernelrelease>.tests/test_kconfig.py:test_every_architecture_fragment_declares_btfensures no architecture fragment dropsCONFIG_DEBUG_INFO_BTF=y.tests/test_check_kernel_artifacts.py:test_kernel_config_must_carry_btf,test_check_image_refuses_config_without_btf, andtest_a_release_whose_config_lacks_btf_is_refusedverify gate refusal on configurations lacking BTF.- Continuous Integration:
.github/workflows/verify-requirements.ymland.github/workflows/build-matrix.ymlresolve, survival-check and gate all twelve legs on pull requests that touch the build path (thepathsfilters of both workflows).
References¶
- Issue #112:
riscv64 kernels carry no BTF: kconfig/riscv64.config does not request debug information. - Pull Request #159:
fix(kconfig): build BTF into riscv64 kernels and gate BTF on every arch(merge commit5b25755cb93662f3e52603fa59e21065a8fa3416). - Issue #160:
riscv64 kernels build without sched-ext: SCHED_CLASS_EXT is not declared. - GitHub Actions run 38829455519:
build-matrix.yml(dry_run=false). - ADR-0008: Signed Kernel Sources and a Resolved, Survival-Checked Kernel Configuration.
- ADR-0009: Kernel Compilation, the Artifact Gate and the Boot Smoke Test.
- ADR-0011: Function Tracing in the Baseline for BPF Trampolines, and Release Revisions Above 1.