Rev 3675 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3675 | Rev 4377 | ||
---|---|---|---|
Line 197... | Line 197... | ||
197 | } |
197 | } |
198 | 198 | ||
199 | /** ITLB miss handler. */ |
199 | /** ITLB miss handler. */ |
200 | void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate) |
200 | void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate) |
201 | { |
201 | { |
202 | uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
202 | uintptr_t page_16k = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
203 | index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
203 | index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
204 | pte_t *t; |
204 | pte_t *t; |
205 | 205 | ||
206 | page_table_lock(AS, true); |
206 | page_table_lock(AS, true); |
207 | t = page_mapping_find(AS, va); |
207 | t = page_mapping_find(AS, page_16k); |
208 | if (t && PTE_EXECUTABLE(t)) { |
208 | if (t && PTE_EXECUTABLE(t)) { |
209 | /* |
209 | /* |
210 | * The mapping was found in the software page hash table. |
210 | * The mapping was found in the software page hash table. |
211 | * Insert it into ITLB. |
211 | * Insert it into ITLB. |
212 | */ |
212 | */ |
Line 220... | Line 220... | ||
220 | /* |
220 | /* |
221 | * Forward the page fault to the address space page fault |
221 | * Forward the page fault to the address space page fault |
222 | * handler. |
222 | * handler. |
223 | */ |
223 | */ |
224 | page_table_unlock(AS, true); |
224 | page_table_unlock(AS, true); |
225 | if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) { |
225 | if (as_page_fault(page_16k, PF_ACCESS_EXEC, istate) == |
- | 226 | AS_PF_FAULT) { |
|
226 | do_fast_instruction_access_mmu_miss_fault(istate, |
227 | do_fast_instruction_access_mmu_miss_fault(istate, |
227 | __func__); |
228 | __func__); |
228 | } |
229 | } |
229 | } |
230 | } |
230 | } |
231 | } |
Line 240... | Line 241... | ||
240 | * DTLB miss. |
241 | * DTLB miss. |
241 | * @param istate Interrupted state saved on the stack. |
242 | * @param istate Interrupted state saved on the stack. |
242 | */ |
243 | */ |
243 | void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
244 | void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
244 | { |
245 | { |
245 | uintptr_t va; |
246 | uintptr_t page_8k; |
- | 247 | uintptr_t page_16k; |
|
246 | index_t index; |
248 | index_t index; |
247 | pte_t *t; |
249 | pte_t *t; |
248 | 250 | ||
249 | va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
251 | page_8k = (uint64_t) tag.vpn << MMU_PAGE_WIDTH; |
- | 252 | page_16k = ALIGN_DOWN(page_8k, PAGE_SIZE); |
|
250 | index = tag.vpn % MMU_PAGES_PER_PAGE; |
253 | index = tag.vpn % MMU_PAGES_PER_PAGE; |
251 | 254 | ||
252 | if (tag.context == ASID_KERNEL) { |
255 | if (tag.context == ASID_KERNEL) { |
253 | if (!tag.vpn) { |
256 | if (!tag.vpn) { |
254 | /* NULL access in kernel */ |
257 | /* NULL access in kernel */ |
255 | do_fast_data_access_mmu_miss_fault(istate, tag, |
258 | do_fast_data_access_mmu_miss_fault(istate, tag, |
256 | __func__); |
259 | __func__); |
- | 260 | } else if (page_8k >= end_of_identity) { |
|
- | 261 | /* |
|
- | 262 | * The kernel is accessing the I/O space. |
|
- | 263 | * We still do identity mapping for I/O, |
|
- | 264 | * but without caching. |
|
- | 265 | */ |
|
- | 266 | dtlb_insert_mapping(page_8k, KA2PA(page_8k), |
|
- | 267 | PAGESIZE_8K, false, false); |
|
- | 268 | return; |
|
257 | } |
269 | } |
258 | do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected " |
270 | do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected " |
259 | "kernel page fault."); |
271 | "kernel page fault."); |
260 | } |
272 | } |
261 | 273 | ||
262 | page_table_lock(AS, true); |
274 | page_table_lock(AS, true); |
263 | t = page_mapping_find(AS, va); |
275 | t = page_mapping_find(AS, page_16k); |
264 | if (t) { |
276 | if (t) { |
265 | /* |
277 | /* |
266 | * The mapping was found in the software page hash table. |
278 | * The mapping was found in the software page hash table. |
267 | * Insert it into DTLB. |
279 | * Insert it into DTLB. |
268 | */ |
280 | */ |
Line 276... | Line 288... | ||
276 | /* |
288 | /* |
277 | * Forward the page fault to the address space page fault |
289 | * Forward the page fault to the address space page fault |
278 | * handler. |
290 | * handler. |
279 | */ |
291 | */ |
280 | page_table_unlock(AS, true); |
292 | page_table_unlock(AS, true); |
281 | if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
293 | if (as_page_fault(page_16k, PF_ACCESS_READ, istate) == |
- | 294 | AS_PF_FAULT) { |
|
282 | do_fast_data_access_mmu_miss_fault(istate, tag, |
295 | do_fast_data_access_mmu_miss_fault(istate, tag, |
283 | __func__); |
296 | __func__); |
284 | } |
297 | } |
285 | } |
298 | } |
286 | } |
299 | } |
Line 293... | Line 306... | ||
293 | * DTLB miss. |
306 | * DTLB miss. |
294 | * @param istate Interrupted state saved on the stack. |
307 | * @param istate Interrupted state saved on the stack. |
295 | */ |
308 | */ |
296 | void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
309 | void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
297 | { |
310 | { |
298 | uintptr_t va; |
311 | uintptr_t page_16k; |
299 | index_t index; |
312 | index_t index; |
300 | pte_t *t; |
313 | pte_t *t; |
301 | 314 | ||
302 | va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
315 | page_16k = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
303 | index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
316 | index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
304 | 317 | ||
305 | page_table_lock(AS, true); |
318 | page_table_lock(AS, true); |
306 | t = page_mapping_find(AS, va); |
319 | t = page_mapping_find(AS, page_16k); |
307 | if (t && PTE_WRITABLE(t)) { |
320 | if (t && PTE_WRITABLE(t)) { |
308 | /* |
321 | /* |
309 | * The mapping was found in the software page hash table and is |
322 | * The mapping was found in the software page hash table and is |
310 | * writable. Demap the old mapping and insert an updated mapping |
323 | * writable. Demap the old mapping and insert an updated mapping |
311 | * into DTLB. |
324 | * into DTLB. |
312 | */ |
325 | */ |
313 | t->a = true; |
326 | t->a = true; |
314 | t->d = true; |
327 | t->d = true; |
315 | dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, |
328 | dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, |
316 | va + index * MMU_PAGE_SIZE); |
329 | page_16k + index * MMU_PAGE_SIZE); |
317 | dtlb_pte_copy(t, index, false); |
330 | dtlb_pte_copy(t, index, false); |
318 | #ifdef CONFIG_TSB |
331 | #ifdef CONFIG_TSB |
319 | dtsb_pte_copy(t, index, false); |
332 | dtsb_pte_copy(t, index, false); |
320 | #endif |
333 | #endif |
321 | page_table_unlock(AS, true); |
334 | page_table_unlock(AS, true); |
Line 323... | Line 336... | ||
323 | /* |
336 | /* |
324 | * Forward the page fault to the address space page fault |
337 | * Forward the page fault to the address space page fault |
325 | * handler. |
338 | * handler. |
326 | */ |
339 | */ |
327 | page_table_unlock(AS, true); |
340 | page_table_unlock(AS, true); |
328 | if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) { |
341 | if (as_page_fault(page_16k, PF_ACCESS_WRITE, istate) == |
- | 342 | AS_PF_FAULT) { |
|
329 | do_fast_data_access_protection_fault(istate, tag, |
343 | do_fast_data_access_protection_fault(istate, tag, |
330 | __func__); |
344 | __func__); |
331 | } |
345 | } |
332 | } |
346 | } |
333 | } |
347 | } |
Line 422... | Line 436... | ||
422 | #endif |
436 | #endif |
423 | 437 | ||
424 | void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, |
438 | void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, |
425 | const char *str) |
439 | const char *str) |
426 | { |
440 | { |
427 | fault_if_from_uspace(istate, "%s\n", str); |
441 | fault_if_from_uspace(istate, "%s.", str); |
428 | dump_istate(istate); |
442 | dump_istate(istate); |
429 | panic("%s\n", str); |
443 | panic("%s.", str); |
430 | } |
444 | } |
431 | 445 | ||
432 | void do_fast_data_access_mmu_miss_fault(istate_t *istate, |
446 | void do_fast_data_access_mmu_miss_fault(istate_t *istate, |
433 | tlb_tag_access_reg_t tag, const char *str) |
447 | tlb_tag_access_reg_t tag, const char *str) |
434 | { |
448 | { |
435 | uintptr_t va; |
449 | uintptr_t va; |
436 | 450 | ||
437 | va = tag.vpn << MMU_PAGE_WIDTH; |
451 | va = tag.vpn << MMU_PAGE_WIDTH; |
438 | if (tag.context) { |
452 | if (tag.context) { |
439 | fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
453 | fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d).", str, va, |
440 | tag.context); |
454 | tag.context); |
441 | } |
455 | } |
442 | dump_istate(istate); |
456 | dump_istate(istate); |
443 | printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
457 | printf("Faulting page: %p, ASID=%d.\n", va, tag.context); |
444 | panic("%s\n", str); |
458 | panic("%s.", str); |
445 | } |
459 | } |
446 | 460 | ||
447 | void do_fast_data_access_protection_fault(istate_t *istate, |
461 | void do_fast_data_access_protection_fault(istate_t *istate, |
448 | tlb_tag_access_reg_t tag, const char *str) |
462 | tlb_tag_access_reg_t tag, const char *str) |
449 | { |
463 | { |
450 | uintptr_t va; |
464 | uintptr_t va; |
451 | 465 | ||
452 | va = tag.vpn << MMU_PAGE_WIDTH; |
466 | va = tag.vpn << MMU_PAGE_WIDTH; |
453 | 467 | ||
454 | if (tag.context) { |
468 | if (tag.context) { |
455 | fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
469 | fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d).", str, va, |
456 | tag.context); |
470 | tag.context); |
457 | } |
471 | } |
458 | printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
472 | printf("Faulting page: %p, ASID=%d\n", va, tag.context); |
459 | dump_istate(istate); |
473 | dump_istate(istate); |
460 | panic("%s\n", str); |
474 | panic("%s.", str); |
461 | } |
475 | } |
462 | 476 | ||
463 | void dump_sfsr_and_sfar(void) |
477 | void dump_sfsr_and_sfar(void) |
464 | { |
478 | { |
465 | tlb_sfsr_reg_t sfsr; |
479 | tlb_sfsr_reg_t sfsr; |