Overview (plain English)
Core principles drive ctos. Track A / Track B / A9 are subordinate and never override this list for speed or marketing. Full list: principles.md.
- Honesty ledger — Verified only with a probe
- Antifragility — fail-closed sensors + ratchets
- Security — threat model; probed mitigations only
- Performance — measure first; no invented benches
- Document-first / one milestone → one PR
ctos is a learning AArch64 kernel for QEMU virt. It is not a desktop, not POSIX, and not a “secure OS.” Status words need a probe in the honesty ledger. This note does not invent latency, size, or “faster than” numbers. Measured markers live in the ledger; they are one environment each.
Vision: product-vision.md. Pillars: pillars.md. Frozen IDs: fr-nfr.md. Samples: apps-today.md. Porting: building-or-porting.md. Immutability: immutability.md (scoped only). Tracks: A / B / N (subordinate; N1 ADR-066, N2 ADR-067, N3 ADR-070, N3.x ADR-071, N4 ADR-068, N5 ADR-074).
Site chapters (source of truth for the published book): Overview. HTTPS at https://ctos.artof.link is Verified (2026-09-11 after #30). See website.md.
KPIs (what we actually measure)
These are sensors, not product SLOs. A missing marker is a fail. A printed number is not a budget.
Performance (NFR-07 / performance.md)
| What we watch | Probe (do not invent a target) |
|---|---|
| Physical counter moves | Serial perf: cntpct delta=<n> + #[test_case] |
| IRQ-to-handler spread on this virt guest | Serial perf: irq-delta min=… max=… spread=… n=… |
| Debug ELF byte size | Host perf: elf-size bytes=<n> (measurement, not “smaller is better”) |
kernel_main after-MMU → after-init | Serial perf: boot-delta ticks=<n> |
| App-load after OS/app split (A9) | Verified when ledger has perf: app-load (+ ADR-046 / ADR-051 pairs). Not a published bench. |
QEMU TCG jitter is one lab. These are not Raspberry Pi numbers and not a published bench. Read the ledger row for the SHA you care about. A9 expected costs (boot/load, SVC, ASID/TTBR, later COW) vs steady EL0 compute: performance.md. No Verified delta — still one ELF.
Antifragility (NFR-05 / antifragility.md)
| What we watch | Probe |
|---|---|
| Hello + milestone strings still print | scripts/qemu-smoke.sh greps; missing string → fail |
| Tests stay fail-closed | cargo test exit 0; --features force-fail must be non-zero |
| Same failure twice | Becomes a sensor/gate, not another README paragraph |
| Failed history kept | Example: Docker b2bbb99 Failed, then layout fix Verified — the Failed row stays |
Unprobed boot stays Unknown. File presence is not QEMU boot.
Application-support scope
Do not say “applications run on ctos.” First-class samples and the cannot-run list live in apps-today.md. Porting stance: building-or-porting.md.
- Can run (probed): coop EL1 UART workers (
sched: task a/b/ok); one-byte UART RX (input: rx 0x41); standing EL0 stub (el0: standing/el0: restored); a loadedlibctoshello as a standing task untilexit(el0: task-ok). A heartbeat/counter variant is the same shape — not in tree until a probe greps it. - Cannot run: Linux ELF, shell, Python, network servers (Track N is ARP+ICMP+UDP + tiny EL0 net/UDP SVC samples — not sockets), POSIX disk apps, SMP, a POSIX-style userspace. “EL0 isolated” is Verified only as the accepted ADR-091 sentence (one core, TCG default smoke machine; limits there); PAN is enabled on default cortex-a76 (ADR-080). Identity
.data/heap/leftover-RAM tears are ADR-037/038/049. Filesystem stance: filesystem.md (memfs + FAT16 read/write). Gaps to host apps + containers: non-goal: host-apps.md.
Building or porting
First-class page: building-or-porting.md. Short honesty:
- Easiest = in-tree
no_stdcoop EL1 onaarch64-ctos.json, proven withcargo/qemu-smoke/docker-smoke. - POSIX / glibc = not easy, not started.
- SVC ABI +
libctos+ guestPT_LOAD+ standing-as-normal for freestanding EL0 = A1 ABI + A2 CRT + A3 loader + A4 standing-task miles (dual-SVC stub still exists; not a syscall table; not isolation).
OS image vs app payloads (A9)
The sponsor goal for “immutability” here is not a frozen kernel. It is to disconnect OS updates from apps: one OS image artifact, separate app payloads, so you can replace the kernel without rebuilding apps and replace apps without rebuilding the kernel.
- First cut + leftover: two host artifacts (
target/aarch64-ctos/debug/ctos+target/hello-libctos.elf) and a FAT16/helloload path (ADR-030, ADR-032, A9 #48). A2–A4 load that file. Stance: immutability.md. - Cross-update: same app ELF on this OS and documented prior OS
ba6541c. Product freestanding app hosting is Verified under ADR-048/052. Do not say OTA / “immutable OS” marketing / Linux hosting. - Do not say “immutable OS.”
- Performance:
perf: app-loadmeasures the FAT load path; ADR-046 adds probe-onlyperf: embed-load+perf: slot-delta(QEMU TCG lab pair — not a percent). ADR-051 addsperf: fat-write/perf: memfs-write/perf: fs-write-delta(same-boot write pair — not a percent). Expected costs: boot/load, SVC, ASID/TTBR, optional later COW. Details: performance.md.
Prerequisites
- Nightly Rust (
rust-toolchain.toml),rust-src,llvm-tools-preview qemu-system-aarch64(Debian package is oftenqemu-system-arm)- Optional: Docker linux/arm64 (
./scripts/docker-smoke.sh) — do not pinlinux/amd64 - To change the kernel: one milestone → one branch → one GitHub PR; author ≠ merger (ADR-002)
A machine that has not run scripts/qemu-smoke.sh (or Docker/GHA equivalent) has Unknown boot.
Advantages
- Small, readable
no_stdtree on one ISA (AArch64 / QEMUvirt/ PL011 UART) - Fail-closed smoke: serial markers,
cargo test, force-fail - Honesty ledger: Verified / Unknown / Planned / Failed, with a probe each
- Failures become sensors (layout miss, live-
.textvtable yank, CRLF shebang) - Three pillars named up front — security and speed still need probes
Drawbacks
- QEMU
virtonly. No Raspberry Pi or board claim - Not POSIX, not multi-tenant, not a product runtime. memfs + FAT16 read/write (filesystem.md; ADR-050). Not a container host (non-goal, ADR-029); host
docker-smoke≠ guest Docker. - Umbrella “EL0 isolated” is Verified only as the accepted ADR-091 sentence (M6; history ADR-047). Live identity
.text/.rodata/.data/ heap / leftover RAM are torn (ADR-020/025/037/038/049);_startstays; PAN is enabled on the default-cpu cortex-a76(ADR-080; historical a57pan: absent) - Scoped immutability only (immutability.md): RO+NX / WXN / live
.texttear are probed. Absolute “immutable OS” is incompatible (heap/PTEs/devices must mutate). OS/app slot first cut (A9 / ADR-030) is two artifacts + FAT/hello. Leftover (ADR-032): A2–A4 load FAT; same ELF on this OS andba6541c. - Performance numbers are guest counter deltas, not a latency budget
- Docs website / custom domain: HTTPS serving the book is Verified (website.md)
- Same-login cannot self-merge; a second identity has to land the PR
Honesty
Do not say “secure OS,” “the kernel moved,” “immutable OS,” or “apps update independently of the OS.” Point at the ledger for any number you quote. Say “EL0 isolated” only as the accepted ADR-091 sentence, never wider. The live docs URL is a separate Verified row — do not invent other site claims.