Chapter 38 Key Takeaways: Capstone — A Minimal OS Kernel
-
MinOS is a real, bootable OS — not a simulation or toy. It runs on QEMU with real emulated hardware, handles real interrupts, manages real memory pages, and runs real processes. Every instruction is understood because you wrote it.
-
The boot sequence is a chain of handoffs: BIOS loads the MBR bootloader at
0x7C00in 16-bit real mode → bootloader enables A20, loads kernel from disk, sets up GDT, switches to protected mode, enables paging, jumps to long mode → kernel entry loads 64-bit GDT, sets up stack, zeros BSS, callskernel_main→ kernel_main initializes each component in dependency order. -
Initialization order matters: VGA before IDT (so you can print error messages); GDT before IDT (IDT entries reference the GDT selector); IDT before enabling interrupts (
sti); memory manager before any allocation; TSS before user-mode code. Getting the order wrong produces failures that are difficult to debug. -
The GDT in 64-bit mode is mostly ceremonial, but not entirely: in long mode, code and data segment base/limit are ignored. However, the DPL (privilege level), the L bit (64-bit mode flag), the P bit (present), and especially the TSS descriptor remain fully active.
-
The TSS is essential for privilege transitions: the TSS holds RSP0 — the kernel stack pointer to use when an interrupt or system call occurs in ring 3. Without a valid TSS, a hardware interrupt in user mode has nowhere to switch the stack and will triple-fault.
-
The IDT gate type determines interrupt behavior: interrupt gates (type
0x8E) clear the IF flag on entry (no nested interrupts unless you re-enable them). Trap gates do not. For most MinOS IRQ handlers, interrupt gates are correct. -
The PIT's base frequency is 1,193,182 Hz: to get 100Hz interrupts, load divisor
1193182 / 100 = 11932into the PIT channel 0. Use command byte0x36(channel 0, access lobyte/hibyte, mode 3 square wave). -
Preemptive scheduling happens through the timer interrupt: each timer tick,
scheduler_tick()decrements a counter. When it reaches zero,schedule()switches to the next READY process. The context switch is completed by the interrupt handler's register save/restore combined with changing which process's saved RSP is used oniretq. -
Context switch requires saving and restoring all general-purpose registers: RAX, RBX, RCX, RDX, RSI, RDI, RBP, R8-R15, plus the IRET frame (RIP, CS, RFLAGS, RSP, SS saved by hardware). The easiest implementation saves all this via the interrupt handler wrapper.
-
VGA text mode at
0xB8000is the most convenient debug output: it requires no hardware initialization beyond mapping the physical address. Each character is 2 bytes: ASCII + attribute. Writing to this region is immediate and visible. -
The QEMU
-s -Sflags attach a GDB server:-sopens GDB stub on port 1234;-Ssuspends until GDB connects. This makes the MinOS kernel debuggable with full GDB capabilities including breakpoints, single-stepping, and memory inspection. -
The physical memory bitmap allocator uses 1 bit per 4KB page: for 64MB of RAM, that is 64MB / 4KB / 8 = 2KB of bitmap. All pages within the kernel image (from address 0 to
KERNEL_END) must be marked "used" before the allocator is ready. -
ARM64 MinOS differs primarily in hardware-interface code: UEFI boot (instead of BIOS MBR), system registers (instead of I/O ports), GIC interrupt controller (instead of PIC), TTBR0/TTBR1 (instead of CR3), SVC/ERET (instead of SYSCALL/SYSRET). The C kernel logic — scheduler, allocator, shell — ports unchanged.
-
The three capstone tracks scale in complexity: Track A (bootloader + VGA + shell, ~1200 lines) proves you understand the boot process and basic I/O. Track B (+ scheduler, ~1700 lines) proves you understand interrupts and concurrency. Track C (+ virtual memory + system calls + filesystem, ~2700 lines) proves you understand the full OS primitive set.
-
Completing MinOS is proof by construction: you cannot boot a kernel that contains misconceptions about the hardware. If the GDT is wrong, the mode switch faults. If the IDT is wrong, exceptions triple-fault. If the stack is wrong, every call fails. MinOS boots because every component is correct — and you wrote every component.