diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 2ae7f9ed4cf8..b2a295a9f084 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -275,8 +275,18 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_pagewalk *w, unsigned pte_access, unsigned pte_pkey, u64 access) { - /* strip nested paging fault error codes */ - unsigned int pfec = access; + /* + * Of the error codes that do not contribute to the index in + * fmt->permissions, PK and SS are not supported by shadow paging + * and also not provided to EPT violations, but SS *is* included + * in the NPT exit code. RSVD faults are handled elsewhere. + */ + unsigned int pfec = access & ~PFERR_SS_MASK; + if (WARN_ON_ONCE(pfec & ~(PFERR_PRESENT_MASK | PFERR_WRITE_MASK | + PFERR_USER_MASK | PFERR_FETCH_MASK))) + pfec &= (PFERR_PRESENT_MASK | PFERR_WRITE_MASK | + PFERR_USER_MASK | PFERR_FETCH_MASK); + unsigned long rflags = kvm_x86_call(get_rflags)(vcpu); /* @@ -301,8 +311,6 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_pagewalk *w, kvm_mmu_refresh_passthrough_bits(vcpu, w); fault = (fmt->permissions[index] >> pte_access) & 1; - - WARN_ON_ONCE(pfec & (PFERR_PK_MASK | PFERR_SS_MASK | PFERR_RSVD_MASK)); if (unlikely(fmt->pkru_mask)) { u32 pkru_bits, offset; diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index 27427e7f22fa..e5450faa669e 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -328,7 +328,6 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker, int offset; u64 walk_nx_mask = 0; const int write_fault = access & PFERR_WRITE_MASK; - const int user_fault = access & PFERR_USER_MASK; const int fetch_fault = access & PFERR_FETCH_MASK; /* * Note! Track the error_code that's common to legacy shadow paging @@ -486,7 +485,7 @@ retry_walk: return 1; error: - errcode |= write_fault | user_fault; + errcode |= access & (PFERR_WRITE_MASK | PFERR_USER_MASK | PFERR_SS_MASK); if (fetch_fault && has_pferr_fetch(w)) errcode |= PFERR_FETCH_MASK;