fix: invalidate PTEs of evicted pages before eviction occurs to prevent modificationof pages mid-eviction
This commit is contained in:
@@ -7,7 +7,6 @@
|
|||||||
#include "threads/palloc.h"
|
#include "threads/palloc.h"
|
||||||
|
|
||||||
static uint32_t *active_pd (void);
|
static uint32_t *active_pd (void);
|
||||||
static void invalidate_pagedir (uint32_t *);
|
|
||||||
|
|
||||||
/* Creates a new page directory that has mappings for kernel
|
/* Creates a new page directory that has mappings for kernel
|
||||||
virtual addresses, but none for user virtual addresses.
|
virtual addresses, but none for user virtual addresses.
|
||||||
@@ -278,7 +277,7 @@ active_pd (void)
|
|||||||
This function invalidates the TLB if PD is the active page
|
This function invalidates the TLB if PD is the active page
|
||||||
directory. (If PD is not active then its entries are not in
|
directory. (If PD is not active then its entries are not in
|
||||||
the TLB, so there is no need to invalidate anything.) */
|
the TLB, so there is no need to invalidate anything.) */
|
||||||
static void
|
void
|
||||||
invalidate_pagedir (uint32_t *pd)
|
invalidate_pagedir (uint32_t *pd)
|
||||||
{
|
{
|
||||||
if (active_pd () == pd)
|
if (active_pd () == pd)
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ void pagedir_set_accessed (uint32_t *pd, const void *upage, bool accessed);
|
|||||||
bool pagedir_is_writable (uint32_t *pd, const void *upage);
|
bool pagedir_is_writable (uint32_t *pd, const void *upage);
|
||||||
void pagedir_set_writable (uint32_t *pd, const void *upage, bool writable);
|
void pagedir_set_writable (uint32_t *pd, const void *upage, bool writable);
|
||||||
void pagedir_activate (uint32_t *pd);
|
void pagedir_activate (uint32_t *pd);
|
||||||
|
void invalidate_pagedir (uint32_t *pd);
|
||||||
|
|
||||||
#endif /* userprog/pagedir.h */
|
#endif /* userprog/pagedir.h */
|
||||||
|
|||||||
@@ -93,6 +93,13 @@ frame_alloc (enum palloc_flags flags, void *upage, struct thread *owner)
|
|||||||
ASSERT (victim != NULL); /* get_victim () should never return null. */
|
ASSERT (victim != NULL); /* get_victim () should never return null. */
|
||||||
|
|
||||||
/* 2. Swap out victim into disk. */
|
/* 2. Swap out victim into disk. */
|
||||||
|
/* Mark page as 'not present' and flag the page directory as having
|
||||||
|
been modified *before* eviction begins to prevent the owner of the
|
||||||
|
victim page from accessing/modifying it mid-eviction. */
|
||||||
|
pagedir_clear_page (owner->pagedir, upage);
|
||||||
|
|
||||||
|
// TODO: Lock PTE of victim page for victim process.
|
||||||
|
|
||||||
size_t swap_slot = swap_out (victim->frame);
|
size_t swap_slot = swap_out (victim->frame);
|
||||||
page_set_swap (victim->owner, victim->upage, swap_slot);
|
page_set_swap (victim->owner, victim->upage, swap_slot);
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
#define ADDR_START_BIT 12
|
#define ADDR_START_BIT 12
|
||||||
|
|
||||||
/* Updates the 'owner' thread's page table entry for virtual address 'upage'
|
/* Updates the 'owner' thread's page table entry for virtual address 'upage'
|
||||||
to have a present bit of 0 and stores the specified swap slot value in the
|
to flag the page as being stored in swap, and stores the specified swap slot
|
||||||
entry for later retrieval from disk. */
|
value in the entry at the address bits for later retrieval from disk. */
|
||||||
void
|
void
|
||||||
page_set_swap (struct thread *owner, void *upage, size_t swap_slot)
|
page_set_swap (struct thread *owner, void *upage, size_t swap_slot)
|
||||||
{
|
{
|
||||||
@@ -19,9 +19,7 @@ page_set_swap (struct thread *owner, void *upage, size_t swap_slot)
|
|||||||
uint32_t swap_slot_bits = (swap_slot << ADDR_START_BIT) & PTE_ADDR;
|
uint32_t swap_slot_bits = (swap_slot << ADDR_START_BIT) & PTE_ADDR;
|
||||||
*pte = (*pte & PTE_FLAGS) | swap_slot_bits;
|
*pte = (*pte & PTE_FLAGS) | swap_slot_bits;
|
||||||
|
|
||||||
/* Mark page as 'not present' and flag the page directory as having
|
invalidate_pagedir (owner->pagedir);
|
||||||
been modified. */
|
|
||||||
pagedir_clear_page (owner->pagedir, upage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true iff the page with user address 'upage' owned by 'owner'
|
/* Returns true iff the page with user address 'upage' owned by 'owner'
|
||||||
|
|||||||
Reference in New Issue
Block a user