Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752959AbcCYOWD (ORCPT ); Fri, 25 Mar 2016 10:22:03 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:34744 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751683AbcCYOV7 (ORCPT ); Fri, 25 Mar 2016 10:21:59 -0400 Subject: Re: [PATCH 1/4] KVM: MMU: fix permission_fault() To: Xiao Guangrong References: <1458911978-19430-1-git-send-email-guangrong.xiao@linux.intel.com> Cc: gleb@kernel.org, mtosatti@redhat.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org From: Paolo Bonzini Message-ID: <56F54983.4010508@redhat.com> Date: Fri, 25 Mar 2016 15:21:55 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <1458911978-19430-1-git-send-email-guangrong.xiao@linux.intel.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2252 Lines: 69 On 25/03/2016 14:19, Xiao Guangrong wrote: > WARN_ON(pfec & (PFERR_PK_MASK | PFERR_RSVD_MASK)); > - pfec |= PFERR_PRESENT_MASK; > + errcode = PFERR_PRESENT_MASK; > > if (unlikely(mmu->pkru_mask)) { > u32 pkru_bits, offset; > @@ -193,11 +193,11 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, > ((pte_access & PT_USER_MASK) << (PFERR_RSVD_BIT - PT_USER_SHIFT)); > > pkru_bits &= mmu->pkru_mask >> offset; > - pfec |= -pkru_bits & PFERR_PK_MASK; > + errcode |= -pkru_bits & PFERR_PK_MASK; > fault |= (pkru_bits != 0); > } > > - return -(uint32_t)fault & pfec; > + return -(uint32_t)fault & errcode; > } I have another doubt here. If you get a fault due to U=0, you would not get PFERR_PK_MASK. This is checked implicitly through the pte_user bit which we moved to PFERR_RSVD_BIT. However, if you get a fault due to W=0 _and_ PKRU.AD=1 or PKRU.WD=1 for the page's protection key, would the PK bit be set in the error code? If not, we would need something like this: diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 81bffd1524c4..6835a551a5c4 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -172,12 +172,11 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long smap = (cpl - 3) & (rflags & X86_EFLAGS_AC); int index = (pfec >> 1) + (smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1)); - bool fault = (mmu->permissions[index] >> pte_access) & 1; WARN_ON(pfec & (PFERR_PK_MASK | PFERR_RSVD_MASK)); - errcode = PFERR_PRESENT_MASK; + errcode = (mmu->permissions[index] >> pte_access) & PFERR_PRESENT_MASK; - if (unlikely(mmu->pkru_mask)) { + if (unlikely(-errcode & mmu->pkru_mask)) { u32 pkru_bits, offset; /* @@ -188,11 +187,10 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, ((pte_access & PT_USER_MASK) << (PFERR_RSVD_BIT - PT_USER_SHIFT)); pkru_bits &= mmu->pkru_mask >> offset; - errcode |= -pkru_bits & PFERR_PK_MASK; - fault |= (pkru_bits != 0); + errcode |= pkru_bits ? PFERR_PK_MASK | PFERR_PRESENT_MASK : 0; } - return -(uint32_t)fault & errcode; + return errcode; } void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm); Thanks, Paolo