diff --git a/Makefile b/Makefile index 9dad6ad..01b26d2 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS))) -USER_TARGET := $(OBJ_DIR)/app_naive_malloc +USER_TARGET := $(OBJ_DIR)/app_sum_sequence #------------------------targets------------------------ $(OBJ_DIR): @-mkdir -p $(OBJ_DIR) diff --git a/kernel/strap.c b/kernel/strap.c index 8f3086b..3e2ff08 100644 --- a/kernel/strap.c +++ b/kernel/strap.c @@ -6,6 +6,9 @@ #include "process.h" #include "strap.h" #include "syscall.h" +#include "pmm.h" +#include "vmm.h" +#include "util/functions.h" #include "spike_interface/spike_utils.h" @@ -41,6 +44,28 @@ void handle_mtimer_trap() { } +// +// the page fault handler. added @lab2_3. parameters: +// sepc: the pc when fault happens; +// stval: the virtual address that causes pagefault when being accessed. +// +void handle_user_page_fault(uint64 mcause, uint64 sepc, uint64 stval) { + sprint("handle_page_fault: %lx\n", stval); + switch (mcause) { + case CAUSE_STORE_PAGE_FAULT: + // TODO (lab2_3): implement the operations that solve the page fault to + // dynamically increase application stack. + // hint: first allocate a new physical page, and then, maps the new page to the + // virtual address that causes the page fault. + panic( "You need to implement the operations that actually handle the page fault in lab2_3.\n" ); + + break; + default: + sprint("unknown page fault.\n"); + break; + } +} + // // kernel/smode_trap.S will pass control to smode_trap_handler, when a trap happens // in S-mode. @@ -58,15 +83,25 @@ void smode_trap_handler(void) { // 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" ); + // use switch-case instead of if-else, as there are many cases since lab2_3. + switch (cause) { + case CAUSE_USER_ECALL: + handle_syscall(current->trapframe); + break; + case CAUSE_MTIMER_S_TRAP: + handle_mtimer_trap(); + break; + case CAUSE_STORE_PAGE_FAULT: + case CAUSE_LOAD_PAGE_FAULT: + // the address of missing page is stored in stval + // call handle_user_page_fault to process page faults + handle_user_page_fault(cause, read_csr(sepc), read_csr(stval)); + break; + default: + 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" ); + break; } // continue (come back to) the execution of current process. diff --git a/user/app_naive_malloc.c b/user/app_naive_malloc.c deleted file mode 100644 index adf40bf..0000000 --- a/user/app_naive_malloc.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Below is the given application for lab2_2. - */ - -#include "user_lib.h" -#include "util/types.h" - -struct my_structure { - char c; - int n; -}; - -int main(void) { - struct my_structure* s = (struct my_structure*)naive_malloc(); - s->c = 'a'; - s->n = 1; - - printu("s: %lx, {%c %d}\n", s, s->c, s->n); - - naive_free(s); - exit(0); -} diff --git a/user/app_sum_sequence.c b/user/app_sum_sequence.c new file mode 100644 index 0000000..809d341 --- /dev/null +++ b/user/app_sum_sequence.c @@ -0,0 +1,28 @@ +/* + * The application of lab2_3. + */ + +#include "user_lib.h" +#include "util/types.h" + +// +// compute the summation of an arithmetic sequence. for a given "n", compute +// result = n + (n-1) + (n-2) + ... + 0 +// sum_sequence() calls itself recursively till 0. The recursive call, however, +// may consume more memory (from stack) than a physical 4KB page, leading to a page fault. +// PKE kernel needs to improved to handle such page fault by expanding the stack. +// +uint64 sum_sequence(uint64 n) { + if (n == 0) + return 0; + else + return sum_sequence( n-1 ) + n; +} + +int main(void) { + // we need a large enough "n" to trigger pagefaults in the user stack + uint64 n = 1000; + + printu("Summation of an arithmetic sequence from 0 to %ld is: %ld \n", n, sum_sequence(1000) ); + exit(0); +}