[PATCH 3/3] KVM: VMX: VMXON/VMXOFF usage changes.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Dongxiao Xu <dongxiao.xu@xxxxxxxxx>

Intel SDM also suggests that VMXOFF should be called after doing
VMCLEAR. Therefore VMXON should be called before VMPTRLD.

Signed-off-by: Dongxiao Xu <dongxiao.xu@xxxxxxxxx>
---
 arch/x86/kvm/vmx.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index aaf5b52..dd3a7fa 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -161,8 +161,11 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
 
 static int init_rmode(struct kvm *kvm);
 static u64 construct_eptp(unsigned long root_hpa);
+static void kvm_cpu_vmxon(u64 addr);
+static void kvm_cpu_vmxoff(void);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
+static DEFINE_PER_CPU(bool, vmx_mode);
 
 static unsigned long *vmx_io_bitmap_a;
 static unsigned long *vmx_io_bitmap_b;
@@ -755,7 +758,9 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u64 tsc_this, delta, new_offset;
+	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
 
+	kvm_cpu_vmxon(phys_addr);
 	vmcs_load(vmx->vmcs);
 
 	if (vcpu->cpu != cpu) {
@@ -796,6 +801,7 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
 	vmcs_clear(vmx->vmcs);
 	rdtscll(vmx->vcpu.arch.host_tsc);
 	vmx->launched = 0;
+	kvm_cpu_vmxoff();
 }
 
 static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
@@ -1187,9 +1193,11 @@ static __init int vmx_disabled_by_bios(void)
 
 static void kvm_cpu_vmxon(u64 addr)
 {
+	int cpu = raw_smp_processor_id();
 	asm volatile (ASM_VMX_VMXON_RAX
 			: : "a"(&addr), "m"(addr)
 			: "memory", "cc");
+	per_cpu(vmx_mode, cpu) = 1;
 }
 
 static int hardware_enable(void *garbage)
@@ -1223,12 +1231,16 @@ static int hardware_enable(void *garbage)
  */
 static void kvm_cpu_vmxoff(void)
 {
+	int cpu = raw_smp_processor_id();
 	asm volatile (__ex(ASM_VMX_VMXOFF) : : : "cc");
+	per_cpu(vmx_mode, cpu) = 0;
 }
 
 static void hardware_disable(void *garbage)
 {
-	kvm_cpu_vmxoff();
+	int cpu = raw_smp_processor_id();
+	if (per_cpu(vmx_mode, cpu))
+		kvm_cpu_vmxoff();
 	write_cr4(read_cr4() & ~X86_CR4_VMXE);
 }
 
@@ -3930,6 +3942,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 {
 	int err;
 	struct vcpu_vmx *vmx = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
+	u64 phys_addr = __pa(per_cpu(vmxarea, smp_processor_id()));
 
 	if (!vmx)
 		return ERR_PTR(-ENOMEM);
@@ -3951,9 +3964,11 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 		goto free_msrs;
 
 	preempt_disable();
+	kvm_cpu_vmxon(phys_addr);
 	vmcs_load(vmx->vmcs);
 	err = vmx_vcpu_setup(vmx);
 	vmcs_clear(vmx->vmcs);
+	kvm_cpu_vmxoff();
 	preempt_enable();
 
 	if (err)
@@ -4091,10 +4106,13 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	int cpu = raw_smp_processor_id();
+	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
 	u32 exec_control;
 
 	vmx->rdtscp_enabled = false;
 	if (vmx_rdtscp_supported()) {
+		kvm_cpu_vmxon(phys_addr);
 		vmcs_load(vmx->vmcs);
 		exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
 		if (exec_control & SECONDARY_EXEC_RDTSCP) {
@@ -4108,6 +4126,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 			}
 		}
 		vmcs_clear(vmx->vmcs);
+		kvm_cpu_vmxoff();
 	}
 }
 
-- 
1.6.3
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux