docs: architecture describes what is built now

kernel (threads, demand paging, TLB shootdowns, dynamic linking, RAM direct map), syscalls, filesystem (/proc, /sys,
/dev), terminals (12, VT handshake, ptys), networking (r8169 through LDLS), LDLS (module sets; Linux code may ship),
devices (what stays in the kernel; hybrid.md's lasting content), boot (the loader's placement of the kernel),
graphics (fbdev, GMMOS, QR 1-40), audio (ALSA over OSS), debugging, usb. New: packages.md (the apk root) and
desktop.md (Xorg on the framebuffer).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
Nexoniarz 2026-10-26 07:57:25 +01:00
commit 2556a955b3
15 changed files with 921 additions and 341 deletions

View file

@ -131,6 +131,42 @@ when the early console is set up. So a low framebuffer is attached exactly as
before, and a high one is attached a few dozen instructions later, immediately
after `kvmalloc()` — still thousands of lines before anything else happens.
### Where the kernel goes, and how it gets there
The kernel is linked at physical **16 MB** (`KERNPHYS` in `memlayout.h`, repeated in
`kernel.ld`, which must agree) and is about 34 MB with the ramdisk inside it. From the
old 1 MB it ran across 8 MB, where OVMF keeps ACPI NVS memory that outlives the firmware,
so it was overwritten on every boot, after `ExitBootServices`. Firmware leaves its
leftovers low; above 16 MB is where a machine is most reliably empty. (The 15 MB below
the kernel is not given to the page allocator yet.)
**Every free page of that range is claimed first.** A segment lying wholly on claimed
pages is read straight home; one that is not is read into a buffer elsewhere and
**copied home after `ExitBootServices`**, when boot-services memory is ours. An HP
all-in-one from 2012 used to freeze at the start of the loading bar because the loader
said "could not reserve" and read the kernel there anyway, over the firmware's own memory
with the firmware still running on it. Memory under the kernel that outlives the firmware
(ACPI NVS, runtime services) is named, and so is the loader or its stack sitting in the
range. Segments are read a megabyte at a time, so the bar moves through the ramdisk and
shows where a machine stopped.
The copy and the jump themselves run from **one page below the kernel's lowest address**,
allocated as loader code before the firmware exits: a short position-independent routine,
the copy list and a stack, switching to the loader's page tables and its own stack before
it copies anything. Doing the copy from code the firmware had placed wherever it liked put
some of it inside the kernel's range on that machine: a triple fault and a reset. The
routine is `sysv_abi`, because UEFI code is the Microsoft convention and the first try loaded
the framebuffer address into `rsp`.
**No 1 GB pages, no problem.** Intel's desktop CPUs before Haswell have none, and there the
PS bit in a PDPT entry is reserved: the first access after the switch is a page fault that
cannot be handled either. Both the loader and the kernel check CPUID `0x80000001` EDX bit 26;
without it the low 4 GB is four page directories of 2 MB pages (placed below the kernel, with
the staged segments kept below 4 GB), and the kernel gives each gigabyte of its direct map
and of `ioremap()` a page directory of its own. Neither KVM nor QEMU enforces the reserved
bit, so the fault could not be reproduced here; with the fallback forced on, the kernel
boots at 2 and 8 GB and both CPUs start.
### The loader jumped out from under itself
A machine with a lot of RAM froze at "Starting the kernel" — the splash still
@ -610,7 +646,9 @@ in the one process that runs first.
## What it does not do
- **No BIOS path.** A machine without UEFI does not boot SchOS.
- **No BIOS path.** A machine without UEFI does not boot SchOS. The ISO carries a real EFI
system partition (MBR type `0xEF`, FAT16 by cluster count, the type old firmware reads best),
so a stick written with `dd` or `write.sh` boots on strict firmware as well as on lenient.
- **The quiet boot hides a slow one.** With nothing printing between the
loader and the greeting, a boot that stalls for ten seconds looks the same as
one that does not. F8 is the answer and it has to be pressed *before* the
@ -621,9 +659,11 @@ in the one process that runs first.
with its partitions, but nothing mounts it. See [usb.md](usb.md).
- **NVMe and AHCI poll for completion**, one command at a time per disk. That
is enough to boot and run from them, not to be fast.
- **`make ramroot` is the only way to boot with no data disk.** It links a
filesystem image into the kernel binary, which costs boot time and carries a
licensing constraint — see [../licensing.md](../licensing.md) §4.
- **The live ISO is a ramdisk root.** `make iso` builds the root as a SchFS image,
compresses it ([scff.md](scff.md)) and links it into the kernel; nothing is written to
the machine's disks, and everything written to the root is gone at reboot. There is
no installer, and no kernel that finds a root on a disk by SchFS's GPT type as its
*default*. `make ramroot` is the same without compression.
- **The 32-bit multiboot entry is dead code.** It is left in place deliberately:
deleting kernel entry code is its own piece of work with its own way of
failing silently.