Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
On 07/02/2012 03:32 AM, Mao, Junjie wrote: >> > I think this means I can replace the code here with a check in >> nested_vmx_run. Do I understand correctly? >> >> Correct, but the check already exists: >> if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control, >> nested_vmx_procbased_ctls_low, >> nested_vmx_procbased_ctls_high) || >> !vmx_control_verify(vmcs12->secondary_vm_exec_control, >> nested_vmx_secondary_ctls_low, >> nested_vmx_secondary_ctls_high) || >> !vmx_control_verify(vmcs12->pin_based_vm_exec_control, >> nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) >> || >> !vmx_control_verify(vmcs12->vm_exit_controls, >> nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) || >> !vmx_control_verify(vmcs12->vm_entry_controls, >> nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high)) >> { >> nested_vmx_failValid(vcpu, >> VMXERR_ENTRY_INVALID_CONTROL_FIELD); >> return 1; >> } >> >> So all that is needed is to initializr nested_vmx_entry_ctls_high properly. > > nested_vmx_entry_ctls_high only contains > SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES at present, which means it should be > safe to simply remove the code. Yes, I misread the code as initializing it to what the cpu supports, but it is correct as is. So just drop this check. -- error compiling committee.c: too many arguments to function -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
> -Original Message- > From: Avi Kivity [mailto:a...@redhat.com] > Sent: Friday, June 29, 2012 10:52 PM > To: Mao, Junjie > Cc: 'kvm@vger.kernel.org' > Subject: Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with > EPT > > On 06/29/2012 05:37 AM, Mao, Junjie wrote: > > > > > > > > > > > static void vmx_set_supported_cpuid(u32 func, struct > > > > kvm_cpuid_entry2 > > > > *entry) @@ -6610,6 +6641,9 @@ static void prepare_vmcs02(struct > > > kvm_vcpu *vcpu, struct vmcs12 *vmcs12) > > > > > > > > page_to_phys(vmx->nested.apic_access_page)); > > > > } > > > > > > > > + /* Explicitly disable INVPCID until PCID for L2 guest > > > > is supported > */ > > > > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > > > > + > > > > > > We can't just disable it without the guest knowing. If we don't > > > expose INCPCID through the MSR, then we should fail VMKLAUNCH or > > > VMRESUME is this bit is set. > > > > I think this means I can replace the code here with a check in > nested_vmx_run. Do I understand correctly? > > Correct, but the check already exists: > if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control, > nested_vmx_procbased_ctls_low, > nested_vmx_procbased_ctls_high) || > !vmx_control_verify(vmcs12->secondary_vm_exec_control, > nested_vmx_secondary_ctls_low, > nested_vmx_secondary_ctls_high) || > !vmx_control_verify(vmcs12->pin_based_vm_exec_control, > nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) > || > !vmx_control_verify(vmcs12->vm_exit_controls, > nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) || > !vmx_control_verify(vmcs12->vm_entry_controls, > nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high)) > { > nested_vmx_failValid(vcpu, > VMXERR_ENTRY_INVALID_CONTROL_FIELD); > return 1; > } > > So all that is needed is to initializr nested_vmx_entry_ctls_high properly. nested_vmx_entry_ctls_high only contains SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES at present, which means it should be safe to simply remove the code. > > > > > > > > vmcs_write32(SECONDARY_VM_EXEC_CONTROL, > exec_control); > > > > } > > > > > > > > @@ -528,6 +528,10 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, > > > > unsigned > > > long cr0) > > > > return 1; > > > > } > > > > > > > > + if ((old_cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PG) && > > > > + kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE)) > > > > + return 1; > > > > > > Why check old_cr0? > > > > MOV to CR0 causes a general-protection exception if it would clear CR0.PG to > 0 while CR4.PCIDE = 1. This check reflects the restriction. > > It should not be possible to have cr0.pg=0 and cr4.pcide=1 in the first place. > We are guaranteed that old_cr0.pg=1. > I see. Thanks for the suggestion. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
On 06/29/2012 05:37 AM, Mao, Junjie wrote: > > > > > > > > static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 > > > *entry) @@ -6610,6 +6641,9 @@ static void prepare_vmcs02(struct > > kvm_vcpu *vcpu, struct vmcs12 *vmcs12) > > > page_to_phys(vmx->nested.apic_access_page)); > > > } > > > > > > + /* Explicitly disable INVPCID until PCID for L2 guest is > > > supported */ > > > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > > > + > > > > We can't just disable it without the guest knowing. If we don't expose > > INCPCID through the MSR, then we should fail VMKLAUNCH or VMRESUME is > > this bit is set. > > I think this means I can replace the code here with a check in > nested_vmx_run. Do I understand correctly? Correct, but the check already exists: if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control, nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high) || !vmx_control_verify(vmcs12->secondary_vm_exec_control, nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high) || !vmx_control_verify(vmcs12->pin_based_vm_exec_control, nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) || !vmx_control_verify(vmcs12->vm_exit_controls, nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) || !vmx_control_verify(vmcs12->vm_entry_controls, nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high)) { nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); return 1; } So all that is needed is to initializr nested_vmx_entry_ctls_high properly. > > > > > vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); > > > } > > > > > > @@ -528,6 +528,10 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned > > long cr0) > > > return 1; > > > } > > > > > > + if ((old_cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PG) && > > > + kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE)) > > > + return 1; > > > > Why check old_cr0? > > MOV to CR0 causes a general-protection exception if it would clear CR0.PG to > 0 while CR4.PCIDE = 1. This check reflects the restriction. It should not be possible to have cr0.pg=0 and cr4.pcide=1 in the first place. We are guaranteed that old_cr0.pg=1. > > > > > > > > > + if ((cr4 & X86_CR4_PCIDE) && !(old_cr4 & X86_CR4_PCIDE)) { > > > + if (!guest_cpuid_has_pcid(vcpu)) > > > + return 1; > > > + > > > + /* PCID can not be enabled when cr3[11:0]!=000H or EFER.LMA=0 */ > > > + if ((kvm_read_cr3(vcpu) & X86_CR3_PCID_MASK) > > || !is_long_mode(vcpu)) > > > + return 1; > > > + } > > > + > > > if (kvm_x86_ops->set_cr4(vcpu, cr4)) > > > return 1; > > > > > > - if ((cr4 ^ old_cr4) & pdptr_bits) > > > + if (((cr4 ^ old_cr4) & pdptr_bits) || > > > + (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE))) > > > kvm_mmu_reset_context(vcpu); > > > > > > You can do > > > > > > if ((cr4 ^ old_cr4) & (pdptr_bits | X86_CR4_PCIDE)) > > ... > > TLB is not invalidated when CR4.PCIDE is changed from 0 to 1. Ok. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
> -Original Message- > From: Avi Kivity [mailto:a...@redhat.com] > Sent: Thursday, June 28, 2012 11:49 PM > To: Mao, Junjie > Cc: 'kvm@vger.kernel.org' > Subject: Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with > EPT > > On 06/14/2012 05:04 AM, Mao, Junjie wrote: > > This patch handles PCID/INVPCID for guests. > > > > Process-context identifiers (PCIDs) are a facility by which a logical > > processor may cache information for multiple linear-address spaces so > > that the processor may retain cached information when software > > switches to a different linear address space. Refer to section 4.10.1 > > in IA32 Intel Software Developer's Manual Volume 3A for details. > > > > For guests with EPT, the PCID feature is enabled and INVPCID behaves > > as running natively. > > For guests without EPT, the PCID feature is disabled and INVPCID triggers > #UD. > > > > > > #endif > > unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; > > + unsigned f_pcid = boot_cpu_has(X86_FEATURE_PCID) ? F(PCID) : 0; > > Unneeded, just put F(PCID) below. Understood. Thanks for your suggestion. > > > + unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : > > +0; > > > > /* cpuid 1.edx */ > > const u32 kvm_supported_word0_x86_features = @@ -228,7 +230,7 @@ > > static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, > > 0 /* DS-CPL, VMX, SMX, EST */ | > > 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ | > > F(FMA) | F(CX16) | 0 /* xTPR Update, PDCM */ | > > - 0 /* Reserved, DCA */ | F(XMM4_1) | > > + f_pcid | 0 /* Reserved, DCA */ | F(XMM4_1) | > > > > @@ -1739,6 +1745,11 @@ static bool vmx_rdtscp_supported(void) > > return cpu_has_vmx_rdtscp(); > > } > > > > +static bool vmx_invpcid_supported(void) { > > + return cpu_has_vmx_invpcid(); > > Should that have && ept_enabled? You turn off invpcid below if !ept_enabled. > > > +} > > + > > /* > > * Swap MSR entry in host/guest MSR entry array. > > */ > > @@ -2458,7 +2469,8 @@ static __init int setup_vmcs_config(struct > vmcs_config *vmcs_conf) > > SECONDARY_EXEC_ENABLE_EPT | > > SECONDARY_EXEC_UNRESTRICTED_GUEST | > > SECONDARY_EXEC_PAUSE_LOOP_EXITING | > > - SECONDARY_EXEC_RDTSCP; > > + SECONDARY_EXEC_RDTSCP | > > + SECONDARY_EXEC_ENABLE_INVPCID; > > if (adjust_vmx_controls(min2, opt2, > > MSR_IA32_VMX_PROCBASED_CTLS2, > > &_cpu_based_2nd_exec_control) < 0) @@ > > -3731,6 > +3743,8 @@ static > > u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx) > > if (!enable_ept) { > > exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; > > enable_unrestricted_guest = 0; > > + /* Enable INVPCID for non-ept guests may cause performance > regression. */ > > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > > } > > if (!enable_unrestricted_guest) > > exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; > > This code is unneeded.. > > > @@ -6467,6 +6481,23 @@ static void vmx_cpuid_update(struct kvm_vcpu > *vcpu) > > } > > } > > } > > + > > + if (vmx_invpcid_supported()) { > > + exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); > > + /* Exposing INVPCID only when PCID is exposed */ > > + best = kvm_find_cpuid_entry(vcpu, 0x7, 0); > > + if (best && (best->ecx & bit(X86_FEATURE_INVPCID)) && > guest_cpuid_has_pcid(vcpu)) { > > + exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; > > + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, > > +exec_control); > > + } else { > > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > > + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, > > +exec_control); > > + if (best) > > + best->ecx &= ~bit(X86_FEATURE_INVPCID); > > + } > > + } > > } > > Since you override it here anyway. But maybe it's needed if the host never > calls KVM_SET
Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
On 06/28/2012 06:49 PM, Avi Kivity wrote: > On 06/14/2012 05:04 AM, Mao, Junjie wrote: >> This patch handles PCID/INVPCID for guests. >> >> Process-context identifiers (PCIDs) are a facility by which a logical >> processor >> may cache information for multiple linear-address spaces so that the >> processor >> may retain cached information when software switches to a different linear >> address space. Refer to section 4.10.1 in IA32 Intel Software Developer's >> Manual >> Volume 3A for details. >> >> For guests with EPT, the PCID feature is enabled and INVPCID behaves as >> running >> natively. >> For guests without EPT, the PCID feature is disabled and INVPCID triggers >> #UD. >> Oh, and sorry about the late review. -- error compiling committee.c: too many arguments to function -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
On 06/14/2012 05:04 AM, Mao, Junjie wrote: > This patch handles PCID/INVPCID for guests. > > Process-context identifiers (PCIDs) are a facility by which a logical > processor > may cache information for multiple linear-address spaces so that the processor > may retain cached information when software switches to a different linear > address space. Refer to section 4.10.1 in IA32 Intel Software Developer's > Manual > Volume 3A for details. > > For guests with EPT, the PCID feature is enabled and INVPCID behaves as > running > natively. > For guests without EPT, the PCID feature is disabled and INVPCID triggers #UD. > > > #endif > unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; > + unsigned f_pcid = boot_cpu_has(X86_FEATURE_PCID) ? F(PCID) : 0; Unneeded, just put F(PCID) below. > + unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0; > > /* cpuid 1.edx */ > const u32 kvm_supported_word0_x86_features = > @@ -228,7 +230,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, > u32 function, > 0 /* DS-CPL, VMX, SMX, EST */ | > 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ | > F(FMA) | F(CX16) | 0 /* xTPR Update, PDCM */ | > - 0 /* Reserved, DCA */ | F(XMM4_1) | > + f_pcid | 0 /* Reserved, DCA */ | F(XMM4_1) | > @@ -1739,6 +1745,11 @@ static bool vmx_rdtscp_supported(void) > return cpu_has_vmx_rdtscp(); > } > > +static bool vmx_invpcid_supported(void) > +{ > + return cpu_has_vmx_invpcid(); Should that have && ept_enabled? You turn off invpcid below if !ept_enabled. > +} > + > /* > * Swap MSR entry in host/guest MSR entry array. > */ > @@ -2458,7 +2469,8 @@ static __init int setup_vmcs_config(struct vmcs_config > *vmcs_conf) > SECONDARY_EXEC_ENABLE_EPT | > SECONDARY_EXEC_UNRESTRICTED_GUEST | > SECONDARY_EXEC_PAUSE_LOOP_EXITING | > - SECONDARY_EXEC_RDTSCP; > + SECONDARY_EXEC_RDTSCP | > + SECONDARY_EXEC_ENABLE_INVPCID; > if (adjust_vmx_controls(min2, opt2, > MSR_IA32_VMX_PROCBASED_CTLS2, > &_cpu_based_2nd_exec_control) < 0) > @@ -3731,6 +3743,8 @@ static u32 vmx_secondary_exec_control(struct vcpu_vmx > *vmx) > if (!enable_ept) { > exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; > enable_unrestricted_guest = 0; > + /* Enable INVPCID for non-ept guests may cause performance > regression. */ > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > } > if (!enable_unrestricted_guest) > exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST; This code is unneeded.. > @@ -6467,6 +6481,23 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) > } > } > } > + > + if (vmx_invpcid_supported()) { > + exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); > + /* Exposing INVPCID only when PCID is exposed */ > + best = kvm_find_cpuid_entry(vcpu, 0x7, 0); > + if (best && (best->ecx & bit(X86_FEATURE_INVPCID)) && > guest_cpuid_has_pcid(vcpu)) { > + exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; > + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, > + exec_control); > + } else { > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, > + exec_control); > + if (best) > + best->ecx &= ~bit(X86_FEATURE_INVPCID); > + } > + } > } Since you override it here anyway. But maybe it's needed if the host never calls KVM_SET_CPUID. > > static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) > @@ -6610,6 +6641,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, > struct vmcs12 *vmcs12) > page_to_phys(vmx->nested.apic_access_page)); > } > > + /* Explicitly disable INVPCID until PCID for L2 guest is > supported */ > + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; > + We can't just disable it without the guest knowing. If we don't expose INCPCID through the MSR, then we should fail VMKLAUNCH or VMRESUME is this bit is set. > vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); > } > > @@ -528,6 +528,10 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) > return 1; > } > > + if ((old_cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PG) && > + kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE)) > + return 1; Why check old_cr0? > > + if ((cr4 & X86_CR4_PCIDE
RE: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
Hi, Avi Any comments for the patch? Best Regards Junjie Mao > -Original Message- > From: Marcelo Tosatti [mailto:mtosa...@redhat.com] > Sent: Saturday, June 16, 2012 10:32 AM > To: Mao, Junjie > Cc: 'kvm@vger.kernel.org'; Avi Kivity > Subject: Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with > EPT > > On Thu, Jun 14, 2012 at 02:04:25AM +, Mao, Junjie wrote: > > This patch handles PCID/INVPCID for guests. > > > > Process-context identifiers (PCIDs) are a facility by which a logical > > processor may cache information for multiple linear-address spaces so > > that the processor may retain cached information when software > > switches to a different linear address space. Refer to section 4.10.1 > > in IA32 Intel Software Developer's Manual Volume 3A for details. > > > > For guests with EPT, the PCID feature is enabled and INVPCID behaves > > as running natively. > > For guests without EPT, the PCID feature is disabled and INVPCID triggers > #UD. > > > > Changes from v3: > > Rebase to the latest tree > > Expose PCID to nested guests > > Remove the pcid_supported callback > > > > Changes from v2: > > Seperate management of PCID and INVPCID > > Prevent PCID bit in CPUID from exposing on guest hypervisors > > Don't check the lower 12 bits when loading cr3 if cr4.PCIDE is set > > Explicitly disable INVPCID for L2 guests > > Support both enable and disable INVPCID in vmx_cpuid_update() > > > > Changes from v1: > > Move cr0/cr4 writing checks to x86.c > > Update comments for the reason why PCID is disabled for non-EPT guests > > Do not support PCID/INVPCID for nested guests at present > > Clean up useless symbols > > > > Signed-off-by: Junjie Mao > > Looks good to me. > > > --- > > arch/x86/include/asm/kvm_host.h|4 ++- > > arch/x86/include/asm/processor-flags.h |2 + > > arch/x86/include/asm/vmx.h |2 + > > arch/x86/kvm/cpuid.c |6 +++- > > arch/x86/kvm/cpuid.h |8 +++ > > arch/x86/kvm/svm.c |6 + > > arch/x86/kvm/vmx.c | 37 > +++- > > arch/x86/kvm/x86.c | 24 > ++-- > > 8 files changed, 82 insertions(+), 7 deletions(-) > > > > diff --git a/arch/x86/include/asm/kvm_host.h > > b/arch/x86/include/asm/kvm_host.h index db7c1f2..95828a4 100644 > > --- a/arch/x86/include/asm/kvm_host.h > > +++ b/arch/x86/include/asm/kvm_host.h > > @@ -48,12 +48,13 @@ > > > > #define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1) > > #define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | > > X86_CR3_PCD)) > > +#define CR3_PCID_ENABLED_RESERVED_BITS 0xFF00ULL > > #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | > \ > > 0xFF00ULL) > > #define CR4_RESERVED_BITS > \ > > (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | > X86_CR4_DE\ > > | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ > > - | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \ > > + | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | > X86_CR4_PCIDE \ > > | X86_CR4_OSXSAVE | X86_CR4_SMEP | > X86_CR4_RDWRGSFS \ > > | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) > > > > @@ -661,6 +662,7 @@ struct kvm_x86_ops { > > u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio); > > int (*get_lpage_level)(void); > > bool (*rdtscp_supported)(void); > > + bool (*invpcid_supported)(void); > > void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment, > > bool host); > > > > void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3); diff > > --git a/arch/x86/include/asm/processor-flags.h > > b/arch/x86/include/asm/processor-flags.h > > index f8ab3ea..aea1d1d 100644 > > --- a/arch/x86/include/asm/processor-flags.h > > +++ b/arch/x86/include/asm/processor-flags.h > > @@ -44,6 +44,7 @@ > > */ > > #define X86_CR3_PWT0x0008 /* Page Write Through */ > > #define X86_CR3_PCD0x0010 /* Page Cache Disable */ > > +#define X86_CR3_PCID_MASK 0x0fff /* PCID Mask */ > > > > /* > > * Intel CPU features in CR4 > > @@ -61,6 +62,7 @@ > > #define X86_CR4_OSXMMEXCPT 0x040
Re: [PATCH v4] KVM: x86: Implement PCID/INVPCID for guests with EPT
On Thu, Jun 14, 2012 at 02:04:25AM +, Mao, Junjie wrote: > This patch handles PCID/INVPCID for guests. > > Process-context identifiers (PCIDs) are a facility by which a logical > processor > may cache information for multiple linear-address spaces so that the processor > may retain cached information when software switches to a different linear > address space. Refer to section 4.10.1 in IA32 Intel Software Developer's > Manual > Volume 3A for details. > > For guests with EPT, the PCID feature is enabled and INVPCID behaves as > running > natively. > For guests without EPT, the PCID feature is disabled and INVPCID triggers #UD. > > Changes from v3: > Rebase to the latest tree > Expose PCID to nested guests > Remove the pcid_supported callback > > Changes from v2: > Seperate management of PCID and INVPCID > Prevent PCID bit in CPUID from exposing on guest hypervisors > Don't check the lower 12 bits when loading cr3 if cr4.PCIDE is set > Explicitly disable INVPCID for L2 guests > Support both enable and disable INVPCID in vmx_cpuid_update() > > Changes from v1: > Move cr0/cr4 writing checks to x86.c > Update comments for the reason why PCID is disabled for non-EPT guests > Do not support PCID/INVPCID for nested guests at present > Clean up useless symbols > > Signed-off-by: Junjie Mao Looks good to me. > --- > arch/x86/include/asm/kvm_host.h|4 ++- > arch/x86/include/asm/processor-flags.h |2 + > arch/x86/include/asm/vmx.h |2 + > arch/x86/kvm/cpuid.c |6 +++- > arch/x86/kvm/cpuid.h |8 +++ > arch/x86/kvm/svm.c |6 + > arch/x86/kvm/vmx.c | 37 > +++- > arch/x86/kvm/x86.c | 24 ++-- > 8 files changed, 82 insertions(+), 7 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index db7c1f2..95828a4 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -48,12 +48,13 @@ > > #define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1) > #define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | > X86_CR3_PCD)) > +#define CR3_PCID_ENABLED_RESERVED_BITS 0xFF00ULL > #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | \ > 0xFF00ULL) > #define CR4_RESERVED_BITS \ > (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ > | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ > - | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \ > + | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | > X86_CR4_PCIDE \ > | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_RDWRGSFS \ > | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) > > @@ -661,6 +662,7 @@ struct kvm_x86_ops { > u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio); > int (*get_lpage_level)(void); > bool (*rdtscp_supported)(void); > + bool (*invpcid_supported)(void); > void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment, bool > host); > > void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3); > diff --git a/arch/x86/include/asm/processor-flags.h > b/arch/x86/include/asm/processor-flags.h > index f8ab3ea..aea1d1d 100644 > --- a/arch/x86/include/asm/processor-flags.h > +++ b/arch/x86/include/asm/processor-flags.h > @@ -44,6 +44,7 @@ > */ > #define X86_CR3_PWT 0x0008 /* Page Write Through */ > #define X86_CR3_PCD 0x0010 /* Page Cache Disable */ > +#define X86_CR3_PCID_MASK 0x0fff /* PCID Mask */ > > /* > * Intel CPU features in CR4 > @@ -61,6 +62,7 @@ > #define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ > #define X86_CR4_VMXE 0x2000 /* enable VMX virtualization */ > #define X86_CR4_RDWRGSFS 0x0001 /* enable RDWRGSFS support */ > +#define X86_CR4_PCIDE0x0002 /* enable PCID support */ > #define X86_CR4_OSXSAVE 0x0004 /* enable xsave and xrestore */ > #define X86_CR4_SMEP 0x0010 /* enable SMEP support */ > > diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h > index 31f180c..b81525c 100644 > --- a/arch/x86/include/asm/vmx.h > +++ b/arch/x86/include/asm/vmx.h > @@ -60,6 +60,7 @@ > #define SECONDARY_EXEC_WBINVD_EXITING0x0040 > #define SECONDARY_EXEC_UNRESTRICTED_GUEST0x0080 > #define SECONDARY_EXEC_PAUSE_LOOP_EXITING0x0400 > +#define SECONDARY_EXEC_ENABLE_INVPCID0x1000 > > > #define PIN_BASED_EXT_INTR_MASK 0x0001 > @@ -281,6 +282,7 @@ enum vmcs_field { > #define EXIT_REASON_EPT_MISCONFIG 49 > #define EXIT_REASON_WBINVD