| 6807 | } |
| 6808 | |
| 6809 | int |
| 6810 | pmap_fault(pmap_t pmap, uint64_t esr, uint64_t far) |
| 6811 | { |
| 6812 | pt_entry_t pte, *ptep; |
| 6813 | register_t intr; |
| 6814 | uint64_t ec, par; |
| 6815 | int lvl, rv; |
| 6816 | |
| 6817 | rv = KERN_FAILURE; |
| 6818 | |
| 6819 | ec = ESR_ELx_EXCEPTION(esr); |
| 6820 | switch (ec) { |
| 6821 | case EXCP_INSN_ABORT_L: |
| 6822 | case EXCP_INSN_ABORT: |
| 6823 | case EXCP_DATA_ABORT_L: |
| 6824 | case EXCP_DATA_ABORT: |
| 6825 | break; |
| 6826 | default: |
| 6827 | return (rv); |
| 6828 | } |
| 6829 | |
| 6830 | if (pmap->pm_stage == PM_STAGE2) |
| 6831 | return (pmap_stage2_fault(pmap, esr, far)); |
| 6832 | |
| 6833 | /* Data and insn aborts use same encoding for FSC field. */ |
| 6834 | switch (esr & ISS_DATA_DFSC_MASK) { |
| 6835 | case ISS_DATA_DFSC_AFF_L1: |
| 6836 | case ISS_DATA_DFSC_AFF_L2: |
| 6837 | case ISS_DATA_DFSC_AFF_L3: |
| 6838 | PMAP_LOCK(pmap); |
| 6839 | ptep = pmap_pte(pmap, far, &lvl); |
| 6840 | if (ptep != NULL) { |
| 6841 | pmap_set_bits(ptep, ATTR_AF); |
| 6842 | rv = KERN_SUCCESS; |
| 6843 | /* |
| 6844 | * XXXMJ as an optimization we could mark the entry |
| 6845 | * dirty if this is a write fault. |
| 6846 | */ |
| 6847 | } |
| 6848 | PMAP_UNLOCK(pmap); |
| 6849 | break; |
| 6850 | case ISS_DATA_DFSC_PF_L1: |
| 6851 | case ISS_DATA_DFSC_PF_L2: |
| 6852 | case ISS_DATA_DFSC_PF_L3: |
| 6853 | if ((ec != EXCP_DATA_ABORT_L && ec != EXCP_DATA_ABORT) || |
| 6854 | (esr & ISS_DATA_WnR) == 0) |
| 6855 | return (rv); |
| 6856 | PMAP_LOCK(pmap); |
| 6857 | ptep = pmap_pte(pmap, far, &lvl); |
| 6858 | if (ptep != NULL && |
| 6859 | ((pte = pmap_load(ptep)) & ATTR_SW_DBM) != 0) { |
| 6860 | if ((pte & ATTR_S1_AP_RW_BIT) == |
| 6861 | ATTR_S1_AP(ATTR_S1_AP_RO)) { |
| 6862 | pmap_clear_bits(ptep, ATTR_S1_AP_RW_BIT); |
| 6863 | pmap_invalidate_page(pmap, far); |
| 6864 | } |
| 6865 | rv = KERN_SUCCESS; |
| 6866 | } |
no test coverage detected