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; |