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 // ask for clock interrupts.
41 timerinit();
42
43 // keep each CPU's hartid in its tp register, for cpuid().
44 int id = r_mhartid();
45 w_tp(id);
46
47 // switch to supervisor mode and jump to main().
48 asm volatile("mret");
49 }
50
51 // ask each hart to generate timer interrupts.
52 void
53 timerinit()
54 {
55 // enable supervisor-mode timer interrupts.
56 w_mie(r_mie() | MIE_STIE);
57
58 // enable the sstc extension (i.e. stimecmp).
59 w_menvcfg(r_menvcfg() | (1L << 63));
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 }