From 3ef5264b6e3858b6e89311795a7f5e05ec02cb6a Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Tue, 26 Nov 2024 04:43:25 +0000 Subject: [PATCH] feat: allow stack to grow for process up to 8MB in size --- src/Makefile.build | 1 + src/userprog/exception.c | 7 +++++++ src/vm/stackgrowth.c | 38 ++++++++++++++++++++++++++++++++++++++ src/vm/stackgrowth.h | 11 +++++++++++ 4 files changed, 57 insertions(+) create mode 100644 src/vm/stackgrowth.c create mode 100644 src/vm/stackgrowth.h diff --git a/src/Makefile.build b/src/Makefile.build index c0d535e..4167f37 100644 --- a/src/Makefile.build +++ b/src/Makefile.build @@ -63,6 +63,7 @@ userprog_SRC += userprog/tss.c # TSS management. # Virtual memory code. vm_SRC += devices/swap.c # Swap block manager. +vm_SRC += vm/stackgrowth.c #vm_SRC = vm/file.c # Some other file. # Filesystem code. diff --git a/src/userprog/exception.c b/src/userprog/exception.c index 0a20b53..500cb89 100644 --- a/src/userprog/exception.c +++ b/src/userprog/exception.c @@ -4,6 +4,7 @@ #include "userprog/gdt.h" #include "threads/interrupt.h" #include "threads/thread.h" +#include "vm/stackgrowth.h" /* Number of page faults processed. */ static long long page_fault_cnt; @@ -145,6 +146,12 @@ page_fault (struct intr_frame *f) write = (f->error_code & PF_W) != 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 body, and replace it with code that brings in the page to which fault_addr refers. */ diff --git a/src/vm/stackgrowth.c b/src/vm/stackgrowth.c new file mode 100644 index 0000000..164eb9d --- /dev/null +++ b/src/vm/stackgrowth.c @@ -0,0 +1,38 @@ +#include +#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; + + +} \ No newline at end of file diff --git a/src/vm/stackgrowth.h b/src/vm/stackgrowth.h new file mode 100644 index 0000000..0502210 --- /dev/null +++ b/src/vm/stackgrowth.h @@ -0,0 +1,11 @@ +#ifndef GROWSTACK_H +#define GROWSTACK_H + +#include + +#define MAX_STACK_SIZE 8388608 // (8MB) + +bool needs_new_page (void *addr, void *esp); +bool grow_stack (void *addr); + +#endif //GROWSTACK_H