diff --git a/src/userprog/exception.c b/src/userprog/exception.c index e0d5c64..a87f7d5 100644 --- a/src/userprog/exception.c +++ b/src/userprog/exception.c @@ -157,30 +157,33 @@ page_fault (struct intr_frame *f) write = (f->error_code & PF_W) != 0; user = (f->error_code & PF_U) != 0; - if (!user || !not_present) + /* Select the appropriate stack pointer based on the context of the fault. */ + void *esp = user ? f->esp : thread_current()->curr_esp; + + /* If the fault address is in a user page that is not present, then it might + be just that the stack needs to grow or that it needs to be lazily loaded. + So we attempt to grow the stack. If this does not work, we check our SPT to + see if the page is expected to have data loaded in memory. */ + void *upage = pg_round_down (fault_addr); + if (not_present && is_user_vaddr (upage) && upage != NULL) + { + if (is_valid_stack_access (fault_addr, esp)) + if (grow_stack (upage)) + return; + + if (try_fetch_page (upage, write)) + return; + } + + /* If the page fault occurred in kernel mode, then we intentionally indicate + a fault (for get_user() etc). */ + if (!user) { f->eip = (void *)f->eax; f->eax = 0xffffffff; return; } - /* If the fault address is in a user page that is not present, then it might - be just that the stack needs to grow or that it needs to be lazily loaded. - So we attempt to grow the stack. If this does not work, we check our SPT to see if the page - is expected to have data loaded in memory. */ - void *upage = pg_round_down (fault_addr); - if (not_present && is_user_vaddr (upage) && upage != NULL) - { - if (is_valid_stack_access (fault_addr, f->esp)) - { - if (grow_stack (upage)) - return; - } - - if (try_fetch_page (upage, write)) - return; - } - /* To implement virtual memory, delete the rest of the function body, and replace it with code that brings in the page to which fault_addr refers. */