Permission fault can be more than just a write fault. Execution fault can also occur if the page is flagged with the XN bit. kvm_decode_fault() returns a value that indicates the fault type (read, write, exec). Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> --- arch/arm/include/asm/kvm_mmu.h | 14 ++++++++++---- arch/arm/kvm/mmu.c | 10 ++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 970f3b5..257e2bc 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -58,15 +58,21 @@ static inline void kvm_set_pte(pte_t *pte, pte_t new_pte) flush_pmd_entry(pte); } -static inline bool kvm_is_write_fault(unsigned long hsr) +enum kvm_fault_type { + KVM_READ_FAULT, + KVM_WRITE_FAULT, + KVM_EXEC_FAULT, +}; + +static inline enum kvm_fault_type kvm_decode_fault(unsigned long hsr) { unsigned long hsr_ec = hsr >> HSR_EC_SHIFT; if (hsr_ec == HSR_EC_IABT) - return false; + return KVM_EXEC_FAULT; else if ((hsr & HSR_ISV) && !(hsr & HSR_WNR)) - return false; + return KVM_READ_FAULT; else - return true; + return KVM_WRITE_FAULT; } static inline void kvm_clean_pgd(pgd_t *pgd) diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 633b546..58a45d1 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -510,12 +510,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, pte_t new_pte, *ptep; pfn_t pfn; int ret; - bool write_fault, writable; + bool writable; + enum kvm_fault_type fault_type; unsigned long mmu_seq; struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; - write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu)); - if (fault_status == FSC_PERM && !write_fault) { + fault_type = kvm_decode_fault(kvm_vcpu_get_hsr(vcpu)); + if (fault_status == FSC_PERM && fault_type == KVM_READ_FAULT) { kvm_err("Unexpected L2 read permission error\n"); return -EFAULT; } @@ -537,7 +538,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, */ smp_rmb(); - pfn = gfn_to_pfn_prot(vcpu->kvm, gfn, write_fault, &writable); + pfn = gfn_to_pfn_prot(vcpu->kvm, gfn, + fault_type == KVM_WRITE_FAULT, &writable); if (is_error_pfn(pfn)) return -EFAULT; -- 1.8.1.2 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm