[RHEL7,COMMIT] KVM: MMU: return page fault error code from permission_fault

Submitted by Konstantin Khorenko on May 16, 2018, 9:50 a.m.

Details

Message ID 201805160950.w4G9okup029959@finist_ce7.work
State New
Series "KVM: MMU: return page fault error code from permission_fault"
Headers show

Commit Message

Konstantin Khorenko May 16, 2018, 9:50 a.m.
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.50.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.47.6
------>
commit 63d06d53365fc3366fed549e10a8dbaa675e62d9
Author: Paolo Bonzini <pbonzini@redhat.com>
Date:   Wed May 16 12:50:46 2018 +0300

    KVM: MMU: return page fault error code from permission_fault
    
    This will help in the implementation of PKRU, where the PK bit of the page
    fault error code cannot be computed in advance (unlike I/D, R/W and U/S).
    
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    
    (cherry picked from commit f13577e8aa863cf3b4f17541bc74f8e9b0b40c90)
    Signed-off-by: Jan Dakinevich <jan.dakinevich@virtuozzo.com>
    
    =====================
    Patchset description:
    
    EPT fixes and enhancements
    
    Backport of EPT fixes from upstream for
    https://jira.sw.ru/browse/PSBM-84046
    
    Bandan Das (3):
      kvm: mmu: don't set the present bit unconditionally
      kvm: mmu: track read permission explicitly for shadow EPT page tables
      kvm: vmx: advertise support for ept execute only
    
    Junaid Shahid (2):
      kvm: x86: mmu: Use symbolic constants for EPT Violation Exit
        Qualifications
      kvm: x86: mmu: Rename EPT_VIOLATION_READ/WRITE/INSTR constants
    
    KarimAllah Ahmed (2):
      kvm: Map PFN-type memory regions as writable (if possible)
      KVM: x86: Update the exit_qualification access bits while walking an
        address
    
    Paolo Bonzini (5):
      KVM: nVMX: we support 1GB EPT pages
      kvm: x86: MMU support for EPT accessed/dirty bits
      kvm: nVMX: support EPT accessed/dirty bits
      KVM: MMU: return page fault error code from permission_fault
      KVM: nVMX: fix EPT permissions as reported in exit qualification
---
 arch/x86/kvm/mmu.h         | 15 ++++++++++-----
 arch/x86/kvm/paging_tmpl.h |  5 ++---
 2 files changed, 12 insertions(+), 8 deletions(-)

Patch hide | download patch | download mbox

diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 8330a96fa1c9..dcc90a500c3e 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -146,11 +146,15 @@  static inline bool is_write_protection(struct kvm_vcpu *vcpu)
 }
 
 /*
- * Will a fault with a given page-fault error code (pfec) cause a permission
- * fault with the given access (in ACC_* format)?
+ * Check if a given access (described through the I/D, W/R and U/S bits of a
+ * page fault error code pfec) causes a permission fault with the given PTE
+ * access rights (in ACC_* format).
+ *
+ * Return zero if the access does not fault; return the page fault error code
+ * if the access faults.
  */
-static inline bool permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
-				    unsigned pte_access, unsigned pfec)
+static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+				  unsigned pte_access, unsigned pfec)
 {
 	int cpl = kvm_x86_ops->get_cpl(vcpu);
 	unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
@@ -174,7 +178,8 @@  static inline bool permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 
 	WARN_ON(pfec & PFERR_RSVD_MASK);
 
-	return (mmu->permissions[index] >> pte_access) & 1;
+	pfec |= PFERR_PRESENT_MASK;
+	return -((mmu->permissions[index] >> pte_access) & 1) & pfec;
 }
 
 void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 3b7b51589692..176ec6b5a249 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -371,10 +371,9 @@  static int FNAME(walk_addr_generic)(struct guest_walker *walker,
 		walker->ptes[walker->level - 1] = pte;
 	} while (!is_last_gpte(mmu, walker->level, pte));
 
-	if (unlikely(permission_fault(vcpu, mmu, pte_access, access))) {
-		errcode |= PFERR_PRESENT_MASK;
+	errcode = permission_fault(vcpu, mmu, pte_access, access);
+	if (unlikely(errcode))
 		goto error;
-	}
 
 	gfn = gpte_to_gfn_lvl(pte, walker->level);
 	gfn += (addr & PT_LVL_OFFSET_MASK(walker->level)) >> PAGE_SHIFT;