Tracing a Page Fault End-to-End
Follow a #PF exception from the CPU trap gate through do_page_fault(), VMA lookup, handle_mm_fault(), and finally the page table update — with annotated source at every step.
Annotated, step-by-step walkthroughs of the Linux kernel's most important subsystems. Follow the code from user-space all the way down.
Each tutorial opens with a subsystem overview and the kernel version it targets. You'll know exactly which source files to follow.
Inline code blocks show the exact kernel source with line-level annotations explaining what each piece does and why.
Interactive SVG diagrams visualise data structures and control flow at each stage — hover nodes for details.
Short knowledge checks at the end of each section confirm you've internalised the key concepts before moving on.
Follow a #PF exception from the CPU trap gate through do_page_fault(), VMA lookup, handle_mm_fault(), and finally the page table update — with annotated source at every step.
Understand how the Completely Fair Scheduler maintains its red-black tree runqueue, calculates vruntime, and picks the next task — from enqueue_task_fair() to __schedule().
Trace a syscall from the SYSCALL instruction in user-space through entry_SYSCALL_64, the syscall table dispatch, and back to user-space via SYSRET — including seccomp and audit hooks.
Walk through __alloc_pages(), zone watermark checks, the fast and slow allocation paths, and how the buddy system splits and coalesces page blocks.
Follow the open() syscall through the VFS layer: namei path resolution, dentry cache lookup, inode operations, and finally the file descriptor installation.
Learn to instrument any kernel function at runtime using kprobes and kretprobes — write a minimal kernel module, attach a probe, and read trace output via debugfs.
// page fault handler · annotated source
1/* Step 1: CPU delivers #PF, hardware pushes error_code */2DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)3{4 unsigned long address = read_cr2(); /* faulting VA */← CR2 holds the faulting virtual address5 struct pt_regs *regs = current_pt_regs();67/* Step 2: Dispatch to the arch-independent handler */8 handle_page_fault(regs, error_code, address);← arch/x86/mm/fault.c9}1011/* Step 3: VMA lookup — is this address mapped? */12struct vm_area_struct *vma = find_vma(mm, address);← O(log n) maple tree lookup13if (!vma || vma->vm_start > address)14 goto bad_area; /* → SIGSEGV */1516/* Step 4: Delegate to generic fault handler */17fault = handle_mm_fault(vma, address, flags, regs);← mm/memory.c — COW, swap-in, zero-fill