xv6, line by line
tour 2
Tours2 Power-on to main, on every hart at once

Tour 2 · Boot and build · about 28 minutes · 17 steps

Power-on to main, on every hart at once

QEMU has built a machine with three CPUs (harts), copied kernel/kernel into RAM at 0x80000000, and released all three harts at the same instant. None of them knows it is not alone. They run the same instructions, from the same memory, at the same time, and yet each must end up with its own stack, its own settings and its own identity.

This tour follows all three harts together, from the first instruction of QEMU’s boot ROM at 0x1000, through _entry in kernel/entry.S, through the machine-mode setup in start, to the mret that drops each of them into supervisor mode in main.

The surprise of this tour is what is missing: there is not a single lock on this path, even though three CPUs run it simultaneously. Watch why. Almost everything here is done to a hart’s own registers, and the only shared memory that anyone writes is split so that no two harts ever write the same byte.

Best after: 1. From make qemu to a disk image and a kernel

Who is running where

The machine has three harts, and at the start they are in exactly the same state:

Hart What it is doing
0 Just reset: machine mode, pc = 0x1000, interrupts off, paging off
1 The same
2 The same

Memory already holds the kernel (0x80000000–0x80007860), and the .bss above it (up to 0x80020bb0) is zero. Memory and the devices are the only things they share.

Three harts are running. This tour follows one path through the code, but the machine has three CPUs executing at the same time. Watch the locks held display at the top of each step, and read the Meanwhile, on other harts boxes: they show what the other CPUs could be doing at that very moment.
The route
  1. 1Three harts, one memory, pc = 0x1000 kernel/memlayout.h
  2. 2The boot ROM jumps to the kernel kernel/kernel.ld
  3. 3Every hart starts from the same stack address kernel/entry.S
  4. 4Each hart computes its own offset kernel/entry.S
  5. 5add sp: three harts, three stacks kernel/entry.S
  6. 6One array, three slices, no lock kernel/start.c
  7. 7call start kernel/entry.S
  8. 8Arrange to leave machine mode kernel/start.c
  9. 9A CSR access is one instruction kernel/riscv.h
  10. 10Aim mret at main, and keep paging off kernel/start.c
  11. 11Send every trap to supervisor mode kernel/start.c
  12. 12Let supervisor mode reach all of memory kernel/start.c
  13. 13Each hart sets its own alarm clock kernel/start.c
  14. 14Remember who you are kernel/start.c
  15. 15mret, and every hart is in supervisor mode kernel/start.c
  16. 16Three harts arrive in main kernel/main.c
  17. 17What was shared, what was private kernel/main.c

Keys: ← → step · Home start