return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC;
 }
 
-static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
+static inline
+bool kvm_vcpu_trap_is_permission_fault(const struct kvm_vcpu *vcpu)
 {
-       return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC_TYPE;
+       return esr_fsc_is_permission_fault(kvm_vcpu_get_esr(vcpu));
 }
 
-static __always_inline s8 kvm_vcpu_trap_get_fault_level(const struct kvm_vcpu *vcpu)
+static inline
+bool kvm_vcpu_trap_is_translation_fault(const struct kvm_vcpu *vcpu)
 {
-       /*
-        * Note: With the introduction of FEAT_LPA2 an extra level of
-        * translation (level -1) is added. This level (obviously) doesn't
-        * follow the previous convention of encoding the 4 levels in the 2 LSBs
-        * of the FSC so this function breaks if the fault is for level -1.
-        *
-        * However, stage2 tables always use concatenated tables for first level
-        * lookup and therefore it is guaranteed that the level will be between
-        * 0 and 3, and this function continues to work.
-        */
-       return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC_LEVEL;
+       return esr_fsc_is_translation_fault(kvm_vcpu_get_esr(vcpu));
+}
+
+static inline
+u64 kvm_vcpu_trap_get_perm_fault_granule(const struct kvm_vcpu *vcpu)
+{
+       unsigned long esr = kvm_vcpu_get_esr(vcpu);
+
+       BUG_ON(!esr_fsc_is_permission_fault(esr));
+       return BIT(ARM64_HW_PGTABLE_LEVEL_SHIFT(esr & ESR_ELx_FSC_LEVEL));
 }
 
 static __always_inline bool kvm_vcpu_abt_issea(const struct kvm_vcpu *vcpu)
                 * first), then a permission fault to allow the flags
                 * to be set.
                 */
-               switch (kvm_vcpu_trap_get_fault_type(vcpu)) {
-               case ESR_ELx_FSC_PERM:
-                       return true;
-               default:
-                       return false;
-               }
+               return kvm_vcpu_trap_is_permission_fault(vcpu);
        }
 
        if (kvm_vcpu_trap_is_iabt(vcpu))
 
 
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                          struct kvm_memory_slot *memslot, unsigned long hva,
-                         unsigned long fault_status)
+                         bool fault_is_perm)
 {
        int ret = 0;
        bool write_fault, writable, force_pte = false;
        gfn_t gfn;
        kvm_pfn_t pfn;
        bool logging_active = memslot_is_logging(memslot);
-       s8 fault_level = kvm_vcpu_trap_get_fault_level(vcpu);
        long vma_pagesize, fault_granule;
        enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
        struct kvm_pgtable *pgt;
 
-       fault_granule = 1UL << ARM64_HW_PGTABLE_LEVEL_SHIFT(fault_level);
+       if (fault_is_perm)
+               fault_granule = kvm_vcpu_trap_get_perm_fault_granule(vcpu);
        write_fault = kvm_is_write_fault(vcpu);
        exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu);
        VM_BUG_ON(write_fault && exec_fault);
 
-       if (fault_status == ESR_ELx_FSC_PERM && !write_fault && !exec_fault) {
+       if (fault_is_perm && !write_fault && !exec_fault) {
                kvm_err("Unexpected L2 read permission error\n");
                return -EFAULT;
        }
         * only exception to this is when dirty logging is enabled at runtime
         * and a write fault needs to collapse a block entry into a table.
         */
-       if (fault_status != ESR_ELx_FSC_PERM ||
-           (logging_active && write_fault)) {
+       if (!fault_is_perm || (logging_active && write_fault)) {
                ret = kvm_mmu_topup_memory_cache(memcache,
                                                 kvm_mmu_cache_min_pages(vcpu->arch.hw_mmu));
                if (ret)
         * backed by a THP and thus use block mapping if possible.
         */
        if (vma_pagesize == PAGE_SIZE && !(force_pte || device)) {
-               if (fault_status ==  ESR_ELx_FSC_PERM &&
-                   fault_granule > PAGE_SIZE)
+               if (fault_is_perm && fault_granule > PAGE_SIZE)
                        vma_pagesize = fault_granule;
                else
                        vma_pagesize = transparent_hugepage_adjust(kvm, memslot,
                }
        }
 
-       if (fault_status != ESR_ELx_FSC_PERM && !device && kvm_has_mte(kvm)) {
+       if (!fault_is_perm && !device && kvm_has_mte(kvm)) {
                /* Check the VMM hasn't introduced a new disallowed VMA */
                if (mte_allowed) {
                        sanitise_mte_tags(kvm, pfn, vma_pagesize);
         * permissions only if vma_pagesize equals fault_granule. Otherwise,
         * kvm_pgtable_stage2_map() should be called to change block size.
         */
-       if (fault_status == ESR_ELx_FSC_PERM && vma_pagesize == fault_granule)
+       if (fault_is_perm && vma_pagesize == fault_granule)
                ret = kvm_pgtable_stage2_relax_perms(pgt, fault_ipa, prot);
        else
                ret = kvm_pgtable_stage2_map(pgt, fault_ipa, vma_pagesize,
  */
 int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
 {
-       unsigned long fault_status;
+       unsigned long esr;
        phys_addr_t fault_ipa;
        struct kvm_memory_slot *memslot;
        unsigned long hva;
        gfn_t gfn;
        int ret, idx;
 
-       fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
+       esr = kvm_vcpu_get_esr(vcpu);
 
        fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
        is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
 
-       if (fault_status == ESR_ELx_FSC_FAULT) {
+       if (esr_fsc_is_permission_fault(esr)) {
                /* Beyond sanitised PARange (which is the IPA limit) */
                if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
                        kvm_inject_size_fault(vcpu);
                              kvm_vcpu_get_hfar(vcpu), fault_ipa);
 
        /* Check the stage-2 fault is trans. fault or write fault */
-       if (fault_status != ESR_ELx_FSC_FAULT &&
-           fault_status != ESR_ELx_FSC_PERM &&
-           fault_status != ESR_ELx_FSC_ACCESS) {
+       if (!esr_fsc_is_translation_fault(esr) &&
+           !esr_fsc_is_permission_fault(esr) &&
+           !esr_fsc_is_access_flag_fault(esr)) {
                kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
                        kvm_vcpu_trap_get_class(vcpu),
                        (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
        /* Userspace should not be able to register out-of-bounds IPAs */
        VM_BUG_ON(fault_ipa >= kvm_phys_size(vcpu->arch.hw_mmu));
 
-       if (fault_status == ESR_ELx_FSC_ACCESS) {
+       if (esr_fsc_is_access_flag_fault(esr)) {
                handle_access_fault(vcpu, fault_ipa);
                ret = 1;
                goto out_unlock;
        }
 
-       ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status);
+       ret = user_mem_abort(vcpu, fault_ipa, memslot, hva,
+                            esr_fsc_is_permission_fault(esr));
        if (ret == 0)
                ret = 1;
 out: