Rev 983 | Rev 1288 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 983 | Rev 1044 | ||
---|---|---|---|
Line 85... | Line 85... | ||
85 | * @param istate Interrupted register context. |
85 | * @param istate Interrupted register context. |
86 | */ |
86 | */ |
87 | void tlb_refill(istate_t *istate) |
87 | void tlb_refill(istate_t *istate) |
88 | { |
88 | { |
89 | entry_lo_t lo; |
89 | entry_lo_t lo; |
90 | entry_hi_t hi; |
90 | entry_hi_t hi; |
- | 91 | asid_t asid; |
|
91 | __address badvaddr; |
92 | __address badvaddr; |
92 | pte_t *pte; |
93 | pte_t *pte; |
93 | 94 | ||
94 | badvaddr = cp0_badvaddr_read(); |
95 | badvaddr = cp0_badvaddr_read(); |
95 | 96 | ||
96 | spinlock_lock(&AS->lock); |
97 | spinlock_lock(&AS->lock); |
- | 98 | asid = AS->asid; |
|
- | 99 | spinlock_unlock(&AS->lock); |
|
- | 100 | ||
- | 101 | page_table_lock(AS, true); |
|
97 | 102 | ||
98 | pte = find_mapping_and_check(badvaddr); |
103 | pte = find_mapping_and_check(badvaddr); |
99 | if (!pte) |
104 | if (!pte) |
100 | goto fail; |
105 | goto fail; |
101 | 106 | ||
102 | /* |
107 | /* |
103 | * Record access to PTE. |
108 | * Record access to PTE. |
104 | */ |
109 | */ |
105 | pte->a = 1; |
110 | pte->a = 1; |
106 | 111 | ||
107 | prepare_entry_hi(&hi, AS->asid, badvaddr); |
112 | prepare_entry_hi(&hi, asid, badvaddr); |
108 | prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
113 | prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
109 | 114 | ||
110 | /* |
115 | /* |
111 | * New entry is to be inserted into TLB |
116 | * New entry is to be inserted into TLB |
112 | */ |
117 | */ |
Line 120... | Line 125... | ||
120 | cp0_entry_lo1_write(lo.value); |
125 | cp0_entry_lo1_write(lo.value); |
121 | } |
126 | } |
122 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
127 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
123 | tlbwr(); |
128 | tlbwr(); |
124 | 129 | ||
125 | spinlock_unlock(&AS->lock); |
130 | page_table_unlock(AS, true); |
126 | return; |
131 | return; |
127 | 132 | ||
128 | fail: |
133 | fail: |
129 | spinlock_unlock(&AS->lock); |
134 | page_table_unlock(AS, true); |
130 | tlb_refill_fail(istate); |
135 | tlb_refill_fail(istate); |
131 | } |
136 | } |
132 | 137 | ||
133 | /** Process TLB Invalid Exception |
138 | /** Process TLB Invalid Exception |
134 | * |
139 | * |
Line 152... | Line 157... | ||
152 | hi.value = cp0_entry_hi_read(); |
157 | hi.value = cp0_entry_hi_read(); |
153 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
158 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
154 | cp0_entry_hi_write(hi.value); |
159 | cp0_entry_hi_write(hi.value); |
155 | tlbp(); |
160 | tlbp(); |
156 | index.value = cp0_index_read(); |
161 | index.value = cp0_index_read(); |
157 | 162 | ||
158 | spinlock_lock(&AS->lock); |
163 | page_table_lock(AS, true); |
159 | 164 | ||
160 | /* |
165 | /* |
161 | * Fail if the entry is not in TLB. |
166 | * Fail if the entry is not in TLB. |
162 | */ |
167 | */ |
163 | if (index.p) { |
168 | if (index.p) { |
Line 189... | Line 194... | ||
189 | else |
194 | else |
190 | cp0_entry_lo1_write(lo.value); |
195 | cp0_entry_lo1_write(lo.value); |
191 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
196 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
192 | tlbwi(); |
197 | tlbwi(); |
193 | 198 | ||
194 | spinlock_unlock(&AS->lock); |
199 | page_table_unlock(AS, true); |
195 | return; |
200 | return; |
196 | 201 | ||
197 | fail: |
202 | fail: |
198 | spinlock_unlock(&AS->lock); |
203 | page_table_unlock(AS, true); |
199 | tlb_invalid_fail(istate); |
204 | tlb_invalid_fail(istate); |
200 | } |
205 | } |
201 | 206 | ||
202 | /** Process TLB Modified Exception |
207 | /** Process TLB Modified Exception |
203 | * |
208 | * |
Line 221... | Line 226... | ||
221 | hi.value = cp0_entry_hi_read(); |
226 | hi.value = cp0_entry_hi_read(); |
222 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
227 | prepare_entry_hi(&hi, hi.asid, badvaddr); |
223 | cp0_entry_hi_write(hi.value); |
228 | cp0_entry_hi_write(hi.value); |
224 | tlbp(); |
229 | tlbp(); |
225 | index.value = cp0_index_read(); |
230 | index.value = cp0_index_read(); |
226 | 231 | ||
227 | spinlock_lock(&AS->lock); |
232 | page_table_lock(AS, true); |
228 | 233 | ||
229 | /* |
234 | /* |
230 | * Fail if the entry is not in TLB. |
235 | * Fail if the entry is not in TLB. |
231 | */ |
236 | */ |
232 | if (index.p) { |
237 | if (index.p) { |
Line 265... | Line 270... | ||
265 | else |
270 | else |
266 | cp0_entry_lo1_write(lo.value); |
271 | cp0_entry_lo1_write(lo.value); |
267 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
272 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
268 | tlbwi(); |
273 | tlbwi(); |
269 | 274 | ||
270 | spinlock_unlock(&AS->lock); |
275 | page_table_unlock(AS, true); |
271 | return; |
276 | return; |
272 | 277 | ||
273 | fail: |
278 | fail: |
274 | spinlock_unlock(&AS->lock); |
279 | page_table_unlock(AS, true); |
275 | tlb_modified_fail(istate); |
280 | tlb_modified_fail(istate); |
276 | } |
281 | } |
277 | 282 | ||
278 | void tlb_refill_fail(istate_t *istate) |
283 | void tlb_refill_fail(istate_t *istate) |
279 | { |
284 | { |
Line 347... | Line 352... | ||
347 | } else { |
352 | } else { |
348 | /* |
353 | /* |
349 | * Mapping not found in page tables. |
354 | * Mapping not found in page tables. |
350 | * Resort to higher-level page fault handler. |
355 | * Resort to higher-level page fault handler. |
351 | */ |
356 | */ |
- | 357 | page_table_unlock(AS, true); |
|
352 | if (as_page_fault(badvaddr)) { |
358 | if (as_page_fault(badvaddr)) { |
353 | /* |
359 | /* |
354 | * The higher-level page fault handler succeeded, |
360 | * The higher-level page fault handler succeeded, |
355 | * The mapping ought to be in place. |
361 | * The mapping ought to be in place. |
356 | */ |
362 | */ |
- | 363 | page_table_lock(AS, true); |
|
357 | pte = page_mapping_find(AS, badvaddr); |
364 | pte = page_mapping_find(AS, badvaddr); |
358 | ASSERT(pte && pte->p); |
365 | ASSERT(pte && pte->p); |
359 | return pte; |
366 | return pte; |
- | 367 | } else { |
|
- | 368 | page_table_lock(AS, true); |
|
- | 369 | printf("Page fault.\n"); |
|
- | 370 | return NULL; |
|
360 | } |
371 | } |
- | 372 | ||
361 | } |
373 | } |
362 | - | ||
363 | /* |
- | |
364 | * Handler cannot succeed if badvaddr has no mapping. |
- | |
365 | */ |
- | |
366 | if (!pte) { |
- | |
367 | printf("No such mapping.\n"); |
- | |
368 | return NULL; |
- | |
369 | } |
- | |
370 | - | ||
371 | /* |
- | |
372 | * Handler cannot succeed if the mapping is marked as invalid. |
- | |
373 | */ |
- | |
374 | if (!pte->p) { |
- | |
375 | printf("Invalid mapping.\n"); |
- | |
376 | return NULL; |
- | |
377 | } |
- | |
378 | - | ||
379 | return pte; |
- | |
380 | } |
374 | } |
381 | 375 | ||
382 | void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn) |
376 | void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn) |
383 | { |
377 | { |
384 | lo->value = 0; |
378 | lo->value = 0; |