Commit Graph

74 Commits

Author SHA1 Message Date
Daniel Samson b0f894f50c
M9: user-space VFS server + client file API (open/read/write/stat + stdio)
The payoff milestone: files are served by a user-space process, reached over
IPC — the kernel never sees a path or an fd.

- lib/vfs_proto.zig: the VFS wire protocol (Op, Request/Reply fixed header +
  inline payload, Stat), shared by client and server; one message <= MSG_MAX.
- lib/ipc.zig: replyWait() — the server-side dual-return stub (length in rax,
  badge in rdx via a "+{rdx}" read-write operand), deferred from M7.
- sbin/vfs.zig: the real VFS server — an in-heap ramfs (open creates a node)
  with an IPC_ReplyWait dispatch loop serving open/read/write/stat/close.
  Registers its endpoint under the well-known vfs id at startup.
- lib/unistd.zig: POSIX-style client API in rt — a per-process fd table +
  open/close/read/write/lseek/stat, each an IPC_Call to the VFS. The kernel
  knows nothing of fds; the table lives here.
- lib/stdio.zig: C stdio over unistd — FILE + fopen/fclose/fread/fwrite/
  fseek/ftell/rewind/feof/ferror/fputs/fputc/fgetc (unbuffered for now).
- sbin/vfstest.zig: a client that opens/writes/seeks/reads a file and only
  heartbeats "vfstest: ok" if the round trip matched. Packed in the initrd.
- New `vfs` test drives it end to end. initrd test relaxed to generic
  liveness. Suite 31/31.
2026-07-09 07:48:24 +01:00
Daniel Samson 750a73f050
M8: initrd handoff + multi-binary shipping
Ship more than one user binary: the bootloader now ferries an initrd bundle
(the VFS server + future drivers) alongside sbin/init, and the kernel unpacks
and spawns each program.

- src/user/proto/initrd.zig: the container format (Header{magic,count} +
  Entry{name[32],offset,len} + blobs) with a validating Reader, shared by the
  kernel and the packer.
- tools/mkinitrd.py: host-side packer (Python — trivial format, and sidesteps
  the reworked Zig 0.16 std fs/args API). build.zig runs it on the built user
  binaries via addSystemCommand and installs initrd.img to zig-out/bin + the
  ESP root.
- BootInfo gains initrd_base/initrd_len; efi.zig loadInit refactored into a
  shared loadFile, and loadInitrd ferries \initrd.img into surviving
  LoaderData like init.
- main.zig startInitrdBinaries(): parse the image, spawn every entry (kernel-
  spawns-all for now; init takes over via sys_spawn later).
- sbin/vfs.zig: a heartbeat stub (the real VFS server is M9), packed into the
  initrd to prove the pipeline.
- New `initrd` test: parse + spawn + confirm the vfs stub reaches ring 3 and
  heartbeats. Harness ships initrd.img on the ESP. Suite 30/30.
2026-07-09 07:36:25 +01:00
Daniel Samson 0a8c81b17a
M6: user runtime library `rt` + C-convention heap
Add lib/ — the shared user-space runtime every user binary links against
(init now, servers/drivers later): syscall wrappers, the heap, IPC stub,
and the process start shim.

- lib/heap.zig: the kernel first-fit free-list ported to user space, grown
  via the mmap syscall instead of pmm+mapPage. Dual API over one global free
  list: extern "C" malloc/free/calloc/realloc (C ABI for future C code) and a
  std.mem.Allocator adapter (with in-place resize) for Zig std containers.
- lib/syscall.zig + sys.zig: raw syscall0..5 (arg3 in r10) and typed
  yield/write/sleep/exit/mmap/munmap over danos.Syscall.
- lib/start.zig: naked _start -> rt_start -> root.main() (SysV realign via
  call), panic -> exit(127).
- lib/user.ld: the user link script, moved from sbin/linker.ld (shared by all
  user binaries).
- build.zig: register the `rt` module; add an addUserBinary() helper that is
  the one recipe for every user binary (freestanding, .large, use_lld,
  user.ld, image_base), replacing the bespoke init block.
- sbin/init.zig: migrated onto rt; drops its hand-rolled syscall2/shims. Now
  proves the heap (alloc -> write from a heap pointer -> free) before the
  heartbeat loop. Serial shows "init: heap ok". Suite 28/28.
2026-07-09 07:08:32 +01:00
Daniel Samson 9316f9f1c3
M5: rename usermode->process, add yield + mmap/munmap syscalls
Start the user-space driver track (VFS + IPC + heap). This lays the
process/syscall foundation the runtime heap will grow on.

- Rename usermode.zig -> process.zig; drop the retired hello/ping blob and
  its `user` test (subsumed by the real /sbin/init exerciser). Keep the
  isolation-proof pf blob and the user-pf test.
- Add danos.Syscall as the single source of truth for syscall numbers, shared
  by the kernel dispatcher and (later) the user runtime lib. Dispatch on the
  enum. New calls: 1=yield, 4=mmap, 5=munmap. Widen debug_write's bounds
  check to the whole user low half so heap buffers are writable.
