Implement VM #63
@@ -146,9 +146,9 @@ page_fault (struct intr_frame *f)
|
|||||||
write = (f->error_code & PF_W) != 0;
|
write = (f->error_code & PF_W) != 0;
|
||||||
user = (f->error_code & PF_U) != 0;
|
user = (f->error_code & PF_U) != 0;
|
||||||
|
|
||||||
if (user && needs_new_page (fault_addr, f->esp))
|
if (user)
|
||||||
{
|
{
|
||||||
if (grow_stack (fault_addr))
|
if (try_alloc_new_page (fault_addr, f->esp))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -455,20 +455,6 @@ fd_get_file (int fd)
|
|||||||
return hash_entry (e, struct open_file, elem);
|
return hash_entry (e, struct open_file, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
try_alloc_new_page (const void *ptr)
|
|
||||||
{
|
|
||||||
if (needs_new_page (ptr, thread_current()->curr_esp))
|
|
||||||
{
|
|
||||||
if (!grow_stack (ptr))
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validates if a block of memory starting at START and of size SIZE bytes is
|
/* Validates if a block of memory starting at START and of size SIZE bytes is
|
||||||
fully contained within user virtual memory. Kills the thread (by exiting with
|
fully contained within user virtual memory. Kills the thread (by exiting with
|
||||||
failure) if the memory is invalid. Otherwise, returns (nothing) normally.
|
failure) if the memory is invalid. Otherwise, returns (nothing) normally.
|
||||||
@@ -480,6 +466,8 @@ validate_user_pointer (const void *start, size_t size)
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
struct thread *t = thread_current ();
|
||||||
|
|
||||||
const void *end = start + size - 1;
|
const void *end = start + size - 1;
|
||||||
|
|
||||||
/* Check if the start and end pointers are valid user virtual addresses. */
|
/* Check if the start and end pointers are valid user virtual addresses. */
|
||||||
@@ -489,9 +477,9 @@ validate_user_pointer (const void *start, size_t size)
|
|||||||
/* We now need to check if the entire memory block is mapped to physical
|
/* We now need to check if the entire memory block is mapped to physical
|
||||||
memory by the page table. */
|
memory by the page table. */
|
||||||
for (const void *ptr = pg_round_down (start); ptr <= end; ptr += PGSIZE)
|
for (const void *ptr = pg_round_down (start); ptr <= end; ptr += PGSIZE)
|
||||||
if (pagedir_get_page (thread_current ()->pagedir, ptr) == NULL)
|
if (pagedir_get_page (t->pagedir, ptr) == NULL)
|
||||||
{
|
{
|
||||||
if (!try_alloc_new_page (ptr))
|
if (!try_alloc_new_page (ptr, t->curr_esp))
|
||||||
syscall_exit (EXIT_FAILURE);
|
syscall_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,6 +496,7 @@ validate_user_string (const char *str)
|
|||||||
|
|
||||||
/* Calculate the offset of the string within the (first) page. */
|
/* Calculate the offset of the string within the (first) page. */
|
||||||
size_t offset = (uintptr_t) str % PGSIZE;
|
size_t offset = (uintptr_t) str % PGSIZE;
|
||||||
|
struct thread *t = thread_current ();
|
||||||
|
|
||||||
/* We move page by page, checking if the page is mapped to physical memory. */
|
/* We move page by page, checking if the page is mapped to physical memory. */
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -519,8 +508,8 @@ validate_user_string (const char *str)
|
|||||||
if (!is_user_vaddr(page))
|
if (!is_user_vaddr(page))
|
||||||
syscall_exit (EXIT_FAILURE);
|
syscall_exit (EXIT_FAILURE);
|
||||||
|
|
||||||
if (pagedir_get_page (thread_current ()->pagedir, page) == NULL)
|
if (pagedir_get_page (t->pagedir, page) == NULL)
|
||||||
if (!try_alloc_new_page (str))
|
if (!try_alloc_new_page (str, t->curr_esp))
|
||||||
syscall_exit (EXIT_FAILURE);
|
syscall_exit (EXIT_FAILURE);
|
||||||
|
|
||||||
while (offset < PGSIZE)
|
while (offset < PGSIZE)
|
||||||
|
|||||||
@@ -7,9 +7,28 @@
|
|||||||
|
|
||||||
#define MAX_STACK_ACCESS_DIST 32
|
#define MAX_STACK_ACCESS_DIST 32
|
||||||
|
|
||||||
/* Validates a given address for being <=32 bytes away from the stack pointer or
|
static bool needs_new_page (const void *addr, const void *esp);
|
||||||
above the stack */
|
static bool grow_stack (const void *addr);
|
||||||
bool needs_new_page (void *addr, void *esp)
|
|
||||||
|
bool
|
||||||
|
try_alloc_new_page (const void *ptr, const void *esp)
|
||||||
|
{
|
||||||
|
if (needs_new_page (ptr, esp))
|
||||||
|
{
|
||||||
|
if (!grow_stack (ptr))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validates a given address for being a stack query and not a generic erroneous
|
||||||
|
address
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
needs_new_page (const void *addr, const void *esp)
|
||||||
{
|
{
|
||||||
return (is_user_vaddr (addr) &&
|
return (is_user_vaddr (addr) &&
|
||||||
(uint32_t*)addr >= ((uint32_t*)esp - MAX_STACK_ACCESS_DIST) &&
|
(uint32_t*)addr >= ((uint32_t*)esp - MAX_STACK_ACCESS_DIST) &&
|
||||||
@@ -18,7 +37,8 @@ bool needs_new_page (void *addr, void *esp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Extends the stack by the necessary number of pages */
|
/* Extends the stack by the necessary number of pages */
|
||||||
bool grow_stack (void *addr)
|
static bool
|
||||||
|
grow_stack (const void *addr)
|
||||||
{
|
{
|
||||||
struct thread *t = thread_current ();
|
struct thread *t = thread_current ();
|
||||||
void *last_page = pg_round_down (addr);
|
void *last_page = pg_round_down (addr);
|
||||||
@@ -35,6 +55,4 @@ bool grow_stack (void *addr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#define MAX_STACK_SIZE 8388608 // (8MB)
|
#define MAX_STACK_SIZE 8388608 // (8MB)
|
||||||
|
|
||||||
bool needs_new_page (void *addr, void *esp);
|
bool try_alloc_new_page (const void *ptr, const void *esp);
|
||||||
bool grow_stack (void *addr);
|
|
||||||
|
|
||||||
#endif /* vm/frame.h */
|
#endif /* vm/frame.h */
|
||||||
|
|||||||
Reference in New Issue
Block a user