KVM: selftests: Compare wall time from xen shinfo against KVM_GET_CLOCK
authorVitaly Kuznetsov <vkuznets@redhat.com>
Tue, 6 Feb 2024 15:19:50 +0000 (16:19 +0100)
committerSean Christopherson <seanjc@google.com>
Thu, 25 Apr 2024 23:03:17 +0000 (16:03 -0700)
commit201142d160104c9ce4afc861d4cfbd7a432c5aa8
tree455284dda044a552070acf846976a0eaf16fca51
parentd85465f2773da69e2838505ca3575aa3b22dba69
KVM: selftests: Compare wall time from xen shinfo against KVM_GET_CLOCK

xen_shinfo_test is observed to be flaky failing sporadically with
"VM time too old". With min_ts/max_ts debug print added:

Wall clock (v 32698181704906491.986255664
Time info 1: v 1282712 tsc 33530585736 time 14014430025 mul 3587552223 shift 4294967295 flags 1
Time info 2: v 1282712 tsc 33530585736 time 14014430025 mul 3587552223 shift 4294967295 flags 1
min_ts: 1704906491.986312153
max_ts: 1704906506.001006963
==== Test Assertion Failure ====
  x86_64/xen_shinfo_test.c:1003: cmp_timespec(&min_ts, &vm_ts) <= 0
  pid=32724 tid=32724 errno=4 - Interrupted system call
     1 0x00000000004030ad: main at xen_shinfo_test.c:1003
     2 0x00007fca6b23feaf: ?? ??:0
     3 0x00007fca6b23ff5f: ?? ??:0
     4 0x0000000000405e04: _start at ??:?
  VM time too old

The test compares wall clock data from shinfo (which is the output of
kvm_get_wall_clock_epoch()) against clock_gettime(CLOCK_REALTIME) in the
host system before the VM is created. In the example above, it compares

 shinfo: 1704906491.986255664 vs min_ts: 1704906491.986312153

and fails as the later is greater than the former.  While this sounds like
a sane test, it doesn't pass reality check: kvm_get_wall_clock_epoch()
calculates guest's epoch (realtime when the guest was created) by
subtracting kvmclock from the current realtime and the calculation happens
when shinfo is setup. The problem is that kvmclock is a raw clock and
realtime clock is affected by NTP. This means that if realtime ticks with a
slightly reduced frequency, "guest's epoch" calculated by
kvm_get_wall_clock_epoch() will actually tick backwards! This is not a big
issue from guest's perspective as the guest can't really observe this but
this epoch can't be compared with a fixed clock_gettime() on the host.

Replace the check with comparing wall clock data from shinfo to
KVM_GET_CLOCK. The later gives both realtime and kvmclock so guest's epoch
can be calculated by subtraction. Note, CLOCK_REALTIME is susceptible to
leap seconds jumps but there's no better alternative in KVM at this
moment. Leave a comment and accept 1s delta.

Reported-by: Jan Richter <jarichte@redhat.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Link: https://lore.kernel.org/r/20240206151950.31174-1-vkuznets@redhat.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c