diff options
Diffstat (limited to 'userprog/exception.c')
| -rw-r--r-- | userprog/exception.c | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/userprog/exception.c b/userprog/exception.c index 54621fa..debe7f0 100644 --- a/userprog/exception.c +++ b/userprog/exception.c | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | #include <inttypes.h> | 2 | #include <inttypes.h> |
| 3 | #include <stdio.h> | 3 | #include <stdio.h> |
| 4 | #include "userprog/gdt.h" | 4 | #include "userprog/gdt.h" |
| 5 | #include "userprog/process.h" | ||
| 6 | #include "userprog/syscall.h" | ||
| 5 | #include "threads/interrupt.h" | 7 | #include "threads/interrupt.h" |
| 6 | #include "threads/thread.h" | 8 | #include "threads/thread.h" |
| 7 | #include "threads/vaddr.h" | 9 | #include "threads/vaddr.h" |
| @@ -128,7 +130,8 @@ page_fault (struct intr_frame *f) | |||
| 128 | bool write; /* True: access was write, false: access was read. */ | 130 | bool write; /* True: access was write, false: access was read. */ |
| 129 | bool user; /* True: access by user, false: access by kernel. */ | 131 | bool user; /* True: access by user, false: access by kernel. */ |
| 130 | void *fault_addr; /* Fault address. */ | 132 | void *fault_addr; /* Fault address. */ |
| 131 | struct page_table_entry *pte; | 133 | void *sp; /* Stack pointer. */ |
| 134 | struct page_table_entry *pte; /* Page table entry. */ | ||
| 132 | 135 | ||
| 133 | /* Obtain faulting address, the virtual address that was | 136 | /* Obtain faulting address, the virtual address that was |
| 134 | accessed to cause the fault. It may point to code or to | 137 | accessed to cause the fault. It may point to code or to |
| @@ -151,38 +154,57 @@ page_fault (struct intr_frame *f) | |||
| 151 | write = (f->error_code & PF_W) != 0; | 154 | write = (f->error_code & PF_W) != 0; |
| 152 | user = (f->error_code & PF_U) != 0; | 155 | user = (f->error_code & PF_U) != 0; |
| 153 | 156 | ||
| 154 | /* To implement virtual memory, adapt the rest of the function | 157 | /* accessing r/o page is always wrong */ |
| 155 | body, adding code that brings in the page to | 158 | if (!not_present) |
| 156 | which fault_addr refers. */ | 159 | thread_exit (); |
| 157 | if (is_user_vaddr(fault_addr)) { | 160 | |
| 158 | pte = page_table_fetch (&thread_current ()->page_table, pg_round_down (fault_addr)); | 161 | if (is_user_vaddr (fault_addr)) |
| 159 | if (pte != NULL) | ||
| 160 | page_load (pte); | ||
| 161 | else | ||
| 162 | { | 162 | { |
| 163 | printf ("Page fault %p\n", pte); | 163 | /* if page fault occurs during syscall, use saved stack pointer */ |
| 164 | kill (f); | 164 | sp = (!user) ? syscall_sp : f->esp; |
| 165 | } | 165 | |
| 166 | /* try to fetch page entry */ | ||
| 167 | pte = page_table_fetch (&thread_current ()->page_table, | ||
| 168 | pg_round_down (fault_addr)); | ||
| 169 | |||
| 170 | /* we got a page entry so try to load the page */ | ||
| 171 | if (pte != NULL) | ||
| 172 | { | ||
| 173 | if (page_load (pte)) | ||
| 174 | return; | ||
| 175 | printf ("Unable to load page at %p in %s context.\n", | ||
| 176 | fault_addr, user ? "user" : "kernel"); | ||
| 177 | } | ||
| 178 | /* there's no page in our page table but we might still have an valid | ||
| 179 | stack access and need to expand our stack. so just check for that. | ||
| 180 | the maxium offset we consider as a valid access is caused by the PUSHA | ||
| 181 | instruction. it's 32 bytes below the current stack pointer */ | ||
| 182 | else if (fault_addr >= (sp - 32) && (PHYS_BASE - fault_addr) <= STACK_SIZE) | ||
| 183 | { | ||
| 184 | if (process_grow_stack (pg_round_down (fault_addr))) | ||
| 185 | return; | ||
| 186 | printf ("Unable to grow stack %p in %s context.\n", | ||
| 187 | fault_addr, user ? "user" : "kernel"); | ||
| 188 | } | ||
| 166 | 189 | ||
| 167 | //TODO | ||
| 168 | #if 0 | ||
| 169 | if (! user) { | ||
| 170 | /* syscall exception; set eax and eip */ | 190 | /* syscall exception; set eax and eip */ |
| 171 | f->eip = (void*)f->eax; | 191 | if (!user) |
| 172 | f->eax = 0xFFFFFFFF; | 192 | { |
| 173 | return; | 193 | f->eip = (void*)f->eax; |
| 174 | } else { | 194 | f->eax = 0xFFFFFFFF; |
| 195 | return; | ||
| 196 | } | ||
| 197 | |||
| 175 | /* user process access violation */ | 198 | /* user process access violation */ |
| 176 | thread_exit(); | 199 | thread_exit (); |
| 200 | return; | ||
| 177 | } | 201 | } |
| 178 | #endif | 202 | |
| 179 | } else { | 203 | 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", | 204 | fault_addr, |
| 181 | fault_addr, | 205 | not_present ? "not present" : "rights violation", |
| 182 | not_present ? "not present" : "rights violation", | 206 | write ? "writing" : "reading", |
| 183 | write ? "writing" : "reading", | 207 | user ? "user" : "kernel"); |
| 184 | user ? "user" : "kernel"); | 208 | kill (f); |
| 185 | kill (f); | ||
| 186 | } | ||
| 187 | } | 209 | } |
| 188 | 210 | ||
