KVM: VMX: Enable Virtual Processor Identification (VPID)
PATCH 1/1 KVM: VMX: Enable Virtual Processor Identification (VPID)
From 39551508c869f678f028655c062b3cb5fe4715bc Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 17 Jan 2008 15:14:33 +0800
Subject: [PATCH] KVM: VMX: Enable Virtual Processor Identification (VPID)
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
--- arch/x86/kvm/vmx.c | 84 +++++++++++++++++++++++++++++++++++++++++++- arch/x86/kvm/vmx.h | 6 +++ include/asm-x86/kvm_host.h | 1 + 3 files changed, 90 insertions(+), 1 deletions(-)
arch/x86/kvm/vmx.c +7 -0
@@ -37,6 +37,9 @@ MODULE_LICENSE("GPL");static int bypass_guest_pf =1 ;module_param (bypass_guest_pf, bool,0 ); +static int enable_vpid =1 ; +module_param (enable_vpid, bool,0 ); +struct vmcs {u32 revision_id;u32 abort;
@@ -71,6 +74,7 @@ struct vcpu_vmx {unsigned rip; } irq; } rmode; +int vpid; };static inline struct vcpu_vmx *to_vmx (struct kvm_vcpu *vcpu)
@@ -86,6 +90,9 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);static struct page *vmx_io_bitmap_a;static struct page *vmx_io_bitmap_b; +static DECLARE_BITMAP(vmx_vpid_bitmap, VPID_BITMAP_SIZE / BITS_PER_BYTE); +static DEFINE_SPINLOCK (vmx_vpid_lock); + static struct vmcs_config { int size; int order;
@@ -204,6 +211,12 @@ static inline int vm_need_virtualize_apic_accesses(struct
kvm *kvm)
(irqchip_in_kernel(kvm)));
}
+static inline int cpu_has_vmx_vpid(void)
+{
+ return (vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_VPID);
+}
+
static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
{
int i;
@@ -214,6 +227,25 @@ static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
return -1;
}
+static inline void __invvpid(int ext, u16 vpid, gva_t gva) +{
+ struct {
+ u64 vpid:16;
+ u64 rsvd:48;
+ u64 gva;
+ } operand = {vpid, 0, gva};
+
+ if (!enable_vpid || !cpu_has_vmx_vpid())
+ return;
+
+ asm volatile (ASM_VMX_INVVPID
+ /* CF==1 or ZF==1 --> rc = -1 */ + "; ja 1f ; ud2 ; 1:\n" + : + : "a" (&operand), "c" (ext) + : "memory");
+}
+
static struct kvm_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr) {
int i;
@@ -257,6 +289,19 @@ static void vcpu_clear(struct vcpu_vmx *vmx)
vmx->launched = 0;
}
+static inline void vpid_sync_vcpu_all(struct vcpu_vmx *vmx)
+{
+ if (vmx->vpid == 0)
+ return;
+
+ __invvpid(VPID_SYNC_EXTENT_SINGLE_CONTEXT, vmx->vpid, 0);
+}
+
+static inline void vpid_sync_all(void)
+{
+ __invvpid(VPID_SYNC_EXTENT_ALL_CONTEXT, 0, 0);
+}
+
static unsigned long vmcs_readl(unsigned long field)
{
unsigned long value;
@@ -493,6 +538,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
if (vcpu->cpu != cpu) {
vcpu_clear(vmx);
kvm_migrate_apic_timer(vcpu);
+ vpid_sync_vcpu_all(vmx);
}
if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
@@ -973,7 +1019,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
min = 0;
opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
- SECONDARY_EXEC_WBINVD_EXITING;
+ SECONDARY_EXEC_WBINVD_EXITING |
+ SECONDARY_EXEC_ENABLE_VPID;
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,
&_cpu_based_2nd_exec_control) < 0)
return -EIO;
@@ -1276,6 +1323,8 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) {
+ vpid_sync_vcpu_all(to_vmx(vcpu));
+
vmcs_writel(GUEST_CR3, cr3);
if (vcpu->arch.cr0 & X86_CR0_PE)
vmx_fpu_deactivate(vcpu);
@@ -1492,6 +1541,22 @@ out:
return r;
}
+static void allocate_vpid(struct vcpu_vmx *vmx)
+{
+ int vpid;
+
+ vmx->vpid = 0;
+ if (!enable_vpid || !cpu_has_vmx_vpid())
+ return;
+ spin_lock(&vmx_vpid_lock);
+ vpid = find_first_zero_bit(vmx_vpid_bitmap, VPID_BITMAP_SIZE);
+ if (vpid < VPID_BITMAP_SIZE) {
+ vmx->vpid = vpid;
+ __set_bit(vpid, vmx_vpid_bitmap);
+ }
+ spin_unlock(&vmx_vpid_lock);
+}
+
/*
* Sets up the vmcs for emulated real mode.
*/
@@ -1530,6 +1595,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
exec_control &=
~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ if (vmx->vpid == 0)
+ exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
}
@@ -1705,6 +1772,11 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmcs_write64(APIC_ACCESS_ADDR,
page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
+ if (vmx->vpid != 0) {
+ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+ printk(KERN_DEBUG "VPID enabled, VPID is 0x%x\n", vmx->vpid);
+ }
+
vmx->vcpu.arch.cr0 = 0x60000010; vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */ vmx_set_cr4(&vmx->vcpu, 0);
@@ -1714,6 +1786,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmx_fpu_activate(&vmx->vcpu); update_exception_bitmap(&vmx->vcpu);
+ vpid_sync_all();
+
return 0;
out:
@@ -2490,6 +2564,10 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ spin_lock(&vmx_vpid_lock);
+ if (vmx->vpid != 0)
+ __clear_bit(vmx->vpid, vmx_vpid_bitmap);
+ spin_unlock(&vmx_vpid_lock);
vmx_free_vmcs(vcpu);
kfree(vmx->host_msrs);
kfree(vmx->guest_msrs);
@@ -2506,6 +2584,8 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
if (!vmx)
return ERR_PTR(-ENOMEM);
+ allocate_vpid(vmx);
+
err = kvm_vcpu_init(&vmx->vcpu, kvm, id); if (err)
goto free_vcpu;
@@ -2650,6 +2730,8 @@ static int __init vmx_init(void)
memset(iova, 0xff, PAGE_SIZE); kunmap(vmx_io_bitmap_b);
+ set_bit(0, vmx_vpid_bitmap); /* 0 is reversed for host */
+
r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE); if (r)
goto out1;
arch/x86/kvm/vmx.h +6 -0
@@ -49,6 +49,7 @@* Definitions of Secondary Processor-Based VM-Execution Controls. */ #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 +#define SECONDARY_EXEC_ENABLE_VPID 0x00000020#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
@@ -65,6 +66,7 @@/* VMCS Encodings */ enum vmcs_field { +VIRTUAL_PROCESSOR_ID =0x00000000 ,GUEST_ES_SELECTOR =0x00000800 ,GUEST_CS_SELECTOR =0x00000802 ,GUEST_SS_SELECTOR =0x00000804 ,
@@ -321,4 +323,8 @@ enum vmcs_field {#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 +#define VPID_BITMAP_SIZE (1 << 16)*BITS_PER_BYTE +#define VPID_SYNC_EXTENT_SINGLE_CONTEXT 1 +#define VPID_SYNC_EXTENT_ALL_CONTEXT 2 +#endif
include/asm-x86/kvm_host.h +0 -0
@@ -600,6 +600,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu,
u32 error_code)
#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4" #define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4" #define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
#define MSR_IA32_TIME_STAMP_COUNTER 0x010
Signature · 1 line
debian.1.5.3.7.1-dirty
From 39551508c869f678f028655c062b3cb5fe4715bc Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 17 Jan 2008 15:14:33 +0800
Subject: [PATCH] KVM: VMX: Enable Virtual Processor Identification (VPID)
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
--- arch/x86/kvm/vmx.c | 84 +++++++++++++++++++++++++++++++++++++++++++- arch/x86/kvm/vmx.h | 6 +++ include/asm-x86/kvm_host.h | 1 + 3 files changed, 90 insertions(+), 1 deletions(-)
arch/x86/kvm/vmx.c +83 -1
180 lines not on this page · raw message
arch/x86/kvm/vmx.h +6 -0
@@ -49,6 +49,7 @@* Definitions of Secondary Processor-Based VM-Execution Controls. */ #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 +#define SECONDARY_EXEC_ENABLE_VPID 0x00000020#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
@@ -65,6 +66,7 @@/* VMCS Encodings */ enum vmcs_field { +VIRTUAL_PROCESSOR_ID =0x00000000 ,GUEST_ES_SELECTOR =0x00000800 ,GUEST_CS_SELECTOR =0x00000802 ,GUEST_SS_SELECTOR =0x00000804 ,
@@ -321,4 +323,8 @@ enum vmcs_field {#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 +#define VPID_BITMAP_SIZE (1 << 16)*BITS_PER_BYTE +#define VPID_SYNC_EXTENT_SINGLE_CONTEXT 1 +#define VPID_SYNC_EXTENT_ALL_CONTEXT 2 +#endif
include/asm-x86/kvm_host.h +1 -0
@@ -600,6 +600,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4"#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4"#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30" +#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"#define MSR_IA32_TIME_STAMP_COUNTER 0x010
Signature · 1 line
debian.1.5.3.7.1-dirty
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 200801241426.55928.sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Quoted 9 lines · Sheng
From
39551508c869f678f028655c062b3cb5fe4715bcMon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 17 Jan 2008 15:14:33 +0800
Subject: [PATCH] KVM: VMX: Enable Virtual Processor Identification (VPID)To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
Is it something supported by new processors only? If yes, could you please tell us which CPU support that?
Thanks,
Aurelien
Signature · 9 lines
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [email protected] | [email protected] `- people.debian.org/~aurel32 | www.aurel32.net ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 6 lines · On Thursday 24 January 2008 19:15:57 Aurelien Jarno wrote:
Quoted 5 lines · Sheng
From
39551508c869f678f028655c062b3cb5fe4715bcMon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 17 Jan 2008 15:14:33 +0800
Subject: [PATCH] KVM: VMX: Enable Virtual Processor Identification (VPID)
Quoted 6 lines
Quoted 3 lines
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
Is it something supported by new processors only? If yes, could you please tell us which CPU support that?
Nehalem microarchitecture.
Signature · 7 lines
Thanks Yang, Sheng ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Quoted 8 lines · Sheng
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
+#define
VPID_BITMAP_SIZE(1 << 16)*BITS_PER_BYTE
This is strange; I think that just (1 << 16) would be simpler later on.
Please also rename to VMX_NR_VPIDS, since this header is generally implementation independent (just declares vmx constants).
arch/x86/kvm/vmx.c static DEFINE_PER_CPU(struct vmcs *, current_vmcs); · line 94
Quoted 7 lines
static inline struct
vcpu_vmx*to_vmx(structkvm_vcpu*vcpu)arch/x86/kvm/vmx.c +1
-0@@ -86,6 +90,9 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);static struct page *vmx_io_bitmap_a;static struct page *vmx_io_bitmap_b; +static DECLARE_BITMAP(vmx_vpid_bitmap, VPID_BITMAP_SIZE / BITS_PER_BYTE);
Like here, you could pass VPID_BITMAP_SIZE.
arch/x86/kvm/vmx.c out: · line 1552
Quoted 11 lines
arch/x86/kvm/vmx.c +9
-0+static void allocate_vpid (struct vcpu_vmx *vmx) +{ +int vpid; + + vmx->vpid =0 ; +if (!enable_vpid || !cpu_has_vmx_vpid ()) +return ; +spin_lock (&vmx_vpid_lock); + vpid =find_first_zero_bit (vmx_vpid_bitmap,VPID_BITMAP_SIZE );
This can overflow since VPID_BITMAP_SIZE is 64K * 8.
arch/x86/kvm/vmx.c static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) · line 1778
Quoted 7 lines
apic_access_page));arch/x86/kvm/vmx.c +4
-0+if (vmx->vpid !=0 ) { +vmcs_write16 (VIRTUAL_PROCESSOR_ID , vmx->vpid); +printk (KERN_DEBUG "VPID enabled, VPID is 0x%x\n" , vmx->vpid); + }
Please drop the printk().
arch/x86/kvm/vmx.c static int __init vmx_init(void) · line 2734
Quoted 5 lines
ap_b);arch/x86/kvm/vmx.c +2
-0+set_bit (0 , vmx_vpid_bitmap);/* 0 is reversed for host */ +
reversed -> reserved, some letters got reserved here. See also Rik can Riel's signature.
Need to add vpid support to vmx_flush_tlb() (and perhaps call it from vmx_set_cr3).
Signature · 7 lines
Any sufficiently difficult bug is indistinguishable from a feature. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 47987B7C.1080509-atKUWr5tajBWk0Htik3J/[email protected]
Quoted 24 lines · On Thursday 24 January 2008 19:50:20 Avi Kivity wrote:
Quoted 7 lines · Sheng
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
+#define
VPID_BITMAP_SIZE(1 << 16)*BITS_PER_BYTEThis is strange; I think that just (1 << 16) would be simpler later on.
Please also rename to
VMX_NR_VPIDS, since this header is generally implementation independent (just declares vmx constants).Review static DEFINE_PER_CPU(struct vmcs *, current_vmcs); · line 94
Quoted 7 lines
static inline struct
vcpu_vmx*to_vmx(structkvm_vcpu*vcpu)(quoted diff) +1
-0@@ -86,6 +90,9 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs); static struct page *vmx_io_bitmap_a; static struct page *vmx_io_bitmap_b; +static DECLARE_BITMAP(vmx_vpid_bitmap, VPID_BITMAP_SIZE / BITS_PER_BYTE);Like here, you could pass
VPID_BITMAP_SIZE.
Quoted 11 lines
Review static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
Quoted 9 lines
(quoted diff) +9
-0+static void allocate_vpid(struct vcpu_vmx *vmx) +{ + int vpid; + + vmx->vpid = 0; + if (!enable_vpid || !cpu_has_vmx_vpid()) + return; + spin_lock(&vmx_vpid_lock); + vpid = find_first_zero_bit(vmx_vpid_bitmap, VPID_BITMAP_SIZE);This can overflow since
VPID_BITMAP_SIZEis 64K * 8.
O... Sorry for silly fault...
Quoted 17 lines
Review
Quoted 7 lines
apic_access_page));(quoted diff) +4
-0+ if (vmx->vpid != 0) { + vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); + printk(KERN_DEBUG "VPID enabled, VPID is 0x%x\n", vmx->vpid); + }Please drop the
printk().Review
Quoted 4 lines
ap_b);(quoted diff) +2
-0+ set_bit(0, vmx_vpid_bitmap); /* 0 is reversed for host */ +reversed -> reserved, some letters got reserved here. See also Rik can Riel's signature.
...
Quoted 3 lines
Need to add vpid support to
vmx_flush_tlb()(and perhaps call it fromvmx_set_cr3).
Yeah.
Here is the updated patch:
---
From 111566e3753b1abc24b073ad549fb97819d216cb Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 17 Jan 2008 15:14:33 +0800
Subject: [PATCH] KVM: VMX: Enable Virtual Processor Identification (VPID)
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
--- arch/x86/kvm/vmx.c | 90 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/vmx.h | 6 +++ include/asm-x86/kvm_host.h | 1 + 3 files changed, 92 insertions(+), 5 deletions(-)
arch/x86/kvm/vmx.c +7 -0
@@ -37,6 +37,9 @@ MODULE_LICENSE("GPL");static int bypass_guest_pf =1 ;module_param (bypass_guest_pf, bool,0 ); +static int enable_vpid =1 ; +module_param (enable_vpid, bool,0 ); +struct vmcs {u32 revision_id;u32 abort;
@@ -71,6 +74,7 @@ struct vcpu_vmx {unsigned rip; } irq; } rmode; +int vpid; };static inline struct vcpu_vmx *to_vmx (struct kvm_vcpu *vcpu)
@@ -86,6 +90,9 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);static struct page *vmx_io_bitmap_a;static struct page *vmx_io_bitmap_b; +static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS); +static DEFINE_SPINLOCK (vmx_vpid_lock); + static struct vmcs_config { int size; int order;
@@ -204,6 +211,12 @@ static inline int vm_need_virtualize_apic_accesses(struct
kvm *kvm)
(irqchip_in_kernel(kvm)));
}
+static inline int cpu_has_vmx_vpid(void)
+{
+ return (vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_VPID);
+}
+
static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
{
int i;
@@ -214,6 +227,25 @@ static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
return -1;
}
+static inline void __invvpid(int ext, u16 vpid, gva_t gva) +{
+ struct {
+ u64 vpid:16;
+ u64 rsvd:48;
+ u64 gva;
+ } operand = {vpid, 0, gva};
+
+ if (!enable_vpid || !cpu_has_vmx_vpid())
+ return;
+
+ asm volatile (ASM_VMX_INVVPID
+ /* CF==1 or ZF==1 --> rc = -1 */ + "; ja 1f ; ud2 ; 1:\n" + : + : "a" (&operand), "c" (ext) + : "memory");
+}
+
static struct kvm_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr) {
int i;
@@ -257,6 +289,19 @@ static void vcpu_clear(struct vcpu_vmx *vmx)
vmx->launched = 0;
}
+static inline void vpid_sync_vcpu_all(struct vcpu_vmx *vmx)
+{
+ if (vmx->vpid == 0)
+ return;
+
+ __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vmx->vpid, 0);
+}
+
+static inline void vpid_sync_all(void)
+{
+ __invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
+}
+
static unsigned long vmcs_readl(unsigned long field)
{
unsigned long value;
@@ -493,6 +538,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
if (vcpu->cpu != cpu) {
vcpu_clear(vmx);
kvm_migrate_apic_timer(vcpu);
+ vpid_sync_vcpu_all(vmx);
}
if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
@@ -973,7 +1019,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
min = 0;
opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
- SECONDARY_EXEC_WBINVD_EXITING;
+ SECONDARY_EXEC_WBINVD_EXITING |
+ SECONDARY_EXEC_ENABLE_VPID;
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,
&_cpu_based_2nd_exec_control) < 0)
return -EIO;
@@ -1240,6 +1287,11 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
#endif
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+{
+ vpid_sync_vcpu_all(to_vmx(vcpu));
+}
+
static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
{
vcpu->arch.cr4 &= KVM_GUEST_CR4_MASK;
@@ -1276,6 +1328,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) {
+ vmx_flush_tlb(vcpu);
vmcs_writel(GUEST_CR3, cr3);
if (vcpu->arch.cr0 & X86_CR0_PE)
vmx_fpu_deactivate(vcpu);
@@ -1492,6 +1545,22 @@ out:
return r;
}
+static void allocate_vpid(struct vcpu_vmx *vmx)
+{
+ int vpid;
+
+ vmx->vpid = 0;
+ if (!enable_vpid || !cpu_has_vmx_vpid())
+ return;
+ spin_lock(&vmx_vpid_lock);
+ vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
+ if (vpid < VMX_NR_VPIDS) {
+ vmx->vpid = vpid;
+ __set_bit(vpid, vmx_vpid_bitmap);
+ }
+ spin_unlock(&vmx_vpid_lock);
+}
+
/*
* Sets up the vmcs for emulated real mode.
*/
@@ -1530,6 +1599,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
exec_control &=
~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ if (vmx->vpid == 0)
+ exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
}
@@ -1705,6 +1776,9 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmcs_write64(APIC_ACCESS_ADDR,
page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
+ if (vmx->vpid != 0)
+ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+
vmx->vcpu.arch.cr0 = 0x60000010; vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */ vmx_set_cr4(&vmx->vcpu, 0);
@@ -1714,6 +1788,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmx_fpu_activate(&vmx->vcpu); update_exception_bitmap(&vmx->vcpu);
+ vpid_sync_all();
+
return 0;
out:
@@ -2222,10 +2298,6 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
return 0;
}
-static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
-{
-}
-
static void update_tpr_threshold(struct kvm_vcpu *vcpu)
{
int max_irr, tpr;
@@ -2490,6 +2562,10 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ spin_lock(&vmx_vpid_lock);
+ if (vmx->vpid != 0)
+ __clear_bit(vmx->vpid, vmx_vpid_bitmap);
+ spin_unlock(&vmx_vpid_lock);
vmx_free_vmcs(vcpu);
kfree(vmx->host_msrs);
kfree(vmx->guest_msrs);
@@ -2506,6 +2582,8 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
if (!vmx)
return ERR_PTR(-ENOMEM);
+ allocate_vpid(vmx);
+
err = kvm_vcpu_init(&vmx->vcpu, kvm, id); if (err)
goto free_vcpu;
@@ -2650,6 +2728,8 @@ static int __init vmx_init(void)
memset(iova, 0xff, PAGE_SIZE); kunmap(vmx_io_bitmap_b);
+ set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
+
r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE); if (r)
goto out1;
arch/x86/kvm/vmx.h +6 -0
@@ -49,6 +49,7 @@* Definitions of Secondary Processor-Based VM-Execution Controls. */ #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 +#define SECONDARY_EXEC_ENABLE_VPID 0x00000020#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
@@ -65,6 +66,7 @@/* VMCS Encodings */ enum vmcs_field { +VIRTUAL_PROCESSOR_ID =0x00000000 ,GUEST_ES_SELECTOR =0x00000800 ,GUEST_CS_SELECTOR =0x00000802 ,GUEST_SS_SELECTOR =0x00000804 ,
@@ -321,4 +323,8 @@ enum vmcs_field {#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 +#define VMX_NR_VPIDS (1 << 16) +#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1 +#define VMX_VPID_EXTENT_ALL_CONTEXT 2 +#endif
include/asm-x86/kvm_host.h +0 -0
@@ -600,6 +600,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu,
u32 error_code)
#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4" #define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4" #define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
#define MSR_IA32_TIME_STAMP_COUNTER 0x010
Signature · 1 line
debian.1.5.3.7.1-dirty
From 111566e3753b1abc24b073ad549fb97819d216cb Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 17 Jan 2008 15:14:33 +0800
Subject: [PATCH] KVM: VMX: Enable Virtual Processor Identification (VPID)
To allow TLB entries to be retained across VM entry and VM exit, the VMM can now identify distinct address spaces through a new virtual-processor ID (VPID) field of the VMCS.
--- arch/x86/kvm/vmx.c | 90 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/vmx.h | 6 +++ include/asm-x86/kvm_host.h | 1 + 3 files changed, 92 insertions(+), 5 deletions(-)
arch/x86/kvm/vmx.c +85 -5
198 lines not on this page · raw message
arch/x86/kvm/vmx.h +6 -0
@@ -49,6 +49,7 @@* Definitions of Secondary Processor-Based VM-Execution Controls. */ #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 +#define SECONDARY_EXEC_ENABLE_VPID 0x00000020#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
@@ -65,6 +66,7 @@/* VMCS Encodings */ enum vmcs_field { +VIRTUAL_PROCESSOR_ID =0x00000000 ,GUEST_ES_SELECTOR =0x00000800 ,GUEST_CS_SELECTOR =0x00000802 ,GUEST_SS_SELECTOR =0x00000804 ,
@@ -321,4 +323,8 @@ enum vmcs_field {#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 +#define VMX_NR_VPIDS (1 << 16) +#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1 +#define VMX_VPID_EXTENT_ALL_CONTEXT 2 +#endif
include/asm-x86/kvm_host.h +1 -0
@@ -600,6 +600,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4"#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4"#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30" +#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"#define MSR_IA32_TIME_STAMP_COUNTER 0x010
Signature · 1 line
debian.1.5.3.7.1-dirty
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel
A message that is not in the archive (sent off-list or not yet received): 200801251212.29031.sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Avi Kivity
AppliedQuoted 3 lines · Sheng
Here is the updated patch:
Applied, thanks.
arch/x86/kvm/vmx.c static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) · line 1795
Quoted 9 lines
arch/x86/kvm/vmx.c +2
-0@@ -1714,6 +1788,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)vmx_fpu_activate (&vmx->vcpu);update_exception_bitmap (&vmx->vcpu); +vpid_sync_all (); +return 0 ;
This causes the new instruction to be executed unconditionally, which would #UD on older processors, no? I replaced it with vpid_sync_vcpu_all() which seems sufficient, or do I miss something?
Signature · 7 lines
Any sufficiently difficult bug is indistinguishable from a feature. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 4799873F.1070503-atKUWr5tajBWk0Htik3J/[email protected]
Quoted 9 lines · On Friday 25 January 2008 14:52:47 Avi Kivity wrote:
Quoted 1 line · Sheng
Here is the updated patch:
Applied, thanks.
Quoted 4 lines
arch/x86/kvm/vmx.c +0
-0@@ -1714,6 +1788,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)vmx_fpu_activate (&vmx->vcpu);update_exception_bitmap (&vmx->vcpu);
Quoted 7 lines
arch/x86/kvm/vmx.c static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) · line 1793
Quoted 3 lines
arch/x86/kvm/vmx.c +2
-0+vpid_sync_all (); +return 0 ;This causes the new instruction to be executed unconditionally, which would #UD on older processors, no? I replaced it with
vpid_sync_vcpu_all()which seems sufficient, or do I miss something?
I think it's OK for there is a judgment in __invvpid() to see if machine has the ability(also if it is allowed to using VPID). :)
Thanks!
Signature · 7 lines
Thanks Yang, Sheng ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 200801251501.54884.sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Quoted 3 lines · Sheng
I think it's OK for there is a judgment in
__invvpid()to see if machine has the ability(also if it is allowed to using VPID). :)
Oh right, I missed that.
We can remove it now since it will only be called if vpid != 0, and that happens only on vpid enabled machines, no?
Signature · 7 lines
Any sufficiently difficult bug is indistinguishable from a feature. ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
A message that is not in the archive (sent off-list or not yet received): 479989C0.90307-atKUWr5tajBWk0Htik3J/[email protected]
Quoted 8 lines · On Friday 25 January 2008 15:03:28 Avi Kivity wrote:
Quoted 2 lines · Sheng
I think it's OK for there is a judgment in
__invvpid()to see if machine has the ability(also if it is allowed to using VPID). :)Oh right, I missed that.
We can remove it now since it will only be called if vpid != 0, and that happens only on vpid enabled machines, no?
Yes. I think we can replace vpid_sync_all() with vpid_sync_vcpu_all(), then there was no reference to vpid_sync_all() now...
BTW: vpid_sync_all() can be used after VMX_ON, but just in case... So we may remove it for now.
Signature · 7 lines
Thanks Yang, Sheng ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/