From e88a8c4c379d721e9901752d440a05295087da11 Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 19 Jun 2012 01:44:56 +0200 Subject: implement page table and use it for lazy loading of segments --- userprog/exception.c | 16 +++++++++++++++- userprog/process.c | 35 ++++++++++++----------------------- userprog/process.h | 1 + 3 files changed, 28 insertions(+), 24 deletions(-) (limited to 'userprog') diff --git a/userprog/exception.c b/userprog/exception.c index 17620ad..54621fa 100644 --- a/userprog/exception.c +++ b/userprog/exception.c @@ -5,6 +5,7 @@ #include "threads/interrupt.h" #include "threads/thread.h" #include "threads/vaddr.h" +#include "vm/page.h" /* Number of page faults processed. */ static long long page_fault_cnt; @@ -121,12 +122,13 @@ kill (struct intr_frame *f) description of "Interrupt 14--Page Fault Exception (#PF)" in [IA32-v3a] section 5.15 "Exception and Interrupt Reference". */ static void -page_fault (struct intr_frame *f) +page_fault (struct intr_frame *f) { bool not_present; /* True: not-present page, false: writing r/o page. */ bool write; /* True: access was write, false: access was read. */ bool user; /* True: access by user, false: access by kernel. */ void *fault_addr; /* Fault address. */ + struct page_table_entry *pte; /* Obtain faulting address, the virtual address that was accessed to cause the fault. It may point to code or to @@ -153,6 +155,17 @@ page_fault (struct intr_frame *f) body, adding code that brings in the page to which fault_addr refers. */ if (is_user_vaddr(fault_addr)) { + pte = page_table_fetch (&thread_current ()->page_table, pg_round_down (fault_addr)); + if (pte != NULL) + page_load (pte); + else + { + printf ("Page fault %p\n", pte); + kill (f); + } + + //TODO +#if 0 if (! user) { /* syscall exception; set eax and eip */ f->eip = (void*)f->eax; @@ -162,6 +175,7 @@ page_fault (struct intr_frame *f) /* user process access violation */ thread_exit(); } +#endif } else { printf ("Page fault at %p: %s error %s page in %s context.\n", fault_addr, diff --git a/userprog/process.c b/userprog/process.c index c13c051..15883d9 100644 --- a/userprog/process.c +++ b/userprog/process.c @@ -18,6 +18,7 @@ #include "threads/synch.h" #include "threads/thread.h" #include "threads/vaddr.h" +#include "vm/page.h" /* data structure to communicate with the thread initializing a new process */ struct start_aux_data { @@ -128,6 +129,8 @@ start_process (void *aux) process->parent_tid = aux_data->parent_thread->tid; thread->process = process; + page_table_init (&thread->page_table); + /* Initialize interrupt frame and load executable. */ memset (&if_, 0, sizeof if_); if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; @@ -251,6 +254,8 @@ process_exit (void) pagedir_destroy (pd); } + page_table_free (&thread->page_table); + /* Destroy the process structure if the parent is not alive * any more. Atomic test and set would be sufficient here. */ @@ -478,8 +483,6 @@ load (const char *args, void (**eip) (void), void **esp) /* load() helpers. */ -static bool install_page (void *upage, void *kpage, bool writable); - /* Checks whether PHDR describes a valid, loadable segment in FILE and returns true if so, false otherwise. */ static bool @@ -556,29 +559,15 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; size_t page_zero_bytes = PGSIZE - page_read_bytes; - /* Get a page of memory. */ - uint8_t *kpage = palloc_get_page (PAL_USER); - if (kpage == NULL) - return false; - - /* Load this page. */ - if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) - { - palloc_free_page (kpage); + /* add segment to page table for on demand loading */ + if (!page_table_insert_segment (file, ofs, upage, page_read_bytes, + page_zero_bytes, writable)) return false; - } - memset (kpage + page_read_bytes, 0, page_zero_bytes); - - /* Add the page to the process's address space. */ - if (!install_page (upage, kpage, writable)) - { - palloc_free_page (kpage); - return false; - } /* Advance. */ read_bytes -= page_read_bytes; zero_bytes -= page_zero_bytes; + ofs += page_read_bytes; upage += PGSIZE; } return true; @@ -602,7 +591,7 @@ setup_stack (uint32_t **esp, const char *args) if (kpage == NULL) return false; - if (! install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true)) { + if (! process_install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true)) { palloc_free_page (kpage); return false; } @@ -706,8 +695,8 @@ setup_stack (uint32_t **esp, const char *args) with palloc_get_page(). Returns true on success, false if UPAGE is already mapped or if memory allocation fails. */ -static bool -install_page (void *upage, void *kpage, bool writable) +bool +process_install_page (void *upage, void *kpage, bool writable) { struct thread *t = thread_current (); diff --git a/userprog/process.h b/userprog/process.h index 1609801..b7bca5d 100644 --- a/userprog/process.h +++ b/userprog/process.h @@ -37,6 +37,7 @@ tid_t process_execute (const char *file_name); int process_wait (tid_t); void process_exit (void); void process_activate (void); +bool process_install_page (void *upage, void *kpage, bool writable); int process_open_file(const char* fname); struct file* process_get_file(int fd); -- cgit v1.2.3