Appendix D · An xv6 File Map¶
An appendix in this book is a reference, not a chapter: no argument, no narrative, and everything
in it either cites a primary source or comes from a stamped result under bench/results/.
This one is walked from the submodule at its pinned commit rather than written, so every line
count here is one that wc -l will agree with on the tree you have checked out — and a file renamed
upstream fails CI rather than quietly making this page wrong.
How much kernel there is¶
| The kernel, counted | Value |
|---|---|
Files in kernel/ | 44 |
| Lines in all of them | 6603 |
| Files a chapter reads | 27 |
| Lines in those | 5137 |
| Files nothing in this book opens | 17 |
Conditions: target xv6 · the xv6 submodule’s source, read rather than built · xv6-riscv @ 9e3161a · none · none · 2026-09-17 · Source: bench/results/filemap-xv6.json, code hash 72ccf96c95f8b570.
That first figure is the reason this book uses xv6 at all. A production kernel is far too large for anybody to read through; this one is small enough that the files Part IV opens are most of it, as the last two rows say, and the rest is not hidden from you — it is just not what any chapter needed.
Which chapter reads which file¶
| File | Lines | Read by | For |
|---|---|---|---|
kernel/entry.S | 21 | ch16 | the first instructions the kernel runs, before there is a stack |
kernel/start.c | 66 | ch16 | the machine-mode setup that hands over to supervisor mode |
kernel/syscall.c | 151 | ch16 | the dispatch table, and how arguments cross the boundary |
kernel/syscall.h | 23 | ch16 | the call numbers |
kernel/sysproc.c | 112 | ch16 | the process calls, including the one the traps chapter’s workload uses |
kernel/trampoline.S | 153 | ch16 | uservec and userret — the register moves the traps chapter counts |
kernel/trap.c | 220 | ch16 | where a trap is decided, and where a page fault would be handled |
kernel/memlayout.h | 63 | ch17 | what is mapped where, and why the trampoline is at the top |
kernel/riscv.h | 417 | ch17 | the Sv39 field definitions, as macros over a 64-bit word |
kernel/vm.c | 491 | ch17 | the page-table walk, mapping, and the kernel’s own address space |
kernel/exec.c | 176 | ch18 | what a fresh address space is built out of |
kernel/kalloc.c | 82 | ch18 | the physical page allocator a fault ends up calling |
kernel/console.c | 203 | ch19 | a device driver small enough to read in full |
kernel/kernelvec.S | 64 | ch19 | the trap path taken when the kernel itself is interrupted |
kernel/plic.c | 47 | ch19 | which device is allowed to interrupt which hart |
kernel/uart.c | 155 | ch19 | the registers underneath it |
kernel/sleeplock.c | 55 | ch20 | the other kind, and when each is correct |
kernel/spinlock.c | 116 | ch20 | the lock, and the memory barriers around it |
kernel/spinlock.h | 8 | ch20 | what a lock is made of |
kernel/proc.c | 701 | ch21 | the scheduler, and both halves of a context switch |
kernel/proc.h | 104 | ch21 | the context the scheduling chapter counts the registers of |
kernel/swtch.S | 42 | ch21 | the switch itself — fourteen registers and nothing else |
kernel/bio.c | 153 | ch22 | the buffer cache, and why a read can cost nothing |
kernel/file.c | 179 | ch22 | what a file descriptor actually is |
kernel/fs.c | 741 | ch22 | inodes, blocks, and the path from a name to a byte |
kernel/log.c | 261 | ch22 | the write-ahead log the file-system chapter counts the amplification of |
kernel/virtio_disk.c | 333 | ch22 | the only device in the system that makes you wait |
Conditions: target xv6 · the xv6 submodule’s source, read rather than built · xv6-riscv @ 9e3161a · none · none · 2026-09-17 · Source: bench/results/filemap-xv6.json, code hash 72ccf96c95f8b570.
Keep this open from ch16 onwards. The rows are grouped by chapter because that is how you
will arrive here: a chapter is discussing something, and the question is which of the files in
kernel/ to open beside it.
What is not in the table¶
Everything else in kernel/ — headers describing on-disk and in-memory structures, the string and
printing routines, the linker script, the parts of the build no chapter discusses. They are not
listed individually because a list of them is a directory listing, which you already have.
Two absences are deliberate rather than incidental.
main.c is not mapped to a chapter. It is worth reading early and it belongs to no chapter in
particular: it is the order in which everything else is initialised, which is a useful thing to
have seen once and a poor thing to study in isolation.
Nothing in user/ is mapped either. The book’s own programs live in xv6/apps/, and the
kernel’s user programs are read in passing rather than studied — with one exception:
ch16 explains why the shell is the worst possible thing to measure.
What this cannot tell you¶
Where a symbol is. This maps files, not functions. grep -rn over kernel/ answers that
question faster than any table could, and stays right when upstream moves something.
What the file does. The “For” column says what a chapter goes there for, which is narrower
on purpose. fs.c does a great deal that ch22 never mentions.
Anything about a different xv6. The commit is pinned and recorded in the conditions line under each table. MIT’s xv6 changes; a map of one version describing another is exactly the failure this page is generated to avoid.