You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
riscv-pke/kernel/machine/minit.c

133 lines
4.8 KiB

/*
* Machine-mode C startup codes
*/
#include "util/types.h"
#include "kernel/riscv.h"
#include "kernel/config.h"
#include "spike_interface/spike_utils.h"
//
// global variables are placed in the .data section.
// stack0 is the privilege mode stack(s) of the proxy kernel on CPU(s)
// allocates 4KB stack space for each processor (hart)
//
// NCPU is defined to be 1 in kernel/config.h, as we consider only one HART in basic
// labs.
//
__attribute__((aligned(16))) char stack0[4096 * NCPU];
// sstart() is the supervisor state entry point defined in kernel/kernel.c
extern void s_start();
// M-mode trap entry point, added @lab1_2
extern void mtrapvec();
// htif is defined in spike_interface/spike_htif.c, marks the availability of HTIF
extern uint64 htif;
// g_mem_size is defined in spike_interface/spike_memory.c, size of the emulated memory
extern uint64 g_mem_size;
// struct riscv_regs is define in kernel/riscv.h, and g_itrframe is used to save
// registers when interrupt hapens in M mode. added @lab1_2
riscv_regs g_itrframe;
//
// get the information of HTIF (calling interface) and the emulated memory by
// parsing the Device Tree Blog (DTB, actually DTS) stored in memory.
//
// the role of DTB is similar to that of Device Address Resolution Table (DART)
// in Intel series CPUs. it records the details of devices and memory of the
// platform simulated using Spike.
//
void init_dtb(uint64 dtb) {
// defined in spike_interface/spike_htif.c, enabling Host-Target InterFace (HTIF)
query_htif(dtb);
if (htif) sprint("HTIF is available!\r\n");
// defined in spike_interface/spike_memory.c, obtain information about emulated memory
query_mem(dtb);
sprint("(Emulated) memory size: %ld MB\n", g_mem_size >> 20);
}
//
// delegate (almost all) interrupts and most exceptions to S-mode.
// after delegation, syscalls will handled by the PKE OS kernel running in S-mode.
//
static void delegate_traps() {
// supports_extension macro is defined in kernel/riscv.h
if (!supports_extension('S')) {
// confirm that our processor supports supervisor mode. abort if it does not.
sprint("S mode is not supported.\n");
return;
}
// macros used in following two statements are defined in kernel/riscv.h
uintptr_t interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP;
uintptr_t exceptions = (1U << CAUSE_MISALIGNED_FETCH) | (1U << CAUSE_FETCH_PAGE_FAULT) |
(1U << CAUSE_BREAKPOINT) | (1U << CAUSE_LOAD_PAGE_FAULT) |
(1U << CAUSE_STORE_PAGE_FAULT) | (1U << CAUSE_USER_ECALL);
// writes 64-bit values (interrupts and exceptions) to 'mideleg' and 'medeleg' (two
// priviledged registers of RV64G machine) respectively.
//
// write_csr and read_csr are macros defined in kernel/riscv.h
write_csr(mideleg, interrupts);
write_csr(medeleg, exceptions);
assert(read_csr(mideleg) == interrupts);
assert(read_csr(medeleg) == exceptions);
}
//
// enabling timer interrupt (irq) in Machine mode. added @lab1_3
//
void timerinit(uintptr_t hartid) {
// fire timer irq after TIMER_INTERVAL from now.
*(uint64*)CLINT_MTIMECMP(hartid) = *(uint64*)CLINT_MTIME + TIMER_INTERVAL;
// enable machine-mode timer irq in MIE (Machine Interrupt Enable) csr.
write_csr(mie, read_csr(mie) | MIE_MTIE);
}
//
// m_start: machine mode C entry point.
//
void m_start(uintptr_t hartid, uintptr_t dtb) {
// init the spike file interface (stdin,stdout,stderr)
// functions with "spike_" prefix are all defined in codes under spike_interface/,
// sprint is also defined in spike_interface/spike_utils.c
spike_file_init();
sprint("In m_start, hartid:%d\n", hartid);
// init HTIF (Host-Target InterFace) and memory by using the Device Table Blob (DTB)
// init_dtb() is defined above.
init_dtb(dtb);
// save the address of trap frame for interrupt in M mode to "mscratch". added @lab1_2
write_csr(mscratch, &g_itrframe);
// set previous privilege mode to S (Supervisor), and will enter S mode after 'mret'
// write_csr is a macro defined in kernel/riscv.h
write_csr(mstatus, ((read_csr(mstatus) & ~MSTATUS_MPP_MASK) | MSTATUS_MPP_S));
// set M Exception Program Counter to sstart, for mret (requires gcc -mcmodel=medany)
write_csr(mepc, (uint64)s_start);
// setup trap handling vector for machine mode. added @lab1_2
write_csr(mtvec, (uint64)mtrapvec);
// enable machine-mode interrupts. added @lab1_3
write_csr(mstatus, read_csr(mstatus) | MSTATUS_MIE);
// delegate all interrupts and exceptions to supervisor mode.
// delegate_traps() is defined above.
delegate_traps();
// also enables interrupt handling in supervisor mode. added @lab1_3
write_csr(sie, read_csr(sie) | SIE_SEIE | SIE_STIE | SIE_SSIE);
// init timing. added @lab1_3
timerinit(hartid);
// switch to supervisor mode (S mode) and jump to s_start(), i.e., set pc to mepc
asm volatile("mret");
}