Skip to content

start.c

#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"

void main();
void timerinit();

TIP

entry.S needs one stack per CPU.

__attribute__ ((aligned (16))) char stack0[4096 * NCPU];

TIP

entry.S jumps here in machine mode on stack0.

void
start()
{

TIP

set M Previous Privilege mode to Supervisor, for mret.

  unsigned long x = r_mstatus();
  x &= ~MSTATUS_MPP_MASK;
  x |= MSTATUS_MPP_S;
  w_mstatus(x);

TIP

set M Exception Program Counter to main, for mret. requires gcc -mcmodel=medany

  w_mepc((uint64)main);

TIP

disable paging for now.

  w_satp(0);

TIP

delegate all interrupts and exceptions to supervisor mode.

  w_medeleg(0xffff);
  w_mideleg(0xffff);
  w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE);

TIP

configure Physical Memory Protection to give supervisor mode access to all of physical memory.

  w_pmpaddr0(0x3fffffffffffffull);
  w_pmpcfg0(0xf);

TIP

ask for clock interrupts.

  timerinit();

TIP

keep each CPU's hartid in its tp register, for cpuid().

  int id = r_mhartid();
  w_tp(id);

TIP

switch to supervisor mode and jump to main().

  asm volatile("mret");
}

TIP

ask each hart to generate timer interrupts.

void
timerinit()
{

TIP

enable supervisor-mode timer interrupts.

  w_mie(r_mie() | MIE_STIE);
  

TIP

enable the sstc extension (i.e. stimecmp).

  w_menvcfg(r_menvcfg() | (1L << 63)); 
  

TIP

allow supervisor to use stimecmp and time.

  w_mcounteren(r_mcounteren() | 2);
  

TIP

ask for the very first timer interrupt.

  w_stimecmp(r_time() + 1000000);
}