fix: don't discriminate between user and kernel page fault contexts for stack growth, lazy loading, and swapping
This commit is contained in:
@@ -156,49 +156,42 @@ page_fault (struct intr_frame *f)
|
|||||||
user = (f->error_code & PF_U) != 0;
|
user = (f->error_code & PF_U) != 0;
|
||||||
|
|
||||||
#ifdef VM
|
#ifdef VM
|
||||||
struct thread *t = thread_current ();
|
|
||||||
void *upage = pg_round_down (fault_addr);
|
void *upage = pg_round_down (fault_addr);
|
||||||
|
if (not_present && is_user_vaddr(upage))
|
||||||
/* If the fault address is in a user page that is not present, then it might
|
|
||||||
be an executable file page that needs to be lazily loaded. So, we check the
|
|
||||||
SPT to determine if this is the case, and if so load the page from disk. */
|
|
||||||
if (not_present && is_user_vaddr (upage))
|
|
||||||
{
|
{
|
||||||
|
struct thread *t = thread_current ();
|
||||||
|
void *esp = user ? f->esp : t->curr_esp;
|
||||||
|
|
||||||
|
/* Check if the non-present user page is in the swap partition.
|
||||||
|
If so, swap it back into main memory, updating the PTE for
|
||||||
|
the faulted virtual address to point to the newly allocated
|
||||||
|
frame. */
|
||||||
|
if (page_in_swap (t, fault_addr))
|
||||||
|
{
|
||||||
|
size_t swap_slot = page_get_swap (t, fault_addr);
|
||||||
|
void *kpage = frame_alloc (0, upage, t);
|
||||||
|
swap_in (kpage, swap_slot);
|
||||||
|
|
||||||
|
bool writeable = pagedir_is_writable (t->pagedir, upage);
|
||||||
|
if (pagedir_set_page (t->pagedir, upage, kpage, writeable)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle user page faults that need to be resolved by dynamic
|
||||||
|
stack growth by checking if this is such a fault and responding
|
||||||
|
accordingly. */
|
||||||
|
if (handle_stack_fault (fault_addr, esp)) return;
|
||||||
|
|
||||||
|
/* Handle user page faults that need to be resolved by lazy loading
|
||||||
|
of executable files by checking if they contain entries in the
|
||||||
|
SPT hash map and responding accordingly. */
|
||||||
if (try_fetch_page (upage, write))
|
if (try_fetch_page (upage, write))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user)
|
/* Allows for page faults within a kernel context to communicate with
|
||||||
|
user pages for sending error codes. */
|
||||||
|
if (!user)
|
||||||
{
|
{
|
||||||
if (not_present)
|
|
||||||
{
|
|
||||||
/* Check if the non-present user page is in the swap partition.
|
|
||||||
If so, swap it back into main memory, updating the PTE for
|
|
||||||
the faulted virtual address to point to the newly allocated
|
|
||||||
frame. */
|
|
||||||
if (page_in_swap (t, fault_addr))
|
|
||||||
{
|
|
||||||
size_t swap_slot = page_get_swap (t, fault_addr);
|
|
||||||
void *kpage = frame_alloc (0, upage, t);
|
|
||||||
swap_in (kpage, swap_slot);
|
|
||||||
|
|
||||||
bool writeable = pagedir_is_writable (t->pagedir, upage);
|
|
||||||
if (pagedir_set_page (t->pagedir, upage, kpage, writeable)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle user page faults that need to be resolved by dynamic
|
|
||||||
stack growth by checking if this is such a fault and responding
|
|
||||||
accordingly. */
|
|
||||||
if (handle_stack_fault (fault_addr, f->esp)) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Handle kernel page faults that need to be resolved by dynamic stack
|
|
||||||
growth by checking if this is such a fault and responding
|
|
||||||
accordingly. */
|
|
||||||
if (not_present && handle_stack_fault (fault_addr, t->curr_esp)) return;
|
|
||||||
|
|
||||||
f->eip = (void *)f->eax;
|
f->eip = (void *)f->eax;
|
||||||
f->eax = 0xffffffff;
|
f->eax = 0xffffffff;
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user