xv6, line by line
kernel/start.c

kernel/start.c

C · 66 lines · annotated 100% · kernel · upstream

About this file

The first C code xv6 runs. Every hart arrives here from kernel/entry.S with its own stack, still in machine mode, the most powerful privilege mode.

The xv6 kernel is designed to run in supervisor mode, one level down. Machine mode holds a few powers supervisor mode lacks, so start uses them once, to set up everything the supervisor-mode kernel will need, and then leaves machine mode for good:

  1. arrange for mret to “return” into main in supervisor mode;
  2. hand all traps to supervisor mode (trap delegation);
  3. allow supervisor mode to access all of physical memory (PMP);
  4. enable two hardware features: automatic page-table A/D bits and the supervisor timer;
  5. remember the hart’s ID in tp, since supervisor mode cannot read it;
  6. execute mret.

Every one of these steps writes a CSR, each through a one-line wrapper from kernel/riscv.h such as w_mstatus.

Read before: kernel/entry.S. Read next: kernel/main.c.

1#include "types.h"
2#include "param.h"
4#include "riscv.h"
5#include "defs.h"
7void main();
8void timerinit();
10// entry.S needs one stack per CPU.
11__attribute__((aligned(16))) char stack0[4096 * NCPU];
13// entry.S jumps here in machine mode on stack0.
14void
17 // set M Previous Privilege mode to Supervisor, for mret.
18 unsigned long x = r_mstatus();
23 // set M Exception Program Counter to main, for mret.
24 // requires gcc -mcmodel=medany
27 // disable paging for now.
30 // delegate all interrupts and exceptions to supervisor mode.
31 w_medeleg(0xffff);
32 w_mideleg(0xffff);
35 // configure Physical Memory Protection to give supervisor mode
36 // access to all of physical memory.
37 w_pmpaddr0(0x3fffffffffffffull);
40 // enable hardware updates of page table A and D bits
43 // ask for clock interrupts.
46 // keep each CPU's hartid in its tp register, for cpuid().
47 int id = r_mhartid();
50 // switch to supervisor mode and jump to main().
51 asm volatile("mret");
54// ask each hart to generate timer interrupts.
55void
58 // enable the sstc extension (i.e. stimecmp).
61 // allow supervisor to use stimecmp and time.
64 // ask for the very first timer interrupt.
65 w_stimecmp(r_time() + 1000000);