Rev 2927 | Rev 3588 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2927 | Rev 3197 | ||
|---|---|---|---|
| Line 45... | Line 45... | ||
| 45 | * |
45 | * |
| 46 | * Try to find PTE for faulting address. |
46 | * Try to find PTE for faulting address. |
| 47 | * The as->lock must be held on entry to this function |
47 | * The as->lock must be held on entry to this function |
| 48 | * if lock is true. |
48 | * if lock is true. |
| 49 | * |
49 | * |
| 50 | * @param as Address space. |
50 | * @param as Address space. |
| 51 | * @param lock Lock/unlock the address space. |
51 | * @param lock Lock/unlock the address space. |
| 52 | * @param badvaddr Faulting virtual address. |
52 | * @param badvaddr Faulting virtual address. |
| 53 | * @param access Access mode that caused the fault. |
53 | * @param access Access mode that caused the fault. |
| 54 | * @param istate Pointer to interrupted state. |
54 | * @param istate Pointer to interrupted state. |
| 55 | * @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
55 | * @param pfrc Pointer to variable where as_page_fault() return code |
| - | 56 | * will be stored. |
|
| 56 | * @return PTE on success, NULL otherwise. |
57 | * @return PTE on success, NULL otherwise. |
| 57 | * |
58 | * |
| 58 | */ |
59 | */ |
| - | 60 | static pte_t * |
|
| 59 | static pte_t *find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) |
61 | find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, |
| - | 62 | istate_t *istate, int *pfrc) |
|
| 60 | { |
63 | { |
| 61 | /* |
64 | /* |
| 62 | * Check if the mapping exists in page tables. |
65 | * Check if the mapping exists in page tables. |
| 63 | */ |
66 | */ |
| 64 | pte_t *pte = page_mapping_find(as, badvaddr); |
67 | pte_t *pte = page_mapping_find(as, badvaddr); |
| Line 75... | Line 78... | ||
| 75 | * Mapping not found in page tables. |
78 | * Mapping not found in page tables. |
| 76 | * Resort to higher-level page fault handler. |
79 | * Resort to higher-level page fault handler. |
| 77 | */ |
80 | */ |
| 78 | page_table_unlock(as, lock); |
81 | page_table_unlock(as, lock); |
| 79 | switch (rc = as_page_fault(badvaddr, access, istate)) { |
82 | switch (rc = as_page_fault(badvaddr, access, istate)) { |
| 80 | case AS_PF_OK: |
83 | case AS_PF_OK: |
| 81 | /* |
84 | /* |
| 82 | * The higher-level page fault handler succeeded, |
85 | * The higher-level page fault handler succeeded, |
| 83 | * The mapping ought to be in place. |
86 | * The mapping ought to be in place. |
| 84 | */ |
87 | */ |
| 85 | page_table_lock(as, lock); |
88 | page_table_lock(as, lock); |
| 86 | pte = page_mapping_find(as, badvaddr); |
89 | pte = page_mapping_find(as, badvaddr); |
| 87 | ASSERT((pte) && (pte->p)); |
90 | ASSERT((pte) && (pte->p)); |
| 88 | *pfrc = 0; |
91 | *pfrc = 0; |
| 89 | return pte; |
92 | return pte; |
| 90 | case AS_PF_DEFER: |
93 | case AS_PF_DEFER: |
| 91 | page_table_lock(as, lock); |
94 | page_table_lock(as, lock); |
| 92 | *pfrc = rc; |
95 | *pfrc = rc; |
| 93 | return NULL; |
96 | return NULL; |
| 94 | case AS_PF_FAULT: |
97 | case AS_PF_FAULT: |
| 95 | page_table_lock(as, lock); |
98 | page_table_lock(as, lock); |
| 96 | printf("Page fault.\n"); |
99 | printf("Page fault.\n"); |
| 97 | *pfrc = rc; |
100 | *pfrc = rc; |
| 98 | return NULL; |
101 | return NULL; |
| 99 | default: |
102 | default: |
| 100 | panic("unexpected rc (%d)\n", rc); |
103 | panic("unexpected rc (%d)\n", rc); |
| 101 | } |
104 | } |
| 102 | } |
105 | } |
| 103 | } |
106 | } |
| 104 | 107 | ||
| 105 | 108 | ||
| Line 112... | Line 115... | ||
| 112 | if (s) |
115 | if (s) |
| 113 | symbol = s; |
116 | symbol = s; |
| 114 | s = get_symtab_entry(istate->lr); |
117 | s = get_symtab_entry(istate->lr); |
| 115 | if (s) |
118 | if (s) |
| 116 | sym2 = s; |
119 | sym2 = s; |
| 117 | panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); |
120 | panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, |
| - | 121 | istate->pc, symbol, sym2); |
|
| 118 | } |
122 | } |
| 119 | 123 | ||
| 120 | 124 | ||
| 121 | static void pht_insert(const uintptr_t vaddr, const pfn_t pfn) |
125 | static void pht_insert(const uintptr_t vaddr, const pfn_t pfn) |
| 122 | { |
126 | { |
| Line 145... | Line 149... | ||
| 145 | bool found = false; |
149 | bool found = false; |
| 146 | 150 | ||
| 147 | /* Find unused or colliding |
151 | /* Find unused or colliding |
| 148 | PTE in PTEG */ |
152 | PTE in PTEG */ |
| 149 | for (i = 0; i < 8; i++) { |
153 | for (i = 0; i < 8; i++) { |
| 150 | if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) { |
154 | if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && |
| - | 155 | (phte[base + i].api == api))) { |
|
| 151 | found = true; |
156 | found = true; |
| 152 | break; |
157 | break; |
| 153 | } |
158 | } |
| 154 | } |
159 | } |
| 155 | 160 | ||
| Line 158... | Line 163... | ||
| 158 | uint32_t base2 = (~hash & 0x3ff) << 3; |
163 | uint32_t base2 = (~hash & 0x3ff) << 3; |
| 159 | 164 | ||
| 160 | /* Find unused or colliding |
165 | /* Find unused or colliding |
| 161 | PTE in PTEG */ |
166 | PTE in PTEG */ |
| 162 | for (i = 0; i < 8; i++) { |
167 | for (i = 0; i < 8; i++) { |
| - | 168 | if ((!phte[base2 + i].v) || |
|
| 163 | if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) { |
169 | ((phte[base2 + i].vsid == vsid) && |
| - | 170 | (phte[base2 + i].api == api))) { |
|
| 164 | found = true; |
171 | found = true; |
| 165 | base = base2; |
172 | base = base2; |
| 166 | h = 1; |
173 | h = 1; |
| 167 | break; |
174 | break; |
| 168 | } |
175 | } |
| Line 212... | Line 219... | ||
| 212 | bool found = false; |
219 | bool found = false; |
| 213 | 220 | ||
| 214 | /* Find unused or colliding |
221 | /* Find unused or colliding |
| 215 | PTE in PTEG */ |
222 | PTE in PTEG */ |
| 216 | for (i = 0; i < 8; i++) { |
223 | for (i = 0; i < 8; i++) { |
| - | 224 | if ((!phte_physical[base + i].v) || |
|
| 217 | if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) { |
225 | ((phte_physical[base + i].vsid == vsid) && |
| - | 226 | (phte_physical[base + i].api == api))) { |
|
| 218 | found = true; |
227 | found = true; |
| 219 | break; |
228 | break; |
| 220 | } |
229 | } |
| 221 | } |
230 | } |
| 222 | 231 | ||
| Line 225... | Line 234... | ||
| 225 | uint32_t base2 = (~hash & 0x3ff) << 3; |
234 | uint32_t base2 = (~hash & 0x3ff) << 3; |
| 226 | 235 | ||
| 227 | /* Find unused or colliding |
236 | /* Find unused or colliding |
| 228 | PTE in PTEG */ |
237 | PTE in PTEG */ |
| 229 | for (i = 0; i < 8; i++) { |
238 | for (i = 0; i < 8; i++) { |
| - | 239 | if ((!phte_physical[base2 + i].v) || |
|
| 230 | if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) { |
240 | ((phte_physical[base2 + i].vsid == vsid) && |
| - | 241 | (phte_physical[base2 + i].api == api))) { |
|
| 231 | found = true; |
242 | found = true; |
| 232 | base = base2; |
243 | base = base2; |
| 233 | h = 1; |
244 | h = 1; |
| 234 | break; |
245 | break; |
| 235 | } |
246 | } |
| Line 252... | Line 263... | ||
| 252 | } |
263 | } |
| 253 | 264 | ||
| 254 | 265 | ||
| 255 | /** Process Instruction/Data Storage Interrupt |
266 | /** Process Instruction/Data Storage Interrupt |
| 256 | * |
267 | * |
| 257 | * @param n Interrupt vector number. |
268 | * @param n Interrupt vector number. |
| 258 | * @param istate Interrupted register context. |
269 | * @param istate Interrupted register context. |
| 259 | * |
270 | * |
| 260 | */ |
271 | */ |
| 261 | void pht_refill(int n, istate_t *istate) |
272 | void pht_refill(int n, istate_t *istate) |
| 262 | { |
273 | { |
| 263 | uintptr_t badvaddr; |
274 | uintptr_t badvaddr; |
| Line 282... | Line 293... | ||
| 282 | } else |
293 | } else |
| 283 | badvaddr = istate->pc; |
294 | badvaddr = istate->pc; |
| 284 | 295 | ||
| 285 | page_table_lock(as, lock); |
296 | page_table_lock(as, lock); |
| 286 | 297 | ||
| 287 | pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
298 | pte = find_mapping_and_check(as, lock, badvaddr, |
| - | 299 | PF_ACCESS_READ /* FIXME */, istate, &pfrc); |
|
| 288 | if (!pte) { |
300 | if (!pte) { |
| 289 | switch (pfrc) { |
301 | switch (pfrc) { |
| 290 | case AS_PF_FAULT: |
302 | case AS_PF_FAULT: |
| 291 | goto fail; |
303 | goto fail; |
| 292 | break; |
304 | break; |
| 293 | case AS_PF_DEFER: |
305 | case AS_PF_DEFER: |
| 294 | /* |
306 | /* |
| 295 | * The page fault came during copy_from_uspace() |
307 | * The page fault came during copy_from_uspace() |
| 296 | * or copy_to_uspace(). |
308 | * or copy_to_uspace(). |
| 297 | */ |
309 | */ |
| 298 | page_table_unlock(as, lock); |
310 | page_table_unlock(as, lock); |
| 299 | return; |
311 | return; |
| 300 | default: |
312 | default: |
| 301 | panic("Unexpected pfrc (%d)\n", pfrc); |
313 | panic("Unexpected pfrc (%d)\n", pfrc); |
| 302 | } |
314 | } |
| 303 | } |
315 | } |
| 304 | 316 | ||
| 305 | pte->a = 1; /* Record access to PTE */ |
317 | pte->a = 1; /* Record access to PTE */ |
| 306 | pht_insert(badvaddr, pte->pfn); |
318 | pht_insert(badvaddr, pte->pfn); |
| Line 314... | Line 326... | ||
| 314 | } |
326 | } |
| 315 | 327 | ||
| 316 | 328 | ||
| 317 | /** Process Instruction/Data Storage Interrupt in Real Mode |
329 | /** Process Instruction/Data Storage Interrupt in Real Mode |
| 318 | * |
330 | * |
| 319 | * @param n Interrupt vector number. |
331 | * @param n Interrupt vector number. |
| 320 | * @param istate Interrupted register context. |
332 | * @param istate Interrupted register context. |
| 321 | * |
333 | * |
| 322 | */ |
334 | */ |
| 323 | bool pht_real_refill(int n, istate_t *istate) |
335 | bool pht_real_refill(int n, istate_t *istate) |
| 324 | { |
336 | { |
| 325 | uintptr_t badvaddr; |
337 | uintptr_t badvaddr; |
| Line 371... | Line 383... | ||
| 371 | ); |
383 | ); |
| 372 | phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000); |
384 | phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000); |
| 373 | 385 | ||
| 374 | uint32_t i; |
386 | uint32_t i; |
| 375 | for (i = 0; i < 8192; i++) { |
387 | for (i = 0; i < 8192; i++) { |
| 376 | if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && (phte[i].vsid < ((asid << 4) + 16))) |
388 | if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && |
| - | 389 | (phte[i].vsid < ((asid << 4) + 16))) |
|
| 377 | phte[i].v = 0; |
390 | phte[i].v = 0; |
| 378 | } |
391 | } |
| 379 | tlb_invalidate_all(); |
392 | tlb_invalidate_all(); |
| 380 | } |
393 | } |
| 381 | 394 | ||
| Line 405... | Line 418... | ||
| 405 | length <<= 1; \ |
418 | length <<= 1; \ |
| 406 | tmp >>= 1; \ |
419 | tmp >>= 1; \ |
| 407 | } \ |
420 | } \ |
| 408 | } else \ |
421 | } else \ |
| 409 | length = 0; \ |
422 | length = 0; \ |
| 410 | printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, lower & 0xffff0000, length, mask, ((upper >> 1) & 1) ? " supervisor" : "", (upper & 1) ? " user" : ""); |
423 | printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \ |
| - | 424 | sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \ |
|
| - | 425 | lower & 0xffff0000, length, mask, \ |
|
| - | 426 | ((upper >> 1) & 1) ? " supervisor" : "", \ |
|
| - | 427 | (upper & 1) ? " user" : ""); |
|
| 411 | 428 | ||
| 412 | 429 | ||
| 413 | void tlb_print(void) |
430 | void tlb_print(void) |
| 414 | { |
431 | { |
| 415 | uint32_t sr; |
432 | uint32_t sr; |
| Line 419... | Line 436... | ||
| 419 | asm volatile ( |
436 | asm volatile ( |
| 420 | "mfsrin %0, %1\n" |
437 | "mfsrin %0, %1\n" |
| 421 | : "=r" (vsid) |
438 | : "=r" (vsid) |
| 422 | : "r" (sr << 28) |
439 | : "r" (sr << 28) |
| 423 | ); |
440 | ); |
| - | 441 | printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, |
|
| 424 | printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, ((vsid >> 30) & 1) ? " supervisor" : "", ((vsid >> 29) & 1) ? " user" : ""); |
442 | sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, |
| - | 443 | ((vsid >> 30) & 1) ? " supervisor" : "", |
|
| - | 444 | ((vsid >> 29) & 1) ? " user" : ""); |
|
| 425 | } |
445 | } |
| 426 | 446 | ||
| 427 | uint32_t upper; |
447 | uint32_t upper; |
| 428 | uint32_t lower; |
448 | uint32_t lower; |
| 429 | uint32_t mask; |
449 | uint32_t mask; |