Skip to content

Syscalls

Userspace enters the kernel through SYSCALL, and the kernel returns through SYSRET. There is no interrupt gate for system calls and no argument block on the stack: the call number goes in rax, and up to six arguments go in registers.

Register Carries
rax the call number on the way in, the result on the way out
rdi, rsi, rdx, r10, r8, r9 arguments one through six
rcx, r11 clobbered by the instruction itself: return address and RFLAGS

The fourth argument is in r10 rather than rcx for the reason the last row gives: SYSCALL puts the return address in rcx before any handler runs, so an argument left there would be gone.

// The whole of the userspace side, from programs/edos_lib/src/sys.rs.
pub unsafe fn syscall2(num: u64, arg1: u64, arg2: u64) -> u64 {
let ret: u64;
unsafe {
asm!(
"syscall",
in("rax") num,
in("rdi") arg1,
in("rsi") arg2,
lateout("rax") ret,
lateout("rcx") _,
lateout("r11") _,
options(nostack),
);
}
ret
}

There is no errno global and no negative-value convention shared across the table. A call that returns a u64 signals failure with u64::MAX; one that returns a signed value signals it with -1. Either way the number itself carries no detail, so the failing handler stores a code on the calling thread and userspace reads it back with call 0x400.

The code is per thread, and every handler that can fail clears it before doing any work, so a stale value from an earlier call cannot be mistaken for a fresh one. A call that succeeds leaves it cleared.

Paths are NUL-terminated and are rejected past 1024 bytes. Every pointer userspace hands over is copied through checked helpers rather than dereferenced: a bad address is EFAULT, not a kernel fault.

