mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 13:43:55 +08:00
KVM: MMU: fix permission_fault()
kvm-unit-tests complained about the PFEC is not set properly, e.g,: test pte.rw pte.d pte.nx pde.p pde.rw pde.pse user fetch: FAIL: error code 15 expected 5 Dump mapping: address: 0x123400000000 ------L4: 3e95007 ------L3: 3e96007 ------L2: 2000083 It's caused by the reason that PFEC returned to guest is copied from the PFEC triggered by shadow page table This patch fixes it and makes the logic of updating errcode more clean Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com> [Do not assume pfec.p=1. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
4a6cd3ba6f
commit
7a98205dee
@ -173,10 +173,9 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
|||||||
int index = (pfec >> 1) +
|
int index = (pfec >> 1) +
|
||||||
(smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
|
(smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
|
||||||
bool fault = (mmu->permissions[index] >> pte_access) & 1;
|
bool fault = (mmu->permissions[index] >> pte_access) & 1;
|
||||||
|
u32 errcode = PFERR_PRESENT_MASK;
|
||||||
|
|
||||||
WARN_ON(pfec & (PFERR_PK_MASK | PFERR_RSVD_MASK));
|
WARN_ON(pfec & (PFERR_PK_MASK | PFERR_RSVD_MASK));
|
||||||
pfec |= PFERR_PRESENT_MASK;
|
|
||||||
|
|
||||||
if (unlikely(mmu->pkru_mask)) {
|
if (unlikely(mmu->pkru_mask)) {
|
||||||
u32 pkru_bits, offset;
|
u32 pkru_bits, offset;
|
||||||
|
|
||||||
@ -189,15 +188,15 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
|||||||
pkru_bits = (kvm_read_pkru(vcpu) >> (pte_pkey * 2)) & 3;
|
pkru_bits = (kvm_read_pkru(vcpu) >> (pte_pkey * 2)) & 3;
|
||||||
|
|
||||||
/* clear present bit, replace PFEC.RSVD with ACC_USER_MASK. */
|
/* clear present bit, replace PFEC.RSVD with ACC_USER_MASK. */
|
||||||
offset = pfec - 1 +
|
offset = (pfec & ~1) +
|
||||||
((pte_access & PT_USER_MASK) << (PFERR_RSVD_BIT - PT_USER_SHIFT));
|
((pte_access & PT_USER_MASK) << (PFERR_RSVD_BIT - PT_USER_SHIFT));
|
||||||
|
|
||||||
pkru_bits &= mmu->pkru_mask >> offset;
|
pkru_bits &= mmu->pkru_mask >> offset;
|
||||||
pfec |= -pkru_bits & PFERR_PK_MASK;
|
errcode |= -pkru_bits & PFERR_PK_MASK;
|
||||||
fault |= (pkru_bits != 0);
|
fault |= (pkru_bits != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -(uint32_t)fault & pfec;
|
return -(u32)fault & errcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm);
|
void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm);
|
||||||
|
@ -360,7 +360,7 @@ retry_walk:
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (unlikely(is_rsvd_bits_set(mmu, pte, walker->level))) {
|
if (unlikely(is_rsvd_bits_set(mmu, pte, walker->level))) {
|
||||||
errcode |= PFERR_RSVD_MASK | PFERR_PRESENT_MASK;
|
errcode = PFERR_RSVD_MASK | PFERR_PRESENT_MASK;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user