* [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
@ 2012-05-18 6:17 Mao, Junjie
2012-05-18 21:51 ` Marcelo Tosatti
0 siblings, 1 reply; 10+ messages in thread
From: Mao, Junjie @ 2012-05-18 6:17 UTC (permalink / raw)
To: Marcelo Tosatti, nyh@math.technion.ac.il; +Cc: 'kvm@vger.kernel.org'
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 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 <junjie.mao@intel.com>
---
arch/x86/include/asm/cpufeature.h | 1 +
arch/x86/include/asm/kvm_host.h | 5 ++-
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 | 12 ++++++++
arch/x86/kvm/vmx.c | 49 +++++++++++++++++++++++++++++++-
arch/x86/kvm/x86.c | 24 +++++++++++++--
9 files changed, 102 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 8d67d42..1aedbc0 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -203,6 +203,7 @@
#define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Protection */
#define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */
#define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
+#define X86_FEATURE_INVPCID (9*32+10) /* INVPCID instruction */
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 74c9edf..2c250e6 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -47,12 +47,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 0xFFFFFF0000000000ULL
#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | \
0xFFFFFF0000000000ULL)
#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))
@@ -660,6 +661,8 @@ 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 (*pcid_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 0x00000008 /* Page Write Through */
#define X86_CR3_PCD 0x00000010 /* Page Cache Disable */
+#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */
/*
* Intel CPU features in CR4
@@ -61,6 +62,7 @@
#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
#define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
#define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
+#define X86_CR4_PCIDE 0x00020000 /* enable PCID support */
#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
#define X86_CR4_SMEP 0x00100000 /* 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_EXITING 0x00000040
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
+#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
#define PIN_BASED_EXT_INTR_MASK 0x00000001
@@ -281,6 +282,7 @@ enum vmcs_field {
#define EXIT_REASON_EPT_MISCONFIG 49
#define EXIT_REASON_WBINVD 54
#define EXIT_REASON_XSETBV 55
+#define EXIT_REASON_INVPCID 58
/*
* Interruption-information format
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 9fed5be..fd0b6b9 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -201,6 +201,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
unsigned f_lm = 0;
#endif
unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
+ unsigned f_pcid = kvm_x86_ops->pcid_supported() ? F(PCID) : 0;
+ 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) |
F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
F(F16C) | F(RDRAND);
@@ -247,7 +249,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
/* cpuid 7.0.ebx */
const u32 kvm_supported_word9_x86_features =
- F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS);
+ F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS) | f_invpcid;
/* all calls to cpuid_count() should be made on the same cpu */
get_cpu();
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 26d1fb4..e531d39 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -51,4 +51,12 @@ static inline bool guest_cpuid_has_osvw(struct kvm_vcpu *vcpu)
return best && (best->ecx & bit(X86_FEATURE_OSVW));
}
+static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 1, 0);
+ return best && (best->ecx & bit(X86_FEATURE_PCID));
+}
+
#endif
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 0b7690e..d42fcbe 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -4012,6 +4012,16 @@ static bool svm_rdtscp_supported(void)
return false;
}
+static bool svm_pcid_supported(void)
+{
+ return false;
+}
+
+static bool svm_invpcid_supported(void)
+{
+ return false;
+}
+
static bool svm_has_wbinvd_exit(void)
{
return true;
@@ -4280,6 +4290,8 @@ static struct kvm_x86_ops svm_x86_ops = {
.cpuid_update = svm_cpuid_update,
.rdtscp_supported = svm_rdtscp_supported,
+ .pcid_supported = svm_pcid_supported,
+ .invpcid_supported = svm_invpcid_supported,
.set_supported_cpuid = svm_set_supported_cpuid,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d2bd719..1408d0b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -839,6 +839,12 @@ static inline bool cpu_has_vmx_rdtscp(void)
SECONDARY_EXEC_RDTSCP;
}
+static inline bool cpu_has_vmx_invpcid(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_INVPCID;
+}
+
static inline bool cpu_has_virtual_nmis(void)
{
return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
@@ -1711,6 +1717,22 @@ static bool vmx_rdtscp_supported(void)
return cpu_has_vmx_rdtscp();
}
+static bool vmx_pcid_supported(void)
+{
+ /*
+ * This function is only for determining whether to expose PCID bit
+ * in KVM_GET_SUPPORTED_CPUID ioctl. The HYPERVISOR bit is used to
+ * prevent guest hypervisors from exposing it as PCID is currently
+ * not supported on L2 guests.
+ */
+ return (boot_cpu_has(X86_FEATURE_PCID) && !cpu_has_hypervisor);
+}
+
+static bool vmx_invpcid_supported(void)
+{
+ return cpu_has_vmx_invpcid();
+}
+
/*
* Swap MSR entry in host/guest MSR entry array.
*/
@@ -2424,7 +2446,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)
@@ -3687,6 +3710,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;
@@ -6420,6 +6445,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);
+ }
+ }
}
static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
@@ -6563,6 +6605,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;
+
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
}
@@ -7154,6 +7199,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
.cpuid_update = vmx_cpuid_update,
.rdtscp_supported = vmx_rdtscp_supported,
+ .pcid_supported = vmx_pcid_supported,
+ .invpcid_supported = vmx_invpcid_supported,
.set_supported_cpuid = vmx_set_supported_cpuid,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c9d99e5..479eb0b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -527,6 +527,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;
+
kvm_x86_ops->set_cr0(vcpu, cr0);
if ((cr0 ^ old_cr0) & X86_CR0_PG) {
@@ -603,10 +607,20 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
kvm_read_cr3(vcpu)))
return 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);
if ((cr4 ^ old_cr4) & X86_CR4_OSXSAVE)
@@ -625,8 +639,12 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
}
if (is_long_mode(vcpu)) {
- if (cr3 & CR3_L_MODE_RESERVED_BITS)
- return 1;
+ if (kvm_read_cr4(vcpu) & X86_CR4_PCIDE) {
+ if (cr3 & CR3_PCID_ENABLED_RESERVED_BITS)
+ return 1;
+ } else
+ if (cr3 & CR3_L_MODE_RESERVED_BITS)
+ return 1;
} else {
if (is_pae(vcpu)) {
if (cr3 & CR3_PAE_RESERVED_BITS)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-18 6:17 [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT Mao, Junjie
@ 2012-05-18 21:51 ` Marcelo Tosatti
2012-05-21 0:40 ` Mao, Junjie
0 siblings, 1 reply; 10+ messages in thread
From: Marcelo Tosatti @ 2012-05-18 21:51 UTC (permalink / raw)
To: Mao, Junjie; +Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
On Fri, May 18, 2012 at 06:17:05AM +0000, 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 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 <junjie.mao@intel.com>
> ---
> arch/x86/include/asm/cpufeature.h | 1 +
> arch/x86/include/asm/kvm_host.h | 5 ++-
> 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 | 12 ++++++++
> arch/x86/kvm/vmx.c | 49 +++++++++++++++++++++++++++++++-
> arch/x86/kvm/x86.c | 24 +++++++++++++--
> 9 files changed, 102 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
> index 8d67d42..1aedbc0 100644
> --- a/arch/x86/include/asm/cpufeature.h
> +++ b/arch/x86/include/asm/cpufeature.h
> @@ -203,6 +203,7 @@
> #define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Protection */
> #define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */
> #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
> +#define X86_FEATURE_INVPCID (9*32+10) /* INVPCID instruction */
>
> #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 74c9edf..2c250e6 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -47,12 +47,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 0xFFFFFF0000000000ULL
> #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | \
> 0xFFFFFF0000000000ULL)
> #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))
>
> @@ -660,6 +661,8 @@ 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 (*pcid_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 0x00000008 /* Page Write Through */
> #define X86_CR3_PCD 0x00000010 /* Page Cache Disable */
> +#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */
>
> /*
> * Intel CPU features in CR4
> @@ -61,6 +62,7 @@
> #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
> #define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
> #define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
> +#define X86_CR4_PCIDE 0x00020000 /* enable PCID support */
> #define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
> #define X86_CR4_SMEP 0x00100000 /* 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_EXITING 0x00000040
> #define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
> #define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
> +#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
>
>
> #define PIN_BASED_EXT_INTR_MASK 0x00000001
> @@ -281,6 +282,7 @@ enum vmcs_field {
> #define EXIT_REASON_EPT_MISCONFIG 49
> #define EXIT_REASON_WBINVD 54
> #define EXIT_REASON_XSETBV 55
> +#define EXIT_REASON_INVPCID 58
>
> /*
> * Interruption-information format
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index 9fed5be..fd0b6b9 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -201,6 +201,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
> unsigned f_lm = 0;
> #endif
> unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
> + unsigned f_pcid = kvm_x86_ops->pcid_supported() ? F(PCID) : 0;
> + 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) |
> F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
> 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
> F(F16C) | F(RDRAND);
> @@ -247,7 +249,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
>
> /* cpuid 7.0.ebx */
> const u32 kvm_supported_word9_x86_features =
> - F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS);
> + F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS) | f_invpcid;
>
> /* all calls to cpuid_count() should be made on the same cpu */
> get_cpu();
> diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
> index 26d1fb4..e531d39 100644
> --- a/arch/x86/kvm/cpuid.h
> +++ b/arch/x86/kvm/cpuid.h
> @@ -51,4 +51,12 @@ static inline bool guest_cpuid_has_osvw(struct kvm_vcpu *vcpu)
> return best && (best->ecx & bit(X86_FEATURE_OSVW));
> }
>
> +static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_cpuid_entry2 *best;
> +
> + best = kvm_find_cpuid_entry(vcpu, 1, 0);
> + return best && (best->ecx & bit(X86_FEATURE_PCID));
> +}
> +
> #endif
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 0b7690e..d42fcbe 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -4012,6 +4012,16 @@ static bool svm_rdtscp_supported(void)
> return false;
> }
>
> +static bool svm_pcid_supported(void)
> +{
> + return false;
> +}
> +
> +static bool svm_invpcid_supported(void)
> +{
> + return false;
> +}
> +
> static bool svm_has_wbinvd_exit(void)
> {
> return true;
> @@ -4280,6 +4290,8 @@ static struct kvm_x86_ops svm_x86_ops = {
> .cpuid_update = svm_cpuid_update,
>
> .rdtscp_supported = svm_rdtscp_supported,
> + .pcid_supported = svm_pcid_supported,
> + .invpcid_supported = svm_invpcid_supported,
>
> .set_supported_cpuid = svm_set_supported_cpuid,
>
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index d2bd719..1408d0b 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -839,6 +839,12 @@ static inline bool cpu_has_vmx_rdtscp(void)
> SECONDARY_EXEC_RDTSCP;
> }
>
> +static inline bool cpu_has_vmx_invpcid(void)
> +{
> + return vmcs_config.cpu_based_2nd_exec_ctrl &
> + SECONDARY_EXEC_ENABLE_INVPCID;
> +}
> +
> static inline bool cpu_has_virtual_nmis(void)
> {
> return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
> @@ -1711,6 +1717,22 @@ static bool vmx_rdtscp_supported(void)
> return cpu_has_vmx_rdtscp();
> }
>
> +static bool vmx_pcid_supported(void)
> +{
> + /*
> + * This function is only for determining whether to expose PCID bit
> + * in KVM_GET_SUPPORTED_CPUID ioctl. The HYPERVISOR bit is used to
> + * prevent guest hypervisors from exposing it as PCID is currently
> + * not supported on L2 guests.
> + */
> + return (boot_cpu_has(X86_FEATURE_PCID) && !cpu_has_hypervisor);
> +}
This is not necessary: KVM will not expose secondary-exec-enable-invpcid
support to the L1 guest, and so L1 guest will not attempt to expose
PCID support to L2 guest.
The boot cpu feature bit is tested by do_cpuid_ent, so this callback
can be removed.
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-18 21:51 ` Marcelo Tosatti
@ 2012-05-21 0:40 ` Mao, Junjie
2012-05-21 22:38 ` Marcelo Tosatti
0 siblings, 1 reply; 10+ messages in thread
From: Mao, Junjie @ 2012-05-21 0:40 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
> -----Original Message-----
> From: Marcelo Tosatti [mailto:mtosatti@redhat.com]
> Sent: Saturday, May 19, 2012 5:51 AM
> To: Mao, Junjie
> Cc: nyh@math.technion.ac.il; 'kvm@vger.kernel.org'
> Subject: Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with
> EPT
>
> On Fri, May 18, 2012 at 06:17:05AM +0000, 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 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 <junjie.mao@intel.com>
> > ---
> > arch/x86/include/asm/cpufeature.h | 1 +
> > arch/x86/include/asm/kvm_host.h | 5 ++-
> > 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 | 12 ++++++++
> > arch/x86/kvm/vmx.c | 49
> +++++++++++++++++++++++++++++++-
> > arch/x86/kvm/x86.c | 24 +++++++++++++--
> > 9 files changed, 102 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/cpufeature.h
> > b/arch/x86/include/asm/cpufeature.h
> > index 8d67d42..1aedbc0 100644
> > --- a/arch/x86/include/asm/cpufeature.h
> > +++ b/arch/x86/include/asm/cpufeature.h
> > @@ -203,6 +203,7 @@
> > #define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution
> Protection */
> > #define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation
> extensions */
> > #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
> > +#define X86_FEATURE_INVPCID (9*32+10) /* INVPCID instruction */
> >
> > #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
> >
> > diff --git a/arch/x86/include/asm/kvm_host.h
> > b/arch/x86/include/asm/kvm_host.h index 74c9edf..2c250e6 100644
> > --- a/arch/x86/include/asm/kvm_host.h
> > +++ b/arch/x86/include/asm/kvm_host.h
> > @@ -47,12 +47,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 0xFFFFFF0000000000ULL
> > #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS |
> \
> > 0xFFFFFF0000000000ULL)
> > #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))
> >
> > @@ -660,6 +661,8 @@ 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 (*pcid_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 0x00000008 /* Page Write Through */
> > #define X86_CR3_PCD 0x00000010 /* Page Cache Disable */
> > +#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */
> >
> > /*
> > * Intel CPU features in CR4
> > @@ -61,6 +62,7 @@
> > #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE
> exceptions */
> > #define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
> > #define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
> > +#define X86_CR4_PCIDE 0x00020000 /* enable PCID support */
> > #define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
> > #define X86_CR4_SMEP 0x00100000 /* 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_EXITING 0x00000040
> > #define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
> > #define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
> > +#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
> >
> >
> > #define PIN_BASED_EXT_INTR_MASK 0x00000001
> > @@ -281,6 +282,7 @@ enum vmcs_field {
> > #define EXIT_REASON_EPT_MISCONFIG 49
> > #define EXIT_REASON_WBINVD 54
> > #define EXIT_REASON_XSETBV 55
> > +#define EXIT_REASON_INVPCID 58
> >
> > /*
> > * Interruption-information format
> > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index
> > 9fed5be..fd0b6b9 100644
> > --- a/arch/x86/kvm/cpuid.c
> > +++ b/arch/x86/kvm/cpuid.c
> > @@ -201,6 +201,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2
> *entry, u32 function,
> > unsigned f_lm = 0;
> > #endif
> > unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
> > + unsigned f_pcid = kvm_x86_ops->pcid_supported() ? F(PCID) : 0;
> > + 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) |
> > F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
> > 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
> > F(F16C) | F(RDRAND);
> > @@ -247,7 +249,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2
> > *entry, u32 function,
> >
> > /* cpuid 7.0.ebx */
> > const u32 kvm_supported_word9_x86_features =
> > - F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS);
> > + F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS) |
> > +f_invpcid;
> >
> > /* all calls to cpuid_count() should be made on the same cpu */
> > get_cpu();
> > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index
> > 26d1fb4..e531d39 100644
> > --- a/arch/x86/kvm/cpuid.h
> > +++ b/arch/x86/kvm/cpuid.h
> > @@ -51,4 +51,12 @@ static inline bool guest_cpuid_has_osvw(struct
> kvm_vcpu *vcpu)
> > return best && (best->ecx & bit(X86_FEATURE_OSVW)); }
> >
> > +static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu) {
> > + struct kvm_cpuid_entry2 *best;
> > +
> > + best = kvm_find_cpuid_entry(vcpu, 1, 0);
> > + return best && (best->ecx & bit(X86_FEATURE_PCID)); }
> > +
> > #endif
> > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index
> > 0b7690e..d42fcbe 100644
> > --- a/arch/x86/kvm/svm.c
> > +++ b/arch/x86/kvm/svm.c
> > @@ -4012,6 +4012,16 @@ static bool svm_rdtscp_supported(void)
> > return false;
> > }
> >
> > +static bool svm_pcid_supported(void)
> > +{
> > + return false;
> > +}
> > +
> > +static bool svm_invpcid_supported(void) {
> > + return false;
> > +}
> > +
> > static bool svm_has_wbinvd_exit(void) {
> > return true;
> > @@ -4280,6 +4290,8 @@ static struct kvm_x86_ops svm_x86_ops = {
> > .cpuid_update = svm_cpuid_update,
> >
> > .rdtscp_supported = svm_rdtscp_supported,
> > + .pcid_supported = svm_pcid_supported,
> > + .invpcid_supported = svm_invpcid_supported,
> >
> > .set_supported_cpuid = svm_set_supported_cpuid,
> >
> > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index
> > d2bd719..1408d0b 100644
> > --- a/arch/x86/kvm/vmx.c
> > +++ b/arch/x86/kvm/vmx.c
> > @@ -839,6 +839,12 @@ static inline bool cpu_has_vmx_rdtscp(void)
> > SECONDARY_EXEC_RDTSCP;
> > }
> >
> > +static inline bool cpu_has_vmx_invpcid(void) {
> > + return vmcs_config.cpu_based_2nd_exec_ctrl &
> > + SECONDARY_EXEC_ENABLE_INVPCID;
> > +}
> > +
> > static inline bool cpu_has_virtual_nmis(void) {
> > return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
> @@
> > -1711,6 +1717,22 @@ static bool vmx_rdtscp_supported(void)
> > return cpu_has_vmx_rdtscp();
> > }
> >
> > +static bool vmx_pcid_supported(void)
> > +{
> > + /*
> > + * This function is only for determining whether to expose PCID bit
> > + * in KVM_GET_SUPPORTED_CPUID ioctl. The HYPERVISOR bit is used to
> > + * prevent guest hypervisors from exposing it as PCID is currently
> > + * not supported on L2 guests.
> > + */
> > + return (boot_cpu_has(X86_FEATURE_PCID) && !cpu_has_hypervisor); }
>
> This is not necessary: KVM will not expose secondary-exec-enable-invpcid
> support to the L1 guest, and so L1 guest will not attempt to expose PCID
> support to L2 guest.
>
On a platform with PCID but without INVPCID, PCID will be exposed when both L1 and L2 are running with '-cpu host' if the '!cpu_has_hypervisor' check doesn't exist. Lacking of INVPCID doesn't prevent PCID from being exposed.
> The boot cpu feature bit is tested by do_cpuid_ent, so this callback can be
> removed.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-21 0:40 ` Mao, Junjie
@ 2012-05-21 22:38 ` Marcelo Tosatti
2012-05-22 0:46 ` Mao, Junjie
0 siblings, 1 reply; 10+ messages in thread
From: Marcelo Tosatti @ 2012-05-21 22:38 UTC (permalink / raw)
To: Mao, Junjie; +Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
On Mon, May 21, 2012 at 12:40:42AM +0000, Mao, Junjie wrote:
> > -----Original Message-----
> > From: Marcelo Tosatti [mailto:mtosatti@redhat.com]
> > Sent: Saturday, May 19, 2012 5:51 AM
> > To: Mao, Junjie
> > Cc: nyh@math.technion.ac.il; 'kvm@vger.kernel.org'
> > Subject: Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with
> > EPT
> >
> > On Fri, May 18, 2012 at 06:17:05AM +0000, 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 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 <junjie.mao@intel.com>
> > > ---
> > > arch/x86/include/asm/cpufeature.h | 1 +
> > > arch/x86/include/asm/kvm_host.h | 5 ++-
> > > 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 | 12 ++++++++
> > > arch/x86/kvm/vmx.c | 49
> > +++++++++++++++++++++++++++++++-
> > > arch/x86/kvm/x86.c | 24 +++++++++++++--
> > > 9 files changed, 102 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/arch/x86/include/asm/cpufeature.h
> > > b/arch/x86/include/asm/cpufeature.h
> > > index 8d67d42..1aedbc0 100644
> > > --- a/arch/x86/include/asm/cpufeature.h
> > > +++ b/arch/x86/include/asm/cpufeature.h
> > > @@ -203,6 +203,7 @@
> > > #define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution
> > Protection */
> > > #define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation
> > extensions */
> > > #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
> > > +#define X86_FEATURE_INVPCID (9*32+10) /* INVPCID instruction */
> > >
> > > #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
> > >
> > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > b/arch/x86/include/asm/kvm_host.h index 74c9edf..2c250e6 100644
> > > --- a/arch/x86/include/asm/kvm_host.h
> > > +++ b/arch/x86/include/asm/kvm_host.h
> > > @@ -47,12 +47,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 0xFFFFFF0000000000ULL
> > > #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS |
> > \
> > > 0xFFFFFF0000000000ULL)
> > > #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))
> > >
> > > @@ -660,6 +661,8 @@ 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 (*pcid_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 0x00000008 /* Page Write Through */
> > > #define X86_CR3_PCD 0x00000010 /* Page Cache Disable */
> > > +#define X86_CR3_PCID_MASK 0x00000fff /* PCID Mask */
> > >
> > > /*
> > > * Intel CPU features in CR4
> > > @@ -61,6 +62,7 @@
> > > #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE
> > exceptions */
> > > #define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
> > > #define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
> > > +#define X86_CR4_PCIDE 0x00020000 /* enable PCID support */
> > > #define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
> > > #define X86_CR4_SMEP 0x00100000 /* 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_EXITING 0x00000040
> > > #define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
> > > #define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
> > > +#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
> > >
> > >
> > > #define PIN_BASED_EXT_INTR_MASK 0x00000001
> > > @@ -281,6 +282,7 @@ enum vmcs_field {
> > > #define EXIT_REASON_EPT_MISCONFIG 49
> > > #define EXIT_REASON_WBINVD 54
> > > #define EXIT_REASON_XSETBV 55
> > > +#define EXIT_REASON_INVPCID 58
> > >
> > > /*
> > > * Interruption-information format
> > > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index
> > > 9fed5be..fd0b6b9 100644
> > > --- a/arch/x86/kvm/cpuid.c
> > > +++ b/arch/x86/kvm/cpuid.c
> > > @@ -201,6 +201,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2
> > *entry, u32 function,
> > > unsigned f_lm = 0;
> > > #endif
> > > unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
> > > + unsigned f_pcid = kvm_x86_ops->pcid_supported() ? F(PCID) : 0;
> > > + 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) |
> > > F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
> > > 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
> > > F(F16C) | F(RDRAND);
> > > @@ -247,7 +249,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2
> > > *entry, u32 function,
> > >
> > > /* cpuid 7.0.ebx */
> > > const u32 kvm_supported_word9_x86_features =
> > > - F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS);
> > > + F(FSGSBASE) | F(BMI1) | F(AVX2) | F(SMEP) | F(BMI2) | F(ERMS) |
> > > +f_invpcid;
> > >
> > > /* all calls to cpuid_count() should be made on the same cpu */
> > > get_cpu();
> > > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index
> > > 26d1fb4..e531d39 100644
> > > --- a/arch/x86/kvm/cpuid.h
> > > +++ b/arch/x86/kvm/cpuid.h
> > > @@ -51,4 +51,12 @@ static inline bool guest_cpuid_has_osvw(struct
> > kvm_vcpu *vcpu)
> > > return best && (best->ecx & bit(X86_FEATURE_OSVW)); }
> > >
> > > +static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu) {
> > > + struct kvm_cpuid_entry2 *best;
> > > +
> > > + best = kvm_find_cpuid_entry(vcpu, 1, 0);
> > > + return best && (best->ecx & bit(X86_FEATURE_PCID)); }
> > > +
> > > #endif
> > > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index
> > > 0b7690e..d42fcbe 100644
> > > --- a/arch/x86/kvm/svm.c
> > > +++ b/arch/x86/kvm/svm.c
> > > @@ -4012,6 +4012,16 @@ static bool svm_rdtscp_supported(void)
> > > return false;
> > > }
> > >
> > > +static bool svm_pcid_supported(void)
> > > +{
> > > + return false;
> > > +}
> > > +
> > > +static bool svm_invpcid_supported(void) {
> > > + return false;
> > > +}
> > > +
> > > static bool svm_has_wbinvd_exit(void) {
> > > return true;
> > > @@ -4280,6 +4290,8 @@ static struct kvm_x86_ops svm_x86_ops = {
> > > .cpuid_update = svm_cpuid_update,
> > >
> > > .rdtscp_supported = svm_rdtscp_supported,
> > > + .pcid_supported = svm_pcid_supported,
> > > + .invpcid_supported = svm_invpcid_supported,
> > >
> > > .set_supported_cpuid = svm_set_supported_cpuid,
> > >
> > > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index
> > > d2bd719..1408d0b 100644
> > > --- a/arch/x86/kvm/vmx.c
> > > +++ b/arch/x86/kvm/vmx.c
> > > @@ -839,6 +839,12 @@ static inline bool cpu_has_vmx_rdtscp(void)
> > > SECONDARY_EXEC_RDTSCP;
> > > }
> > >
> > > +static inline bool cpu_has_vmx_invpcid(void) {
> > > + return vmcs_config.cpu_based_2nd_exec_ctrl &
> > > + SECONDARY_EXEC_ENABLE_INVPCID;
> > > +}
> > > +
> > > static inline bool cpu_has_virtual_nmis(void) {
> > > return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
> > @@
> > > -1711,6 +1717,22 @@ static bool vmx_rdtscp_supported(void)
> > > return cpu_has_vmx_rdtscp();
> > > }
> > >
> > > +static bool vmx_pcid_supported(void)
> > > +{
> > > + /*
> > > + * This function is only for determining whether to expose PCID bit
> > > + * in KVM_GET_SUPPORTED_CPUID ioctl. The HYPERVISOR bit is used to
> > > + * prevent guest hypervisors from exposing it as PCID is currently
> > > + * not supported on L2 guests.
> > > + */
> > > + return (boot_cpu_has(X86_FEATURE_PCID) && !cpu_has_hypervisor); }
> >
> > This is not necessary: KVM will not expose secondary-exec-enable-invpcid
> > support to the L1 guest, and so L1 guest will not attempt to expose PCID
> > support to L2 guest.
> >
>
> On a platform with PCID but without INVPCID, PCID will be exposed when both L1 and L2 are running with '-cpu host' if the '!cpu_has_hypervisor' check doesn't exist. Lacking of INVPCID doesn't prevent PCID from being exposed.
Is it correct to expose PCID when INVPCID-EXITING is not supported ?
That is, if INVPCID-EXITING is not supported by VMX, it should not
expose PCID (because INVPCID is not emulated, and as you mentioned
emulating it would be slow), no?
The problem with cpu_has_hypervisor check is that its Linux specific.
Any solution should also take into account other OSes running as L1
guest and virtualizing L2 guest.
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-21 22:38 ` Marcelo Tosatti
@ 2012-05-22 0:46 ` Mao, Junjie
2012-05-23 1:52 ` Marcelo Tosatti
0 siblings, 1 reply; 10+ messages in thread
From: Mao, Junjie @ 2012-05-22 0:46 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
> > > @@
> > > > -1711,6 +1717,22 @@ static bool vmx_rdtscp_supported(void)
> > > > return cpu_has_vmx_rdtscp();
> > > > }
> > > >
> > > > +static bool vmx_pcid_supported(void) {
> > > > + /*
> > > > + * This function is only for determining whether to expose PCID bit
> > > > + * in KVM_GET_SUPPORTED_CPUID ioctl. The HYPERVISOR bit is
> used to
> > > > + * prevent guest hypervisors from exposing it as PCID is currently
> > > > + * not supported on L2 guests.
> > > > + */
> > > > + return (boot_cpu_has(X86_FEATURE_PCID)
> && !cpu_has_hypervisor);
> > > > +}
> > >
> > > This is not necessary: KVM will not expose
> > > secondary-exec-enable-invpcid support to the L1 guest, and so L1
> > > guest will not attempt to expose PCID support to L2 guest.
> > >
> >
> > On a platform with PCID but without INVPCID, PCID will be exposed when
> both L1 and L2 are running with '-cpu host' if the '!cpu_has_hypervisor' check
> doesn't exist. Lacking of INVPCID doesn't prevent PCID from being exposed.
>
> Is it correct to expose PCID when INVPCID-EXITING is not supported ?
>
> That is, if INVPCID-EXITING is not supported by VMX, it should not expose PCID
> (because INVPCID is not emulated, and as you mentioned emulating it would
> be slow), no?
Though PCID brings little performance gain without INVPCID, it doesn't prevent PCID from being exposed as these two features are controlled separately now. And there do exist platforms which has PCID but doesn't have INVPCID. It's up to the user to decide whether to use PCID when INVPCID is not present.
The previous patch regards PCID and INVPCID as a whole because qemu doesn't support cpuid leaf 7 configuration at present. This is not the case in this version.
>
> The problem with cpu_has_hypervisor check is that its Linux specific.
> Any solution should also take into account other OSes running as L1 guest and
> virtualizing L2 guest.
Is there any other way, which applies to all host hypervisors, to know if kvm is running as a guest hypervisor?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-22 0:46 ` Mao, Junjie
@ 2012-05-23 1:52 ` Marcelo Tosatti
2012-05-23 5:02 ` Mao, Junjie
0 siblings, 1 reply; 10+ messages in thread
From: Marcelo Tosatti @ 2012-05-23 1:52 UTC (permalink / raw)
To: Mao, Junjie; +Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
On Tue, May 22, 2012 at 12:46:54AM +0000, Mao, Junjie wrote:
> > > > @@
> > > > > -1711,6 +1717,22 @@ static bool vmx_rdtscp_supported(void)
> > > > > return cpu_has_vmx_rdtscp();
> > > > > }
> > > > >
> > > > > +static bool vmx_pcid_supported(void) {
> > > > > + /*
> > > > > + * This function is only for determining whether to expose PCID bit
> > > > > + * in KVM_GET_SUPPORTED_CPUID ioctl. The HYPERVISOR bit is
> > used to
> > > > > + * prevent guest hypervisors from exposing it as PCID is currently
> > > > > + * not supported on L2 guests.
> > > > > + */
> > > > > + return (boot_cpu_has(X86_FEATURE_PCID)
> > && !cpu_has_hypervisor);
> > > > > +}
> > > >
> > > > This is not necessary: KVM will not expose
> > > > secondary-exec-enable-invpcid support to the L1 guest, and so L1
> > > > guest will not attempt to expose PCID support to L2 guest.
> > > >
> > >
> > > On a platform with PCID but without INVPCID, PCID will be exposed when
> > both L1 and L2 are running with '-cpu host' if the '!cpu_has_hypervisor' check
> > doesn't exist. Lacking of INVPCID doesn't prevent PCID from being exposed.
> >
> > Is it correct to expose PCID when INVPCID-EXITING is not supported ?
> >
> > That is, if INVPCID-EXITING is not supported by VMX, it should not expose PCID
> > (because INVPCID is not emulated, and as you mentioned emulating it would
> > be slow), no?
>
> Though PCID brings little performance gain without INVPCID, it doesn't prevent PCID from being exposed as these two features are controlled separately now. And there do exist platforms which has PCID but doesn't have INVPCID. It's up to the user to decide whether to use PCID when INVPCID is not present.
OK, so in case INVPCID is not available, all instructions which would
otherwise flush PCID-tagged TLB entries in VMX root operation also flush
them in VMX non root operation. Example: CR3 write.
>
> The previous patch regards PCID and INVPCID as a whole because qemu doesn't support cpuid leaf 7 configuration at present. This is not the case in this version.
> > The problem with cpu_has_hypervisor check is that its Linux specific.
> > Any solution should also take into account other OSes running as L1 guest and
> > virtualizing L2 guest.
>
> Is there any other way, which applies to all host hypervisors, to know if kvm is running as a guest hypervisor?
The point is that other hypervisor might be running as L1 guest.
The problem with enabling PCID for the L2 guest is that it
can share same PCID values with the L1 hypervisor.
However, if the L1 hypervisor enables and configures VPID (given that
the L0 hypervisor emulates and exposes it), there is no problem
in enabling PCID for both L1 and L2 guests because TLB entries
will be differentiated by their VPID values, even if their PCID
values are the same.
So i think that checking whether EPT _and_ VPID are supported
should be a precondition to enable PCID support for guests.
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-23 1:52 ` Marcelo Tosatti
@ 2012-05-23 5:02 ` Mao, Junjie
2012-05-25 0:59 ` Marcelo Tosatti
0 siblings, 1 reply; 10+ messages in thread
From: Mao, Junjie @ 2012-05-23 5:02 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
> >
> > The previous patch regards PCID and INVPCID as a whole because qemu
> doesn't support cpuid leaf 7 configuration at present. This is not the case in this
> version.
> > > The problem with cpu_has_hypervisor check is that its Linux specific.
> > > Any solution should also take into account other OSes running as L1
> > > guest and virtualizing L2 guest.
> >
> > Is there any other way, which applies to all host hypervisors, to know if kvm is
> running as a guest hypervisor?
>
> The point is that other hypervisor might be running as L1 guest.
>
> The problem with enabling PCID for the L2 guest is that it can share same PCID
> values with the L1 hypervisor.
>
> However, if the L1 hypervisor enables and configures VPID (given that
> the L0 hypervisor emulates and exposes it), there is no problem in enabling
> PCID for both L1 and L2 guests because TLB entries will be differentiated by
> their VPID values, even if their PCID values are the same.
>
This may not be a problem because:
1. If both L1 and L2 use VPID, there's no problem as you have mentioned.
2. If neither L1 and L2 use VPID, the TLB entries are all tagged with VPID 0 and any VM entries or exits will invalidate them.
3. If one of L1 and L2 uses VPID but the other don't, the TLB entries still have different VPID and won't affect each other.
I haven't thought over exposing PCID to L2 guests before but it seems that no problem exists in exposing PCID to L2 guests. Is it looks ok to you if PCID is always exposed, no matter for L1 or L2 guests?
> So i think that checking whether EPT _and_ VPID are supported should be a
> precondition to enable PCID support for guests.
>
Should this check be carried out on L0 too? If so, this will add one more dependency of PCID on VPID, which doesn't exist in the manual.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-23 5:02 ` Mao, Junjie
@ 2012-05-25 0:59 ` Marcelo Tosatti
2012-05-29 14:19 ` Avi Kivity
0 siblings, 1 reply; 10+ messages in thread
From: Marcelo Tosatti @ 2012-05-25 0:59 UTC (permalink / raw)
To: Mao, Junjie, Avi Kivity
Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
On Wed, May 23, 2012 at 05:02:28AM +0000, Mao, Junjie wrote:
> > >
> > > The previous patch regards PCID and INVPCID as a whole because qemu
> > doesn't support cpuid leaf 7 configuration at present. This is not the case in this
> > version.
> > > > The problem with cpu_has_hypervisor check is that its Linux specific.
> > > > Any solution should also take into account other OSes running as L1
> > > > guest and virtualizing L2 guest.
> > >
> > > Is there any other way, which applies to all host hypervisors, to know if kvm is
> > running as a guest hypervisor?
> >
> > The point is that other hypervisor might be running as L1 guest.
> >
> > The problem with enabling PCID for the L2 guest is that it can share same PCID
> > values with the L1 hypervisor.
> >
> > However, if the L1 hypervisor enables and configures VPID (given that
> > the L0 hypervisor emulates and exposes it), there is no problem in enabling
> > PCID for both L1 and L2 guests because TLB entries will be differentiated by
> > their VPID values, even if their PCID values are the same.
> >
>
> This may not be a problem because:
>
> 1. If both L1 and L2 use VPID, there's no problem as you have mentioned.
> 2. If neither L1 and L2 use VPID, the TLB entries are all tagged with VPID 0 and any VM entries or exits will invalidate them.
> 3. If one of L1 and L2 uses VPID but the other don't, the TLB entries still have different VPID and won't affect each other.
>
> I haven't thought over exposing PCID to L2 guests before but it seems that no problem exists in exposing PCID to L2 guests. Is it looks ok to you if PCID is always exposed, no matter for L1 or L2 guests?
Yes, it appears to be OK, because of the TLB flush on vm-entry/vm-exit
without VPID (2 above).
Avi ?
> > So i think that checking whether EPT _and_ VPID are supported should be a
> > precondition to enable PCID support for guests.
> >
>
> Should this check be carried out on L0 too? If so, this will add one more dependency of PCID on VPID, which doesn't exist in the manual.
Actually it is not necessary because L0 cannot access data which is
EPT-tagged (and you already require EPT).
So it is fine to remove the cpu_has_hypervisor check along with
vmx_pcid_supported().
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-25 0:59 ` Marcelo Tosatti
@ 2012-05-29 14:19 ` Avi Kivity
2012-06-14 2:02 ` Mao, Junjie
0 siblings, 1 reply; 10+ messages in thread
From: Avi Kivity @ 2012-05-29 14:19 UTC (permalink / raw)
To: Marcelo Tosatti
Cc: Mao, Junjie, nyh@math.technion.ac.il,
'kvm@vger.kernel.org'
On 05/25/2012 03:59 AM, Marcelo Tosatti wrote:
>> >
>> > The problem with enabling PCID for the L2 guest is that it can share same PCID
>> > values with the L1 hypervisor.
>> >
>> > However, if the L1 hypervisor enables and configures VPID (given that
>> > the L0 hypervisor emulates and exposes it), there is no problem in enabling
>> > PCID for both L1 and L2 guests because TLB entries will be differentiated by
>> > their VPID values, even if their PCID values are the same.
>> >
>>
>> This may not be a problem because:
>>
>> 1. If both L1 and L2 use VPID, there's no problem as you have mentioned.
>> 2. If neither L1 and L2 use VPID, the TLB entries are all tagged with VPID 0 and any VM entries or exits will invalidate them.
>> 3. If one of L1 and L2 uses VPID but the other don't, the TLB entries still have different VPID and won't affect each other.
>>
>> I haven't thought over exposing PCID to L2 guests before but it seems that no problem exists in exposing PCID to L2 guests. Is it looks ok to you if PCID is always exposed, no matter for L1 or L2 guests?
>
> Yes, it appears to be OK, because of the TLB flush on vm-entry/vm-exit
> without VPID (2 above).
>
> Avi ?
I agree.
>
>> > So i think that checking whether EPT _and_ VPID are supported should be a
>> > precondition to enable PCID support for guests.
>> >
>>
>> Should this check be carried out on L0 too? If so, this will add one more dependency of PCID on VPID, which doesn't exist in the manual.
>
> Actually it is not necessary because L0 cannot access data which is
> EPT-tagged (and you already require EPT).
>
> So it is fine to remove the cpu_has_hypervisor check along with
> vmx_pcid_supported().
>
We can hide INVPCID from the nested guest (by not exposing
IA32_EPT_VPID_CAP) but we can't avoid exposing PCID. So we have to be
sure that if a nested guest sets CR4.PCID, it should work fine.
btw, it looks like the lines
vmx_set_cr0(vcpu, vmcs12->guest_cr0);
vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
vmx_set_cr4(vcpu, vmcs12->guest_cr4);
vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
in prepare_vmcs02() are too dangerous. They only let the hardware check
cr4, but not software, so a future cr4 bit which is not handled
correctly by kvm can be set in a nested guest. L1 appears to be
protected, we use kvm_set_cr4().
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT
2012-05-29 14:19 ` Avi Kivity
@ 2012-06-14 2:02 ` Mao, Junjie
0 siblings, 0 replies; 10+ messages in thread
From: Mao, Junjie @ 2012-06-14 2:02 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti
Cc: nyh@math.technion.ac.il, 'kvm@vger.kernel.org'
Terribly sorry for the late reply. I'm out of work for some unexpected issues the last few weeks.
> >> > So i think that checking whether EPT _and_ VPID are supported
> >> > should be a precondition to enable PCID support for guests.
> >> >
> >>
> >> Should this check be carried out on L0 too? If so, this will add one more
> dependency of PCID on VPID, which doesn't exist in the manual.
> >
> > Actually it is not necessary because L0 cannot access data which is
> > EPT-tagged (and you already require EPT).
> >
> > So it is fine to remove the cpu_has_hypervisor check along with
> > vmx_pcid_supported().
> >
>
> We can hide INVPCID from the nested guest (by not exposing
> IA32_EPT_VPID_CAP) but we can't avoid exposing PCID. So we have to be
> sure that if a nested guest sets CR4.PCID, it should work fine.
>
I'll update the patch so that guest hypervisor can also expose PCID to L2 guests if it is supported.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-06-14 2:02 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-18 6:17 [PATCH v3] KVM: x86: Implement PCID/INVPCID for guests with EPT Mao, Junjie
2012-05-18 21:51 ` Marcelo Tosatti
2012-05-21 0:40 ` Mao, Junjie
2012-05-21 22:38 ` Marcelo Tosatti
2012-05-22 0:46 ` Mao, Junjie
2012-05-23 1:52 ` Marcelo Tosatti
2012-05-23 5:02 ` Mao, Junjie
2012-05-25 0:59 ` Marcelo Tosatti
2012-05-29 14:19 ` Avi Kivity
2012-06-14 2:02 ` Mao, Junjie
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox