root/kernel/start.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. start
  2. timerinit

   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 // a scratch area per CPU for machine-mode timer interrupts.
  14 uint64 timer_scratch[NCPU][5];
  15 
  16 // assembly code in kernelvec.S for machine-mode timer interrupt.
  17 extern void timervec();
  18 
  19 // entry.S jumps here in machine mode on stack0.
  20 void
  21 start()
  22 {
  23   // set M Previous Privilege mode to Supervisor, for mret.
  24   unsigned long x = r_mstatus();
  25   x &= ~MSTATUS_MPP_MASK;
  26   x |= MSTATUS_MPP_S;
  27   w_mstatus(x);
  28 
  29   // set M Exception Program Counter to main, for mret.
  30   // requires gcc -mcmodel=medany
  31   w_mepc((uint64)main);
  32 
  33   // disable paging for now.
  34   w_satp(0);
  35 
  36   // delegate all interrupts and exceptions to supervisor mode.
  37   w_medeleg(0xffff);
  38   w_mideleg(0xffff);
  39   w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE);
  40 
  41   // configure Physical Memory Protection to give supervisor mode
  42   // access to all of physical memory.
  43   w_pmpaddr0(0x3fffffffffffffull);
  44   w_pmpcfg0(0xf);
  45 
  46   // ask for clock interrupts.
  47   timerinit();
  48 
  49   // keep each CPU's hartid in its tp register, for cpuid().
  50   int id = r_mhartid();
  51   w_tp(id);
  52 
  53   // switch to supervisor mode and jump to main().
  54   asm volatile("mret");
  55 }
  56 
  57 // arrange to receive timer interrupts.
  58 // they will arrive in machine mode at
  59 // at timervec in kernelvec.S,
  60 // which turns them into software interrupts for
  61 // devintr() in trap.c.
  62 void
  63 timerinit()
  64 {
  65   // each CPU has a separate source of timer interrupts.
  66   int id = r_mhartid();
  67 
  68   // ask the CLINT for a timer interrupt.
  69   int interval = 1000000; // cycles; about 1/10th second in qemu.
  70   *(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + interval;
  71 
  72   // prepare information in scratch[] for timervec.
  73   // scratch[0..2] : space for timervec to save registers.
  74   // scratch[3] : address of CLINT MTIMECMP register.
  75   // scratch[4] : desired interval (in cycles) between timer interrupts.
  76   uint64 *scratch = &timer_scratch[id][0];
  77   scratch[3] = CLINT_MTIMECMP(id);
  78   scratch[4] = interval;
  79   w_mscratch((uint64)scratch);
  80 
  81   // set the machine-mode trap handler.
  82   w_mtvec((uint64)timervec);
  83 
  84   // enable machine-mode interrupts.
  85   w_mstatus(r_mstatus() | MSTATUS_MIE);
  86 
  87   // enable machine-mode timer interrupts.
  88   w_mie(r_mie() | MIE_MTIE);
  89 }

/* [<][>][^][v][top][bottom][index][help] */