feat: implement page swapping
This commit is contained in:
@@ -1,10 +1,18 @@
|
|||||||
#include "userprog/exception.h"
|
#include "userprog/exception.h"
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "stdbool.h"
|
||||||
#include "userprog/gdt.h"
|
#include "userprog/gdt.h"
|
||||||
#include "threads/interrupt.h"
|
#include "threads/interrupt.h"
|
||||||
#include "threads/thread.h"
|
#include "threads/thread.h"
|
||||||
|
#include "userprog/pagedir.h"
|
||||||
|
#ifdef VM
|
||||||
#include "vm/stackgrowth.h"
|
#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. */
|
/* Number of page faults processed. */
|
||||||
static long long page_fault_cnt;
|
static long long page_fault_cnt;
|
||||||
@@ -147,9 +155,26 @@ page_fault (struct intr_frame *f)
|
|||||||
user = (f->error_code & PF_U) != 0;
|
user = (f->error_code & PF_U) != 0;
|
||||||
|
|
||||||
#ifdef VM
|
#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
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ page_set_swap (struct thread *owner, void *upage, size_t swap_slot)
|
|||||||
pagedir_clear_page (owner->pagedir, upage);
|
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
|
/* 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
|
to be in the swap disk via the owner's page table, returns its stored
|
||||||
swap slot. Otherwise panics the kernel. */
|
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);
|
uint32_t *pte = lookup_page (owner->pagedir, upage, false);
|
||||||
|
|
||||||
|
ASSERT (pte != NULL);
|
||||||
ASSERT ((*pte & PTE_P) == 0);
|
ASSERT ((*pte & PTE_P) == 0);
|
||||||
ASSERT ((*pte & (1 << SWAP_FLAG_BIT)) != 0);
|
|
||||||
|
|
||||||
/* Masks the address bits and returns truncated value. */
|
/* Masks the address bits and returns truncated value. */
|
||||||
return ((*pte & PTE_ADDR) >> ADDR_START_BIT);
|
return ((*pte & PTE_ADDR) >> ADDR_START_BIT);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "threads/thread.h"
|
#include "threads/thread.h"
|
||||||
|
|
||||||
void page_set_swap (struct thread *, void *, size_t);
|
void page_set_swap (struct thread *, void *, size_t);
|
||||||
|
bool page_in_swap (struct thread *, void *);
|
||||||
size_t page_get_swap (struct thread *, void *);
|
size_t page_get_swap (struct thread *, void *);
|
||||||
|
|
||||||
#endif /* vm/frame.h */
|
#endif /* vm/frame.h */
|
||||||
|
|||||||
Reference in New Issue
Block a user