Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751890AbdHAKsS (ORCPT ); Tue, 1 Aug 2017 06:48:18 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59453 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751836AbdHAKsP (ORCPT ); Tue, 1 Aug 2017 06:48:15 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 93F94C076438 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=pbonzini@redhat.com Subject: Re: [PATCH] KVM: nVMX: INVPCID support To: David Hildenbrand , linux-kernel@vger.kernel.org, kvm@vger.kernel.org References: <1501161639-9707-1-git-send-email-pbonzini@redhat.com> <0b82ca85-7b3e-9dc4-a102-24d0e9033dcd@redhat.com> From: Paolo Bonzini Message-ID: <42be1e05-b6e4-42db-5ed8-276d61c4334d@redhat.com> Date: Tue, 1 Aug 2017 12:48:10 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: <0b82ca85-7b3e-9dc4-a102-24d0e9033dcd@redhat.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 01 Aug 2017 10:48:15 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3867 Lines: 107 On 27/07/2017 20:29, David Hildenbrand wrote: > On 27.07.2017 15:20, Paolo Bonzini wrote: >> Expose the "Enable INVPCID" secondary execution control to the guest >> and properly reflect the exit reason. >> >> In addition, before this patch the guest was always running with >> INVPCID enabled, causing pcid.flat's "Test on INVPCID when disabled" >> test to fail. > > Did you wanted to send "KVM: nVMX: do not fill vm_exit_intr_error_code > in prepare_vmcs12" I can spot on kvm/queue? (but sent this patch twice > instead?) > >> >> Signed-off-by: Paolo Bonzini >> --- >> arch/x86/kvm/vmx.c | 34 +++++++++++++++++++++++++--------- >> 1 file changed, 25 insertions(+), 9 deletions(-) >> >> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c >> index ed43fd824264..9c3c6c524430 100644 >> --- a/arch/x86/kvm/vmx.c >> +++ b/arch/x86/kvm/vmx.c >> @@ -8189,6 +8189,10 @@ static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason) >> * table is L0's fault. >> */ >> return false; >> + case EXIT_REASON_INVPCID: >> + return >> + nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_INVPCID) && >> + nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING); > > (why the extra line after the return ?) I'm used to do return first_long_condition && second_long_condition; but I admit it looks a bit weird with 8-space indent. >> case EXIT_REASON_WBINVD: >> return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING); >> case EXIT_REASON_XSETBV: >> @@ -9440,7 +9444,6 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu) >> >> static void vmx_cpuid_update(struct kvm_vcpu *vcpu) >> { >> - struct kvm_cpuid_entry2 *best; >> struct vcpu_vmx *vmx = to_vmx(vcpu); >> u32 secondary_exec_ctl = vmx_secondary_exec_control(vmx); >> >> @@ -9459,15 +9462,27 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) >> } >> } >> >> - /* Exposing INVPCID only when PCID is exposed */ >> - best = kvm_find_cpuid_entry(vcpu, 0x7, 0); >> - if (vmx_invpcid_supported() && >> - (!best || !(best->ebx & bit(X86_FEATURE_INVPCID)) || >> - !guest_cpuid_has_pcid(vcpu))) { >> - secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID; >> + if (vmx_invpcid_supported()) { >> + /* Exposing INVPCID only when PCID is exposed */ >> + struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 0x7, 0); >> + bool invpcid_enabled = >> + best && best->ebx & bit(X86_FEATURE_INVPCID) && > > I thought parentheses are recommended around &, but I am usually wrong > about these things :) In general the compiler complains about those things, so I didn't add the parentheses here. In can see why it doesn't, because & ^ | are consistently above && ||. The problems in general stem from the precedence between & ^ | and && ||. >> + guest_cpuid_has_pcid(vcpu); >> >> - if (best) >> - best->ebx &= ~bit(X86_FEATURE_INVPCID); >> + if (!invpcid_enabled) { >> + secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID; >> + if (best) >> + best->ebx &= ~bit(X86_FEATURE_INVPCID); >> + } > > Can't we rewrite that a little bit, avoiding that "best" handling > (introducing guest_cpuid_disable_invpcid() and guest_cpuid_has_invpcid()) > > bool invpcid_enabled = guest_cpuid_has_pcid(vcpu) && > guest_cpuid_has_invpcid(); > > if (!invpcid_enabled) { > secondary_exec_ctl &= ~SECONDARY_EXEC_ENABLE_INVPCID; > /* make sure there is no no INVPCID without PCID */ > guest_cpuid_disable_invpcid(vcpu); > } I don't know... if you need a comment, it means the different structure of the code doesn't spare many doubts from the reader. And the code doesn't become much simpler since you have to handle "nested" anyway. What I tried to do was to mimic as much as possible the rdtscp case, but it cannot be exactly the same due to the interaction between PCID and INVPCID. Paolo