Architecture
Limine loads the kernel over UEFI using the Limine boot protocol at base revision 6, and
calls main():
- GDT, IDT, frame allocator, kernel heap.
- ACPI tables, local APIC, I/O APIC, HPET. The APIC timer is calibrated against the HPET at boot; on a typical guest that lands around 1000 MHz with a 3.5 GHz TSC.
- SMP bring-up. Each application processor enables
SYSCALL/SYSRET, turns on the FPU and SSE, and initialises its own scheduler before reporting online. - The reaper and inode-eviction kernel threads, then the block page cache.
- PCI enumeration and driver init: virtio-gpu, xHCI, e1000e, Intel HDA, AHCI.
- Write-back and journal-committer kernel threads,
fs::init,window::init. - A
system-mountkernel thread mounts the root filesystem, then devfs on/dev, procfs on/procand memfs on/tmp. - It loads
bin/edos-initand queues it on the scheduler.
The whole sequence takes about 1.6 seconds on a four-core guest with KVM, and the boot log on the home page is that sequence verbatim.
The root filesystem is chosen from the Limine command line:
root=UUID=87654321-4321-8765-cba9-987654321fed rootfstype=efsmount_system_fs enumerates GPT partitions and mounts the one whose partition GUID
matches. Two details matter:
- The ISO carries a complete GPT disk image as a Limine boot module. A RAM-backed block device exposes it, which is how the ISO boots to a desktop with nothing else attached. Writes go into the module’s own memory, so the live root is writable and forgets everything on reboot.
- When both a real disk and the live root match, the real disk wins, so an installed
machine boots its installed system.
root=liveforces the live root instead.
If nothing matches, the kernel logs every partition it saw and falls back to a memfs root, which boots but keeps nothing. It never mounts an arbitrary partition just because one was there.
The kernel starts one process. bin/edos-init supervises edos-wm, edos-taskbar and
edos-terminal: it spawns them, waits on them, and restarts them with backoff. Session
policy lives in userspace, and a binary that fails to load is logged rather than
panicking the kernel.
Memory
Section titled “Memory”- A bitmap frame allocator over the Limine memory map.
- Per-process page tables, with the kernel mapped in the higher half of every address space.
- VMAs tracked per thread, with demand paging: a mapping is a promise, and the frame arrives on the fault.
- Copy-on-write
fork. - TLB shootdown by IPI when a mapping that other CPUs may have cached changes.
- Shared memory regions, which is how userspace window buffers reach the compositor.
User address space is reclaimed: find_free_address is a first fit over the VMA tree,
so an mmap/munmap cycle returns the same address rather than walking forward forever.
Scheduling
Section titled “Scheduling”Per-CPU run queues with work stealing, preemptive and timer-driven. Threads are either kernel threads, spawned by name at boot, or user threads belonging to a process.
ps shows both, with the CPU each one last ran on and the milliseconds it has
accumulated:

Two rules shape most of the kernel’s locking:
- Nothing parks with preemption suppressed or interrupts disabled.
thread_park,thread_sleepandthread_yielddebug-assert on it. Dropimpls reachable from a dying thread never block. No disk I/O, no blocking mutex, no waiting. Work that must block is posted to a kernel thread instead; inode eviction is the canonical example.
Both are enforced in debug builds, and both exist because violating them produces hangs that are extremely hard to attribute after the fact. Lock order covers the third rule.
Syscalls
Section titled “Syscalls”Entry is through SYSCALL/SYSRET. There are 102 syscalls, grouped by area: filesystem,
I/O, memory, networking, shared memory, synchronisation, process control and windowing.
The syscall reference lists every one with its arguments, its return value
and the errors it can raise.
Introspection
Section titled “Introspection”Rather than printf debugging, the kernel exposes counters through procfs:
| Path | What it shows |
|---|---|
/proc/meminfo |
frames total, free and used; page size |
/proc/processes |
every thread with its state, CPU and accumulated time |
/proc/block_cache |
block page cache occupancy and hit rates |
/proc/ahci_stats |
NCQ submissions, completions, and stalls |
/proc/inflight_stats |
outstanding block I/O |
/proc/evict_stats |
inode evictions, including ones dropped under pressure |
/proc/lock_order_stats |
rank violations observed by the tracker |
/proc/kernel |
the kernel log ring, which is what dmesg reads |
/proc/cmdline |
the Limine command line |