* Handle access and R/W emulation faults. */
| 6402 | * Handle access and R/W emulation faults. |
| 6403 | */ |
| 6404 | int |
| 6405 | pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode) |
| 6406 | { |
| 6407 | pt1_entry_t *pte1p, pte1; |
| 6408 | pt2_entry_t *pte2p, pte2; |
| 6409 | |
| 6410 | if (pmap == NULL) |
| 6411 | pmap = kernel_pmap; |
| 6412 | |
| 6413 | /* |
| 6414 | * In kernel, we should never get abort with FAR which is in range of |
| 6415 | * pmap->pm_pt1 or PT2MAP address spaces. If it happens, stop here |
| 6416 | * and print out a useful abort message and even get to the debugger |
| 6417 | * otherwise it likely ends with never ending loop of aborts. |
| 6418 | */ |
| 6419 | if (__predict_false(IN_RANGE2(far, pmap->pm_pt1, NB_IN_PT1))) { |
| 6420 | /* |
| 6421 | * All L1 tables should always be mapped and present. |
| 6422 | * However, we check only current one herein. For user mode, |
| 6423 | * only permission abort from malicious user is not fatal. |
| 6424 | * And alignment abort as it may have higher priority. |
| 6425 | */ |
| 6426 | if (!usermode || (idx != FAULT_ALIGN && idx != FAULT_PERM_L2)) { |
| 6427 | CTR4(KTR_PMAP, "%s: pmap %#x pm_pt1 %#x far %#x", |
| 6428 | __func__, pmap, pmap->pm_pt1, far); |
| 6429 | panic("%s: pm_pt1 abort", __func__); |
| 6430 | } |
| 6431 | return (KERN_INVALID_ADDRESS); |
| 6432 | } |
| 6433 | if (__predict_false(IN_RANGE2(far, PT2MAP, PT2MAP_SIZE))) { |
| 6434 | /* |
| 6435 | * PT2MAP should be always mapped and present in current |
| 6436 | * L1 table. However, only existing L2 tables are mapped |
| 6437 | * in PT2MAP. For user mode, only L2 translation abort and |
| 6438 | * permission abort from malicious user is not fatal. |
| 6439 | * And alignment abort as it may have higher priority. |
| 6440 | */ |
| 6441 | if (!usermode || (idx != FAULT_ALIGN && |
| 6442 | idx != FAULT_TRAN_L2 && idx != FAULT_PERM_L2)) { |
| 6443 | CTR4(KTR_PMAP, "%s: pmap %#x PT2MAP %#x far %#x", |
| 6444 | __func__, pmap, PT2MAP, far); |
| 6445 | panic("%s: PT2MAP abort", __func__); |
| 6446 | } |
| 6447 | return (KERN_INVALID_ADDRESS); |
| 6448 | } |
| 6449 | |
| 6450 | /* |
| 6451 | * A pmap lock is used below for handling of access and R/W emulation |
| 6452 | * aborts. They were handled by atomic operations before so some |
| 6453 | * analysis of new situation is needed to answer the following question: |
| 6454 | * Is it safe to use the lock even for these aborts? |
| 6455 | * |
| 6456 | * There may happen two cases in general: |
| 6457 | * |
| 6458 | * (1) Aborts while the pmap lock is locked already - this should not |
| 6459 | * happen as pmap lock is not recursive. However, under pmap lock only |
| 6460 | * internal kernel data should be accessed and such data should be |
| 6461 | * mapped with A bit set and NM bit cleared. If double abort happens, |
no test coverage detected