diff --git a/src/examples/Makefile b/src/examples/Makefile index b6b902f..3bb6ac9 100644 --- a/src/examples/Makefile +++ b/src/examples/Makefile @@ -4,7 +4,7 @@ SRCDIR = .. # To add a new test, put its name on the PROGS list # and then add a name_SRC line that lists its source files. PROGS = cat cmp cp echo halt hex-dump mcat mcp rm \ - bubsort insult lineup matmult recursor + bubsort insult lineup matmult recursor args-ovf # Should work from task 2 onward. cat_SRC = cat.c @@ -18,6 +18,7 @@ lineup_SRC = lineup.c ls_SRC = ls.c recursor_SRC = recursor.c rm_SRC = rm.c +args-ovf_SRC = args-ovf.c # Should work in task 3; also in task 4 if VM is included. bubsort_SRC = bubsort.c diff --git a/src/examples/args-ovf b/src/examples/args-ovf new file mode 100755 index 0000000..ba2990e Binary files /dev/null and b/src/examples/args-ovf differ diff --git a/src/userprog/process.c b/src/userprog/process.c index efc0f45..afc39f4 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -28,6 +28,10 @@ (for the purposes of alignment). */ #define WORD_SIZE 4 +/* Defines non-negative integer division wherein the result is always rounded + up. */ +#define DIV_CEIL(x, y) ((x + (y - 1)) / y) + /* Keeps track of the position of pointers to user program arguments within a linked list. */ struct arg_elem @@ -222,13 +226,19 @@ process_init_stack (char *cmd_saveptr, void **esp, char *file_name) + return_addr_size; /* If pushing the rest of the data required for the stack would cause - overflow, allocate an extra page that is contiguous within the - virtual address space (below the current address range). */ - if (PHYS_BASE - *esp + remaining_size > PGSIZE) + overflow, allocate as many extra pages as needed to the user process + contiguously in the virtual address space below the initial page. */ + int overflow_bytes = (PHYS_BASE - *esp) + remaining_size - PGSIZE; + if (overflow_bytes > 0) { - uint8_t *kpage = palloc_get_page (PAL_USER | PAL_ZERO); - if (!install_page (((uint8_t *) PHYS_BASE) - PGSIZE * 2, kpage, true)) - return false; + int pages_needed = DIV_CEIL (overflow_bytes, PGSIZE); + for (int i = 1; i < pages_needed + 1; i++) + { + uint8_t *kpage = palloc_get_page (PAL_USER | PAL_ZERO); + if (!install_page (((uint8_t *) PHYS_BASE) - PGSIZE * (i + 1), + kpage, true)) + return false; + } } /* Align stack pointer to word size before pushing argv elements for