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);
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,
*
* Xen clock source is a variant of TSC source.
*/
+static uint64_t xen_timer_last;
static uint64_t xen_timer_cpu_frequency(void)
{
uint32_t version;
uint64_t ret;
uint64_t last;
- static uint64_t last_value;
do {
version = info->version & ~1;
/* 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