Compare commits

..

2 Commits

Author SHA1 Message Date
Zhiyuan Shao 6df8c85479 init commit of lab1_3 2021-08-18 10:38:56 +08:00
Zhiyuan Shao 8c64512cab init commit of lab1_2 2021-08-18 10:36:55 +08:00
9 changed files with 182 additions and 19 deletions

View File

@ -69,8 +69,9 @@ USER_CPPS := user/*.c
USER_CPPS := $(wildcard $(USER_CPPS))
USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS)))
USER_TARGET := $(OBJ_DIR)/app_helloworld
USER_TARGET := $(OBJ_DIR)/app_long_loop
#------------------------targets------------------------
$(OBJ_DIR):
@-mkdir -p $(OBJ_DIR)

View File

@ -4,6 +4,9 @@
// we use only one HART (cpu) in fundamental experiments
#define NCPU 1
//interval of timer interrupt
#define TIMER_INTERVAL 1000000
#define DRAM_BASE 0x80000000
/* we use fixed physical (also logical) addresses for the stacks and trap frames as in

View File

@ -16,11 +16,15 @@ __attribute__((aligned(16))) char stack0[4096 * NCPU];
// sstart is the supervisor state entry point
extern void s_start(); // defined in kernel/kernel.c
// M-mode trap entry point
extern void mtrapvec();
// htif is defined in kernel/machine/spike_htif.c, marks the availability of HTIF
extern uint64 htif;
// g_mem_size is defined in kernel/machine/spike_memory.c, size of the emulated memory
extern uint64 g_mem_size;
// g_itrframe is used for saving registers when interrupt hapens in M mode
struct riscv_regs g_itrframe;
//
// get the information of HTIF (calling interface) and the emulated memory by
@ -62,6 +66,17 @@ static void delegate_traps() {
assert(read_csr(medeleg) == exceptions);
}
//
// enabling timer interrupt (irq) in Machine mode
//
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.
//
@ -73,14 +88,26 @@ void m_start(uintptr_t hartid, uintptr_t dtb) {
// init HTIF (Host-Target InterFace) and memory by using the Device Table Blob (DTB)
init_dtb(dtb);
// save the address of frame for interrupt in M mode to csr "mscratch".
write_csr(mscratch, &g_itrframe);
// set previous privilege mode to S (Supervisor), and will enter S mode after 'mret'
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
write_csr(mtvec, (uint64)mtrapvec);
// enable machine-mode interrupts.
write_csr(mstatus, read_csr(mstatus) | MSTATUS_MIE);
// delegate all interrupts and exceptions to supervisor mode.
delegate_traps();
write_csr(sie, read_csr(sie) | SIE_SEIE | SIE_STIE | SIE_SSIE);
timerinit(hartid);
// switch to supervisor mode and jump to s_start(), i.e., set pc to mepc
asm volatile("mret");

63
kernel/machine/mtrap.c Normal file
View File

@ -0,0 +1,63 @@
#include "kernel/riscv.h"
#include "kernel/process.h"
#include "spike_interface/spike_utils.h"
static void handle_instruction_access_fault() { panic("Instruction access fault!"); }
static void handle_load_access_fault() { panic("Load access fault!"); }
static void handle_store_access_fault() { panic("Store/AMO access fault!"); }
static void handle_illegal_instruction() { panic("Illegal instruction!"); }
static void handle_misaligned_load() { panic("Misaligned Load!"); }
static void handle_misaligned_store() { panic("Misaligned AMO!"); }
static void handle_timer() {
int cpuid = 0;
// setup the timer fired at next time (TIMER_INTERVAL from now)
*(uint64*)CLINT_MTIMECMP(cpuid) = *(uint64*)CLINT_MTIMECMP(cpuid) + TIMER_INTERVAL;
// setup a soft interrupt in sip (S-mode Interrupt Pending) to be handled in S-mode
write_csr(sip, SIP_SSIP);
}
//
// handle_mtrap calls cooresponding functions to handle an exception of a given type.
//
void handle_mtrap() {
uint64 mcause = read_csr(mcause);
switch (mcause) {
case CAUSE_MTIMER:
handle_timer();
break;
case CAUSE_FETCH_ACCESS:
handle_instruction_access_fault();
break;
case CAUSE_LOAD_ACCESS:
handle_load_access_fault();
case CAUSE_STORE_ACCESS:
handle_store_access_fault();
break;
case CAUSE_ILLEGAL_INSTRUCTION:
// TODO (lab1_2): call handle_illegal_instruction to implement illegal instruction
// interception, and finish lab1_2.
panic( "call handle_illegal_instruction to accomplish illegal instruction interception for lab1_2.\n" );
break;
case CAUSE_MISALIGNED_LOAD:
handle_misaligned_load();
break;
case CAUSE_MISALIGNED_STORE:
handle_misaligned_store();
break;
default:
sprint("machine trap(): unexpected mscause %p\n", mcause);
sprint(" mepc=%p mtval=%p\n", read_csr(mepc), read_csr(mtval));
panic( "unexpected exception happened in M-mode.\n" );
break;
}
}

View File

@ -0,0 +1,38 @@
#include "util/load_store.S"
#
# M-mode trap entry point
#
.globl mtrapvec
.align 4
mtrapvec:
# swap a0 and mscratch
# so that a0 points to interrupt frame
csrrw a0, mscratch, a0
# save the registers in interrupt frame
addi t6, a0, 0
store_all_registers
# save the user a0 in itrframe->a0
csrr t0, mscratch
sd t0, 72(a0)
# use stack0 for sp
la sp, stack0
li a3, 4096
csrr a4, mhartid
addi a4, a4, 1
mul a3, a3, a4
add sp, sp, a3
// save the address of interrupt frame in the csr "mscratch"
csrw mscratch, a0
call handle_mtrap
// restore all registers
csrr t6, mscratch
restore_all_registers
mret

View File

@ -52,6 +52,18 @@
#define CAUSE_LOAD_PAGE_FAULT 0xd // Load page fault
#define CAUSE_STORE_PAGE_FAULT 0xf // Store/AMO page fault
// irqs (interrupts)
#define CAUSE_MTIMER 0x8000000000000007
#define CAUSE_MTIMER_S_TRAP 0x8000000000000001
//Supervisor interrupt-pending register
#define SIP_SSIP (1L << 1)
// core local interruptor (CLINT), which contains the timer.
#define CLINT 0x2000000L
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8 * (hartid))
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
// fields of sstatus, the Supervisor mode Status register
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable

View File

@ -26,6 +26,18 @@ static void handle_syscall(trapframe *tf) {
}
//
// global variable that store the recorded "ticks"
static uint64 g_ticks = 0;
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.
@ -40,8 +52,12 @@ void smode_trap_handler(void) {
current->trapframe->epc = read_csr(sepc);
// if the cause of trap is syscall from user application
if (read_csr(scause) == CAUSE_USER_ECALL) {
uint64 cause = read_csr(scause);
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));

View File

@ -1,17 +0,0 @@
/*
* Below is the given application for lab1_1.
*
* You can build this app (as well as our PKE OS kernel) by command:
* $ make
*
* Or run this app (with the support from PKE OS kernel) by command:
* $ make run
*/
#include "user_lib.h"
int main(void) {
printu("Hello world!\n");
exit(0);
}

20
user/app_long_loop.c Normal file
View File

@ -0,0 +1,20 @@
/*
* Below is the given application for lab1_3.
* This app performs a long loop, during which, timers are
* generated and pop messages to our screen.
*/
#include "user_lib.h"
#include "util/types.h"
int main(void) {
printu("Hello world!\n");
int i;
for (i = 0; i < 100000000; ++i) {
if (i % 5000000 == 0) printu("wait %d\n", i);
}
exit(0);
return 0;
}