diff mbox series

[v2,1/2] x86/shim: suspend and resume platform time correctly

Message ID 1580852977-23866-2-git-send-email-igor.druzhinin@citrix.com (mailing list archive)
State New, archived
Headers show
Series PV shim timekeeping fixes | expand

Commit Message

Igor Druzhinin Feb. 4, 2020, 9:49 p.m. UTC
Similarly to S3, platform time needs to be saved on guest suspend
and restored on resume respectively. This should account for expected
jumps in PV clock counter value after resume. time_suspend/resume()
are safe to use in PVH setting as is since any existing operations
with PIT/HPET that they do would simply be ignored if PIT/HPET is
not present.

Additionally, add resume callback for Xen PV clocksource to avoid
its breakage on migration.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
---
 xen/arch/x86/pv/shim.c |  7 ++++++-
 xen/arch/x86/time.c    | 12 +++++++++---
 2 files changed, 15 insertions(+), 4 deletions(-)

Comments

Roger Pau Monné Feb. 5, 2020, 9:13 a.m. UTC | #1
On Tue, Feb 04, 2020 at 09:49:36PM +0000, Igor Druzhinin wrote:
> Similarly to S3, platform time needs to be saved on guest suspend
> and restored on resume respectively. This should account for expected
> jumps in PV clock counter value after resume. time_suspend/resume()
> are safe to use in PVH setting as is since any existing operations
> with PIT/HPET that they do would simply be ignored if PIT/HPET is
> not present.
> 
> Additionally, add resume callback for Xen PV clocksource to avoid
> its breakage on migration.
> 
> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>

Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>

Thanks.
diff mbox series

Patch

diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index 7a898fd..6b26eaa 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -325,9 +325,13 @@  int pv_shim_shutdown(uint8_t reason)
         if ( v != current )
             vcpu_pause_by_systemcontroller(v);
 
+    /* Prepare timekeeping code to suspend.*/
+    time_suspend();
+
     rc = xen_hypercall_shutdown(SHUTDOWN_suspend);
     if ( rc )
     {
+        time_resume();
         for_each_vcpu ( d, v )
             if ( v != current )
                 vcpu_unpause_by_systemcontroller(v);
@@ -335,8 +339,9 @@  int pv_shim_shutdown(uint8_t reason)
         return rc;
     }
 
-    /* Resume the shim itself first. */
+    /* Resume the shim itself and timekeeping first. */
     hypervisor_resume();
+    time_resume();
 
     /*
      * ATM there's nothing Xen can do if the console/store pfn changes,
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index f6b26f8..7e7a62e 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -565,6 +565,7 @@  static struct platform_timesource __initdata plt_tsc =
  *
  * Xen clock source is a variant of TSC source.
  */
+static uint64_t xen_timer_last;
 
 static uint64_t xen_timer_cpu_frequency(void)
 {
@@ -610,7 +611,6 @@  static uint64_t read_xen_timer(void)
     uint32_t version;
     uint64_t ret;
     uint64_t last;
-    static uint64_t last_value;
 
     do {
         version = info->version & ~1;
@@ -626,20 +626,26 @@  static uint64_t read_xen_timer(void)
 
     /* Maintain a monotonic global value */
     do {
-        last = read_atomic(&last_value);
+        last = read_atomic(&xen_timer_last);
         if ( ret < last )
             return last;
-    } while ( unlikely(cmpxchg(&last_value, last, ret) != last) );
+    } while ( unlikely(cmpxchg(&xen_timer_last, last, ret) != last) );
 
     return ret;
 }
 
+static void resume_xen_timer(struct platform_timesource *pts)
+{
+    write_atomic(&xen_timer_last, 0);
+}
+
 static struct platform_timesource __initdata plt_xen_timer =
 {
     .id = "xen",
     .name = "XEN PV CLOCK",
     .read_counter = read_xen_timer,
     .init = init_xen_timer,
+    .resume = resume_xen_timer,
     .counter_bits = 63,
 };
 #endif