Compare commits
2 Commits
lab1_1_sys
...
lab1_3_irq
Author | SHA1 | Date |
---|---|---|
Zhiyuan Shao | 6df8c85479 | |
Zhiyuan Shao | 8c64512cab |
3
Makefile
3
Makefile
|
@ -69,8 +69,9 @@ USER_CPPS := user/*.c
|
||||||
USER_CPPS := $(wildcard $(USER_CPPS))
|
USER_CPPS := $(wildcard $(USER_CPPS))
|
||||||
USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(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------------------------
|
#------------------------targets------------------------
|
||||||
$(OBJ_DIR):
|
$(OBJ_DIR):
|
||||||
@-mkdir -p $(OBJ_DIR)
|
@-mkdir -p $(OBJ_DIR)
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
// we use only one HART (cpu) in fundamental experiments
|
// we use only one HART (cpu) in fundamental experiments
|
||||||
#define NCPU 1
|
#define NCPU 1
|
||||||
|
|
||||||
|
//interval of timer interrupt
|
||||||
|
#define TIMER_INTERVAL 1000000
|
||||||
|
|
||||||
#define DRAM_BASE 0x80000000
|
#define DRAM_BASE 0x80000000
|
||||||
|
|
||||||
/* we use fixed physical (also logical) addresses for the stacks and trap frames as in
|
/* we use fixed physical (also logical) addresses for the stacks and trap frames as in
|
||||||
|
|
|
@ -16,11 +16,15 @@ __attribute__((aligned(16))) char stack0[4096 * NCPU];
|
||||||
|
|
||||||
// sstart is the supervisor state entry point
|
// sstart is the supervisor state entry point
|
||||||
extern void s_start(); // defined in kernel/kernel.c
|
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
|
// htif is defined in kernel/machine/spike_htif.c, marks the availability of HTIF
|
||||||
extern uint64 htif;
|
extern uint64 htif;
|
||||||
// g_mem_size is defined in kernel/machine/spike_memory.c, size of the emulated memory
|
// g_mem_size is defined in kernel/machine/spike_memory.c, size of the emulated memory
|
||||||
extern uint64 g_mem_size;
|
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
|
// 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);
|
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.
|
// 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 HTIF (Host-Target InterFace) and memory by using the Device Table Blob (DTB)
|
||||||
init_dtb(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'
|
// 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));
|
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)
|
// set M Exception Program Counter to sstart, for mret (requires gcc -mcmodel=medany)
|
||||||
write_csr(mepc, (uint64)s_start);
|
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 all interrupts and exceptions to supervisor mode.
|
||||||
delegate_traps();
|
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
|
// switch to supervisor mode and jump to s_start(), i.e., set pc to mepc
|
||||||
asm volatile("mret");
|
asm volatile("mret");
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -52,6 +52,18 @@
|
||||||
#define CAUSE_LOAD_PAGE_FAULT 0xd // Load page fault
|
#define CAUSE_LOAD_PAGE_FAULT 0xd // Load page fault
|
||||||
#define CAUSE_STORE_PAGE_FAULT 0xf // Store/AMO 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
|
// fields of sstatus, the Supervisor mode Status register
|
||||||
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
|
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
|
||||||
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
|
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
|
||||||
|
|
|
@ -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
|
// kernel/smode_trap.S will pass control to smode_trap_handler, when a trap happens
|
||||||
// in S-mode.
|
// in S-mode.
|
||||||
|
@ -40,8 +52,12 @@ void smode_trap_handler(void) {
|
||||||
current->trapframe->epc = read_csr(sepc);
|
current->trapframe->epc = read_csr(sepc);
|
||||||
|
|
||||||
// if the cause of trap is syscall from user application
|
// 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);
|
handle_syscall(current->trapframe);
|
||||||
|
} else if (cause == CAUSE_MTIMER_S_TRAP) { //soft trap generated by timer interrupt in M mode
|
||||||
|
handle_mtimer_trap();
|
||||||
} else {
|
} else {
|
||||||
sprint("smode_trap_handler(): unexpected scause %p\n", read_csr(scause));
|
sprint("smode_trap_handler(): unexpected scause %p\n", read_csr(scause));
|
||||||
sprint(" sepc=%p stval=%p\n", read_csr(sepc), read_csr(stval));
|
sprint(" sepc=%p stval=%p\n", read_csr(sepc), read_csr(stval));
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue