summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/x86.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 14e7efdd74ed..4180e18e0cbb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1798,12 +1798,11 @@ static void kvm_setup_guest_pvclock(struct pvclock_vcpu_time_info *ref_hv_clock,
int kvm_guest_time_update(struct kvm_vcpu *v)
{
+ u64 tgt_tsc_hz, tsc_timestamp, host_tsc, master_tsc, master_ns;
struct kvm_arch *ka __maybe_unused = &v->kvm->arch;
struct pvclock_vcpu_time_info hv_clock = {};
- u64 tgt_tsc_hz;
struct kvm_vcpu_arch *vcpu = &v->arch;
s64 kernel_ns;
- u64 tsc_timestamp, host_tsc;
/*
* If the host uses TSC clock, then passthrough TSC as stable
@@ -1816,10 +1815,16 @@ int kvm_guest_time_update(struct kvm_vcpu *v)
do {
seq = read_seqcount_begin(&ka->pvclock_sc);
use_master_clock = ka->use_master_clock;
- if (use_master_clock) {
- host_tsc = ka->master_cycle_now;
- kernel_ns = ka->master_kernel_ns;
+ if (!use_master_clock)
+ continue;
+
+ if (!kvm_get_time_and_clockread(&kernel_ns, &host_tsc)) {
+ use_master_clock = false;
+ continue;
}
+
+ master_tsc = ka->master_cycle_now;
+ master_ns = ka->master_kernel_ns;
} while (read_seqcount_retry(&ka->pvclock_sc, seq));
#else
const bool use_master_clock = false;
@@ -1885,8 +1890,18 @@ int kvm_guest_time_update(struct kvm_vcpu *v)
hv_clock.tsc_shift = vcpu->pvclock_tsc_shift;
hv_clock.tsc_to_system_mul = vcpu->pvclock_tsc_mul;
- hv_clock.tsc_timestamp = tsc_timestamp;
- hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
+ /*
+ * If the master clock is NOT in use, the reference time placed in the
+ * hv_clock is "now". If master clock is in use, the reference time is
+ * the master clock's snapshot from some time in the past, not "now".
+ */
+ if (use_master_clock) {
+ hv_clock.tsc_timestamp = kvm_read_l1_tsc(v, master_tsc);
+ hv_clock.system_time = master_ns + v->kvm->arch.kvmclock_offset;
+ } else {
+ hv_clock.tsc_timestamp = tsc_timestamp;
+ hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
+ }
/* If the host uses TSC clocksource, then it is stable */
hv_clock.flags = 0;