Implement VM #63
@@ -63,6 +63,7 @@ userprog_SRC += userprog/tss.c # TSS management.
|
|||||||
|
|
||||||
# Virtual memory code.
|
# Virtual memory code.
|
||||||
vm_SRC += devices/swap.c # Swap block manager.
|
vm_SRC += devices/swap.c # Swap block manager.
|
||||||
|
vm_SRC += vm/stackgrowth.c
|
||||||
#vm_SRC = vm/file.c # Some other file.
|
#vm_SRC = vm/file.c # Some other file.
|
||||||
|
|
||||||
# Filesystem code.
|
# Filesystem code.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#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 "vm/stackgrowth.h"
|
||||||
|
|
||||||
/* Number of page faults processed. */
|
/* Number of page faults processed. */
|
||||||
static long long page_fault_cnt;
|
static long long page_fault_cnt;
|
||||||
@@ -145,6 +146,12 @@ 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 (grow_stack (fault_addr))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* To implement virtual memory, delete the rest of the function
|
/* To implement virtual memory, delete the rest of the function
|
||||||
body, and replace it with code that brings in the page to
|
body, and replace it with code that brings in the page to
|
||||||
which fault_addr refers. */
|
which fault_addr refers. */
|
||||||
|
|||||||
38
src/vm/stackgrowth.c
Normal file
38
src/vm/stackgrowth.c
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "stackgrowth.h"
|
||||||
|
#include "threads/palloc.h"
|
||||||
|
#include "threads/thread.h"
|
||||||
|
#include "threads/vaddr.h"
|
||||||
|
#include "userprog/pagedir.h"
|
||||||
|
|
||||||
|
/* Validates a given address for being <=32 bytes away from the stack pointer or
|
||||||
|
above the stack */
|
||||||
|
bool needs_new_page (void *addr, void *esp)
|
||||||
|
{
|
||||||
|
return (is_user_vaddr (addr) &&
|
||||||
|
(uint32_t*)addr >= ((uint32_t*)esp - 32) &&
|
||||||
|
((PHYS_BASE - pg_round_down (addr))
|
||||||
|
<= MAX_STACK_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extends the stack by the necessary number of pages */
|
||||||
|
bool grow_stack (void *addr)
|
||||||
|
{
|
||||||
|
struct thread *t = thread_current ();
|
||||||
|
void *last_page = pg_round_down (addr);
|
||||||
|
|
||||||
|
uint8_t *new_page = palloc_get_page (PAL_USER | PAL_ZERO);
|
||||||
|
if ( new_page == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool added_page = pagedir_get_page (t->pagedir, last_page) == NULL
|
||||||
|
&& pagedir_set_page (t->pagedir, last_page, new_page, true);
|
||||||
|
|
||||||
|
if (!added_page) {
|
||||||
|
palloc_free_page (new_page);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
11
src/vm/stackgrowth.h
Normal file
11
src/vm/stackgrowth.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef GROWSTACK_H
|
||||||
|
#define GROWSTACK_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define MAX_STACK_SIZE 8388608 // (8MB)
|
||||||
|
|
||||||
|
bool needs_new_page (void *addr, void *esp);
|
||||||
|
bool grow_stack (void *addr);
|
||||||
|
|
||||||
|
#endif //GROWSTACK_H
|
||||||
Reference in New Issue
Block a user