diff --git a/Makefile b/Makefile index 3c40d53..5ed973d 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,8 @@ USER_CPPS := $(wildcard $(USER_CPPS)) USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS))) -USER_TARGET := $(OBJ_DIR)/app_illegal_instruction + +USER_TARGET := $(OBJ_DIR)/app_long_loop #------------------------targets------------------------ $(OBJ_DIR): @-mkdir -p $(OBJ_DIR) diff --git a/kernel/config.h b/kernel/config.h index 95a8668..156ef62 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -4,6 +4,9 @@ // we use only one HART (cpu) in fundamental experiments #define NCPU 1 +//interval of timer interrupt. added @lab1_3 +#define TIMER_INTERVAL 1000000 + #define DRAM_BASE 0x80000000 /* we use fixed physical (also logical) addresses for the stacks and trap frames as in diff --git a/kernel/machine/minit.c b/kernel/machine/minit.c index 82ec357..b258f71 100644 --- a/kernel/machine/minit.c +++ b/kernel/machine/minit.c @@ -76,6 +76,17 @@ static void delegate_traps() { 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. // @@ -103,10 +114,19 @@ void m_start(uintptr_t hartid, uintptr_t dtb) { // 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"); } diff --git a/kernel/machine/mtrap.c b/kernel/machine/mtrap.c index 7a16011..72566ba 100644 --- a/kernel/machine/mtrap.c +++ b/kernel/machine/mtrap.c @@ -14,12 +14,25 @@ static void handle_misaligned_load() { panic("Misaligned Load!"); } static void handle_misaligned_store() { panic("Misaligned AMO!"); } +// added @lab1_3 +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 a handling function according to the type of a machine mode interrupt (trap). // 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; diff --git a/kernel/riscv.h b/kernel/riscv.h index 6d8700c..419baac 100644 --- a/kernel/riscv.h +++ b/kernel/riscv.h @@ -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). added @lab1_3 +#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 diff --git a/kernel/strap.c b/kernel/strap.c index e1befad..8f3086b 100644 --- a/kernel/strap.c +++ b/kernel/strap.c @@ -26,6 +26,21 @@ static void handle_syscall(trapframe *tf) { } +// +// 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. @@ -41,8 +56,13 @@ void smode_trap_handler(void) { // if the cause of trap is syscall from user application. // read_csr() and CAUSE_USER_ECALL are macros defined in kernel/riscv.h - if (read_csr(scause) == CAUSE_USER_ECALL) { + 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)); diff --git a/user/app_illegal_instruction.c b/user/app_illegal_instruction.c deleted file mode 100644 index 3ff98cb..0000000 --- a/user/app_illegal_instruction.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Below is the given application for lab1_2. - * This app attempts to issue M-mode instruction in U-mode, and consequently raises an exception. - */ - -#include "user_lib.h" -#include "util/types.h" - -int main(void) { - printu("Going to hack the system by running privilege instructions.\n"); - // we are now in U(user)-mode, but the "csrw" instruction requires M-mode privilege. - // Attempting to execute such instruction will raise illegal instruction exception. - asm volatile("csrw sscratch, 0"); - exit(0); -} diff --git a/user/app_long_loop.c b/user/app_long_loop.c new file mode 100644 index 0000000..8b4d873 --- /dev/null +++ b/user/app_long_loop.c @@ -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; +}