System Calls
The syscall surface is defined in include/uapi/syscalls.h and dispatched by a single switch in src/kernel/core/syscall.cpp.
ABI
Userspace invokes syscalls with the syscall instruction via inline wrappers (src/usr/libc/syscall.h):
- Number in
rax; arguments inrdi,rsi,rdx,r10,r8,r9; return value inrax.rcxandr11are clobbered. - Per-core MSRs:
STAR(kernel CS0x08, user selector base with the AMD SYSRET quirk),LSTAR=syscall_entry,SFMASKclears TF/IF/DF/NT/RF/AC,EFER.SCEenabled. - The entry path (
src/arch/x86_64/boot/usermode.asm) swaps to the kernel stack via per-CPU GS data, builds aSyscallFrame(registers plus savedrip/cs/rflags/rsp/ss), and enables interrupts — syscalls run with interrupts on. - On return, pending signals are checked, volatile registers are zeroed (no kernel state leaks to user), and
o64 sysretreturns. Non-canonicalrcxtakes aniretqfallback instead. - A legacy
int 0x80gate (DPL 3) reaches the same handler; userspace does not use it.
Error conventions: classic calls return (uint64_t)-1; extended calls (270 and up) return negative errno values (-4 EINTR, -9 EBADF, -11 EAGAIN, -12 ENOMEM, -14 EFAULT, -16 EBUSY, -19 ENODEV, -22 EINVAL, -24 EMFILE, -28 ENOSPC, -32 EPIPE, -110 ETIMEDOUT). User pointers are validated against the process VMA list; string copies are bounded; data copies use SMAP-aware fixup paths.
Files and Descriptors
| # | Name | Purpose |
|---|---|---|
| 0 | SYS_READ |
Read from fd; stdin polls keyboard + serial |
| 1 | SYS_WRITE |
Write to fd; stdout/stderr go to boot log / serial |
| 2 | SYS_OPEN |
Open with O_CREAT/O_TRUNC/O_APPEND |
| 3 | SYS_CLOSE |
Close fd |
| 4 | SYS_STAT |
Stat a path |
| 22 | SYS_PIPE |
Create a pipe (two fds) |
| 33 | SYS_DUP2 |
Duplicate fd |
| 78 | SYS_GETDENTS |
Stateful readdir: one entry per call |
| 83 | SYS_MKDIR |
Create directory |
| 87 | SYS_UNLINK |
Delete file |
| 224 | SYS_RENAME |
Rename file or directory |
| 225 | SYS_RMDIR |
Remove empty directory |
| 277 | SYS_FTRUNCATE |
Truncate open file (FAT32: to 0 only) |
| 279 | SYS_FSIZE |
Size of an open file (used to validate memfd buffers) |
| 280 | SYS_SYNC |
Flush page cache and filesystem state |
| 281 | SYS_LSEEK |
Reposition fd offset (SEEK_SET/CUR/END from uapi/fs.h) |
Processes, Threads, Signals
| # | Name | Purpose |
|---|---|---|
| 13 | SYS_SIGACTION |
Install or query a signal handler |
| 15 | SYS_SIGRETURN |
Return from a signal handler |
| 24 | SYS_YIELD |
Voluntary reschedule |
| 37 | SYS_KILL |
Send a signal to a pid |
| 39 | SYS_GETPID |
Current pid |
| 57 | SYS_FORK |
Clone the process (CoW) |
| 59 | SYS_EXEC |
Replace the process image |
| 60 | SYS_EXIT |
Exit with status; kills the other live threads in the group |
| 61 | SYS_WAIT4 |
Wait for children (WNOHANG = 1) |
| 62 | SYS_GETPROCS |
Snapshot the process list |
| 102 | SYS_GETUID |
Current uid |
| 105 | SYS_SETUID |
Set uid (root only) |
| 271 | SYS_THREAD_CREATE |
Create a thread sharing the address space and fd table |
| 297 | SYS_THREAD_EXIT |
Terminate only the calling thread (never returns) |
| 298 | SYS_THREAD_DETACH |
Mark a child thread detached (self-reap, no join) |
Thread syscalls: SYS_THREAD_CREATE(entry, arg, stack_top, flags, stack_lo, stack_size) builds the entry frame from the caller's live syscall frame (user segments and rflags carry over; arg reaches the entry in rdi) and returns the new thread's pid, or -22 for a null entry/stack_top/frame, -12 when the thread's TLS block cannot be allocated or installed, -14 when the recorded TLS template VAs are not readable (a bad template, not a memory shortage), and -11 while an exec is tearing the caller's thread group down (the group is being replaced; retry after the exec resolves). flags (arg4) honors THREAD_DETACHED (uapi/syscalls_ext.h) — the thread is created detached, never waitable — and ignores unknown bits; stack_lo/stack_size (arg5/arg6) record a range that SYS_THREAD_EXIT unmaps, with 0/0 keeping the caller-managed stack of the original form. SYS_THREAD_EXIT(status) ends only the calling thread after unmapping its recorded range and TLS mapping; SYS_THREAD_DETACH(tid) returns -10 when tid is not a live child thread (forked children lead their own group). Threads are processes with their own pids: SYS_GETPID in a thread returns the thread pid, and a joinable thread is reaped by SYS_WAIT4 from its creator. See Processes — Threads and Processes — Thread-Local Storage.
Memory
| # | Name | Purpose |
|---|---|---|
| 9 | SYS_MMAP |
Anonymous or memfd-backed mapping |
| 10 | SYS_MUNMAP |
Unmap a range |
| 270 | SYS_FUTEX |
FUTEX_WAIT / FUTEX_WAKE (WAIT takes a relative timeout in arg4; wakes are matched by the physical address of the 32-bit word) |
| 272-274 | SYS_EPOLL_CREATE/CTL/WAIT |
Epoll instances over fds |
| 275 | SYS_MPROTECT |
Change protections on mapped pages |
| 276 | SYS_MEMFD_CREATE |
Anonymous memory-file fd (max 16 MiB) |
Futex: FUTEX_WAIT(uaddr, expected, timeout_ms) takes a relative timeout in milliseconds (arg4; 0 = infinite, sub-tick timeouts round up to one timer tick) and returns -11 when the word holds a different value, -110 on expiry, -12 when the timed-wait registration cannot be allocated, and -4 when a fatal signal interrupts the wait (both the timed and untimed waits recheck fatal signals right before parking). FUTEX_WAKE(uaddr, count) wakes up to count waiters parked on that exact word — the count is literal, POSIX-style, so 0 wakes none — and returns how many it woke; the word is keyed by physical address, so the same shared frame mapped at different virtual addresses — cross-process shared memfd pages — still matches.
Display, GUI, Input, Sound
| # | Name | Purpose |
|---|---|---|
| 205-207 | SYS_SOUND_PLAY/WRITE/CONFIG |
PLAY: file playback via the kernel parser. WRITE: streaming PCM push (fails without an open stream). CONFIG: card format |
| 282 | SYS_SOUND_STREAM_OPEN |
Open streaming playback (rate, channels, 16-bit); stops previous playback |
| 283 | SYS_SOUND_STREAM_END |
No more stream data; drain queued PCM then auto-close (immediately when nothing was queued) |
| 284 | SYS_SOUND_STOP |
Abort the stream and stop the card |
| 285 | SYS_SOUND_PAUSE |
Pause stream playback (idempotent; latches if DMA has not started) |
| 286 | SYS_SOUND_RESUME |
Resume stream playback (idempotent; clears a latched pause) |
| 287 | SYS_SOUND_STATUS |
Fill sound_status (uapi/sound.h): played/queued bytes, format, flags (paused includes the latch, owned marks the caller's own stream) |
| 288 | SYS_SOUND_VOLUME |
Card master volume 0-100 |
| 208 | SYS_FB_INFO |
Framebuffer geometry |
| 209 | SYS_FB_MMAP |
Map the framebuffer at 0x200000000 (WC) |
| 210 | SYS_GET_EVENT |
Pop an event from the process queue (blocking flag) |
| 211 | SYS_FB_FLUSH |
Store fence for WC writes |
| 212 | SYS_FB_BLIT |
Full-frame blit from a user buffer |
| 214 | SYS_FB_BLIT_RECT |
Rect blit |
| 244 | SYS_POST_EVENT |
Push an event into another process's queue |
| 245 | SYS_GUI_REGISTER_WM |
Caller becomes the window manager |
| 246 | SYS_GUI_SET_FOCUS |
WM-only: set the focused pid |
| 247-262 | SYS_DISPLAY_* |
KMS-style display API (see below) |
| 289 | SYS_INPUT_ENUM_DEVICES |
Fill InputDeviceInfo[] (uapi/input.h); returns total count |
| 290 | SYS_INPUT_SET_POINTER_SPEED |
Q8 multiplier (256 = 1.0x, clamped 16-1024) applied to mouse deltas |
| 291 | SYS_INPUT_SET_REPEAT_RATE |
USB HID key-repeat delay_ms and rate_ms |
| 292 | SYS_INPUT_SET_DEVICE_ENABLED |
Enable/disable an input source by stable id (PS/2 sentinel or USB slot) |
| 293 | SYS_NET_STATUS |
Fill NetStatus (uapi/syscalls_ext.h): ip/netmask/gateway/dns (host order), link_up, configured, nic |
| 294 | SYS_SOCKET_STATE |
Socket state: NET_TCP_* (mirrors kernel TcpState) for TCP handles, NET_SOCK_UDP_OPEN for UDP; -9 EBADF for unused/invalid handles |
| 295 | SYS_PING |
One blocking ICMP echo probe (ip, timeout_ms, *rtt_ms): 0 + rtt, -110 ETIMEDOUT, -19 ENODEV, -16 EBUSY (probe ring full), -14 EFAULT |
| 296 | SYS_NET_RENEW |
Force a full DHCP exchange: 0 on ACK, -11 EAGAIN before net_init, -19 ENODEV, -16 EBUSY (renew in flight), -100 ENETDOWN |
Display syscalls: GET_CAPS 247, PRESENT 248, WAIT 249, GET_STATUS 250, QUERY_CONNECTORS 252, GET_MODES 253, SET_MODE 254, BUFFER_CREATE 255, BUFFER_MAP 256, BUFFER_DESTROY 257, COMPOSE_SUBMIT 258, EVENT_WAIT 259, ATOMIC_COMMIT 260, BUFFER_SET_WM_ACCESS 261, SURFACE_IMPORT 262. Present requests carry up to 128 damage rects; compose requests up to 32 layers and 32 damage rects. See Display.
Input syscalls: ENUM_DEVICES 289 fills an array of InputDeviceInfo (PS/2 mouse/keyboard plus one entry per USB HID mouse/keyboard stream) and returns the total count (entries beyond the caller's buffer are truncated). SET_POINTER_SPEED scales raw mouse deltas before accumulation (orthogonal to the PS/2 acceleration curve); SET_REPEAT_RATE tunes the USB HID software repeat; SET_DEVICE_ENABLED freezes a source at the driver (its state is preserved, not zeroed). See Input.
Shared Memory
| # | Name | Purpose |
|---|---|---|
| 240 | SYS_SHM_GET |
Allocate a block (max 16 MiB), returns id 0-63 |
| 241 | SYS_SHM_MAP |
Map at 0x300000000 + id * 16 MiB |
| 242 | SYS_SHM_FREE |
Unmap and release |
| 243 | SYS_SHM_INFO |
Block size |
| 251 | SYS_SHM_UNMAP |
Unmap only |
| 263 | SYS_SHM_GET_OWNER |
Owner pid |
| 278 | SYS_FD_TRANSFER |
Copy an fd's vnode into another process (pid 0 = the WM) |
Network
| # | Name | Purpose |
|---|---|---|
| 220 | SYS_SOCKET |
AF_INET; SOCK_STREAM = TCP, SOCK_DGRAM = UDP |
| 221 | SYS_BIND |
Bind a port |
| 222/223 | SYS_SENDTO/RECVFROM |
UDP datagrams |
| 229/230/233 | SYS_CONNECT/SEND/RECV |
TCP stream |
| 234 | SYS_CLOSESOCKET |
Close a socket |
| 235 | SYS_RESOLVE |
DNS hostname to IPv4 |
Socket handles are not file descriptors: handle = kind << 12 | index. See Networking.
System
| # | Name | Purpose |
|---|---|---|
| 169 | SYS_REBOOT |
Reboot |
| 231 | SYS_POWEROFF |
ACPI poweroff |
| 201 | SYS_GETTIME |
RTC wall clock |
| 202 | SYS_GETUPTIME |
Seconds since boot |
| 203 | SYS_GETMEMINFO |
Total/free/used memory |
| 204 | SYS_GETSYSINFO |
Kernel commit, bootloader, timer Hz, CPU count, debug flag |
| 213 | SYS_GET_TSC_FREQ |
Calibrated TSC frequency in MHz (0 if uncalibrated) |
| 215 | SYS_GET_TICKS |
Raw timer ticks |
| 216 | SYS_SLEEP_MS |
Sleep for at least the given milliseconds (real sleep, signal-interruptible) |
| 226 | SYS_GETVOLUMES |
Volume list (max 16) |
| 227/228 | SYS_STORAGE_GET_MODE/SET_MODE |
Storage guard mode; SET is WM-only |
| 232 | SYS_SET_QUIET |
Toggle boot framebuffer logging |
| 236 | SYS_GETRANDOM |
Up to 64 KiB from a seeded xorshift* PRNG (not cryptographic) |