102 calls

  1. 0readRead from a descriptor into a user buffer, advancing its offset.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*mut u8Destination buffer.
    rdxcountusizeBytes to read.
    Returnsi64 — bytes read, 0 at end of file, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Blocks on a pipe, a pty or a tty with nothing buffered. Files are served from the page cache, so a hit never reaches the disk.

  2. 1writeWrite a user buffer to a descriptor.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*const u8Source buffer.
    rdxcountusizeBytes to write.
    Returnsu64 — bytes written, u64::MAX on error
    Errors

    A zero-length write returns 0 without touching the descriptor.

  3. 2openOpen a path and install it in the descriptor table.I/O
    RegArgumentTypeMeaning
    rdipath*const u8NUL-terminated path, at most 1024 bytes.
    rsiflagsu64Access mode and creation flags.
    Returnsi64 — new descriptor, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The low two bits are the access mode: 0 O_RDONLY, 1 O_WRONLY, 2 O_RDWR. 0x40 is O_CREAT, 0x200 O_TRUNC, 0x400 O_APPEND. An append offset is resolved per write rather than at open time.

  4. 3closeRelease a descriptor.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    Returnsi32 — 0 on success, -1 on error
    Errors
  5. 4list_dirPack a directory listing into a user buffer.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to list.
    rsibuf*mut u8Destination buffer.
    rdxbuf_sizeusizeBuffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Entries are fixed-size headers each followed by a name; the return value is a byte count, not an entry count.

  6. 5getcwdCopy the working directory out as a NUL-terminated path.Filesystem
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsisizeusizeBuffer capacity in bytes.
    Returnsi64 — bytes written including the NUL, -1 on error
    Errors
  7. 6chdirChange the working directory of the calling process.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to move to.
    Returnsi64 — 0 on success, -1 on error
    Errors
  8. 7pollWait until one of a set of descriptors is ready.I/O
    RegArgumentTypeMeaning
    rdifds*mut SelectFdArray of descriptors and interests; results are written back in place.
    rsicountusizeNumber of entries.
    rdxtimeout_msu64Timeout in milliseconds.
    Returnsi64 — number of ready descriptors, -1 on error
    Errors

    SelectFd is { fd: u64, interests: PollState, result: PollState }, and PollState is five bools: readable, writable, error, hangup, invalid.

  9. 8fstatMetadata for an open descriptor.Filesystem
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsistatbuf*mut FstatEntryDestination struct.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  10. 9mmapMap anonymous, file-backed or physical memory into the address space.Memory
    RegArgumentTypeMeaning
    rdiaddru64Requested address, or 0 to let the kernel choose.
    rsilengthu64Length in bytes.
    rdxprotu32PROT_READ 0x1, PROT_WRITE 0x2, PROT_EXEC 0x4.
    r10flagsu32MAP_SHARED 0x01, MAP_PRIVATE 0x02, MAP_FIXED 0x10, MAP_ANONYMOUS 0x20, MAP_PHYSICAL 0x40, MAP_WRITE_COMBINING 0x80.
    r8phys_or_fdu64Physical address for MAP_PHYSICAL, descriptor for a file-backed mapping.
    r9file_offsetu64Offset into the file; file-backed mappings only.
    Returnsu64 — mapping address, u64::MAX on error
    Errors

    Pages are faulted in on demand. MAP_PHYSICAL is how a driver in userspace reaches device memory, and it is the reason this call can return EPERM.

  11. 10statMetadata for a path.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Path to inspect.
    rsipath_lenusizeLength of the path in bytes.
    rdxstatbuf*mut FstatEntryDestination struct.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  12. 11munmapRemove a mapping and shoot down the stale TLB entries.Memory
    RegArgumentTypeMeaning
    rdiaddru64Start of the mapping.
    rsilengthu64Length in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errors
  13. 12lseekMove the offset of a file descriptor.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsioffseti64Signed displacement.
    rdxwhenceu320 SEEK_SET, 1 SEEK_CUR, 2 SEEK_END.
    Returnsi64 — the new offset, -1 on error
    Errors

    Only regular files carry an offset; anything else is rejected.

  14. 13ftruncateSet the length of an open file.Filesystem
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsisizeu64New length in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errors
  15. 14fsyncFlush one file, data and metadata, to stable storage.Filesystem
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  16. 15isattyReport whether a descriptor is a terminal.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    Returnsu64 — 1 for a terminal, 0 otherwise
    ErrorsCannot fail.
  17. 16ioctlDevice-specific control, for ptys and for devfs nodes.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsirequestu64Device-defined request code.
    rdxargu64Inline value, or a pointer when arg_len is non-zero.
    r10arg_lenusizeSize of the buffer arg points at.
    r8flagsu64IOCTL_FLAG_READ 1 copies the buffer in, IOCTL_FLAG_WRITE 2 copies it back out.
    Returnsi64 — the device’s own value, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The buffer is bounced through the kernel rather than handed to the driver, so a device never touches a user pointer. devfs nodes are dispatched directly instead of through the filesystem mailbox.

  18. 17preadRead at an explicit offset, leaving the descriptor offset alone.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*mut u8Destination buffer.
    rdxcountusizeBytes to read.
    r10offsetu64Absolute file offset.
    Returnsi64 — bytes read, 0 at end of file, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Threads of one process share a descriptor table, so they share one offset per descriptor: lseek followed by read races by construction. This call is the fix, and it is ESPIPE on anything without an offset.

  19. 18pwriteWrite at an explicit offset, leaving the descriptor offset alone.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*const u8Source buffer.
    rdxcountusizeBytes to write.
    r10offsetu64Absolute file offset.
    Returnsi64 — bytes written, -1 on error
    Errors

    O_APPEND is deliberately not consulted: a positional write that silently lands somewhere else is worse than no call at all.

  20. 19readvRead into a list of buffers, filling each before moving to the next.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiiov*const IoVecArray of { base, len } pairs.
    rdxiovcntusizeNumber of entries, at most IOV_MAX (1024).
    Returnsi64 — total bytes read, 0 at end of file, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Each buffer is a separate underlying read, so the buffers fill in order but the sequence is not atomic against a concurrent reader. A short read ends the sequence, and an error after a partial transfer returns the partial count with errno cleared, as POSIX requires.

  21. 20writevWrite a list of buffers in order.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiiov*const IoVecArray of { base, len } pairs.
    rdxiovcntusizeNumber of entries, at most IOV_MAX (1024).
    Returnsi64 — total bytes written, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    A zero-length entry is skipped rather than ending the run. A total length past i64::MAX is rejected before anything is written.

  22. 21accessTest a path for existence and readability.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Path, not NUL-terminated.
    rsipath_lenusizeLength in bytes.
    rdxmodeu32F_OK 0, X_OK 1, W_OK 2, R_OK 4.
    Returnsi32 — 0 if the access would be permitted, -1 otherwise
    Errorsplus any filesystem failure, mapped from FsError

    Delegates to faccessat with AT_FDCWD. There is one user id, so only the read-only attribute can actually deny anything; undefined mode bits are EINVAL rather than ignored.

  23. 22pipeCreate a pipe and return both ends.I/O
    RegArgumentTypeMeaning
    rdipipefd*mut [u64; 2]Receives [read_fd, write_fd].
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    If the copy back to userspace faults, both descriptors are closed rather than leaked.

  24. 32dupDuplicate a descriptor onto the lowest free number.I/O
    RegArgumentTypeMeaning
    rdioldfdu64Descriptor to duplicate.
    Returnsu64 — the new descriptor, u64::MAX on error
    Errors
  25. 33dup2Duplicate a descriptor onto a chosen number, closing whatever was there.I/O
    RegArgumentTypeMeaning
    rdioldfdu64Descriptor to duplicate.
    rsinewfdu64Target number.
    Returnsu64 — newfd, u64::MAX on error
    Errors
  26. 34msyncFlush the dirty pages of a MAP_SHARED range to storage.Memory
    RegArgumentTypeMeaning
    rdiaddru64Start of the range.
    rsilenu64Length in bytes.
    rdxflagsu32MS_ASYNC 0x1, MS_SYNC 0x2, MS_INVALIDATE 0x4.
    Returnsi64 — 0 on success, -1 on error
    Errors

    The VMA lock collects the work and is dropped before any disk I/O runs.

  27. 35nanosleepSleep for a duration given in nanoseconds.Time
    RegArgumentTypeMeaning
    rdireq*const TimespecRequested duration; tv_nsec must be under 1e9.
    rsirem*mut TimespecAccepted and validated, never written.
    Returnsi32 — 0 on success, -1 on error
    Errors

    A sleep ends on any wake, so the kernel loops until the deadline passes. `rem` stays unwritten because there are no userspace signal handlers yet, which makes an early return unobservable.

  28. 39getpidProcess ID of the caller.Process

    Takes no arguments.

    Returnsu64 — the pid
    ErrorsCannot fail.
  29. 40waitpidWait for a child to exit and collect its status.Process
    RegArgumentTypeMeaning
    rdipidu64Child to wait for.
    rsiblocku641 parks until the child exits, anything else polls.
    rdxstatus*mut i32Receives the exit code; may be null.
    Returnsu64 — the pid, 0 if it has not exited and block was 0, u64::MAX on error
    Errors
  30. 57spawnLoad a program as a new process with three inherited descriptors.Process
    RegArgumentTypeMeaning
    rdipath*const u8Program to load.
    rsiargv*const *const u8NULL-terminated argument vector.
    rdxstdin_fdu64Descriptor to install as stdin.
    r10stdout_fdu64Descriptor to install as stdout.
    r8stderr_fdu64Descriptor to install as stderr.
    Returnsu64 — the child pid, u64::MAX on error
    Errors

    Registers are scarce, so anything richer than three descriptors goes through spawn2.

  31. 59execveReplace this process’s image, keeping its pid.Process
    RegArgumentTypeMeaning
    rdipath*const u8Program to load.
    rsiargv*const *const u8NULL-terminated argument vector.
    rdxenvp*const *const u8NULL-terminated environment.
    Returnsdoes not return on success; u64::MAX on error
    Errors

    One rule dictates the order of the whole implementation: nothing observable changes until the point of no return, and nothing after that point may fail.

  32. 60exitTerminate the calling thread.Process
    RegArgumentTypeMeaning
    rdicodei32Exit status.
    Returnsdoes not return
    ErrorsCannot fail.
  33. 72fcntlDescriptor flags and duplication.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsicmdu64F_DUPFD 0, F_GETFD 1, F_SETFD 2, F_DUPFD_CLOEXEC 1030.
    rdxargu64Command-specific argument.
    Returnsi64 — command-specific, -1 on error
    Errors

    F_GETFL and F_SETFL return EINVAL rather than a plausible-looking zero: there is no O_NONBLOCK here, and a caller told it succeeded would then rely on it.

  34. 76truncateSet a file length by path.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Path, not NUL-terminated.
    rsipath_lenusizeLength in bytes.
    rdxsizeu64New length in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Growing a file creates a hole: the blocks it names are never allocated and read back as zeros. Shrinking zeroes the surviving tail of the last cached page, so a later grow cannot resurrect the old bytes.

  35. 78getdentsStream a directory listing from an entry index.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to list.
    rsipath_lenusizeLength in bytes.
    rdxbuf*mut u8Destination buffer.
    r10buf_sizeusizeBuffer capacity in bytes.
    r8startusizeIndex of the first entry to pack.
    Returnsi64 — bytes written, 0 once `start` is past the last entry, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The caller advances `start` by the number of entries it decoded, so there is no in/out cursor to keep. An entry that cannot fit on its own is EINVAL, not 0, because 0 means end of directory and would silently drop the tail.

  36. 82renameRename or move an entry.Filesystem
    RegArgumentTypeMeaning
    rdiold_path*const u8Existing path.
    rsinew_path*const u8Destination path.
    Returnsi32 — 0 on success, -1 on error
    Errors
  37. 102getuidReal user id of the calling process.System

    Takes no arguments.

    Returnsu64 — the uid
    ErrorsCannot fail.
  38. 104getgidReal group id of the calling process.System

    Takes no arguments.

    Returnsu64 — the gid
    ErrorsCannot fail.
  39. 162syncFlush every dirty block cache page to disk.Filesystem

    Takes no arguments.

    Returnsu64 — always 0
    ErrorsCannot fail.

    Errors are the writeback thread’s to log; the caller is told nothing because it can do nothing.

  40. 169rebootSync every filesystem, then stop or restart the machine.System
    RegArgumentTypeMeaning
    rdicmdu640 power off, 1 reset, 2 halt.
    Returnsdoes not return on success; -1 on error
    Errors

    Soft-off with no AML interpreter: PM1a/PM1b_CNT come from the FADT and SLP_TYPa is decoded structurally out of the DSDT’s \_S5_ package, with emulator ports as a fallback. Reset drives RST_CNT then pulses the 8042. Progress prints to the serial port rather than the log ring, because the kthread that drains the ring will not run again.

  41. 202mountMount a partition at a path.Filesystem
    RegArgumentTypeMeaning
    rdidevice_idu64Block device index.
    rsipartition_idxu64Partition within that device.
    rdxpath*const u8Mount point.
    r10fs_type*const u8Filesystem name, e.g. efs or fat32.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  42. 203list_partitionsDescribe every partition the kernel enumerated, as text.Filesystem
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsisizeu64Buffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errors
  43. 204mkdirCreate a directory.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to create.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  44. 205rmdirRemove an empty directory.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to remove.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  45. 206rmdir_allRemove a directory and everything under it.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Root of the subtree to remove.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The recursion lives in the kernel because a userspace walk would race with anyone else writing into the tree.

  46. 208list_mountsDescribe the mount table as text.Filesystem
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsisizeusizeBuffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errors
  47. 209sleep_msPark the calling thread for a duration.Time
    RegArgumentTypeMeaning
    rdimillisecondsu64How long to sleep.
    Returnsu64 — always 0
    ErrorsCannot fail.
  48. 210monotonic_timeNanoseconds since boot, from the HPET.Time

    Takes no arguments.

    Returnsu64 — nanoseconds
    ErrorsCannot fail.

    Monotonic with microsecond resolution, scaled to nanoseconds. It never goes backwards and never jumps with the wall clock.

  49. 211cloneStart a thread in the calling process’s address space.Process
    RegArgumentTypeMeaning
    rdifuncu64Entry point.
    rsiargu64Value passed to the entry point.
    rdxflagsu64Clone flags.
    r10child_stacku64Top of the stack the child runs on.
    Returnsu64 — the child thread id, u64::MAX on error
    Errors

    The child shares the address space, the descriptor table and the heap break, and gets its own TLS block and stack.

  50. 212futex_waitSleep while a word in memory still holds an expected value.Sync
    RegArgumentTypeMeaning
    rdiaddr*const u32Word to watch.
    rsiexpectedu32Value to sleep on.
    rdxtimeout_nsu64Timeout in nanoseconds; u64::MAX waits forever.
    Returnsu64 — 0 woken with the value changed, 1 value did not match or a spurious wake, 2 timed out, u64::MAX on error
    Errors

    Keyed by the address space plus the address, so two processes sharing a mapping share a queue. The wait queue is dropped when its last waiter leaves.

  51. 213futex_wakeWake waiters parked on a word.Sync
    RegArgumentTypeMeaning
    rdiaddr*const u32Word waiters are parked on.
    rsicountu32How many to wake.
    Returnsu64 — waiters actually woken, u64::MAX on error
    Errors
  52. 214getrandomFill a buffer with random bytes.System
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsilenusizeBytes to generate, at most 1 MiB.
    rdxflagsu64Must be 0.
    Returnsi64 — bytes written, -1 on error
    Errors
  53. 215shm_createCreate a shared memory region.Shared memory
    RegArgumentTypeMeaning
    rdisizeu64Size in bytes.
    Returnsi64 — the region id, -1 on error
    Errors
  54. 216shm_mapMap a shared region into the calling process.Shared memory
    RegArgumentTypeMeaning
    rdishm_idu64Region id.
    rsiaddr_hintu64Suggested address, or 0 to let the kernel choose.
    rdxprotu64PROT_READ 0x1, PROT_WRITE 0x2, PROT_EXEC 0x4.
    Returnsu64 — the mapping address, u64::MAX on error
    Errors

    This is what a window buffer is: the client draws into the region and the compositor reads the same frames.

  55. 217shm_unmapUnmap a shared region from the calling process.Shared memory
    RegArgumentTypeMeaning
    rdiaddru64Address the region was mapped at.
    Returnsi64 — 0 on success, -1 on error
    Errors
  56. 218shm_destroyDestroy a shared region.Shared memory
    RegArgumentTypeMeaning
    rdishm_idu64Region id.
    Returnsi64 — 0 on success, -1 on error
    Errors

    Refused while any mapping is still live.

  57. 219window_createRegister a window with the kernel.Window
    RegArgumentTypeMeaning
    rdixi64Position, x.
    rsiyi64Position, y.
    rdxwidthu64Width in pixels.
    r10heightu64Height in pixels.
    Returnsu64 — the window id, u64::MAX on error
    Errors

    The kernel owns the registry and routes input to it. Decoration, stacking and everything else people call a window manager is userspace.

  58. 220window_destroyRemove a window from the registry.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  59. 221window_setSet a window property.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsipropu64VISIBLE 1, X 2, Y 3, WIDTH 4, HEIGHT 5, TITLE_PTR 6, BUFFER_SHM 7, FLAGS 8.
    rdxvalueu64The value, or a pointer for TITLE_PTR.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    FLAGS carries FLAG_DOCK 1, the undecorated, undraggable window the taskbar uses.

  60. 222window_getRead a window property.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsipropu64Property id, as for window_set.
    Returnsu64 — the property value, u64::MAX on error
    Errors
  61. 223window_pollDrain pending events for a window.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsievents*mut WindowEventDestination array.
    rdxmaxu64Capacity of that array.
    Returnsu64 — events copied, u64::MAX on error
    Errors
  62. 224window_listList every window, for the compositor.Window
    RegArgumentTypeMeaning
    rdibuf*mut WindowListEntryDestination array.
    rsimaxu64Capacity of that array.
    Returnsu64 — entries written, u64::MAX on error
    Errors
  63. 225window_send_eventPost an event to a window the caller does not own.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Target window.
    rsievent*const WindowEventEvent to deliver.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    How the window manager asks a client to close itself.

  64. 226clock_gettimeNanoseconds since the Unix epoch.Time
    RegArgumentTypeMeaning
    rdibuf*mut u8Eight-byte buffer receiving a little-endian u64.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Answered from the monotonic counter plus a wall-clock offset sampled at boot, so it costs a counter read rather than several RTC port round-trips.

  65. 227openptyOpen a pty master and slave pair.I/O
    RegArgumentTypeMeaning
    rdifds*mut [u64; 2]Receives [master_fd, slave_fd].
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    What the terminal emulator opens before it spawns a shell.

  66. 228spawn2Spawn with arguments, an environment and three descriptors.Process
    RegArgumentTypeMeaning
    rdiargs*const SpawnArgsStruct of { path, argv, envp, stdin_fd, stdout_fd, stderr_fd }.
    Returnsu64 — the child pid, u64::MAX on error
    Errors
  67. 229killSend a signal to a process.Process
    RegArgumentTypeMeaning
    rdipidu64Target process.
    rsisignumu32Signal number, 1 to 31.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  68. 230sigactionInstall a signal disposition.Process
    RegArgumentTypeMeaning
    rdisignumu32Signal number, 1 to 31; SIGKILL is rejected.
    rsihandleru320 SIG_DFL, 1 SIG_IGN, otherwise a handler address.
    Returnsu64 — the previous disposition, u64::MAX on error
    Errors
  69. 231shm_sizeSize of a shared region.Shared memory
    RegArgumentTypeMeaning
    rdishm_idu64Region id.
    Returnsi64 — size in bytes, -1 on error
    ErrorsCannot fail.
  70. 232window_damageTell the compositor a window has repainted its buffer.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    Returnsu64 — 0 on success, u64::MAX on error
    ErrorsCannot fail.
  71. 233sigprocmaskRead and change the calling thread’s blocked signal mask.Process
    RegArgumentTypeMeaning
    rdihowu32SIG_BLOCK 0, SIG_UNBLOCK 1, SIG_SETMASK 2.
    rsimasku32The set to apply.
    Returnsu64 — the previous mask, u64::MAX on error
    Errors

    Sets are 32 bits, so the mask goes in and the old one comes back by value rather than through pointers, matching sigaction. A signal sent while blocked is recorded pending without killing or waking the target; widening the mask delivers it immediately, and SIGKILL is dropped from the mask rather than making the call fail.

  72. 234window_grant_shellAppoint another process as part of the shell.Window
    RegArgumentTypeMeaning
    rdipidu64Process to appoint.
    Returnsi32 — 0 on success, -1 on error
    Errors

    Moving, resizing, framing, minimizing and posting events to a window belong to a shell, not to the window’s owner, so they cannot be gated on ownership. They are gated on this instead. Only a process that already holds the privilege may grant it, and the kernel seeds exactly one: `bin/edos-init`, the only process it starts, which appoints the compositor and the panel. The grant is per pid, follows a process’s threads, and is dropped when the process exits.

  73. 240socketCreate a socket and install it in the descriptor table.Network
    RegArgumentTypeMeaning
    rdidomainu64AF_INET 2.
    rsitypeu64SOCK_STREAM 1, SOCK_DGRAM 2.
    rdxprotocolu64Ignored; implied by the type.
    Returnsu64 — the new descriptor, u64::MAX on error
    Errors
  74. 241bindBind a socket to a local address.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*const SockAddrInLocal address.
    rdxaddr_lenu64Size of that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  75. 242connectOpen a connection to a remote address.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*const SockAddrInRemote address.
    rdxaddr_lenu64Size of that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Blocks through the TCP handshake.

  76. 243listenMark a bound socket as accepting connections.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibacklogu32Pending connection queue depth.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  77. 244acceptTake the next established connection off a listening socket.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*mut SockAddrInReceives the peer address; may be null.
    rdxaddr_len*mut u32In and out length for that struct.
    Returnsu64 — descriptor for the new connection, u64::MAX on error
    Errors
  78. 245sendtoSend on a socket, with an explicit destination for datagrams.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*const u8Payload.
    rdxlenu64Payload length.
    r10flagsu64Unused.
    r8addr*const SockAddrInDestination; null on a connected socket.
    r9addr_lenu64Size of that struct.
    Returnsu64 — bytes sent, u64::MAX on error
    Errors
  79. 246recvfromReceive on a socket, optionally reporting the sender.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*mut u8Destination buffer.
    rdxlenu64Buffer capacity.
    r10flagsu64Unused.
    r8addr*mut SockAddrInReceives the sender address; may be null.
    r9addr_len*mut u32In and out length for that struct.
    Returnsu64 — bytes received, u64::MAX on error
    Errors
  80. 247shutdownClose one or both directions of a connection.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsihowu640 read, 1 write, 2 both.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  81. 248setsockoptSet a socket option.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsileveli32Option level.
    rdxoptnamei32Option name.
    r10val*const u8Option value.
    r8val_lenu32Length of that value.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  82. 249pingSend an ICMP echo request and wait for the reply.Network
    RegArgumentTypeMeaning
    rdidst_ip*const [u8; 4]Destination address.
    rsiidu16ICMP identifier.
    rdxsequ16ICMP sequence number.
    r10timeout_msu64Timeout in milliseconds; 0 means 5000.
    Returnsu64 — round-trip time in microseconds, u64::MAX on timeout or error
    Errors

    A raw socket API would be the general answer; this is the one ICMP case userspace actually needs.

  83. 250netinfoDescribe the network interfaces as text.Network
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsilenusizeBuffer capacity in bytes.
    Returnsu64 — bytes written, u64::MAX on error
    Errors
  84. 251getsockoptRead a socket option.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsileveli32Option level.
    rdxoptnamei32Option name.
    r10val*mut u8Receives the value.
    r8val_len*mut u32In and out length for that buffer.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  85. 252getpeernameAddress of the remote end of a connection.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*mut SockAddrInReceives the peer address.
    rdxaddr_len*mut u32In and out length for that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  86. 253getsocknameLocal address a socket is bound to.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*mut SockAddrInReceives the local address.
    rdxaddr_len*mut u32In and out length for that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  87. 254statfsFilesystem statistics for the mount that holds a path.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Any path on the filesystem.
    rsibuf*mut RawStatFsDestination struct.
    rdxbuf_lenusizeSize of that struct.
    Returnsi64 — 0 on success, -1 on error
    Errors
  88. 255forkDuplicate the calling process, copy-on-write.Process

    Takes no arguments.

    Returnsi64 — the child pid in the parent, 0 in the child, -1 on error
    Errors

    Private mappings are marked read-only in both processes and split on the first write fault.

  89. 256getdnsThe resolver address the stack learned from DHCP.Network
    RegArgumentTypeMeaning
    rdiaddr*mut [u8; 4]Receives the resolver address.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    A resolver is configuration, and there is no /etc/resolv.conf convention here, so userspace asks the stack that learned it.

  90. 257openatOpen a path resolved against a directory descriptor.I/O
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10flagsu64Same flag set as open.
    Returnsi64 — new descriptor, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Shares its body with open, which is openat against the cwd. Taking pointer and length rather than a NUL-terminated string means userspace does not have to allocate a CString per open.

  91. 258mkdiratCreate a directory relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    No mode argument: there are no permission bits to observe yet.

  92. 262fstatatStat a path resolved against a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10statbuf*mut FstatEntryReceives the metadata.
    r8flagsu64Must be zero.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    stat is this call against the cwd. A nonzero flags word is rejected rather than ignored: AT_SYMLINK_NOFOLLOW cannot be honoured while the lookup follows links.

  93. 263unlinkatRemove a file or directory relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10flagsu640, or AT_REMOVEDIR (0x200) to remove a directory.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    AT_REMOVEDIR is the only accepted flag; anything else is EINVAL.

  94. 264renameatRename, resolving each side against its own directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdiolddirfdi64Base for the old path, or AT_FDCWD (-100).
    rsioldpath*const u8Existing name.
    rdxoldpath_lenusizeLength in bytes.
    r10newdirfdi64Base for the new path, or AT_FDCWD (-100).
    r8newpath*const u8New name.
    r9newpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    rename routes through the same body, which is what gives it real filesystem error codes instead of a flat EINVAL.

  95. 266symlinkatCreate a symbolic link relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rditarget*const u8What the link points at, stored verbatim.
    rsitarget_lenusizeLength in bytes.
    rdxnewdirfdi64Base for the link path, or AT_FDCWD (-100).
    r10linkpath*const u8Where the link is created.
    r8linkpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The descriptor places the link only. The target is never resolved at creation time, so it may dangle, and a dangling link still takes the name.

  96. 267readlinkatRead a link target relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8The link itself.
    rdxpath_lenusizeLength in bytes.
    r10buf*mut u8Destination buffer.
    r8buf_lenusizeBuffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    readlink is this call against the cwd.

  97. 269faccessatTest access to a path relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10modeu32F_OK 0, X_OK 1, W_OK 2, R_OK 4.
    r8flagsu64Must be zero.
    Returnsi32 — 0 if the access would be permitted, -1 otherwise
    Errorsplus any filesystem failure, mapped from FsError

    Flags are rejected rather than ignored. AT_EACCESS names the only set of ids there is, and AT_SYMLINK_NOFOLLOW cannot be honoured while the lookup follows links.

  98. 280utimensatSet a file’s access and modification times.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10times*const [Timespec; 2]Access time then modification time; null means both now.
    r8flagsu64Must be zero.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    UTIME_NOW stamps the current time and UTIME_OMIT leaves that field alone. EFS applies both in one journal transaction. AT_SYMLINK_NOFOLLOW is rejected, since the underlying set_times follows links.

  99. 1024errnoThe error code the caller’s last failing syscall stored.System

    Takes no arguments.

    Returnsu64 — an Errno discriminant
    ErrorsCannot fail.

    Per thread, and cleared at the start of every handler that can fail. The value is the discriminant below, not a POSIX number.

