M3: real user processes — address spaces, syscall/sysret, swapgs

Per-process address spaces (AddressSpace = a PML4 with an empty user
half and the shared kernel half copied in; create/destroy in paging.zig)
with CR3 switched on context switch and TSS.rsp0/kernel_rsp published per
switch. The GS base now points at an arch per-CPU block and every ring
transition observes the swapgs discipline, so a ring-3 `mov %ax,%gs` can
no longer poison per-CPU access. syscall/sysret is the primary user entry
(int 0x80 kept as a test path); one handler, installed once at boot,
serves both and dispatches on whether the caller is a scheduled process
or a borrowed test thread. spawnProcess loads an ELF into a fresh address
space and schedules it; exit frees the address space after switching to
the kernel tables. New `process` test: init runs twice as a real process
(create/exit/recreate) on its own page tables, coexisting with a kernel
task under preemption. Suite 28/28.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Samson
2026-07-09 00:04:20 +01:00
co-authored by Claude Fable 5
parent 5d57e7b01c
commit 37fb3cb0cf
9 changed files with 318 additions and 17 deletions
+9 -5
View File
@@ -1,11 +1,15 @@
# System Calls
System calls (syscalls) are the bridge between your programs and the operating system's restricted core (kernel).
> **Status:** danos currently has a placeholder M1 surface behind an `int 0x80`
> gate — `0 = exit(code)`, `1 = ping(value)`, `2 = write(ptr, len)` (see
> `src/kernel/usermode.zig`, used by `sbin/init.zig`). It exists to prove the
> ring transition; the microkernel set below replaces it (via `syscall`/`sysret`)
> when processes land (M3).
> **Status:** danos has real user processes (M3). User programs enter the kernel
> via the `syscall` instruction (STAR/LSTAR/SFMASK set per core; the entry stub in
> `isr.s` does the `swapgs` + kernel-stack switch and reuses the interrupt
> dispatcher). The `int 0x80` gate is kept alongside as a minimal test path. The
> current call set is still a placeholder — `0 = exit(code)`, `1 = ping`,
> `2 = write(ptr, len)`, `3 = sleep(ms)` (see `src/kernel/usermode.zig`); the
> handler dispatches on whether the caller is a scheduled process (its own address
> space) or a borrowed test thread. The microkernel set below (IPC_Call /
> IPC_ReplyWait / Yield) replaces it once a second user server exists.
## The Mechanism of a Syscall