Implement VM #63
@@ -1,10 +1,18 @@
|
||||
#include "userprog/exception.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "stdbool.h"
|
||||
#include "userprog/gdt.h"
|
||||
#include "threads/interrupt.h"
|
||||
#include "threads/thread.h"
|
||||
#include "userprog/pagedir.h"
|
||||
#ifdef VM
|
||||
#include "vm/stackgrowth.h"
|
||||
#include "vm/frame.h"
|
||||
#include "vm/page.h"
|
||||
#include "devices/swap.h"
|
||||
#include "threads/vaddr.h"
|
||||
#endif
|
||||
|
||||
/* Number of page faults processed. */
|
||||
static long long page_fault_cnt;
|
||||
@@ -147,9 +155,26 @@ page_fault (struct intr_frame *f)
|
||||
user = (f->error_code & PF_U) != 0;
|
||||
|
||||
#ifdef VM
|
||||
if (user && not_present)
|
||||
if (user)
|
||||
{
|
||||
if (handle_stack_fault (fault_addr, f->esp)) return;
|
||||
if (not_present)
|
||||
{
|
||||
struct thread *t = thread_current ();
|
||||
if (page_in_swap (t, fault_addr))
|
||||
{
|
||||
size_t swap_slot = page_get_swap (t, fault_addr);
|
||||
void *upage = pg_round_down (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 page faults that need to be resolved by dynamic stack growth
|
||||
by checking if this is such a fault and resolving it appropriately. */
|
||||
if (handle_stack_fault (fault_addr, f->esp)) return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -24,6 +24,16 @@ page_set_swap (struct thread *owner, void *upage, size_t swap_slot)
|
||||
pagedir_clear_page (owner->pagedir, upage);
|
||||
}
|
||||
|
||||
/* Returns true iff the page with user address 'upage' owned by 'owner'
|
||||
is flagged to be in the swap disk via the owner's page table. */
|
||||
bool
|
||||
page_in_swap (struct thread *owner, void *upage)
|
||||
{
|
||||
uint32_t *pte = lookup_page (owner->pagedir, upage, false);
|
||||
return pte != NULL &&
|
||||
(*pte & (1 << SWAP_FLAG_BIT)) != 0;
|
||||
}
|
||||
|
||||
/* Given that the page with user address 'upage' owned by 'owner' is flagged
|
||||
to be in the swap disk via the owner's page table, returns its stored
|
||||
swap slot. Otherwise panics the kernel. */
|
||||
@@ -32,8 +42,8 @@ page_get_swap (struct thread *owner, void *upage)
|
||||
{
|
||||
uint32_t *pte = lookup_page (owner->pagedir, upage, false);
|
||||
|
||||
ASSERT (pte != NULL);
|
||||
ASSERT ((*pte & PTE_P) == 0);
|
||||
ASSERT ((*pte & (1 << SWAP_FLAG_BIT)) != 0);
|
||||
|
||||
/* Masks the address bits and returns truncated value. */
|
||||
return ((*pte & PTE_ADDR) >> ADDR_START_BIT);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "threads/thread.h"
|
||||
|
||||
void page_set_swap (struct thread *, void *, size_t);
|
||||
bool page_in_swap (struct thread *, void *);
|
||||
size_t page_get_swap (struct thread *, void *);
|
||||
|
||||
#endif /* vm/frame.h */
|
||||
|
||||
Reference in New Issue
Block a user