Errno is a plain Rust enum, and what userspace reads is its discriminant. These are not the POSIX numbers; a program that hardcodes 2 for ENOENT is reading ENOMEM.

ValueNameMeaning
0ClearNo error. Every handler stores this before it does any work.
1EINVALInvalid argument passed to a syscall.
2ENOMEMMemory allocation failed or memory exhausted.
3EFAULTBad memory address provided by userspace.
4EBADFInvalid or closed file descriptor.
5EACCESOperation requires permissions the caller lacks.
6EPERMOperation not permitted for the current caller.
7ENOENTRequested file or directory does not exist.
8EEXISTAttempted to create an entry that already exists.
9ENOTDIRExpected a directory but encountered a non-directory entry.
10EISDIROperation required a regular file but encountered a directory.
11ENOSPCDevice or filesystem has no space left for the operation.
12EROFSWrite attempted on a read-only filesystem or device.
13EIOGeneric I/O failure from the filesystem or storage layer.
14EINTRSystem call interrupted, e.g. by a signal or a kill.
15ENOEXECFile format is not recognized as an executable.
16EAGAINResource temporarily unavailable; the operation would block.
17ENOTCONNSocket is not connected.
18ECONNREFUSEDConnection was refused by the remote host.
19EADDRINUSEAddress already in use.
20EPIPEBroken pipe: a write to a closed connection.
21EAFNOSUPPORTAddress family not supported.
22ESPIPESeek on a descriptor with no file offset: pipe, socket, tty.
23EBUSYDevice or resource in use, e.g. a disk backing a live mount.
24UNKNOWNPlaceholder for unmapped kernel error codes.

Filesystem failures reach userspace through a mapping rather than as their own codes: FileNotFound becomes ENOENT, NotAFile becomes EISDIR, NotADir becomes ENOTDIR, Busy becomes EBUSY, InvalidFs and InvalidArgument become EINVAL, and everything else, including a corrupt filesystem and an AHCI error, becomes EIO.

Four edits, in this order:

  1. A number constant and a dispatch arm in kernel/src/syscalls/mod.rs. The arm unpacks registers and calls the implementation; it does not contain logic.
  2. The implementation in the matching syscalls/*.rs, taking real types rather than registers, clearing the caller’s error code first and copying user memory through the checked helpers.
  3. A wrapper in programs/edos_lib/, or in the edos_rt crate and the std fork if it has to be reachable through std.
  4. A row here, since this page is transcribed from that table.