qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [QEMU PATCH] kvmclock: advance clock by time window between vm_stop and pre_save
@ 2016-11-04  9:43 Marcelo Tosatti
  2016-11-04 12:28 ` Juan Quintela
                   ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Marcelo Tosatti @ 2016-11-04  9:43 UTC (permalink / raw)
  To: kvm, qemu-devel
  Cc: Dr. David Alan Gilbert, Paolo Bonzini,
	Radim Krčmář, Juan Quintela, Eduardo Habkost


This patch, relative to pre-copy migration codepath,
measures the time between vm_stop() and pre_save(), 
which includes copying the remaining RAM to destination,
and advances the clock by that amount.

In a VM with 5 seconds downtime, this reduces the guest 
clock difference on destination from 5s to 0.2s.

Please do not apply this yet as some codepaths still need
checking, submitting early for comments.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index 0f75dd3..1bd8fd6 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -22,9 +22,11 @@
 #include "kvm_i386.h"
 #include "hw/sysbus.h"
 #include "hw/kvm/clock.h"
+#include "migration/migration.h"
 
 #include <linux/kvm.h>
 #include <linux/kvm_para.h>
+#include <time.h>
 
 #define TYPE_KVM_CLOCK "kvmclock"
 #define KVM_CLOCK(obj) OBJECT_CHECK(KVMClockState, (obj), TYPE_KVM_CLOCK)
@@ -35,7 +37,11 @@ typedef struct KVMClockState {
     /*< public >*/
 
     uint64_t clock;
+    uint64_t ns;
     bool clock_valid;
+
+    uint64_t advance_clock;
+    struct timespec t_aftervmstop;
 } KVMClockState;
 
 struct pvclock_vcpu_time_info {
@@ -100,6 +106,11 @@ static void kvmclock_vm_state_change(void *opaque, int running,
             s->clock = time_at_migration;
         }
 
+        if (s->advance_clock && s->clock + s->advance_clock > s->clock) {
+            s->clock += s->advance_clock;
+            s->advance_clock = 0;
+        }
+
         data.clock = s->clock;
         ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
         if (ret < 0) {
@@ -135,6 +146,18 @@ static void kvmclock_vm_state_change(void *opaque, int running,
             abort();
         }
         s->clock = data.clock;
+        /*
+         * Transition from VM-running to VM-stopped via migration?
+         * Record when the VM was stopped.
+         */
+
+        if (state == RUN_STATE_FINISH_MIGRATE &&
+            !migration_in_postcopy(migrate_get_current())) {
+            clock_gettime(CLOCK_MONOTONIC, &s->t_aftervmstop);
+        } else {
+            s->t_aftervmstop.tv_sec = 0;
+            s->t_aftervmstop.tv_nsec = 0;
+        }
 
         /*
          * If the VM is stopped, declare the clock state valid to
@@ -152,12 +175,66 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
 }
 
+static uint64_t clock_delta(struct timespec *before, struct timespec *after)
+{
+    if (before->tv_sec > after->tv_sec ||
+        (before->tv_sec == after->tv_sec &&
+         before->tv_nsec > after->tv_nsec)) {
+        fprintf(stderr, "clock_delta failed: before=(%ld sec, %ld nsec),"
+                        "after=(%ld sec, %ld nsec)\n", before->tv_sec,
+                        before->tv_nsec, after->tv_sec, after->tv_nsec);
+        abort();
+    }
+
+    return (after->tv_sec - before->tv_sec) * 1000000000ULL +
+            after->tv_nsec - before->tv_nsec;
+}
+
+static void kvmclock_pre_save(void *opaque)
+{
+    KVMClockState *s = opaque;
+    struct timespec now;
+    uint64_t ns;
+
+    if (s->t_aftervmstop.tv_sec == 0) {
+        return;
+    }
+
+    clock_gettime(CLOCK_MONOTONIC, &now);
+
+    ns = clock_delta(&s->t_aftervmstop, &now);
+
+    /*
+     * Linux guests can overflow if time jumps
+     * forward in large increments.
+     * Cap maximum adjustment to 10 minutes.
+     */
+    ns = MIN(ns, 600000000000ULL);
+
+    if (s->clock + ns > s->clock) {
+        s->ns = ns;
+    }
+}
+
+static int kvmclock_post_load(void *opaque, int version_id)
+{
+    KVMClockState *s = opaque;
+
+    /* save the value from incoming migration */
+    s->advance_clock = s->ns;
+
+    return 0;
+}
+
 static const VMStateDescription kvmclock_vmsd = {
     .name = "kvmclock",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
+    .pre_save = kvmclock_pre_save,
+    .post_load = kvmclock_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_UINT64(clock, KVMClockState),
+        VMSTATE_UINT64_V(ns, KVMClockState, 2),
         VMSTATE_END_OF_LIST()
     }
 };

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

end of thread, other threads:[~2017-02-07 12:18 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-04  9:43 [Qemu-devel] [QEMU PATCH] kvmclock: advance clock by time window between vm_stop and pre_save Marcelo Tosatti
2016-11-04 12:28 ` Juan Quintela
2016-11-04 12:35   ` Marcelo Tosatti
2016-11-04 14:00     ` Marcelo Tosatti
2016-11-04 15:25 ` Radim Krčmář
2016-11-04 15:33   ` Paolo Bonzini
2016-11-04 15:48     ` Radim Krčmář
2016-11-04 15:57       ` Paolo Bonzini
2016-11-04 17:16         ` Radim Krčmář
2016-11-04 21:29           ` Paolo Bonzini
2016-11-04 21:47             ` Marcelo Tosatti
2016-11-04 22:35               ` Paolo Bonzini
2016-11-07 14:31           ` Roman Kagan
2016-11-07 19:31             ` Marcelo Tosatti
2016-11-04 16:24       ` Marcelo Tosatti
2016-11-04 17:34         ` Radim Krčmář
2016-11-04 18:29           ` Marcelo Tosatti
2016-11-04 20:07             ` Radim Krčmář
2016-11-04 16:04   ` Marcelo Tosatti
2016-11-04 17:07   ` Marcelo Tosatti
2016-11-04 17:39     ` Radim Krčmář
2016-11-04 18:31       ` Marcelo Tosatti
2016-11-07 13:08       ` Dr. David Alan Gilbert
2016-11-04 16:59 ` [Qemu-devel] [QEMU PATCH v2] " Marcelo Tosatti
2016-11-04 18:57   ` Juan Quintela
2016-11-07 15:46   ` Dr. David Alan Gilbert
2016-11-07 19:41     ` Marcelo Tosatti
2016-11-07 20:03       ` Dr. David Alan Gilbert
2016-11-08  0:06         ` Marcelo Tosatti
2016-11-08 10:22           ` Dr. David Alan Gilbert
2016-11-08 13:32             ` Marcelo Tosatti
2016-11-09 19:32               ` Marcelo Tosatti
2016-11-09 16:23             ` Paolo Bonzini
2016-11-09 16:28               ` Dr. David Alan Gilbert
2016-11-09 16:33                 ` Paolo Bonzini
2016-11-10 11:48               ` Marcelo Tosatti
2016-11-10 17:57                 ` Paolo Bonzini
2016-11-11 14:23                   ` Marcelo Tosatti
2017-02-07 10:02       ` Wanpeng Li
2017-02-07 12:18         ` Marcelo Tosatti

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).