]> Pileus Git - ~andy/linux/blobdiff - drivers/kvm/vmx.c
Pull misc into release branch
[~andy/linux] / drivers / kvm / vmx.c
index b969db1e08304373bf6746eb565cfc283c9c58a7..80628f69916d85c0c58f02f126ff62cf778ea855 100644 (file)
 
 #include "kvm.h"
 #include "vmx.h"
+#include "segment_descriptor.h"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
+
 #include <asm/io.h>
 #include <asm/desc.h>
 
-#include "segment_descriptor.h"
-
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+static int init_rmode_tss(struct kvm *kvm);
+
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 
@@ -160,6 +163,7 @@ static void __vcpu_clear(void *arg)
                vmcs_clear(vcpu->vmcs);
        if (per_cpu(current_vmcs, cpu) == vcpu->vmcs)
                per_cpu(current_vmcs, cpu) = NULL;
+       rdtscll(vcpu->host_tsc);
 }
 
 static void vcpu_clear(struct kvm_vcpu *vcpu)
@@ -376,6 +380,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu)
 {
        u64 phys_addr = __pa(vcpu->vmcs);
        int cpu;
+       u64 tsc_this, delta;
 
        cpu = get_cpu();
 
@@ -409,6 +414,13 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu)
 
                rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
                vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+
+               /*
+                * Make sure the time stamp counter is monotonous.
+                */
+               rdtscll(tsc_this);
+               delta = vcpu->host_tsc - tsc_this;
+               vmcs_write64(TSC_OFFSET, vmcs_read64(TSC_OFFSET) + delta);
        }
 }
 
@@ -942,6 +954,8 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        fix_rmode_seg(VCPU_SREG_DS, &vcpu->rmode.ds);
        fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
        fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
+
+       init_rmode_tss(vcpu->kvm);
 }
 
 #ifdef CONFIG_X86_64
@@ -1180,16 +1194,16 @@ static int init_rmode_tss(struct kvm* kvm)
        }
 
        page = kmap_atomic(p1, KM_USER0);
-       memset(page, 0, PAGE_SIZE);
+       clear_page(page);
        *(u16*)(page + 0x66) = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
        kunmap_atomic(page, KM_USER0);
 
        page = kmap_atomic(p2, KM_USER0);
-       memset(page, 0, PAGE_SIZE);
+       clear_page(page);
        kunmap_atomic(page, KM_USER0);
 
        page = kmap_atomic(p3, KM_USER0);
-       memset(page, 0, PAGE_SIZE);
+       clear_page(page);
        *(page + RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1) = ~0;
        kunmap_atomic(page, KM_USER0);
 
@@ -1238,9 +1252,9 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
        memset(vcpu->regs, 0, sizeof(vcpu->regs));
        vcpu->regs[VCPU_REGS_RDX] = get_rdx_init_val();
        vcpu->cr8 = 0;
-       vcpu->apic_base = 0xfee00000 |
-                       /*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
-                       MSR_IA32_APICBASE_ENABLE;
+       vcpu->apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
+       if (vcpu == &vcpu->kvm->vcpus[0])
+               vcpu->apic_base |= MSR_IA32_APICBASE_BSP;
 
        fx_init(vcpu);
 
@@ -1974,7 +1988,6 @@ static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
 
 static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
 {
-       vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3));
 }
 
 static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1983,13 +1996,13 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        int r;
 
 preempted:
-       if (!vcpu->mmio_read_completed)
-               do_interrupt_requests(vcpu, kvm_run);
-
        if (vcpu->guest_debug.enabled)
                kvm_guest_debug_pre(vcpu);
 
 again:
+       if (!vcpu->mmio_read_completed)
+               do_interrupt_requests(vcpu, kvm_run);
+
        vmx_save_host_state(vcpu);
        kvm_load_guest_fpu(vcpu);