aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorNadav Har'El <nyh@il.ibm.com>2011-08-02 08:54:20 -0400
committerAvi Kivity <avi@redhat.com>2011-09-25 12:18:02 -0400
commitd5c1785d2f3aabe284d91bc7fc8f0abc58525dc9 (patch)
tree1db45488a6ecee728245e9af6f4fe59c4dc6ac4a /arch/x86/kvm/x86.c
parente1a72ae287f3ea4fea63b6f14a662a15e8c11960 (diff)
KVM: L1 TSC handling
KVM assumed in several places that reading the TSC MSR returns the value for L1. This is incorrect, because when L2 is running, the correct TSC read exit emulation is to return L2's value. We therefore add a new x86_ops function, read_l1_tsc, to use in places that specifically need to read the L1 TSC, NOT the TSC of the current level of guest. Note that one change, of one line in kvm_arch_vcpu_load, is made redundant by a different patch sent by Zachary Amsden (and not yet applied): kvm_arch_vcpu_load() should not read the guest TSC, and if it didn't, of course we didn't have to change the call of kvm_get_msr() to read_l1_tsc(). [avi: moved callback to kvm_x86_ops tsc block] Signed-off-by: Nadav Har'El <nyh@il.ibm.com> Acked-by: Zachary Amsdem <zamsden@gmail.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ea8f9f03e92..6b37f18a166 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1098,7 +1098,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
1098 1098
1099 /* Keep irq disabled to prevent changes to the clock */ 1099 /* Keep irq disabled to prevent changes to the clock */
1100 local_irq_save(flags); 1100 local_irq_save(flags);
1101 kvm_get_msr(v, MSR_IA32_TSC, &tsc_timestamp); 1101 tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
1102 kernel_ns = get_kernel_ns(); 1102 kernel_ns = get_kernel_ns();
1103 this_tsc_khz = vcpu_tsc_khz(v); 1103 this_tsc_khz = vcpu_tsc_khz(v);
1104 if (unlikely(this_tsc_khz == 0)) { 1104 if (unlikely(this_tsc_khz == 0)) {
@@ -2218,7 +2218,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
2218 s64 tsc_delta; 2218 s64 tsc_delta;
2219 u64 tsc; 2219 u64 tsc;
2220 2220
2221 kvm_get_msr(vcpu, MSR_IA32_TSC, &tsc); 2221 tsc = kvm_x86_ops->read_l1_tsc(vcpu);
2222 tsc_delta = !vcpu->arch.last_guest_tsc ? 0 : 2222 tsc_delta = !vcpu->arch.last_guest_tsc ? 0 :
2223 tsc - vcpu->arch.last_guest_tsc; 2223 tsc - vcpu->arch.last_guest_tsc;
2224 2224
@@ -2242,7 +2242,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
2242{ 2242{
2243 kvm_x86_ops->vcpu_put(vcpu); 2243 kvm_x86_ops->vcpu_put(vcpu);
2244 kvm_put_guest_fpu(vcpu); 2244 kvm_put_guest_fpu(vcpu);
2245 kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc); 2245 vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
2246} 2246}
2247 2247
2248static int is_efer_nx(void) 2248static int is_efer_nx(void)
@@ -5729,7 +5729,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
5729 if (hw_breakpoint_active()) 5729 if (hw_breakpoint_active())
5730 hw_breakpoint_restore(); 5730 hw_breakpoint_restore();
5731 5731
5732 kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc); 5732 vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
5733 5733
5734 vcpu->mode = OUTSIDE_GUEST_MODE; 5734 vcpu->mode = OUTSIDE_GUEST_MODE;
5735 smp_wmb(); 5735 smp_wmb();