Rev 1196 | Rev 1411 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1196 | Rev 1288 | ||
---|---|---|---|
Line 42... | Line 42... | ||
42 | 42 | ||
43 | static void tlb_refill_fail(istate_t *istate); |
43 | static void tlb_refill_fail(istate_t *istate); |
44 | static void tlb_invalid_fail(istate_t *istate); |
44 | static void tlb_invalid_fail(istate_t *istate); |
45 | static void tlb_modified_fail(istate_t *istate); |
45 | static void tlb_modified_fail(istate_t *istate); |
46 | 46 | ||
47 | static pte_t *find_mapping_and_check(__address badvaddr); |
47 | static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc); |
48 | 48 | ||
49 | static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn); |
49 | static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn); |
50 | static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
50 | static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
51 | 51 | ||
52 | /** Initialize TLB |
52 | /** Initialize TLB |
Line 89... | Line 89... | ||
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 | asid_t asid; |
92 | __address badvaddr; |
92 | __address badvaddr; |
93 | pte_t *pte; |
93 | pte_t *pte; |
- | 94 | int pfrc; |
|
94 | 95 | ||
95 | badvaddr = cp0_badvaddr_read(); |
96 | badvaddr = cp0_badvaddr_read(); |
96 | 97 | ||
97 | spinlock_lock(&AS->lock); |
98 | spinlock_lock(&AS->lock); |
98 | asid = AS->asid; |
99 | asid = AS->asid; |
99 | spinlock_unlock(&AS->lock); |
100 | spinlock_unlock(&AS->lock); |
100 | 101 | ||
101 | page_table_lock(AS, true); |
102 | page_table_lock(AS, true); |
102 | 103 | ||
103 | pte = find_mapping_and_check(badvaddr); |
104 | pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
104 | if (!pte) |
105 | if (!pte) { |
- | 106 | switch (pfrc) { |
|
- | 107 | case AS_PF_FAULT: |
|
105 | goto fail; |
108 | goto fail; |
- | 109 | break; |
|
- | 110 | case AS_PF_DEFER: |
|
- | 111 | /* |
|
- | 112 | * The page fault came during copy_from_uspace() |
|
- | 113 | * or copy_to_uspace(). |
|
- | 114 | */ |
|
- | 115 | page_table_unlock(AS, true); |
|
- | 116 | return; |
|
- | 117 | default: |
|
- | 118 | panic("unexpected pfrc (%d)\n", pfrc); |
|
- | 119 | } |
|
- | 120 | } |
|
106 | 121 | ||
107 | /* |
122 | /* |
108 | * Record access to PTE. |
123 | * Record access to PTE. |
109 | */ |
124 | */ |
110 | pte->a = 1; |
125 | pte->a = 1; |
Line 146... | Line 161... | ||
146 | tlb_index_t index; |
161 | tlb_index_t index; |
147 | __address badvaddr; |
162 | __address badvaddr; |
148 | entry_lo_t lo; |
163 | entry_lo_t lo; |
149 | entry_hi_t hi; |
164 | entry_hi_t hi; |
150 | pte_t *pte; |
165 | pte_t *pte; |
- | 166 | int pfrc; |
|
151 | 167 | ||
152 | badvaddr = cp0_badvaddr_read(); |
168 | badvaddr = cp0_badvaddr_read(); |
153 | 169 | ||
154 | /* |
170 | /* |
155 | * Locate the faulting entry in TLB. |
171 | * Locate the faulting entry in TLB. |
Line 168... | Line 184... | ||
168 | if (index.p) { |
184 | if (index.p) { |
169 | printf("TLB entry not found.\n"); |
185 | printf("TLB entry not found.\n"); |
170 | goto fail; |
186 | goto fail; |
171 | } |
187 | } |
172 | 188 | ||
173 | pte = find_mapping_and_check(badvaddr); |
189 | pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
174 | if (!pte) |
190 | if (!pte) { |
- | 191 | switch (pfrc) { |
|
- | 192 | case AS_PF_FAULT: |
|
175 | goto fail; |
193 | goto fail; |
- | 194 | break; |
|
- | 195 | case AS_PF_DEFER: |
|
- | 196 | /* |
|
- | 197 | * The page fault came during copy_from_uspace() |
|
- | 198 | * or copy_to_uspace(). |
|
- | 199 | */ |
|
- | 200 | page_table_unlock(AS, true); |
|
- | 201 | return; |
|
- | 202 | default: |
|
- | 203 | panic("unexpected pfrc (%d)\n", pfrc); |
|
- | 204 | } |
|
- | 205 | } |
|
176 | 206 | ||
177 | /* |
207 | /* |
178 | * Read the faulting TLB entry. |
208 | * Read the faulting TLB entry. |
179 | */ |
209 | */ |
180 | tlbr(); |
210 | tlbr(); |
Line 215... | Line 245... | ||
215 | tlb_index_t index; |
245 | tlb_index_t index; |
216 | __address badvaddr; |
246 | __address badvaddr; |
217 | entry_lo_t lo; |
247 | entry_lo_t lo; |
218 | entry_hi_t hi; |
248 | entry_hi_t hi; |
219 | pte_t *pte; |
249 | pte_t *pte; |
- | 250 | int pfrc; |
|
220 | 251 | ||
221 | badvaddr = cp0_badvaddr_read(); |
252 | badvaddr = cp0_badvaddr_read(); |
222 | 253 | ||
223 | /* |
254 | /* |
224 | * Locate the faulting entry in TLB. |
255 | * Locate the faulting entry in TLB. |
Line 237... | Line 268... | ||
237 | if (index.p) { |
268 | if (index.p) { |
238 | printf("TLB entry not found.\n"); |
269 | printf("TLB entry not found.\n"); |
239 | goto fail; |
270 | goto fail; |
240 | } |
271 | } |
241 | 272 | ||
242 | pte = find_mapping_and_check(badvaddr); |
273 | pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
243 | if (!pte) |
274 | if (!pte) { |
- | 275 | switch (pfrc) { |
|
- | 276 | case AS_PF_FAULT: |
|
244 | goto fail; |
277 | goto fail; |
- | 278 | break; |
|
- | 279 | case AS_PF_DEFER: |
|
- | 280 | /* |
|
- | 281 | * The page fault came during copy_from_uspace() |
|
- | 282 | * or copy_to_uspace(). |
|
- | 283 | */ |
|
- | 284 | page_table_unlock(AS, true); |
|
- | 285 | return; |
|
- | 286 | default: |
|
- | 287 | panic("unexpected pfrc (%d)\n", pfrc); |
|
- | 288 | } |
|
- | 289 | } |
|
245 | 290 | ||
246 | /* |
291 | /* |
247 | * Fail if the page is not writable. |
292 | * Fail if the page is not writable. |
248 | */ |
293 | */ |
249 | if (!pte->w) |
294 | if (!pte->w) |
Line 319... | Line 364... | ||
319 | * |
364 | * |
320 | * Try to find PTE for faulting address. |
365 | * Try to find PTE for faulting address. |
321 | * The AS->lock must be held on entry to this function. |
366 | * The AS->lock must be held on entry to this function. |
322 | * |
367 | * |
323 | * @param badvaddr Faulting virtual address. |
368 | * @param badvaddr Faulting virtual address. |
- | 369 | * @param istate Pointer to interrupted state. |
|
- | 370 | * @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
|
324 | * |
371 | * |
325 | * @return PTE on success, NULL otherwise. |
372 | * @return PTE on success, NULL otherwise. |
326 | */ |
373 | */ |
327 | pte_t *find_mapping_and_check(__address badvaddr) |
374 | pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc) |
328 | { |
375 | { |
329 | entry_hi_t hi; |
376 | entry_hi_t hi; |
330 | pte_t *pte; |
377 | pte_t *pte; |
331 | 378 | ||
332 | hi.value = cp0_entry_hi_read(); |
379 | hi.value = cp0_entry_hi_read(); |
Line 348... | Line 395... | ||
348 | * Mapping found in page tables. |
395 | * Mapping found in page tables. |
349 | * Immediately succeed. |
396 | * Immediately succeed. |
350 | */ |
397 | */ |
351 | return pte; |
398 | return pte; |
352 | } else { |
399 | } else { |
- | 400 | int rc; |
|
- | 401 | ||
353 | /* |
402 | /* |
354 | * Mapping not found in page tables. |
403 | * Mapping not found in page tables. |
355 | * Resort to higher-level page fault handler. |
404 | * Resort to higher-level page fault handler. |
356 | */ |
405 | */ |
357 | page_table_unlock(AS, true); |
406 | page_table_unlock(AS, true); |
358 | if (as_page_fault(badvaddr)) { |
407 | switch (rc = as_page_fault(badvaddr, istate)) { |
- | 408 | case AS_PF_OK: |
|
359 | /* |
409 | /* |
360 | * The higher-level page fault handler succeeded, |
410 | * The higher-level page fault handler succeeded, |
361 | * The mapping ought to be in place. |
411 | * The mapping ought to be in place. |
362 | */ |
412 | */ |
363 | page_table_lock(AS, true); |
413 | page_table_lock(AS, true); |
364 | pte = page_mapping_find(AS, badvaddr); |
414 | pte = page_mapping_find(AS, badvaddr); |
365 | ASSERT(pte && pte->p); |
415 | ASSERT(pte && pte->p); |
366 | return pte; |
416 | return pte; |
- | 417 | break; |
|
- | 418 | case AS_PF_DEFER: |
|
- | 419 | page_table_lock(AS, true); |
|
- | 420 | *pfrc = AS_PF_DEFER; |
|
- | 421 | return NULL; |
|
367 | } else { |
422 | break; |
- | 423 | case AS_PF_FAULT: |
|
368 | page_table_lock(AS, true); |
424 | page_table_lock(AS, true); |
369 | printf("Page fault.\n"); |
425 | printf("Page fault.\n"); |
- | 426 | *pfrc = AS_PF_FAULT; |
|
370 | return NULL; |
427 | return NULL; |
- | 428 | break; |
|
- | 429 | default: |
|
- | 430 | panic("unexpected rc (%d)\n", rc); |
|
371 | } |
431 | } |
372 | 432 | ||
373 | } |
433 | } |
374 | } |
434 | } |
375 | 435 |