diff --git a/pintos/include/threads/thread.h b/pintos/include/threads/thread.h index c5c1e9a..ef2a175 100644 --- a/pintos/include/threads/thread.h +++ b/pintos/include/threads/thread.h @@ -121,6 +121,7 @@ struct thread { #ifdef VM /* Table for whole virtual memory owned by thread. */ struct supplemental_page_table spt; + uintptr_t user_rsp; #endif /* Owned by thread.c. */ diff --git a/pintos/userprog/syscall.c b/pintos/userprog/syscall.c index e702429..0162264 100644 --- a/pintos/userprog/syscall.c +++ b/pintos/userprog/syscall.c @@ -66,6 +66,7 @@ void syscall_init(void) { /* The main system call interface */ void syscall_handler(struct intr_frame* f) { uint64_t arg1 = f->R.rdi, arg2 = f->R.rsi, arg3 = f->R.rdx; + thread_current()->user_rsp = f->rsp; switch (f->R.rax) { case SYS_HALT: syscall_halt(); diff --git a/pintos/vm/vm.c b/pintos/vm/vm.c index e44e4c7..8247dd5 100644 --- a/pintos/vm/vm.c +++ b/pintos/vm/vm.c @@ -176,9 +176,15 @@ static struct frame * vm_get_frame (void) { return frame; } -/* Growing the stack. */ -static void -vm_stack_growth (void *addr UNUSED) { +static bool vm_stack_growth (void *addr) { + void *stack_bottom; + + if (addr == NULL) { + return false; + } + + stack_bottom = pg_round_down(addr); + return vm_alloc_page(VM_ANON | VM_MARKER_0, stack_bottom, true); } /* Handle the fault on write_protected page */ @@ -193,22 +199,37 @@ bool vm_try_handle_fault (struct intr_frame *f, void *addr, bool user, bool writ spt = &thread_current()->spt; page = NULL; - if (is_kernel_vaddr (addr) || addr == NULL) + if (addr == NULL || is_kernel_vaddr (addr) || !not_present) return false; - if (!not_present) { - page = spt_find_page (spt, addr); + page = spt_find_page (spt, pg_round_down(addr)); + + if (page == NULL) { + uintptr_t rsp; + + if (user) { + rsp = f->rsp; + } else { + rsp = thread_current()->user_rsp; + } - if (page == NULL || !write) + if (addr < (void *)rsp - STACK_HEURISTIC || addr >= (void *)USER_STACK || (uintptr_t)USER_STACK - (uintptr_t)pg_round_down(addr) > STACK_LIMIT) return false; - } - page = spt_find_page (spt, addr); + if (!vm_stack_growth(addr)) { + return false; + } - if (page == NULL || write == 1 && !(page->writable)) - return false; + page = spt_find_page(spt, pg_round_down(addr)); + if (page == NULL) { + return false; + } + } - return vm_do_claim_page (page); + if (write && !page->writable) + return false; + + return vm_do_claim_page(page); } @@ -358,4 +379,3 @@ static bool page_less (const struct hash_elem *a, const struct hash_elem *b, voi // return rsp != NULL && fault_addr >= rsp - STACK_HEURISTIC; // } -