|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v11 23/23] KVM: x86: Use a single time snapshot in kvm_vm_ioctl_set_clock()
From: David Woodhouse <dwmw@xxxxxxxxxxxx>
The KVM_CLOCK_REALTIME handling read CLOCK_REALTIME with
ktime_get_real_ns() and then anchored the result at a different
instant: the master clock reference point captured a few lines
earlier, or a separate get_kvmclock_base_ns() read. The time elapsed
between the two reads is added to the restored clock as error --
bounded by the interrupts-off critical section, but gratuitous now
that the timekeeping core can snapshot CLOCK_REALTIME and
CLOCK_MONOTONIC_RAW at the same instant.
Take one ktime_get_snapshot_id(CLOCK_REALTIME) snapshot and derive
both the realtime correction and the raw reference point from it. In
master clock mode, keep anchoring at master_kernel_ns -- so that
'system_time' cannot go negative for a very small data.clock, as the
existing comment explains -- by projecting the snapshot's realtime
value back to that reference point; CLOCK_REALTIME and
CLOCK_MONOTONIC_RAW tick at the same rate across the few ns in
between, give or take NTP slew.
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
arch/x86/kvm/x86.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 17544b3cc035..4db0c809d120 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4693,19 +4693,41 @@ static int kvm_vm_ioctl_set_clock(struct kvm *kvm, void
__user *argp)
* 'system_time' when 'data.clock' is very small.
*/
if (data.flags & KVM_CLOCK_REALTIME) {
- u64 now_real_ns = ktime_get_real_ns();
+ struct system_time_snapshot snap = {};
+ u64 now_real_ns;
+
+ /*
+ * Snapshot CLOCK_REALTIME and CLOCK_MONOTONIC_RAW at the
+ * same instant, so that the elapsed time applied to
+ * data.clock and the reference point the result is anchored
+ * to are coherent.
+ */
+ ktime_get_snapshot_id(CLOCK_REALTIME, &snap);
+ now_real_ns = ktime_to_ns(snap.systime);
+ now_raw_ns = ktime_to_ns(ktime_mono_to_any(snap.monoraw,
+ TK_OFFS_BOOT));
+
+ /*
+ * When the master clock is in use, anchor at its reference
+ * point instead, projecting the realtime value back to the
+ * same instant. The two clocks tick at the same rate across
+ * the few ns in between, give or take NTP slew.
+ */
+ if (ka->use_master_clock) {
+ now_real_ns -= now_raw_ns - ka->master_kernel_ns;
+ now_raw_ns = ka->master_kernel_ns;
+ }
/*
* Avoid stepping the kvmclock backwards.
*/
if (now_real_ns > data.realtime)
data.clock += now_real_ns - data.realtime;
- }
-
- if (ka->use_master_clock)
+ } else if (ka->use_master_clock) {
now_raw_ns = ka->master_kernel_ns;
- else
+ } else {
now_raw_ns = get_kvmclock_base_ns();
+ }
ka->kvmclock_offset = data.clock - now_raw_ns;
kvm_end_pvclock_update(kvm);
return 0;
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |