Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SVC syscall ABI (Track A / A1 / ADR-021)

ABI + CRT + loader + standing-task + memfs + FAT16 + slot first-cut miles. Sample rebuild recipes are A8 (docs). A9 is two artifacts + FAT /hello (ADR-030) plus leftover cross-update / FAT-only hello (ADR-032). Product “app hosting is done” is Verified under ADR-048 / ADR-052 (freestanding slots). Not Linux. Not POSIX.

Kernel contract: ADR-021. CRT / libctos: ADR-022. Guest loader: ADR-023. Standing-as-normal: ADR-024. Thin VFS + memfs: ADR-027. virtio-blk + FAT16: ADR-028. Parent plan: issue #31. A1: issue #32. A2: issue #33. A3: issue #34. A4: issue #35. A6: issue #37. Code: src/syscall.rs, src/vfs.rs, libctos/, user/hello-libctos/, src/loader.rs, src/el0.rs.

Calling convention

AArch64 SVC #<n> where n is the syscall number. Arguments in x0, x1, x2. Return in x0.

Reserved 0–2 are ADR-013 probes (#0 first-mile return, #1 standing, #2 restore). libctos must not issue them. Public numbers below are the freestanding contract; Linux ABI is out of scope.

Public numbers

NumberNameArgsEffect
16exitx0 = statusHalt the EL0 trip; return to the EL1 caller. Status is recorded. Not a process table.
17uart_writex0 = pointer, x1 = lengthWrite up to 64 user-mapped and kernel-mapped bytes to the virt PL011. \n → \r\n. Reject (including non-canonical / TTBR1 aliases) → x0 = 0.
18yieldnoneDispatch-only hint; return to EL0. Does not switch EL1 tasks (ADR-010).
19fs_createx0 = path, x1 = lengthCreate an empty memfs name and a handle. Path / + [a-z0-9_-].
20fs_openx0 = path, x1 = lengthOpen an existing memfs name.
21fs_readx0 = fd, x1 = buf, x2 = lengthCopy from the handle offset into a user-mapped and kernel-mapped range (cap 64).
22fs_writex0 = fd, x1 = buf, x2 = lengthCopy into the file at the handle offset (cap 64, file cap 256).
23fs_closex0 = fdDrop the handle. The file stays.
24net_macx0 = buf, x1 = length (≥6)Copy guest virtio-net MAC (6 bytes). Kernel owns the NIC (ADR-068).
25net_pingnoneKernel-path ARP + ICMP echo to SLIRP 10.0.2.2. Not sockets.
26net_udp_dnsnoneKernel-path ARP + UDP DNS probe vs SLIRP 10.0.2.3:53 (ADR-071). DNS is probe bait only. Not sockets. Not a DNS product.
27fs_mkdirx0 = path, x1 = lengthCreate a FAT16 root directory via thin VFS (ADR-075). Memfs / nested paths fail closed. Not POSIX mkdir.
28net_tcp_echononeKernel-path thin TCP echo vs QEMU guestfwd 10.0.2.4:7 (ADR-076). Same probe as ADR-074, quiet. Not sockets. Not listen/accept.

Unknown SVC immediates park (fail-closed). Not POSIX. Not Linux VFS.

Track B B2 maps these numbers against Linux AArch64 (svc #0, x8): linux-aarch64-syscall-gap.md. Track B B4 maps ELF / auxv / PT_INTERP against the freestanding loader: ADR-033. Inspection only. Not claiming Linux userspace. Not claiming dynamic Linux ELF. Do not retarget 16–28 to Linux x8.

Probe

Serial svc: yield / svc: user-hi / svc: uart / svc: exit / svc: ok. #[test_case] el0_svc_abi_yield_uart_exit + el0_uart_write_rejects_kernel_data + el0_uart_write_rejects_high_alias. File presence is not that probe.

libctos (A2)

A no_std crate wraps the three public numbers. A hello payload linked against it is copied onto the standing EL0 page (A2) and parsed as ELF64 PT_LOAD on the guest (A3). Serial libctos: hi / libctos: ok / libctos: linked. File presence is not that probe.

Guest loader (A3)

The kernel parses the hello ELF, maps each PT_LOAD into the user map-window, and ERETs to e_entry (ADR-023). Serial loader: mapped / loader: ok. Not a Linux ELF ABI. Not PT_INTERP. A2–A4 and A9 read FAT /hello. Linux ELF/auxv gaps: ADR-033. File presence is not that probe.

Standing task (A4)

The A3 loader is how a payload appears. A4 makes standing EL0 the supported path: is_active() is true for the loaded task until exit; an unexpected fault restores fail-closed (ADR-024). Serial el0: task-enter / el0: task-active / el0: task-exit / el0: task-restored / el0: restore-fail / el0: task-ok. Not isolation. Not a process table. Linux fork/exec/wait is a documented gap (ADR-035). File presence is not that probe.

memfs (A6)

In-RAM named buffers behind a thin VFS (ADR-027, filesystem.md). Serial fs: create / fs: write / fs: read / fs: el0 / fs: ok. File presence is not that probe.

FAT16 (A7)

Same VFS open on virtio-blk (ADR-028). Serial blk: ok / fat: ok. /probe is the known FAT16 file. Write depth: ADR-050 (fat: write / fat: create). Root listing: ADR-056 (fat: readdir / fat: entries) — kernel/VFS probe, no new SVC. Root delete: ADR-057 (fat: delete) — kernel/VFS probe, no new SVC. Root mkdir kernel probe: ADR-073 (fat: mkdir). EL0 fs_mkdir (27): ADR-075. EL0 net_tcp_echo (28): ADR-076. Not POSIX getdents / unlink / mkdir. File presence is not that probe.

Sample recipes (A8)

Rebuild recipes for the probed classes: what-can-run.md, in-tree user/README.md. Coop UART, RX echo, standing EL0 / libctos hello; optional memfs + FAT16. N4 adds 24–25 (ADR-068). N3.x adds 26 (ADR-071). ADR-075 adds 27 (fs_mkdir). ADR-076 adds 28 (net_tcp_echo). File presence is not a new runtime.

OS/app slots (A9)

Host kernel ELF + published hello-libctos.elf. Guest reads FAT /hello through the same VFS and maps it with the A3 loader (ADR-030). Serial slot: fat / slot: mapped / slot: ok / perf: app-load. No production embed on this path (ADR-032): A2–A4 load the same FAT file. Cross-update (same published ELF on this OS and ba6541c) is ledger-Verified. Probe-only include_bytes! in src/slot.rs is ADR-046 measurement only — never print slot: embed. File presence is not that probe.

Product claim + remaining non-goals (Track A)

Product “app hosting is done” is Verified under ADR-048 / ADR-052 for freestanding OS/app slots. Isolation enable (PAN) is non-goal on default cortex-a57 (ADR-047). Identity .data/heap tears are Verified (ADR-037/038). Still not Linux/POSIX/containers; “EL0 isolated” only as the ADR-091 sentence.