- mmap grants zeroed RW+NX pages from a per-process bump arena
  (Task.heap_next, PML4[224] above image+stack); munmap frees the frames.
  Add paging.translateIn / unmapInto (+ arch.translate / unmapUserPageInto)
  as the primitives munmap and future cross-AS copies need.
- New `usermem` test: grant three pages into a fresh AS, translate them,
  release via the munmap path, tear down, and assert no frames leak.
  Suite 28/28 (user -> usermem).
2026-07-09 06:55:09 +01:00
Daniel Samson b9d9e1e523
M4: /sbin/init as PID 1 — a heartbeat process
init is now a real scheduled ring-3 process: it prints a heartbeat and
sleeps, forever. The kernel spawns it at boot via spawnProcess (its own
address space, preemption on) and the boot context drops to idle — the
system's steady state is "kernel idle, init alive in ring 3", beating
~1 Hz. Adds the sleep(ms) syscall. The init/process tests are reshaped
around the heartbeat (repeated syscalls, still-alive, two concurrent
processes on distinct address spaces). Pins init to LLD and folds the
.large code model's .ltext/.lrodata/.ldata into the linker script so its
code segment is R+X. Removes the now-dead borrowed-thread ELF loader
(runInitElf); spawnProcess is the one path. Docs updated. Suite 28/28.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:19:46 +01:00
Daniel Samson f57a73e8a1
M2 step 4: relink the kernel into the higher half
The kernel now links at 0xFFFF_FFFF_8000_0000 (code_model .kernel) and
loads low via the linker script's AT() clauses (.text at 1 MiB). A new
asm _start installs a 64 KiB kernel-owned .bss stack — the loader stack
is a low address that goes away with the identity map — and calls the
Zig entry, which reaches boot_info through the physmap. The user-pf test
blob reads the LAPIC through the physmap window (still present|user, ec
0x5). The low identity map still coexists in the kernel's tables as the
safety net. Suite 27/27.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 22:45:56 +01:00
Daniel Samson 91aff2bc4a
pin the kernel to LLVM+LLD
The self-hosted linker ignores parts of linker.ld (PHDRS, /DISCARD/,
section order). The higher-half move needs the script authoritative.
Suite 27/27 on the LLD build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 22:17:02 +01:00
Daniel Samson 546dd44a2a
isolation M1: ring 3 + a real /sbin/init, end to end
Ring 3 works: user GDT descriptors (sysret-ready layout), TSS.rsp0,
U/S-bit user mappings (W^X preserved), an int 0x80 syscall gate with a
mutable trap frame, and a setjmp-style enter/exit path. /sbin/init is a
real freestanding Zig binary built from sbin/, shipped on the ESP,
loaded by the bootloader (BootInfo.init_base/len), validated and mapped
by an in-kernel user-ELF loader, and run at CPL 3 — syscalls: exit,
ping, write. Tests: user, user-pf (U/S isolation proof, error code
0x5), init. Suite 27/27.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 22:15:07 +01:00
Daniel Samson 7501bd1703
gather kernel tunables into config.zig
max_cpus, max_tasks, kernel/IST stack sizes, and timer_hz move from scattered constants into one config module. root.zig goes back to being just the boot contract. Values unchanged; any can become a -D build option later.
2026-07-08 16:26:36 +01:00
Daniel Samson 43afe6bf2e
schedule tasks across all cores
Per-core GDT/TSS and AP scheduler entry; fix AP SSE + single_threaded.
2026-07-08 12:35:30 +01:00
Daniel Samson ed7f542006
wake application processors to long mode
INIT-SIPI-SIPI plus a self-relocating real-mode trampoline.
2026-07-08 12:35:30 +01:00
Daniel Samson 2ee898a91e
add device platform module with ACPI support 2026-07-08 09:23:41 +01:00
Daniel Samson 6f6ccc8bc9 moving kernel code to kernel/ 2026-07-05 10:19:11 +01:00
Daniel Samson 7c3cffb337 moving efi code to boot 2026-07-05 10:01:01 +01:00
Daniel Samson 99d6bf5ce3 renaming run-efi to run-x86-64 2026-07-03 19:45:44 +01:00
Daniel Samson 50f3610768
Update build to run qemu on MacOS 2026-07-03 16:43:00 +01:00
Daniel Samson 9a834c91ff Pin zig version to 0.16 LTS 2026-07-03 13:49:47 +01:00
Daniel Samson 20b4661ff3 Hardened paging into a real VMM 2026-07-03 13:29:34 +01:00
Daniel Samson c8e89e8115 Cross-architecture test suite 2026-07-03 12:39:26 +01:00
Daniel Samson 0cc71ec8aa Built GDT + IDT + exception handlers 2026-07-03 12:05:41 +01:00
Daniel Samson 628c4f6d57 Move to multi arch support and added memory map 2026-07-03 11:11:19 +01:00
Daniel Samson 6a08081bfe selecting the displays native resolution 2026-07-03 10:07:51 +01:00
Daniel Samson ca3c3d131c booting into the kernel 2026-07-01 19:51:06 +01:00
Daniel Samson 3c8656fb25 started project with basic efi setup 2026-07-01 18:32:56 +01:00