1 #include "types.h"
2 #include "param.h"
3 #include "memlayout.h"
4 #include "riscv.h"
5 #include "defs.h"
6
7 void main();
8 void timerinit();
9
10 // entry.S needs one stack per CPU.
11 __attribute__((aligned(16))) char stack0[4096 * NCPU];
12
13 // entry.S jumps here in machine mode on stack0.
14 void
15 start()
16 {
17 // set M Previous Privilege mode to Supervisor, for mret.
18 unsigned long x = r_mstatus();
19 x &= ~MSTATUS_MPP_MASK;
20 x |= MSTATUS_MPP_S;
21 w_mstatus(x);
22
23 // set M Exception Program Counter to main, for mret.
24 // requires gcc -mcmodel=medany
25 w_mepc((uint64)main);
26
27 // disable paging for now.
28 w_satp(0);
29
30 // delegate all interrupts and exceptions to supervisor mode.
31 w_medeleg(0xffff);
32 w_mideleg(0xffff);
33 w_sie(r_sie() | SIE_SEIE | SIE_STIE);
34
35 // configure Physical Memory Protection to give supervisor mode
36 // access to all of physical memory.
37 w_pmpaddr0(0x3fffffffffffffull);
38 w_pmpcfg0(0xf);
39
40 // enable hardware updates of page table A and D bits
41 w_menvcfg(r_menvcfg() | MENVCFG_ADUE);
42
43 // ask for clock interrupts.
44 timerinit();
45
46 // keep each CPU's hartid in its tp register, for cpuid().
47 int id = r_mhartid();
48 w_tp(id);
49
50 // switch to supervisor mode and jump to main().
51 asm volatile("mret");
52 }
53
54 // ask each hart to generate timer interrupts.
55 void
56 timerinit()
57 {
58 // enable the sstc extension (i.e. stimecmp).
59 w_menvcfg(r_menvcfg() | MENVCFG_STCE);
60
61 // allow supervisor to use stimecmp and time.
62 w_mcounteren(r_mcounteren() | 2);
63
64 // ask for the very first timer interrupt.
65 w_stimecmp(r_time() + 1000000);
66 }