Operating Systems
Virtual Memory Explorer
Walk an AArch64 page table, watch the TLB fill and trigger page faults.
Free 13-chapter course · C · Rust · AArch64 · QEMU
You are going to start with a powered-on AArch64 CPU and nothing else, and you are going to finish with a working kernel that boots into your own interactive shell. Everything is written in C and Rust and runs on QEMU, so there is no hardware to buy and nothing to pay for.
$ make run
qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic -kernel kernel.elf
PurgatoryOS v1.0 booted at EL1
MMU: on · GIC: on · timer: 100Hz · tasks: 2
purgatory> ls /
bin/ docs/ README
purgatory> uptime
up 42 ticks, 2 tasks running
purgatory> ▊ Most operating system tutorials, including the excellent OSDev wiki and Philipp Oppermann's Writing an OS in Rust, target x86. That choice comes with a price. Before you execute a single line of your own kernel, you have to fight through real mode, segmentation, the A20 gate, and a boot protocol that carries forty years of backwards compatibility on its shoulders. None of it teaches you anything about operating systems. It teaches you about the history of one processor family.
AArch64 removes almost all of that friction. The CPU starts in a well-defined exception level, memory-mapped I/O replaces port juggling, and the architecture's four privilege levels map cleanly onto the user and kernel boundary you actually came here to learn. You reach the interesting problems, like virtual memory, interrupts and scheduling, in hours rather than weeks.
It is also the pragmatic choice. ARM64 is the instruction set of every modern phone, every Apple Silicon Mac, and a rapidly growing share of cloud servers. The register conventions, page table formats and exception model you learn in this course are the ones running on the machine in your pocket right now.
From reset vector to an interactive shell on QEMU's virt machine.
Every chapter is a self-contained milestone that ends with a kernel you can actually boot. Each one also has a “What Broke (And Why)” section where I document the bugs I hit while writing the code, because a silent QEMU hang will teach you more about the hardware than a clean happy path ever will.
Stop treating the OS as a black box. Discover why building an AArch64 kernel from scratch on ARM is the ultimate systems programming challenge for 2026. From silicon to shell, we go all the way down.
Step-by-step guide to installing an AArch64 cross-compiler (GCC) and QEMU on macOS and Linux. Write a bare-metal linker script and Makefile to boot your first ARM64 program.
Learn how to write an ARM64 bootloader stub in assembly. We cover AArch64 exception levels (EL2 to EL1), zeroing BSS, stack setup, and jumping to a C kernel_main on bare metal.
Learn how to write a bare-metal C driver for the PL011 UART on AArch64. Master Memory-Mapped I/O (MMIO), the volatile keyword in C, and building a kprint function for QEMU virt without a standard library.
Master ELF sections (.text, .rodata, .data, .bss) and fix alignment bugs in your AArch64 linker script. Learn to verify memory maps using readelf for bare-metal ARM development.
Master the AArch64 MMU on bare metal ARM. A deep dive into page table structures, translation levels (L0-L3), and configuring SCTLR_EL1, TCR_EL1, and MAIR_EL1 for kernel memory protection.
Build an AArch64 exception vector table from scratch, set up the GICv2 Generic Interrupt Controller on QEMU, and write a working ARM Generic Timer interrupt handler. Your kernel finally responds to the hardware.
Write a bump allocator and then a free-list allocator from scratch in C for your AArch64 bare-metal kernel. Learn block headers, first-fit search, coalescing, alignment, and why Rust's no_std offers a safer alternative. Visualize every allocation interactively.
Build a round-robin task scheduler from scratch for your AArch64 bare-metal kernel. Implement the PCB, understand why only callee-saved registers need saving, write the context_switch assembly, and watch two tasks interleave on the UART, the moment your kernel becomes an actual operating system.
Drop your AArch64 tasks into EL0, trap into EL1 with the svc instruction, decode ESR_EL1 EC=0x15, dispatch through a syscall table, and return cleanly with eret. Four real syscalls (write, exit, getpid and yield) and the hardware-enforced privilege boundary that makes them possible.
Carve the C heap allocator out of PurgatoryOS and replace it with a no_std Rust implementation wired in via extern C FFI. Set up aarch64-unknown-none-softfloat, build-std core + alloc, the GlobalAlloc trait, a spin-locked free list, and a Makefile that links libpurgatory_rs.a into the existing kernel.elf, without rewriting a single line of C above the allocator.
Build an in-memory tree filesystem for PurgatoryOS in no_std Rust using Box<Node>, BTreeMap<String, NodeId>, and Vec<u8> on top of Post 11's allocator. Add three new syscalls (open, read, close), a per-task file descriptor table, and a working VFS layer that the shell in Post 13 can type against.
Give PurgatoryOS a prompt. Add uart_getc and a line-discipline buffer, parse commands on top of Post 12's ramdisk, dispatch built-ins (ls, cat, echo, cd, pwd, help, clear), and load /bin/hello as a flat binary at a fixed address. This is the payoff post, where readers finally type into their own kernel.
The series page, From Silicon to Shell: Building an OS for ARM and More , has the same chapters with a topic index.
You need to be comfortable reading and writing basic C, which means pointers, structs, and the compile and link cycle. Everything else, from exception levels to page tables, is built up from first principles as we go.
The tooling is a cross-compiler and QEMU on macOS or Linux. Chapter 2 walks through the full toolchain setup, and your first ARM binary boots about fifteen minutes in.
If you would rather start with how the hardware executes instructions in the first place, From Transistor to System is the companion series on computer architecture.
Want the background first? The Operating Systems learning path puts this project in order with the chapters and explorers that lead up to it.
The versions the series' code was last tested with.
Drive the hardest part of the project yourself before, or after, you implement it.
Operating Systems
Walk an AArch64 page table, watch the TLB fill and trigger page faults.
No. The entire course runs on QEMU's virt machine, which emulates a full AArch64 system in software. You write, build and boot your kernel on macOS or Linux with nothing more than a cross-compiler and QEMU, and everything you learn transfers directly to real ARM boards like the Raspberry Pi.
Expect roughly 25 to 40 hours across 13 chapters, from first boot to an interactive shell. Each chapter is a self-contained milestone with 15 to 40 minutes of reading, plus the time you spend implementing the code and, inevitably, debugging it.
Yes. This course builds the kernel core in C and then brings in Rust through a no_std allocator wired in over the C FFI, which shows how the two languages can coexist in a single kernel image. A kernel written entirely in Rust is possible too, but the mixed approach mirrors how real systems adopt Rust in practice: one subsystem at a time.
You should be comfortable reading and writing basic C, meaning pointers, structs and functions. No assembly, ARM or operating systems background is required, because exception levels, MMU configuration and context switching are all taught from first principles.
AArch64 has a much cleaner architecture, without the decades of legacy boot machinery that x86 drags along, so your time goes into real operating system concepts instead of historical workarounds. It is also the instruction set in every modern phone, every Apple Silicon Mac and a growing share of servers.
Yes, although not because you will ship a commercial kernel. The value is that every abstraction you rely on daily, from processes and virtual memory to system calls and drivers, becomes concrete once you have built it yourself. It is some of the highest-leverage systems knowledge a software engineer can pick up.
Written by the engineers behind BIOS Confessions. 13 of 13 chapters are published, and all of them are free.
Begin with Chapter 1