Skip to content

Kernel ABI

miroslaw edited this page Sep 29, 2026 · 1 revision

Kernel ABI

The kernel exposes exactly 20 syscalls. Nothing else. All numbers are stable and reserved; retired numbers are never reused.

Calling convention

x86_64, syscall instruction:

rax = syscall number
rdi, rsi, rdx, r10, r8 = arguments 0..4
syscall
rax = result: >= 0 on success, -errno on error

Only rcx and r11 are clobbered by the instruction itself. The kernel saves and restores all other argument registers, so userspace may keep live values across a syscall in rdi/rsi/rdx/r10/r8.

Errors use Linux-compatible errno values (see abi.h).

The calls

nr name signature
0 PING (a0) -> u64
1 KPUTS (buf, len) -> bytes
2 EXIT (code) — never returns
3 HANDLE_CREATE (kind, rights, object) -> handle
4 HANDLE_CLOSE (handle) -> 0
5 HANDLE_QUERY (handle, required) -> 1 / -EPERM
10 GETPID () -> pid
12 IPC_CREATE (msg_size, capacity) -> handle
13 IPC_SEND (handle, buf, len) -> 0
14 IPC_RECV (handle, buf, max) -> msg_size
15 IPC_TRY_SEND (handle, buf, len) -> 0 / -EAGAIN
16 IPC_TRY_RECV (handle, buf, max) -> size / -EAGAIN
17 MAP (hint, npages, flags) -> vaddr
18 UNMAP (vaddr, npages) -> 0
19 YIELD () -> 0
20 IPC_SEND_CAP (ch, buf, len, cap, action) -> 0
21 IPC_RECV_CAP (ch, buf, max, out_cap) -> size
22 IPC_TRY_RECV_CAP (ch, buf, max, out_cap) -> size/EAGAIN
24 WAIT (proc_handle) -> exit_code
25 GET_BOOTSTRAP () -> handle
26 SPAWN_ELF (elf_u, size, name_u, cap, flags) -> handle

Reserved numbers

6, 7, 8, 9, 11 were the transitional VFS / fd / brk calls of the pre-microkernel era. 23 was SPAWN (spawn from a kernel-embedded ELF table). All are retired and must not be reused.

Notes

  • KPUTS reuses number 1, which previously carried the fd-based SYS_WRITE. It writes bytes to the kernel console. No fd, no VFS.
  • MAP accepts hint == 0 (kernel chooses an address). Only VM_WRITE is accepted from userspace; VM_PRESENT and VM_USER are added by the kernel.
  • SPAWN_ELF reads a whole ELF64 static executable from a user buffer. The image must be <= 4 MiB. name_u is a short NUL-terminated label used only as the process name and argv[0]. cap is a bootstrap handle to duplicate into the child (or HANDLE_INVALID).

Clone this wiki locally