Kernel Entry & Multi-Entry .vxbin
July 17, 2026 · View on GitHub
Scope: how a Vortex kernel binary is entered — the unified CTA
prologue, the .weak kernel_main model, and the multi-entry .vxbin
symbol-table mechanism that lets one binary hold several named kernels
(the device-side foundation for PoCL / multi-kernel programs). Covers
sw/kernel/src/vx_start.S,
sw/kernel/scripts/vxbin.py,
the link scripts, and
sw/runtime/common/module.cpp.
The runtime module/kernel handle API
is in vortex_runtime_api.md; the KMU CTA
dispatch is in cta_dispatch_architecture.md.
1. Unified entry model
There is a single shared CTA prologue __vx_cta_entry
(vx_start.S:69-136) that sets up
SATP/gp/sp/tp+TLS, runs __libc_init_array, loads kargs into a0 from
MSCRATCH, and dispatches with jalr ra, s11 (s11, callee-saved,
carries the kernel/trampoline address). _start is itself a 2-instruction
stub (:30-66):
lla s11, kernel_main; j __vx_cta_entry, with kernel_main declared
.weak so a multi-entry program needs no dead default stub (the
PC-relative lla resolves a weak-undef to 0 cleanly). Per-kernel entry
stubs live in a .vx_entry section, KEEP'd against --gc-sections by
both link scripts (link32.ld:59-61,
link64.ld:59-61). The dispatch jalr is emitted under .option norvc
so it stays 4 bytes for CTA rewind.
2. Multi-entry .vxbin format
vxbin.py scans the linked ELF for
__vx_kentry_* symbols and, if any exist, appends a VXSYMTAB footer
(:69-104): a string blob + packed
(name → PC) entries + count + magic. A binary with no such symbols is
byte-identical to the legacy single-entry format.
The on-disk .vxbin layout is [min_vma][max_vma][image][VXSYMTAB?]. The
runtime loader module.cpp:75-119
sniffs the trailing magic: with a footer it parses the entries and
vx_module_get_kernel(name) resolves a name to a PC; without a footer it
synthesizes a single "main" → min_vma entry. This keeps legacy
single-kernel binaries working unchanged.
3. Flow
- The compiler emits one
__vx_kentry_<name>stub per kernel into.vx_entry;vxbin.pyrecords them in theVXSYMTABfooter. - At load,
vx_module_load_file/bytesparses the footer into a name→PC table. vx_module_get_kernel("<name>")returns avx_kernel_h; launch programs that PC into the KMU.- Every kernel shares
__vx_cta_entry;s11carries its entry address, kargs arrive ina0.
tests/regression/multikernel/
(kentry.S with add_k/mul_k/acc_k) is the POCL-free in-tree test of
the multi-entry path.
4. Proposed but not yet implemented
- Single-entry regression re-validation: the ~50
single-entry
tests/regressionkernels should be re-run to confirm the legacy path's move from a directjal kernel_maintojalr ra, s11(PoCL's runs already provejalr/CTA-rewind compatibility; this is a test-coverage TODO, not a code gap). - PoCL trampoline interop (
__vx_tramp_<name>) lives in the external mesa/PoCL tree;__vx_cta_entryis agnostic to it by design.