diff options
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 19 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 2 |
3 files changed, 14 insertions, 8 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index c2a01d0513f5..9efc446b5ac6 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -398,6 +398,7 @@ struct kvm_arch{ | |||
398 | 398 | ||
399 | unsigned long irq_sources_bitmap; | 399 | unsigned long irq_sources_bitmap; |
400 | unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; | 400 | unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; |
401 | u64 vm_init_tsc; | ||
401 | }; | 402 | }; |
402 | 403 | ||
403 | struct kvm_vm_stat { | 404 | struct kvm_vm_stat { |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index cee81c9a6653..3312047664a4 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -865,11 +865,8 @@ static u64 guest_read_tsc(void) | |||
865 | * writes 'guest_tsc' into guest's timestamp counter "register" | 865 | * writes 'guest_tsc' into guest's timestamp counter "register" |
866 | * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc | 866 | * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc |
867 | */ | 867 | */ |
868 | static void guest_write_tsc(u64 guest_tsc) | 868 | static void guest_write_tsc(u64 guest_tsc, u64 host_tsc) |
869 | { | 869 | { |
870 | u64 host_tsc; | ||
871 | |||
872 | rdtscll(host_tsc); | ||
873 | vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc); | 870 | vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc); |
874 | } | 871 | } |
875 | 872 | ||
@@ -934,6 +931,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | |||
934 | { | 931 | { |
935 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 932 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
936 | struct kvm_msr_entry *msr; | 933 | struct kvm_msr_entry *msr; |
934 | u64 host_tsc; | ||
937 | int ret = 0; | 935 | int ret = 0; |
938 | 936 | ||
939 | switch (msr_index) { | 937 | switch (msr_index) { |
@@ -959,7 +957,8 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | |||
959 | vmcs_writel(GUEST_SYSENTER_ESP, data); | 957 | vmcs_writel(GUEST_SYSENTER_ESP, data); |
960 | break; | 958 | break; |
961 | case MSR_IA32_TIME_STAMP_COUNTER: | 959 | case MSR_IA32_TIME_STAMP_COUNTER: |
962 | guest_write_tsc(data); | 960 | rdtscll(host_tsc); |
961 | guest_write_tsc(data, host_tsc); | ||
963 | break; | 962 | break; |
964 | case MSR_P6_PERFCTR0: | 963 | case MSR_P6_PERFCTR0: |
965 | case MSR_P6_PERFCTR1: | 964 | case MSR_P6_PERFCTR1: |
@@ -2109,7 +2108,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
2109 | { | 2108 | { |
2110 | u32 host_sysenter_cs, msr_low, msr_high; | 2109 | u32 host_sysenter_cs, msr_low, msr_high; |
2111 | u32 junk; | 2110 | u32 junk; |
2112 | u64 host_pat; | 2111 | u64 host_pat, tsc_this, tsc_base; |
2113 | unsigned long a; | 2112 | unsigned long a; |
2114 | struct descriptor_table dt; | 2113 | struct descriptor_table dt; |
2115 | int i; | 2114 | int i; |
@@ -2237,6 +2236,12 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
2237 | vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); | 2236 | vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); |
2238 | vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); | 2237 | vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); |
2239 | 2238 | ||
2239 | tsc_base = vmx->vcpu.kvm->arch.vm_init_tsc; | ||
2240 | rdtscll(tsc_this); | ||
2241 | if (tsc_this < vmx->vcpu.kvm->arch.vm_init_tsc) | ||
2242 | tsc_base = tsc_this; | ||
2243 | |||
2244 | guest_write_tsc(0, tsc_base); | ||
2240 | 2245 | ||
2241 | return 0; | 2246 | return 0; |
2242 | } | 2247 | } |
@@ -2328,8 +2333,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) | |||
2328 | vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); | 2333 | vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); |
2329 | vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); | 2334 | vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0); |
2330 | 2335 | ||
2331 | guest_write_tsc(0); | ||
2332 | |||
2333 | /* Special registers */ | 2336 | /* Special registers */ |
2334 | vmcs_write64(GUEST_IA32_DEBUGCTL, 0); | 2337 | vmcs_write64(GUEST_IA32_DEBUGCTL, 0); |
2335 | 2338 | ||
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 873602b5edfd..3b2acfd72d7f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4170,6 +4170,8 @@ struct kvm *kvm_arch_create_vm(void) | |||
4170 | /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ | 4170 | /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ |
4171 | set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); | 4171 | set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); |
4172 | 4172 | ||
4173 | rdtscll(kvm->arch.vm_init_tsc); | ||
4174 | |||
4173 | return kvm; | 4175 | return kvm; |
4174 | } | 4176 | } |
4175 | 4177 | ||