Building or porting something to ctos
Plain English. There is no easy POSIX port today. ctos is a kernel you extend in-tree, not a host you drop apps onto.
What already runs (rebuild recipes): What can run today. In-tree index: user/README.md. How to build the kernel: prerequisites. Probes: honesty ledger.
Do not claim an “easy port” path that does not exist.
Today (honest)
Nothing POSIX ports easily.
There is no C library (libc), no dynamic linker, and no POSIX filesystem. Thin VFS + memfs + FAT16 are not Linux open. A1 documented a kernel SVC ABI (exit / uart_write / yield — syscall.md, ADR-021). A2 adds a freestanding libctos CRT you can link in-tree (ADR-022). A3 parses that in-tree ELF on the guest and maps PT_LOAD (ADR-023). That is not an application porting target for Linux binaries. There is no PT_INTERP / glibc path that would run a foreign user-mode binary if you built one elsewhere.
A Linux, musl, or glibc program is a different contract. Recompiling it “for AArch64” does not make it a ctos program.
Easiest today
Write in-tree no_std Rust and ship it as part of the kernel image. Language discipline notes: Why Rust.
Typical shape (A8 recipes — what-can-run.md):
- A cooperative kernel task (same class as
sched: task a/b) or a small kernel module - Use UART /
println!for output;yieldto other tasks - Optional: serial receive for a byte-in gadget
- Optional: link
libctoslikeuser/hello-libctos(published + FAT/hello; not a second-kernel)
Rebuild the whole guest with the existing target:
cargo build # aarch64-ctos.json
./scripts/qemu-smoke.sh # or ./scripts/docker-smoke.sh on linux/arm64
That is rebuild the kernel, not “port an app.” The new code lives in src/ and links into target/aarch64-ctos/debug/ctos.
flowchart LR R["rustup nightly"] --> C["cargo build"] --> S["qemu-smoke"] S --> E["OS ELF + published app ELF<br/>A9 first cut"]
Two host artifacts. QEMU still -kernels the OS ELF. FAT /hello is the app slot. A2–A4 load that file. Cross-update is the leftover two-boot smoke.
Not easy
- Recompile Linux / C / Rust apps against glibc or musl
- Drop in a userspace ELF (
ET_DYNor a LinuxET_EXEC) - Expect
std, files, sockets, threads, or a process table
Those need a loader and a userspace that ctos does not have. The standing user-mode stub is a test mile plus an A1 ABI trip and an A2 libctos hello, not that runtime (el0.md, syscall.md).
Track A miles that already have recipes
A1–A7 are probed. A8 is docs: the recipes on what-can-run.md. Still not “applications port to ctos.” You extend the kernel or link libctos in-tree.
- A stable SVC ABI — A1 (
exit/uart_write/yield). - A freestanding CRT /
libctos— A2. - Guest
PT_LOADof that in-tree ELF — A3. Image is FAT/hello. - Standing EL0 as normal until
exit— A4 / ADR-024. - Isolation cut (identity
.rodata+ PAN ID-field) — A5. PAN is enabled on the default-cpu cortex-a76(ADR-080; PAN enable was a non-goal on the historical-cpu cortex-a57, ADR-047). Leftover identity RAM after the heap is torn (ADR-049);_startstays. - Thin VFS + memfs — A6. Recipe 4.
- virtio-blk + FAT16 read — A7. Recipe 5. FAT16 write depth — ADR-050.
- OS/app slot first cut — A9 / ADR-030. Recipe 6. Leftover cross-update — ADR-032 (Verified host smoke).
A real userspace stays Planned. “EL0 isolated” is Verified only as the accepted ADR-091 sentence (one core, TCG default smoke machine; limits there). Gaps before hosting, and why containers are a non-goal: Hosting apps / containers.
A POSIX filesystem is the same story: not present. Thin VFS + memfs + FAT16 are not Linux open. Direction: Filesystem: new vs extend.
Product hosting still Planned (ADR-048)
An OS image vs app payload first cut and leftover cross-update already exist (A9 #48, ADR-030, ADR-032): same hello-libctos.elf on this OS and documented prior OS ba6541c. Product freestanding “hosting done” is Verified under ADR-048 / ADR-052 (not Linux/POSIX). See hosting-apps.md, overview.md, and immutability.md.