diff options
| author | manuel <manuel@mausz.at> | 2012-06-19 01:44:56 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-06-19 01:44:56 +0200 |
| commit | e88a8c4c379d721e9901752d440a05295087da11 (patch) | |
| tree | b89070c525614267811a10b77a4dbc49ffd96b03 /userprog | |
| parent | d9e0c55d118d0a3923b440b7811f8d1d6db9e1d7 (diff) | |
| download | progos-e88a8c4c379d721e9901752d440a05295087da11.tar.gz progos-e88a8c4c379d721e9901752d440a05295087da11.tar.bz2 progos-e88a8c4c379d721e9901752d440a05295087da11.zip | |
implement page table and use it for lazy loading of segments
Diffstat (limited to 'userprog')
| -rw-r--r-- | userprog/exception.c | 16 | ||||
| -rw-r--r-- | userprog/process.c | 35 | ||||
| -rw-r--r-- | userprog/process.h | 1 |
3 files changed, 28 insertions, 24 deletions
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 @@ | |||
| 5 | #include "threads/interrupt.h" | 5 | #include "threads/interrupt.h" |
| 6 | #include "threads/thread.h" | 6 | #include "threads/thread.h" |
| 7 | #include "threads/vaddr.h" | 7 | #include "threads/vaddr.h" |
| 8 | #include "vm/page.h" | ||
| 8 | 9 | ||
| 9 | /* Number of page faults processed. */ | 10 | /* Number of page faults processed. */ |
| 10 | static long long page_fault_cnt; | 11 | static long long page_fault_cnt; |
| @@ -121,12 +122,13 @@ kill (struct intr_frame *f) | |||
| 121 | description of "Interrupt 14--Page Fault Exception (#PF)" in | 122 | description of "Interrupt 14--Page Fault Exception (#PF)" in |
| 122 | [IA32-v3a] section 5.15 "Exception and Interrupt Reference". */ | 123 | [IA32-v3a] section 5.15 "Exception and Interrupt Reference". */ |
| 123 | static void | 124 | static void |
| 124 | page_fault (struct intr_frame *f) | 125 | page_fault (struct intr_frame *f) |
| 125 | { | 126 | { |
| 126 | bool not_present; /* True: not-present page, false: writing r/o page. */ | 127 | bool not_present; /* True: not-present page, false: writing r/o page. */ |
| 127 | bool write; /* True: access was write, false: access was read. */ | 128 | bool write; /* True: access was write, false: access was read. */ |
| 128 | bool user; /* True: access by user, false: access by kernel. */ | 129 | bool user; /* True: access by user, false: access by kernel. */ |
| 129 | void *fault_addr; /* Fault address. */ | 130 | void *fault_addr; /* Fault address. */ |
| 131 | struct page_table_entry *pte; | ||
| 130 | 132 | ||
| 131 | /* Obtain faulting address, the virtual address that was | 133 | /* Obtain faulting address, the virtual address that was |
| 132 | accessed to cause the fault. It may point to code or to | 134 | accessed to cause the fault. It may point to code or to |
| @@ -153,6 +155,17 @@ page_fault (struct intr_frame *f) | |||
| 153 | body, adding code that brings in the page to | 155 | body, adding code that brings in the page to |
| 154 | which fault_addr refers. */ | 156 | which fault_addr refers. */ |
| 155 | if (is_user_vaddr(fault_addr)) { | 157 | if (is_user_vaddr(fault_addr)) { |
| 158 | pte = page_table_fetch (&thread_current ()->page_table, pg_round_down (fault_addr)); | ||
| 159 | if (pte != NULL) | ||
| 160 | page_load (pte); | ||
| 161 | else | ||
| 162 | { | ||
| 163 | printf ("Page fault %p\n", pte); | ||
| 164 | kill (f); | ||
| 165 | } | ||
| 166 | |||
| 167 | //TODO | ||
| 168 | #if 0 | ||
| 156 | if (! user) { | 169 | if (! user) { |
| 157 | /* syscall exception; set eax and eip */ | 170 | /* syscall exception; set eax and eip */ |
| 158 | f->eip = (void*)f->eax; | 171 | f->eip = (void*)f->eax; |
| @@ -162,6 +175,7 @@ page_fault (struct intr_frame *f) | |||
| 162 | /* user process access violation */ | 175 | /* user process access violation */ |
| 163 | thread_exit(); | 176 | thread_exit(); |
| 164 | } | 177 | } |
| 178 | #endif | ||
| 165 | } else { | 179 | } else { |
| 166 | printf ("Page fault at %p: %s error %s page in %s context.\n", | 180 | printf ("Page fault at %p: %s error %s page in %s context.\n", |
| 167 | fault_addr, | 181 | 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 @@ | |||
| 18 | #include "threads/synch.h" | 18 | #include "threads/synch.h" |
| 19 | #include "threads/thread.h" | 19 | #include "threads/thread.h" |
| 20 | #include "threads/vaddr.h" | 20 | #include "threads/vaddr.h" |
| 21 | #include "vm/page.h" | ||
| 21 | 22 | ||
| 22 | /* data structure to communicate with the thread initializing a new process */ | 23 | /* data structure to communicate with the thread initializing a new process */ |
| 23 | struct start_aux_data { | 24 | struct start_aux_data { |
| @@ -128,6 +129,8 @@ start_process (void *aux) | |||
| 128 | process->parent_tid = aux_data->parent_thread->tid; | 129 | process->parent_tid = aux_data->parent_thread->tid; |
| 129 | thread->process = process; | 130 | thread->process = process; |
| 130 | 131 | ||
| 132 | page_table_init (&thread->page_table); | ||
| 133 | |||
| 131 | /* Initialize interrupt frame and load executable. */ | 134 | /* Initialize interrupt frame and load executable. */ |
| 132 | memset (&if_, 0, sizeof if_); | 135 | memset (&if_, 0, sizeof if_); |
| 133 | if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; | 136 | if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; |
| @@ -251,6 +254,8 @@ process_exit (void) | |||
| 251 | pagedir_destroy (pd); | 254 | pagedir_destroy (pd); |
| 252 | } | 255 | } |
| 253 | 256 | ||
| 257 | page_table_free (&thread->page_table); | ||
| 258 | |||
| 254 | /* Destroy the process structure if the parent is not alive | 259 | /* Destroy the process structure if the parent is not alive |
| 255 | * any more. Atomic test and set would be sufficient here. | 260 | * any more. Atomic test and set would be sufficient here. |
| 256 | */ | 261 | */ |
| @@ -478,8 +483,6 @@ load (const char *args, void (**eip) (void), void **esp) | |||
| 478 | 483 | ||
| 479 | /* load() helpers. */ | 484 | /* load() helpers. */ |
| 480 | 485 | ||
| 481 | static bool install_page (void *upage, void *kpage, bool writable); | ||
| 482 | |||
| 483 | /* Checks whether PHDR describes a valid, loadable segment in | 486 | /* Checks whether PHDR describes a valid, loadable segment in |
| 484 | FILE and returns true if so, false otherwise. */ | 487 | FILE and returns true if so, false otherwise. */ |
| 485 | static bool | 488 | static bool |
| @@ -556,29 +559,15 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, | |||
| 556 | size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; | 559 | size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; |
| 557 | size_t page_zero_bytes = PGSIZE - page_read_bytes; | 560 | size_t page_zero_bytes = PGSIZE - page_read_bytes; |
| 558 | 561 | ||
| 559 | /* Get a page of memory. */ | 562 | /* add segment to page table for on demand loading */ |
| 560 | uint8_t *kpage = palloc_get_page (PAL_USER); | 563 | if (!page_table_insert_segment (file, ofs, upage, page_read_bytes, |
| 561 | if (kpage == NULL) | 564 | page_zero_bytes, writable)) |
| 562 | return false; | ||
| 563 | |||
| 564 | /* Load this page. */ | ||
| 565 | if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) | ||
| 566 | { | ||
| 567 | palloc_free_page (kpage); | ||
| 568 | return false; | 565 | return false; |
| 569 | } | ||
| 570 | memset (kpage + page_read_bytes, 0, page_zero_bytes); | ||
| 571 | |||
| 572 | /* Add the page to the process's address space. */ | ||
| 573 | if (!install_page (upage, kpage, writable)) | ||
| 574 | { | ||
| 575 | palloc_free_page (kpage); | ||
| 576 | return false; | ||
| 577 | } | ||
| 578 | 566 | ||
| 579 | /* Advance. */ | 567 | /* Advance. */ |
| 580 | read_bytes -= page_read_bytes; | 568 | read_bytes -= page_read_bytes; |
| 581 | zero_bytes -= page_zero_bytes; | 569 | zero_bytes -= page_zero_bytes; |
| 570 | ofs += page_read_bytes; | ||
| 582 | upage += PGSIZE; | 571 | upage += PGSIZE; |
| 583 | } | 572 | } |
| 584 | return true; | 573 | return true; |
| @@ -602,7 +591,7 @@ setup_stack (uint32_t **esp, const char *args) | |||
| 602 | if (kpage == NULL) | 591 | if (kpage == NULL) |
| 603 | return false; | 592 | return false; |
| 604 | 593 | ||
| 605 | if (! install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true)) { | 594 | if (! process_install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true)) { |
| 606 | palloc_free_page (kpage); | 595 | palloc_free_page (kpage); |
| 607 | return false; | 596 | return false; |
| 608 | } | 597 | } |
| @@ -706,8 +695,8 @@ setup_stack (uint32_t **esp, const char *args) | |||
| 706 | with palloc_get_page(). | 695 | with palloc_get_page(). |
| 707 | Returns true on success, false if UPAGE is already mapped or | 696 | Returns true on success, false if UPAGE is already mapped or |
| 708 | if memory allocation fails. */ | 697 | if memory allocation fails. */ |
| 709 | static bool | 698 | bool |
| 710 | install_page (void *upage, void *kpage, bool writable) | 699 | process_install_page (void *upage, void *kpage, bool writable) |
| 711 | { | 700 | { |
| 712 | struct thread *t = thread_current (); | 701 | struct thread *t = thread_current (); |
| 713 | 702 | ||
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); | |||
| 37 | int process_wait (tid_t); | 37 | int process_wait (tid_t); |
| 38 | void process_exit (void); | 38 | void process_exit (void); |
| 39 | void process_activate (void); | 39 | void process_activate (void); |
| 40 | bool process_install_page (void *upage, void *kpage, bool writable); | ||
| 40 | 41 | ||
| 41 | int process_open_file(const char* fname); | 42 | int process_open_file(const char* fname); |
| 42 | struct file* process_get_file(int fd); | 43 | struct file* process_get_file(int fd); |
