From c74a8c55aae4d4607670b9d0f192a3cc891acd95 Mon Sep 17 00:00:00 2001 From: EDiasAlberto Date: Wed, 27 Nov 2024 19:21:43 +0000 Subject: [PATCH] Implement stack growth for system calls and add stack pointer tracking to thread --- src/threads/thread.h | 4 ++++ src/userprog/syscall.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/threads/thread.h b/src/threads/thread.h index 4a88577..60f91ce 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -143,6 +143,10 @@ struct thread struct hash open_files; /* Hash Table of FD -> Struct File. */ #endif +#ifdef VM + void *curr_esp; +#endif + /* Owned by thread.c. */ unsigned magic; /* Detects stack overflow. */ }; diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c index 3efe7b5..7fbc939 100644 --- a/src/userprog/syscall.c +++ b/src/userprog/syscall.c @@ -10,6 +10,9 @@ #include "threads/synch.h" #include "userprog/process.h" #include "userprog/pagedir.h" +#ifdef VM +#include "vm/stackgrowth.h" +#endif #include #include @@ -98,6 +101,7 @@ syscall_handler (struct intr_frame *f) /* First, read the system call number from the stack. */ validate_user_pointer (f->esp, sizeof (uintptr_t)); uintptr_t syscall_number = *(int *) f->esp; + thread_current ()->curr_esp = f->esp; /* Ensures the number corresponds to a system call that can be handled. */ if (syscall_number >= LOOKUP_SIZE) @@ -451,6 +455,20 @@ fd_get_file (int fd) 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 fully contained within user virtual memory. Kills the thread (by exiting with failure) if the memory is invalid. Otherwise, returns (nothing) normally. @@ -472,7 +490,10 @@ validate_user_pointer (const void *start, size_t size) memory by the page table. */ for (const void *ptr = pg_round_down (start); ptr <= end; ptr += PGSIZE) if (pagedir_get_page (thread_current ()->pagedir, ptr) == NULL) - syscall_exit (EXIT_FAILURE); + { + if (!try_alloc_new_page (ptr)) + syscall_exit (EXIT_FAILURE); + } } /* Validates if a string is fully contained within user virtual memory. Kills @@ -495,10 +516,13 @@ validate_user_string (const char *str) /* If we reach addresses that are not mapped to physical memory before the end of the string, the thread is terminated. */ - if (!is_user_vaddr(page) || - pagedir_get_page (thread_current ()->pagedir, page) == NULL) + if (!is_user_vaddr(page)) syscall_exit (EXIT_FAILURE); + if (pagedir_get_page (thread_current ()->pagedir, page) == NULL) + if (!try_alloc_new_page (str)) + syscall_exit (EXIT_FAILURE); + while (offset < PGSIZE) { if (*str == '\0')