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/strap.c

75 lines
2.5 KiB

/*
* Utility functions for trap handling in Supervisor mode.
*/
#include "riscv.h"
#include "process.h"
#include "strap.h"
#include "syscall.h"
#include "spike_interface/spike_utils.h"
//
// handling the syscalls. will call do_syscall() defined in kernel/syscall.c
//
static void handle_syscall(trapframe *tf) {
// tf->epc points to the address that our computer will jump to after the trap handling.
// for a syscall, we should return to the NEXT instruction after its handling.
// in RV64G, each instruction occupies exactly 32 bits (i.e., 4 Bytes)
tf->epc += 4;
// TODO (lab1_1): remove the panic call below, and call do_syscall (defined in
// kernel/syscall.c) to conduct real operations of the kernel side for a syscall.
// IMPORTANT: return value should be returned to user app, or else, you will encounter
// problems in later experiments!
panic( "call do_syscall to accomplish the syscall and lab1_1 here.\n" );
}
//
// global variable that store the recorded "ticks". added @lab1_3
static uint64 g_ticks = 0;
//
// added @lab1_3
//
void handle_mtimer_trap() {
sprint("Ticks %d\n", g_ticks);
// TODO (lab1_3): increase g_ticks to record this "tick", and then clear the "SIP"
// field in sip register.
// hint: use write_csr to disable the SIP_SSIP bit in sip.
panic( "lab1_3: increase g_ticks by one, and clear SIP field in sip register.\n" );
}
//
// kernel/smode_trap.S will pass control to smode_trap_handler, when a trap happens
// in S-mode.
//
void smode_trap_handler(void) {
// make sure we are in User mode before entering the trap handling.
// we will consider other previous case in lab1_3 (interrupt).
if ((read_csr(sstatus) & SSTATUS_SPP) != 0) panic("usertrap: not from user mode");
assert(current);
// save user process counter.
current->trapframe->epc = read_csr(sepc);
// if the cause of trap is syscall from user application.
// read_csr() and CAUSE_USER_ECALL are macros defined in kernel/riscv.h
uint64 cause = read_csr(scause);
// we need to handle the timer trap @lab1_3.
if (cause == CAUSE_USER_ECALL) {
handle_syscall(current->trapframe);
} else if (cause == CAUSE_MTIMER_S_TRAP) { //soft trap generated by timer interrupt in M mode
handle_mtimer_trap();
} else {
sprint("smode_trap_handler(): unexpected scause %p\n", read_csr(scause));
sprint(" sepc=%p stval=%p\n", read_csr(sepc), read_csr(stval));
panic( "unexpected exception happened.\n" );
}
// continue (come back to) the execution of current process.
switch_to(current);
}