xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] xen/time: fix system_time for vtsc=1 PV guests
@ 2016-04-21 13:29 Stefano Stabellini
  2016-04-22  9:21 ` Jan Beulich
  0 siblings, 1 reply; 5+ messages in thread
From: Stefano Stabellini @ 2016-04-21 13:29 UTC (permalink / raw)
  To: xen-devel; +Cc: andrew.cooper3, sstabellini, jbeulich

For vtsc=1 PV guests, rdtsc is trapped and calculated from get_s_time()
using gtime_to_gtsc. Similarly the tsc_timestamp, part of struct
vcpu_time_info, is calculated from stime_local_stamp using
gtime_to_gtsc.

However gtime_to_gtsc can return 0, if time < vtsc_offset, which can
actually happen when gtime_to_gtsc is called passing stime_local_stamp
(the caller function is __update_vcpu_system_time).

In that case the pvclock protocol doesn't work properly and the guest is
unable to calculate the system time correctly. As a consequence when the
guest tries to set a timer event (for example calling the
VCPUOP_set_singleshot_timer hypercall), the event will be in the past
causing Linux to hang.

The purpose of the pvclock protocol is to allow the guest to calculate
the system_time in nanosec correctly. The guest calculates as follow:

  from_vtsc_scale(rdtsc - vcpu_time_info.tsc_timestamp) + vcpu_time_info.system_time

Given that with vtsc=1:
  rdtsc = to_vtsc_scale(NOW() - vtsc_offset)
  vcpu_time_info.tsc_timestamp = to_vtsc_scale(vcpu_time_info.system_time - vtsc_offset)

The expression evaluates to NOW(), which is what we want.
However when stime_local_stamp < vtsc_offset,
vcpu_time_info.tsc_timestamp is actually 0, because it cannot be
negative (the field is uint64_t). As a consequence the calculated
overall system_time is not correct.

This patch fixes the issue by passing vtsc_offset as system_time when
vcpu_time_info.tsc_timestamp is 0:
  rdtsc = to_vtsc_scale(NOW() - vtsc_offset)
  vcpu_time_info.tsc_timestamp = 0
  vcpu_time_info.system_time = vtsc_offset

The pvclock expression evaluates to NOW(), which is what we want.

Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>

diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index 687e39b..27b0e5c 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -784,7 +784,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
     struct cpu_time       *t;
     struct vcpu_time_info *u, _u = {};
     struct domain *d = v->domain;
-    s_time_t tsc_stamp;
+    s_time_t stime_stamp, tsc_stamp = 0;
 
     if ( v->vcpu_info == NULL )
         return;
@@ -792,6 +792,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
     t = &this_cpu(cpu_time);
     u = &vcpu_info(v, time);
 
+    stime_stamp = t->stime_local_stamp;
     if ( d->arch.vtsc )
     {
         s_time_t stime = t->stime_local_stamp;
@@ -807,7 +808,11 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
                 tsc_stamp = -gtime_to_gtsc(d, -stime);
         }
         else
+        {
             tsc_stamp = gtime_to_gtsc(d, stime);
+            if (!tsc_stamp)
+                stime_stamp = d->arch.vtsc_offset;
+        }
 
         _u.tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac;
         _u.tsc_shift         = d->arch.vtsc_to_ns.shift;
@@ -829,7 +834,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int force)
     }
 
     _u.tsc_timestamp = tsc_stamp;
-    _u.system_time   = t->stime_local_stamp;
+    _u.system_time   = stime_stamp;
 
     if ( is_hvm_domain(d) )
         _u.tsc_timestamp += v->arch.hvm_vcpu.cache_tsc_offset;

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-04-22 17:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-21 13:29 [PATCH] xen/time: fix system_time for vtsc=1 PV guests Stefano Stabellini
2016-04-22  9:21 ` Jan Beulich
2016-04-22 10:08   ` Stefano Stabellini
2016-04-22 11:12     ` Jan Beulich
2016-04-22 17:56       ` Stefano Stabellini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).