Rev 687 | Rev 704 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 687 | Rev 703 | ||
---|---|---|---|
Line 28... | Line 28... | ||
28 | 28 | ||
29 | #include <arch/mm/tlb.h> |
29 | #include <arch/mm/tlb.h> |
30 | #include <arch/mm/asid.h> |
30 | #include <arch/mm/asid.h> |
31 | #include <mm/tlb.h> |
31 | #include <mm/tlb.h> |
32 | #include <mm/page.h> |
32 | #include <mm/page.h> |
33 | #include <mm/vm.h> |
33 | #include <mm/as.h> |
34 | #include <arch/cp0.h> |
34 | #include <arch/cp0.h> |
35 | #include <panic.h> |
35 | #include <panic.h> |
36 | #include <arch.h> |
36 | #include <arch.h> |
37 | #include <symtab.h> |
37 | #include <symtab.h> |
38 | #include <synch/spinlock.h> |
38 | #include <synch/spinlock.h> |
Line 90... | Line 90... | ||
90 | __address badvaddr; |
90 | __address badvaddr; |
91 | pte_t *pte; |
91 | pte_t *pte; |
92 | 92 | ||
93 | badvaddr = cp0_badvaddr_read(); |
93 | badvaddr = cp0_badvaddr_read(); |
94 | 94 | ||
95 | spinlock_lock(&VM->lock); |
95 | spinlock_lock(&AS->lock); |
96 | 96 | ||
97 | pte = find_mapping_and_check(badvaddr); |
97 | pte = find_mapping_and_check(badvaddr); |
98 | if (!pte) |
98 | if (!pte) |
99 | goto fail; |
99 | goto fail; |
100 | 100 | ||
101 | /* |
101 | /* |
102 | * Record access to PTE. |
102 | * Record access to PTE. |
103 | */ |
103 | */ |
104 | pte->a = 1; |
104 | pte->a = 1; |
105 | 105 | ||
106 | prepare_entry_hi(&hi, VM->asid, badvaddr); |
106 | prepare_entry_hi(&hi, AS->asid, badvaddr); |
107 | prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->lo.d, pte->lo.c, pte->lo.pfn); |
107 | prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->lo.d, pte->lo.c, pte->lo.pfn); |
108 | 108 | ||
109 | /* |
109 | /* |
110 | * New entry is to be inserted into TLB |
110 | * New entry is to be inserted into TLB |
111 | */ |
111 | */ |
Line 119... | Line 119... | ||
119 | cp0_entry_lo1_write(lo.value); |
119 | cp0_entry_lo1_write(lo.value); |
120 | } |
120 | } |
121 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
121 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
122 | tlbwr(); |
122 | tlbwr(); |
123 | 123 | ||
124 | spinlock_unlock(&VM->lock); |
124 | spinlock_unlock(&AS->lock); |
125 | return; |
125 | return; |
126 | 126 | ||
127 | fail: |
127 | fail: |
128 | spinlock_unlock(&VM->lock); |
128 | spinlock_unlock(&AS->lock); |
129 | tlb_refill_fail(pstate); |
129 | tlb_refill_fail(pstate); |
130 | } |
130 | } |
131 | 131 | ||
132 | /** Process TLB Invalid Exception |
132 | /** Process TLB Invalid Exception |
133 | * |
133 | * |
Line 152... | Line 152... | ||
152 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
152 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
153 | cp0_entry_hi_write(hi.value); |
153 | cp0_entry_hi_write(hi.value); |
154 | tlbp(); |
154 | tlbp(); |
155 | index.value = cp0_index_read(); |
155 | index.value = cp0_index_read(); |
156 | 156 | ||
157 | spinlock_lock(&VM->lock); |
157 | spinlock_lock(&AS->lock); |
158 | 158 | ||
159 | /* |
159 | /* |
160 | * Fail if the entry is not in TLB. |
160 | * Fail if the entry is not in TLB. |
161 | */ |
161 | */ |
162 | if (index.p) { |
162 | if (index.p) { |
Line 188... | Line 188... | ||
188 | else |
188 | else |
189 | cp0_entry_lo1_write(lo.value); |
189 | cp0_entry_lo1_write(lo.value); |
190 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
190 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
191 | tlbwi(); |
191 | tlbwi(); |
192 | 192 | ||
193 | spinlock_unlock(&VM->lock); |
193 | spinlock_unlock(&AS->lock); |
194 | return; |
194 | return; |
195 | 195 | ||
196 | fail: |
196 | fail: |
197 | spinlock_unlock(&VM->lock); |
197 | spinlock_unlock(&AS->lock); |
198 | tlb_invalid_fail(pstate); |
198 | tlb_invalid_fail(pstate); |
199 | } |
199 | } |
200 | 200 | ||
201 | /** Process TLB Modified Exception |
201 | /** Process TLB Modified Exception |
202 | * |
202 | * |
Line 221... | Line 221... | ||
221 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
221 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
222 | cp0_entry_hi_write(hi.value); |
222 | cp0_entry_hi_write(hi.value); |
223 | tlbp(); |
223 | tlbp(); |
224 | index.value = cp0_index_read(); |
224 | index.value = cp0_index_read(); |
225 | 225 | ||
226 | spinlock_lock(&VM->lock); |
226 | spinlock_lock(&AS->lock); |
227 | 227 | ||
228 | /* |
228 | /* |
229 | * Fail if the entry is not in TLB. |
229 | * Fail if the entry is not in TLB. |
230 | */ |
230 | */ |
231 | if (index.p) { |
231 | if (index.p) { |
Line 264... | Line 264... | ||
264 | else |
264 | else |
265 | cp0_entry_lo1_write(lo.value); |
265 | cp0_entry_lo1_write(lo.value); |
266 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
266 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
267 | tlbwi(); |
267 | tlbwi(); |
268 | 268 | ||
269 | spinlock_unlock(&VM->lock); |
269 | spinlock_unlock(&AS->lock); |
270 | return; |
270 | return; |
271 | 271 | ||
272 | fail: |
272 | fail: |
273 | spinlock_unlock(&VM->lock); |
273 | spinlock_unlock(&AS->lock); |
274 | tlb_modified_fail(pstate); |
274 | tlb_modified_fail(pstate); |
275 | } |
275 | } |
276 | 276 | ||
277 | void tlb_refill_fail(struct exception_regdump *pstate) |
277 | void tlb_refill_fail(struct exception_regdump *pstate) |
278 | { |
278 | { |
Line 310... | Line 310... | ||
310 | } |
310 | } |
311 | 311 | ||
312 | /** Try to find PTE for faulting address |
312 | /** Try to find PTE for faulting address |
313 | * |
313 | * |
314 | * Try to find PTE for faulting address. |
314 | * Try to find PTE for faulting address. |
315 | * The VM->lock must be held on entry to this function. |
315 | * The AS->lock must be held on entry to this function. |
316 | * |
316 | * |
317 | * @param badvaddr Faulting virtual address. |
317 | * @param badvaddr Faulting virtual address. |
318 | * |
318 | * |
319 | * @return PTE on success, NULL otherwise. |
319 | * @return PTE on success, NULL otherwise. |
320 | */ |
320 | */ |
Line 326... | Line 326... | ||
326 | hi.value = cp0_entry_hi_read(); |
326 | hi.value = cp0_entry_hi_read(); |
327 | 327 | ||
328 | /* |
328 | /* |
329 | * Handler cannot succeed if the ASIDs don't match. |
329 | * Handler cannot succeed if the ASIDs don't match. |
330 | */ |
330 | */ |
331 | if (hi.asid != VM->asid) { |
331 | if (hi.asid != AS->asid) { |
332 | printf("EntryHi.asid=%d, VM->asid=%d\n", hi.asid, VM->asid); |
332 | printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid); |
333 | return NULL; |
333 | return NULL; |
334 | } |
334 | } |
- | 335 | ||
- | 336 | /* |
|
- | 337 | * Check if the mapping exists in page tables. |
|
- | 338 | */ |
|
- | 339 | pte = page_mapping_find(badvaddr, AS->asid, 0); |
|
- | 340 | if (pte && pte->lo.v) { |
|
- | 341 | /* |
|
- | 342 | * Mapping found in page tables. |
|
- | 343 | * Immediately succeed. |
|
- | 344 | */ |
|
- | 345 | return pte; |
|
- | 346 | } else { |
|
- | 347 | /* |
|
- | 348 | * Mapping not found in page tables. |
|
- | 349 | * Resort to higher-level page fault handler. |
|
- | 350 | */ |
|
- | 351 | if (as_page_fault(badvaddr)) { |
|
- | 352 | /* |
|
- | 353 | * The higher-level page fault handler succeeded, |
|
- | 354 | * The mapping ought to be in place. |
|
- | 355 | */ |
|
- | 356 | pte = page_mapping_find(badvaddr, AS->asid, 0); |
|
- | 357 | ASSERT(pte && pte->lo.v); |
|
- | 358 | return pte; |
|
- | 359 | } |
|
335 | 360 | } |
|
- | 361 | ||
336 | /* |
362 | /* |
337 | * Handler cannot succeed if badvaddr has no mapping. |
363 | * Handler cannot succeed if badvaddr has no mapping. |
338 | */ |
364 | */ |
339 | pte = page_mapping_find(badvaddr, VM->asid, 0); |
- | |
340 | if (!pte) { |
365 | if (!pte) { |
341 | printf("No such mapping.\n"); |
366 | printf("No such mapping.\n"); |
342 | return NULL; |
367 | return NULL; |
343 | } |
368 | } |
344 | 369 |