diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c index 35bf3945ac..ac17533923 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 07097c2337..baf502aab9 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