Skip to contentSkip to conversation

improve kvmclock difference on migration

PATCH Superseded Marcelo Tosatti 4 participants 23 messages Nov 14, 2016 – Nov 28, 2016 KVM

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

cover improve kvmclock difference on migration

See patches for details.

#1 lore raw

PATCH 1/2 kvm: sync linux headers

Import KVM_CLOCK_TSC_STABLE.

include/standard-headers/linux/input.h +1 -0
index 7361a16..b472b85 100644
@@ -245,6 +245,7 @@ struct input_mask {
 #define BUS_SPI			0x1C
 #define BUS_RMI			0x1D
 #define BUS_CEC			0x1E
+#define BUS_INTEL_ISHTP		0x1F
 
 /*
  * MT_TOOL types
include/standard-headers/linux/pci_regs.h +14 -1
index 4040951..e5a2e68 100644
@@ -612,6 +612,8 @@
  */
 #define PCI_EXP_DEVCAP2		36	/* Device Capabilities 2 */
 #define  PCI_EXP_DEVCAP2_ARI		0x00000020 /* Alternative Routing-ID */
+#define  PCI_EXP_DEVCAP2_ATOMIC_ROUTE	0x00000040 /* Atomic Op routing */
+#define PCI_EXP_DEVCAP2_ATOMIC_COMP64	0x00000100 /* Atomic 64-bit compare */
 #define  PCI_EXP_DEVCAP2_LTR		0x00000800 /* Latency tolerance reporting */
 #define  PCI_EXP_DEVCAP2_OBFF_MASK	0x000c0000 /* OBFF support mechanism */
 #define  PCI_EXP_DEVCAP2_OBFF_MSG	0x00040000 /* New message signaling */
@@ -619,6 +621,7 @@
 #define PCI_EXP_DEVCTL2		40	/* Device Control 2 */
 #define  PCI_EXP_DEVCTL2_COMP_TIMEOUT	0x000f	/* Completion Timeout Value */
 #define  PCI_EXP_DEVCTL2_ARI		0x0020	/* Alternative Routing-ID */
+#define PCI_EXP_DEVCTL2_ATOMIC_REQ	0x0040	/* Set Atomic requests */
 #define  PCI_EXP_DEVCTL2_IDO_REQ_EN	0x0100	/* Allow IDO for requests */
 #define  PCI_EXP_DEVCTL2_IDO_CMP_EN	0x0200	/* Allow IDO for completions */
 #define  PCI_EXP_DEVCTL2_LTR_EN		0x0400	/* Enable LTR mechanism */
@@ -671,7 +674,8 @@
 #define PCI_EXT_CAP_ID_PMUX	0x1A	/* Protocol Multiplexing */
 #define PCI_EXT_CAP_ID_PASID	0x1B	/* Process Address Space ID */
 #define PCI_EXT_CAP_ID_DPC	0x1D	/* Downstream Port Containment */
-#define PCI_EXT_CAP_ID_MAX	PCI_EXT_CAP_ID_DPC
+#define PCI_EXT_CAP_ID_PTM	0x1F	/* Precision Time Measurement */
+#define PCI_EXT_CAP_ID_MAX	PCI_EXT_CAP_ID_PTM
 
 #define PCI_EXT_CAP_DSN_SIZEOF	12
 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
@@ -964,4 +968,13 @@
 
 #define PCI_EXP_DPC_SOURCE_ID		10	/* DPC Source Identifier */
 
+/* Precision Time Measurement */
+#define PCI_PTM_CAP			0x04	    /* PTM Capability */
+#define  PCI_PTM_CAP_REQ		0x00000001  /* Requester capable */
+#define  PCI_PTM_CAP_ROOT		0x00000004  /* Root capable */
+#define  PCI_PTM_GRANULARITY_MASK	0x0000FF00  /* Clock granularity */
+#define PCI_PTM_CTRL			0x08	    /* PTM Control */
+#define  PCI_PTM_CTRL_ENABLE		0x00000001  /* PTM enable */
+#define  PCI_PTM_CTRL_ROOT		0x00000002  /* Root select */
+
 #endif /* LINUX_PCI_REGS_H */
linux-headers/asm-arm/kvm.h +7 -0
index 541268c..2fb7859 100644
@@ -84,6 +84,13 @@ struct kvm_regs {
 #define KVM_VGIC_V2_DIST_SIZE		0x1000
 #define KVM_VGIC_V2_CPU_SIZE		0x2000
 
+/* Supported VGICv3 address types  */
+#define KVM_VGIC_V3_ADDR_TYPE_DIST	2
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST	3
+
+#define KVM_VGIC_V3_DIST_SIZE		SZ_64K
+#define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K)
+
 #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_PSCI_0_2		1 /* CPU uses PSCI v0.2 */
 
linux-headers/asm-x86/unistd_32.h +3 -0
index abeaf40..d45ea28 100644
@@ -377,5 +377,8 @@
 #define __NR_copy_file_range 377
 #define __NR_preadv2 378
 #define __NR_pwritev2 379
+#define __NR_pkey_mprotect 380
+#define __NR_pkey_alloc 381
+#define __NR_pkey_free 382
 
 #endif /* _ASM_X86_UNISTD_32_H */
linux-headers/asm-x86/unistd_64.h +3 -0
index 73c3d1f..e22db91 100644
@@ -330,5 +330,8 @@
 #define __NR_copy_file_range 326
 #define __NR_preadv2 327
 #define __NR_pwritev2 328
+#define __NR_pkey_mprotect 329
+#define __NR_pkey_alloc 330
+#define __NR_pkey_free 331
 
 #endif /* _ASM_X86_UNISTD_64_H */
linux-headers/asm-x86/unistd_x32.h +3 -0
index e5aea76..84e58b2 100644
@@ -283,6 +283,9 @@
 #define __NR_membarrier (__X32_SYSCALL_BIT + 324)
 #define __NR_mlock2 (__X32_SYSCALL_BIT + 325)
 #define __NR_copy_file_range (__X32_SYSCALL_BIT + 326)
+#define __NR_pkey_mprotect (__X32_SYSCALL_BIT + 329)
+#define __NR_pkey_alloc (__X32_SYSCALL_BIT + 330)
+#define __NR_pkey_free (__X32_SYSCALL_BIT + 331)
 #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
 #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
 #define __NR_ioctl (__X32_SYSCALL_BIT + 514)
linux-headers/linux/kvm.h +7 -0
index 4806e06..bb0ed71 100644
@@ -972,12 +972,19 @@ struct kvm_irqfd {
 	__u8  pad[16];
 };
 
+/* For KVM_CAP_ADJUST_CLOCK */
+
+/* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags.  */
+#define KVM_CLOCK_TSC_STABLE		2
+
 struct kvm_clock_data {
 	__u64 clock;
 	__u32 flags;
 	__u32 pad[9];
 };
 
+/* For KVM_CAP_SW_TLB */
+
 #define KVM_MMU_FSL_BOOKE_NOHV		0
 #define KVM_MMU_FSL_BOOKE_HV		1
 
#2 lore raw

PATCH 2/2 kvmclock: reduce kvmclock difference on migration

In reply to Marcelo Tosatti

Check for KVM_CAP_ADJUST_CLOCK capability KVM_CLOCK_TSC_STABLE, which indicates that KVM_GET_CLOCK returns a value as seen by the guest at that moment.

For new machine types, use this value rather than reading from guest memory.

This reduces kvmclock difference on migration from 5s to 0.1s (when max_downtime == 5s).

---
 hw/i386/kvm/clock.c    |   88 +++++++++++++++++++++++++++++++++++++++++++++++--
 include/hw/i386/pc.h   |    5 ++
 target-i386/kvm.c      |    7 +++
 target-i386/kvm_i386.h |    1 
 4 files changed, 98 insertions(+), 3 deletions(-)
hw/i386/kvm/clock.c +85 -3
Index: qemu-mig-advance-clock/hw/i386/kvm/clock.c
===================================================================
@@ -36,6 +36,12 @@
 
     uint64_t clock;
     bool clock_valid;
+
+    /* whether machine supports reliable KVM_GET_CLOCK */
+    bool mach_use_reliable_get_clock;
+
+    /* whether source host supported reliable KVM_GET_CLOCK */
+    bool src_use_reliable_get_clock;
 } KVMClockState;
 
 struct pvclock_vcpu_time_info {
@@ -91,15 +97,37 @@
 
     if (running) {
         struct kvm_clock_data data = {};
-        uint64_t time_at_migration = kvmclock_current_nsec(s);
+        uint64_t time_at_migration = 0;
 
-        s->clock_valid = false;
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */
+            if (!s->mach_use_reliable_get_clock ||
+                !s->src_use_reliable_get_clock) {
+                time_at_migration = kvmclock_current_nsec(s);
+            }
+        }
 
-        /* We can't rely on the migrated clock value, just discard it */
+        /* We can't rely on the saved clock value, just discard it */
         if (time_at_migration) {
             s->clock = time_at_migration;
         }
 
+        s->clock_valid = false;
+
         data.clock = s->clock;
         ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
         if (ret < 0) {
@@ -152,22 +180,76 @@
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
 }
 
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}
+
+static const VMStateDescription kvmclock_reliable_get_clock = {
+    .name = "kvmclock/src_use_reliable_get_clock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = kvmclock_src_use_reliable_get_clock,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(src_use_reliable_get_clock, KVMClockState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void kvmclock_pre_save(void *opaque)
+{
+    KVMClockState *s = opaque;
+    struct kvm_clock_data data;
+    int ret;
+
+    ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
+    if (ret < 0) {
+        fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
+                abort();
+    }
+    s->clock = data.clock;
+}
+
 static const VMStateDescription kvmclock_vmsd = {
     .name = "kvmclock",
     .version_id = 1,
     .minimum_version_id = 1,
+    .pre_save = kvmclock_pre_save,
     .fields = (VMStateField[]) {
         VMSTATE_UINT64(clock, KVMClockState),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (const VMStateDescription * []) {
+        &kvmclock_reliable_get_clock,
+        NULL
     }
 };
 
+static Property kvmclock_properties[] = {
+    DEFINE_PROP_BOOL("mach_use_reliable_get_clock", KVMClockState,
+                      mach_use_reliable_get_clock, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void kvmclock_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = kvmclock_realize;
     dc->vmsd = &kvmclock_vmsd;
+    dc->props = kvmclock_properties;
 }
 
 static const TypeInfo kvmclock_info = {
include/hw/i386/pc.h +5 -0
Index: qemu-mig-advance-clock/include/hw/i386/pc.h
===================================================================
@@ -370,6 +370,11 @@
 #define PC_COMPAT_2_7 \
     HW_COMPAT_2_7 \
     {\
+        .driver   = "kvmclock",\
+        .property = "mach_use_reliable_get_clock",\
+        .value    = "off",\
+    },\
+    {\
         .driver   = TYPE_X86_CPU,\
         .property = "l3-cache",\
         .value    = "off",\
target-i386/kvm.c +7 -0
Index: qemu-mig-advance-clock/target-i386/kvm.c
===================================================================
@@ -117,6 +117,13 @@
     return kvm_check_extension(kvm_state, KVM_CAP_X86_SMM);
 }
 
+bool kvm_has_adjust_clock_stable(void)
+{
+    int ret = kvm_check_extension(kvm_state, KVM_CAP_ADJUST_CLOCK);
+
+    return (ret == KVM_CLOCK_TSC_STABLE);
+}
+
 bool kvm_allows_irq0_override(void)
 {
     return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
target-i386/kvm_i386.h +1 -0
Index: qemu-mig-advance-clock/target-i386/kvm_i386.h
===================================================================
@@ -17,6 +17,7 @@
 
 bool kvm_allows_irq0_override(void);
 bool kvm_has_smm(void);
+bool kvm_has_adjust_clock_stable(void);
 void kvm_synchronize_all_tsc(void);
 void kvm_arch_reset_vcpu(X86CPU *cs);
 void kvm_arch_do_init_vcpu(X86CPU *cs);
maintainer
#3 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

hw/i386/kvm/clock.c line 109

Quoted 8 lines · Marcelo Tosatti
hw/i386/kvm/clock.c +8 -0
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);

Just assign to s->clock here...

hw/i386/kvm/clock.c line 120

Quoted 11 lines
hw/i386/kvm/clock.c +11 -0
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */
+            if (!s->mach_use_reliable_get_clock ||
+                !s->src_use_reliable_get_clock) {
+                time_at_migration = kvmclock_current_nsec(s);

... and here, so that time_at_migration is not needed anymore.

Also here it's enough to look at s->src_user_reliable_get_clock, because if s->mach_use_reliable_get_clock is false, s->src_use_reliable_get_clock will be false as well.

Quoted 7 lines
hw/i386/kvm/clock.c +3 -1
+            }
+        }
 
-        /* We can't rely on the migrated clock value, just discard it */
+        /* We can't rely on the saved clock value, just discard it */
         if (time_at_migration) {
             s->clock = time_at_migration;

[...]

Quoted 7 lines
hw/i386/kvm/clock.c +6 -0
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,

hw/i386/kvm/clock.c line 198

Quoted 10 lines
hw/i386/kvm/clock.c +10 -0
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}

Here you can just return s->mach_use_reliable_get_clock. To set s->src_use_reliable_get_clock, after issuing KVM_GET_CLOCK you can look at the KVM_CLOCK_TSC_STABLE bit in the kvm_clock struct's flags.

You don't actually need kvm_has_adjust_clock_stable(), but please place the KVM_GET_CLOCK code for kvmclock_pre_save and kvmclock_vm_state_change in a common function.

Also, just another small nit: please make your scripts use the "-p" option on diff. :)

Thanks,

Paolo

#4 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 12 lines · Paolo Bonzini

hw/i386/kvm/clock.c line 109

Quoted 8 lines · Marcelo Tosatti
hw/i386/kvm/clock.c +8 -0
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);
Quoted 1 line

Just assign to s->clock here...

If kvmclock is not enabled, you want to use s->clock, rather than 0.

Quoted 12 lines

hw/i386/kvm/clock.c line 120

Quoted 11 lines
hw/i386/kvm/clock.c +11 -0
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */
+            if (!s->mach_use_reliable_get_clock ||
+                !s->src_use_reliable_get_clock) {
+                time_at_migration = kvmclock_current_nsec(s);
Quoted 1 line

... and here, so that time_at_migration is not needed anymore.

Same as above.

Quoted 3 lines

Also here it's enough to look at s->src_user_reliable_get_clock, because if s->mach_use_reliable_get_clock is false, s->src_use_reliable_get_clock will be false as well.

Yes, but i like the code annotation.

Quoted 21 lines
Quoted 7 lines
hw/i386/kvm/clock.c +3 -1
+            }
+        }
 
-        /* We can't rely on the migrated clock value, just discard it */
+        /* We can't rely on the saved clock value, just discard it */
         if (time_at_migration) {
             s->clock = time_at_migration;

[...]

Quoted 11 lines
hw/i386/kvm/clock.c +10 -0
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
Quoted 8 lines

hw/i386/kvm/clock.c line 198

Quoted 6 lines
hw/i386/kvm/clock.c +6 -0
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}

Here you can just return s->mach_use_reliable_get_clock.

mach_use_reliable_get_clock can be true but host might not support it.

Quoted 3 lines

To set
s->src_use_reliable_get_clock, after issuing KVM_GET_CLOCK you can look at the KVM_CLOCK_TSC_STABLE bit in the kvm_clock struct's flags.

KVM_CLOCK_TSC_STABLE bit in the kvmclock structure != KVM_GET_CLOCK returns reliable value, right?

Quoted 3 lines

You don't actually need kvm_has_adjust_clock_stable(), but please place the KVM_GET_CLOCK code for kvmclock_pre_save and kvmclock_vm_state_change in a common function.

Sure.

Quoted 2 lines

Also, just another small nit: please make your scripts use the "-p" option on diff. :)

Sure.

Quoted 4 lines

Thanks,

Paolo

maintainer
#5 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 30 lines · Marcelo Tosatti
Quoted 12 lines · Paolo Bonzini

hw/i386/kvm/clock.c line 109

Quoted 8 lines · Marcelo Tosatti
hw/i386/kvm/clock.c +8 -0
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);
Quoted 1 line

Just assign to s->clock here...

If kvmclock is not enabled, you want to use s->clock, rather than 0.

Quoted 12 lines
Quoted 11 lines
hw/i386/kvm/clock.c +11 -0
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */
+            if (!s->mach_use_reliable_get_clock ||
+                !s->src_use_reliable_get_clock) {
+                time_at_migration = kvmclock_current_nsec(s);
Quoted 3 lines
Quoted 1 line

... and here, so that time_at_migration is not needed anymore.

Same as above.

You're right.

Quoted 5 lines
Quoted 3 lines

Also here it's enough to look at s->src_user_reliable_get_clock, because if s->mach_use_reliable_get_clock is false, s->src_use_reliable_get_clock will be false as well.

Yes, but i like the code annotation.

Ah, I think we're looking at it differently.

I'm thinking "mach_use_reliable_get_clock is just for migration, src_use_reliable_get_clock is the state". Perhaps you're thinking of enabling/disabling the whole new code for old machines? What is the advantage?

Quoted 30 lines
Quoted 21 lines
Quoted 7 lines
hw/i386/kvm/clock.c +3 -1
+            }
+        }
 
-        /* We can't rely on the migrated clock value, just discard it */
+        /* We can't rely on the saved clock value, just discard it */
         if (time_at_migration) {
             s->clock = time_at_migration;

[...]

Quoted 11 lines
hw/i386/kvm/clock.c +10 -0
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
Quoted 8 lines

hw/i386/kvm/clock.c line 198

Quoted 6 lines
hw/i386/kvm/clock.c +6 -0
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}

Here you can just return s->mach_use_reliable_get_clock.

Quoted 1 line

mach_use_reliable_get_clock can be true but host might not support it.

Yes, but the "needed" function is only required to avoid breaking pc-i440fx-2.7 and earlier. If you return true here, you can still migrate a "false" value for src_use_reliable_get_clock.

Quoted 6 lines
Quoted 3 lines

To set
s->src_use_reliable_get_clock, after issuing KVM_GET_CLOCK you can look at the KVM_CLOCK_TSC_STABLE bit in the kvm_clock struct's flags.

KVM_CLOCK_TSC_STABLE bit in the kvmclock structure != KVM_GET_CLOCK returns reliable value, right?

It is the same as "is using masterclock", which is actually a stricter condition than the KVM_CHECK_EXTENSION return value. The right check to use is whether masterclock is in use, and then the idea is to treat clock,src_use_reliable_get_clock as one tuple that is updated atomically.

Paolo

#6 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 39 lines · Paolo Bonzini
Quoted 30 lines · Marcelo Tosatti
Quoted 12 lines · Paolo Bonzini

hw/i386/kvm/clock.c line 109

Quoted 8 lines · Marcelo Tosatti
hw/i386/kvm/clock.c +8 -0
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);
Quoted 1 line

Just assign to s->clock here...

If kvmclock is not enabled, you want to use s->clock, rather than 0.

Quoted 12 lines
Quoted 11 lines
hw/i386/kvm/clock.c +11 -0
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */
+            if (!s->mach_use_reliable_get_clock ||
+                !s->src_use_reliable_get_clock) {
+                time_at_migration = kvmclock_current_nsec(s);
Quoted 3 lines
Quoted 1 line

... and here, so that time_at_migration is not needed anymore.

Same as above.

You're right.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

Also here it's enough to look at s->src_user_reliable_get_clock, because if s->mach_use_reliable_get_clock is false, s->src_use_reliable_get_clock will be false as well.

Yes, but i like the code annotation.

Ah, I think we're looking at it differently.

Well, i didnt want to mix the meaning of the variables:

+ /* whether machine supports reliable KVM_GET_CLOCK */
+ bool mach_use_reliable_get_clock;
+
+ /* whether source host supported reliable KVM_GET_CLOCK */
+ bool src_use_reliable_get_clock;

See the comments on top (later if you look at the variable, then have to think: well it has one name, but its disabled by that other path as well, so its more than its name,etc...).

Quoted 1 line

I'm thinking "mach_use_reliable_get_clock is just for migration,

Thats whether the machine supports it. New machines have it enabled, olders don't.

Quoted 1 line

src_use_reliable_get_clock is the state".

Thats whether the migration source supported it.

Quoted 2 lines

Perhaps you're thinking of
enabling/disabling the whole new code for old machines?

source          destination         behaviour
supports        supports            on migration use s->clock,

on stop/cont as well

supports ~supports
on migration use s->clock, on stop/cont read from guest mem

~support supports on migration read from guest,
on stop/cont use kvm_get_clock/kvm_set_clock

~support ~support always read from guest memory

Thats what should happen (and thats what the patch should implement).

"support" means host supports your new KVM_GET_CLOCK/KVM_SET_CLOCK.

Quoted 2 lines

What is the
advantage?

Well its necessary to use the correct thing, otherwise you see a time backwards event.

Quoted 31 lines
Quoted 31 lines
Quoted 30 lines
Quoted 8 lines
hw/i386/kvm/clock.c +3 -1
+            }
+        }
 
-        /* We can't rely on the migrated clock value, just discard it */
+        /* We can't rely on the saved clock value, just discard it */
         if (time_at_migration) {
             s->clock = time_at_migration;

[...]

Quoted 7 lines
hw/i386/kvm/clock.c +6 -0
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,

hw/i386/kvm/clock.c line 198

Quoted 10 lines
hw/i386/kvm/clock.c +10 -0
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}

Here you can just return s->mach_use_reliable_get_clock.

Quoted 4 lines
Quoted 1 line

mach_use_reliable_get_clock can be true but host might not support it.

Yes, but the "needed" function is only required to avoid breaking pc-i440fx-2.7 and earlier.

"needed" is required so that the migration between:

SRC             DEST                BEHAVIOUR
~support        supports            on migration read from guest,

on stop/cont use kvm_get_clock/kvm_set_clock

Destination does not use KVM_GET_CLOCK value (which is broken and should not be used).

Quoted 2 lines

If you return true here, you can still
migrate a "false" value for src_use_reliable_get_clock.

But the source only uses a reliable KVM_GET_CLOCK if both conditions are true.

And the subsection is only needed if the source uses a reliable KVM_GET_CLOCK.

Quoted 10 lines
Quoted 6 lines
Quoted 3 lines

To set
s->src_use_reliable_get_clock, after issuing KVM_GET_CLOCK you can look at the KVM_CLOCK_TSC_STABLE bit in the kvm_clock struct's flags.

KVM_CLOCK_TSC_STABLE bit in the kvmclock structure != KVM_GET_CLOCK returns reliable value, right?

It is the same as "is using masterclock", which is actually a stricter condition than the KVM_CHECK_EXTENSION return value. The right check to use is whether masterclock is in use,

Actually its "has a reliable KVM_GET_CLOCK" (which returns get_kernel_clock() + (rdtsc() - tsc_timestamp),

"broken KVM_GET_CLOCK" = get_kernel_clock()

Quoted 4 lines

and then the idea is to treat clock,src_use_reliable_get_clock as one tuple that is updated atomically.

Paolo

Hum, not sure i get this...

maintainer
#7 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 13 lines · Marcelo Tosatti

Well, i didnt want to mix the meaning of the variables:

hw/i386/kvm/clock.c +5 -0
+    /* whether machine supports reliable KVM_GET_CLOCK */
+    bool mach_use_reliable_get_clock;
+
+    /* whether source host supported reliable KVM_GET_CLOCK */
+    bool src_use_reliable_get_clock;

See the comments on top (later if you look at the variable, then have to think: well it has one name, but its disabled by that other path as well, so its more than its name,etc...).

Quoted 4 lines
Quoted 1 line

I'm thinking "mach_use_reliable_get_clock is just for migration,

Thats whether the machine supports it. New machines have it enabled, olders don't.

Yes.

Quoted 3 lines
Quoted 1 line

src_use_reliable_get_clock is the state".

Thats whether the migration source supported it.

But it's not used only for migration. It's used on every vmstate change (running->stop and stop->running, isn't it? I think that, apart from the migration case, it's better to use s->clock if kvmclock is stable, even on older machine types.

Quoted 26 lines
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 6 lines
hw/i386/kvm/clock.c +6 -0
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,

hw/i386/kvm/clock.c line 198

Quoted 10 lines
hw/i386/kvm/clock.c +10 -0
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}

Here you can just return s->mach_use_reliable_get_clock.

Quoted 4 lines
Quoted 1 line

mach_use_reliable_get_clock can be true but host might not support it.

Yes, but the "needed" function is only required to avoid breaking pc-i440fx-2.7 and earlier.

"needed" is required so that the migration between:

Quoted 7 lines
SRC             DEST                BEHAVIOUR
~support        supports            on migration read from guest,

on stop/cont use kvm_get_clock/kvm_set_clock

Destination does not use KVM_GET_CLOCK value (which is broken and should not be used).

If needed returns false, the destination will see
src_use_reliable_get_clock = false anyway.

If needed returns true, the destination can still see src_use_reliable_get_clock = false if that's the value.

needed src_use_reliable_get_clock effect
false false use kvmclock_current_nsec
false true use kvmclock_current_nsec
true false use kvmclock_current_nsec
true true use s->clock

So the idea is:

- set s->clock and s->reliable_get_clock on every KVM_GET_CLOCK

- on migration source, use subsections and s->mach_use_reliable_get_clock to avoid breaking migration on pre-2.8 machine types

- on migration destination, use .pre_load so that s->reliable_get_clock is initialized to false on older machine types

Quoted 8 lines
Quoted 2 lines

If you return true here, you can still
migrate a "false" value for src_use_reliable_get_clock.

But the source only uses a reliable KVM_GET_CLOCK if both conditions are true.

And the subsection is only needed if the source uses a reliable KVM_GET_CLOCK.

Yes, but the point of the subsection is just to avoid breaking migration format.

Quoted 8 lines
Quoted 3 lines

It is the same as "is using masterclock", which is actually a stricter condition than the KVM_CHECK_EXTENSION return value. The right check to use is whether masterclock is in use,

Actually its "has a reliable KVM_GET_CLOCK" (which returns get_kernel_clock() + (rdtsc() - tsc_timestamp),

"broken KVM_GET_CLOCK" = get_kernel_clock()

Yes. And these end up being the same.

Paolo

#8 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 21 lines · Paolo Bonzini
Quoted 13 lines · Marcelo Tosatti

Well, i didnt want to mix the meaning of the variables:

(quoted diff) +5 -0
+    /* whether machine supports reliable KVM_GET_CLOCK */
+    bool mach_use_reliable_get_clock;
+
+    /* whether source host supported reliable KVM_GET_CLOCK */
+    bool src_use_reliable_get_clock;

See the comments on top (later if you look at the variable, then have to think: well it has one name, but its disabled by that other path as well, so its more than its name,etc...).

Quoted 4 lines
Quoted 1 line

I'm thinking "mach_use_reliable_get_clock is just for migration,

Thats whether the machine supports it. New machines have it enabled, olders don't.

Quoted 8 lines

Yes.

Quoted 3 lines
Quoted 1 line

src_use_reliable_get_clock is the state".

Thats whether the migration source supported it.

But it's not used only for migration. It's used on every vmstate change (running->stop and stop->running, isn't it?

No. Its used only if s->clock_valid == false, which means either:

migration/savevm/init.

Now for savevm there is a bug:

Quoted 3 lines

I think that, apart from
the migration case, it's better to use s->clock if kvmclock is stable, even on older machine types.

Yes, its already doing that:

        /* local (running VM) restore */
        if (s->clock_valid) {
            /*
             * if host does not support reliable KVM_GET_CLOCK,
             * read kvmclock value from memory
             */
            if (!kvm_has_adjust_clock_stable()) {
                time_at_migration = kvmclock_current_nsec(s);
            }

It only uses kvmclock_current_nsec() if kvm_has_adjust_clock_stable is false.

Quoted 31 lines
Quoted 31 lines
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 6 lines
(quoted diff) +6 -0
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,

Review

Quoted 10 lines
(quoted diff) +10 -0
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->src_use_reliable_get_clock;
+}

Here you can just return s->mach_use_reliable_get_clock.

Quoted 4 lines
Quoted 1 line

mach_use_reliable_get_clock can be true but host might not support it.

Yes, but the "needed" function is only required to avoid breaking pc-i440fx-2.7 and earlier.

"needed" is required so that the migration between:

SRC             DEST                BEHAVIOUR
~support        supports            on migration read from guest,

on stop/cont use kvm_get_clock/kvm_set_clock

Quoted 5 lines
Quoted 2 lines

Destination does not use KVM_GET_CLOCK value (which is broken and should not be used).

If needed returns false, the destination will see
src_use_reliable_get_clock = false anyway.

Causing it to read the clock from memory, thats what should happen.

Quoted 2 lines

If needed returns true, the destination can still see src_use_reliable_get_clock = false if that's the value.

You are asking me to change from:

+static bool kvmclock_src_use_reliable_get_clock(void *opaque) +{
+ KVMClockState *s = opaque;
+
+ /*

+     * On machine types that support reliable KVM_GET_CLOCK,
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */

+ if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+ s->src_use_reliable_get_clock = true;
+ }
+
+ return s->src_use_reliable_get_clock;
+}

to

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }

    return s->mach_use_reliable_get_clock;
}

Ah, OK, done.

Quoted 10 lines

needed src_use_reliable_get_clock effect
false false use kvmclock_current_nsec
false true use kvmclock_current_nsec
true false use kvmclock_current_nsec
true true use s->clock

So the idea is:

- set s->clock and s->reliable_get_clock on every KVM_GET_CLOCK

Already do that (apart from s->clock_valid which is necessary).

Quoted 3 lines

- on migration source, use subsections and s->mach_use_reliable_get_clock to avoid breaking migration on pre-2.8 machine types

Migration is already broken when you use different machine types.

So s->src_use_reliable_get_clock is only used to indicate to the destination that: "you can use KVM_GET_CLOCK value, its safe".

Quoted 2 lines

- on migration destination, use .pre_load so that s->reliable_get_clock is initialized to false on older machine types

Thats what mach_use_reliable_get_clock does already:

static Property kvmclock_properties[] = {
    DEFINE_PROP_BOOL("mach_use_reliable_get_clock", KVMClockState,
                      mach_use_reliable_get_clock, true),
    DEFINE_PROP_END_OF_LIST(),
};
+        .driver   = "kvmclock",\
+        .property = "mach_use_reliable_get_clock",\
+        .value    = "off",\

+ },\
+ {\

Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

If you return true here, you can still
migrate a "false" value for src_use_reliable_get_clock.

Quoted 8 lines
Quoted 5 lines

But the source only uses a reliable KVM_GET_CLOCK if both conditions are true.

And the subsection is only needed if the source uses a reliable KVM_GET_CLOCK.

Yes, but the point of the subsection is just to avoid breaking migration format.

Its a new creative use of the subsection.

Quoted 10 lines
Quoted 8 lines
Quoted 3 lines

It is the same as "is using masterclock", which is actually a stricter condition than the KVM_CHECK_EXTENSION return value. The right check to use is whether masterclock is in use,

Actually its "has a reliable KVM_GET_CLOCK" (which returns get_kernel_clock() + (rdtsc() - tsc_timestamp),

"broken KVM_GET_CLOCK" = get_kernel_clock()

Yes. And these end up being the same.

No. You can have masterclock enabled, KVM_TSC_STABLE set in pvclock flags, and unreliable KVM_GET_CLOCK (without your patch to KVM_GET_CLOCK).

Paolo not sure if there is anything further you want me to change at this point ?

hw/i386/kvm/clock.c +94 -14
Index: qemu-mig-advance-clock/hw/i386/kvm/clock.c
===================================================================
@@ -36,6 +36,12 @@
 
     uint64_t clock;
     bool clock_valid;
+
+    /* whether machine supports reliable KVM_GET_CLOCK */
+    bool mach_use_reliable_get_clock;
+
+    /* whether source host supported reliable KVM_GET_CLOCK */
+    bool src_use_reliable_get_clock;
 } KVMClockState;
 
 struct pvclock_vcpu_time_info {
@@ -81,6 +87,19 @@
     return nsec + time.system_time;
 }
 
+static uint64_t kvm_get_clock(void)
+{
+    struct kvm_clock_data data;
+    int ret;
+
+    ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
+    if (ret < 0) {
+        fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
+                abort();
+    }
+    return data.clock;
+}
+
 static void kvmclock_vm_state_change(void *opaque, int running,
                                      RunState state)
 {
@@ -91,15 +110,37 @@
 
     if (running) {
         struct kvm_clock_data data = {};
-        uint64_t time_at_migration = kvmclock_current_nsec(s);
+        uint64_t pvclock_via_mem = 0;
 
-        s->clock_valid = false;
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                pvclock_via_mem = kvmclock_current_nsec(s);
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and source host supported
+             * reliable get clock
+             */
+            if (!(s->mach_use_reliable_get_clock &&
+                  s->src_use_reliable_get_clock)) {
+                pvclock_via_mem = kvmclock_current_nsec(s);
+            }
+        }
 
-        /* We can't rely on the migrated clock value, just discard it */
-        if (time_at_migration) {
-            s->clock = time_at_migration;
+        /* We can't rely on the saved clock value, just discard it */
+        if (pvclock_via_mem) {
+            s->clock = pvclock_via_mem;
         }
 
+        s->clock_valid = false;
+
         data.clock = s->clock;
         ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
         if (ret < 0) {
@@ -120,8 +161,6 @@
             }
         }
     } else {
-        struct kvm_clock_data data;
-        int ret;
 
         if (s->clock_valid) {
             return;
@@ -129,13 +168,7 @@
 
         kvm_synchronize_all_tsc();
 
-        ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
-        if (ret < 0) {
-            fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
-            abort();
-        }
-        s->clock = data.clock;
-
+        s->clock = kvm_get_clock();
         /*
          * If the VM is stopped, declare the clock state valid to
          * avoid re-reading it on next vmsave (which would return
@@ -152,22 +185,69 @@
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
 }
 
+static bool kvmclock_src_use_reliable_get_clock(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    /*
+     * On machine types that support reliable KVM_GET_CLOCK,
+     * if host kernel does provide reliable KVM_GET_CLOCK,
+     * set src_use_reliable_get_clock=true so that destination
+     * avoids reading kvmclock from memory.
+     */
+    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
+        s->src_use_reliable_get_clock = true;
+    }
+
+    return s->mach_use_reliable_get_clock;
+}
+
+static const VMStateDescription kvmclock_reliable_get_clock = {
+    .name = "kvmclock/src_use_reliable_get_clock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = kvmclock_src_use_reliable_get_clock,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(src_use_reliable_get_clock, KVMClockState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void kvmclock_pre_save(void *opaque)
+{
+    KVMClockState *s = opaque;
+
+    s->clock = kvm_get_clock();
+}
+
 static const VMStateDescription kvmclock_vmsd = {
     .name = "kvmclock",
     .version_id = 1,
     .minimum_version_id = 1,
+    .pre_save = kvmclock_pre_save,
     .fields = (VMStateField[]) {
         VMSTATE_UINT64(clock, KVMClockState),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (const VMStateDescription * []) {
+        &kvmclock_reliable_get_clock,
+        NULL
     }
 };
 
+static Property kvmclock_properties[] = {
+    DEFINE_PROP_BOOL("mach_use_reliable_get_clock", KVMClockState,
+                      mach_use_reliable_get_clock, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void kvmclock_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = kvmclock_realize;
     dc->vmsd = &kvmclock_vmsd;
+    dc->props = kvmclock_properties;
 }
 
 static const TypeInfo kvmclock_info = {
include/hw/i386/pc.h +5 -0
Index: qemu-mig-advance-clock/include/hw/i386/pc.h
===================================================================
@@ -370,6 +370,11 @@
 #define PC_COMPAT_2_7 \
     HW_COMPAT_2_7 \
     {\
+        .driver   = "kvmclock",\
+        .property = "mach_use_reliable_get_clock",\
+        .value    = "off",\
+    },\
+    {\
         .driver   = TYPE_X86_CPU,\
         .property = "l3-cache",\
         .value    = "off",\
target-i386/kvm.c +7 -0
Index: qemu-mig-advance-clock/target-i386/kvm.c
===================================================================
@@ -117,6 +117,13 @@
     return kvm_check_extension(kvm_state, KVM_CAP_X86_SMM);
 }
 
+bool kvm_has_adjust_clock_stable(void)
+{
+    int ret = kvm_check_extension(kvm_state, KVM_CAP_ADJUST_CLOCK);
+
+    return (ret == KVM_CLOCK_TSC_STABLE);
+}
+
 bool kvm_allows_irq0_override(void)
 {
     return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
target-i386/kvm_i386.h +1 -0
Index: qemu-mig-advance-clock/target-i386/kvm_i386.h
===================================================================
@@ -17,6 +17,7 @@
 
 bool kvm_allows_irq0_override(void);
 bool kvm_has_smm(void);
+bool kvm_has_adjust_clock_stable(void);
 void kvm_synchronize_all_tsc(void);
 void kvm_arch_reset_vcpu(X86CPU *cs);
 void kvm_arch_do_init_vcpu(X86CPU *cs);
maintainer
#9 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 19 lines · Marcelo Tosatti

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }

    return s->mach_use_reliable_get_clock;
}
Quoted 1 line

Ah, OK, done.

s->src_use_reliable_get_clock should not be set with KVM_CHECK_EXTENSION, but rather from the flags returned by KVM_GET_CLOCK.

Quoted 3 lines

So s->src_use_reliable_get_clock is only used to indicate to the destination that: "you can use KVM_GET_CLOCK value, its safe".

Yes, we agree. I was listing all the points, not just those where we disagree. Actually I'm not sure where we disagree, except on using flags from KVM_CHECK_EXTENSION vs. flags from KVM_GET_CLOCK...

Paolo

#10 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 18 lines · Paolo Bonzini
Quoted 15 lines · Marcelo Tosatti

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }
Quoted 8 lines
Quoted 5 lines
    return s->mach_use_reliable_get_clock;
}

Ah, OK, done.

s->src_use_reliable_get_clock should not be set with KVM_CHECK_EXTENSION, but rather from the flags returned by KVM_GET_CLOCK.

Well, thats not right: What matters is the presence of get_kvmclock_ns which returns a value that the guest sees.

get_kernel_monotonic_clock() + kvmclock_offset + (rdtsc() - tsc_timestamp)

IOW what the guest sees. And you changed that in

commit 108b249c453dd7132599ab6dc7e435a7036c193f

Author: Paolo Bonzini <[email protected]>
Date:   Thu Sep 1 14:21:03 2016 +0200

KVM: x86: introduce get_kvmclock_ns

And the correct behaviour (once KVM_GET_CLOCK is fixed per previous message to return rdtsc - tsc_timestamp for the non masterclock case) depends on this commit above, not on masterclock.

Quoted 9 lines
Quoted 3 lines

So s->src_use_reliable_get_clock is only used to indicate to the destination that: "you can use KVM_GET_CLOCK value, its safe".

Yes, we agree. I was listing all the points, not just those where we disagree. Actually I'm not sure where we disagree, except on using flags from KVM_CHECK_EXTENSION vs. flags from KVM_GET_CLOCK...

Paolo

maintainer
#11 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 40 lines · Marcelo Tosatti
Quoted 18 lines · Paolo Bonzini
Quoted 15 lines · Marcelo Tosatti

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }
Quoted 8 lines
Quoted 5 lines
    return s->mach_use_reliable_get_clock;
}

Ah, OK, done.

s->src_use_reliable_get_clock should not be set with KVM_CHECK_EXTENSION, but rather from the flags returned by KVM_GET_CLOCK.

Well, thats not right: What matters is the presence of get_kvmclock_ns which returns a value that the guest sees.

get_kernel_monotonic_clock() + kvmclock_offset + (rdtsc() - tsc_timestamp)

IOW what the guest sees. And you changed that in

commit 108b249c453dd7132599ab6dc7e435a7036c193f

Author: Paolo Bonzini <[email protected]>
Date:   Thu Sep 1 14:21:03 2016 +0200
Quoted 6 lines

KVM: x86: introduce get_kvmclock_ns

And the correct behaviour (once KVM_GET_CLOCK is fixed per previous message to return rdtsc - tsc_timestamp for the non masterclock case) depends on this commit above, not on masterclock.

This commit in turn only gets the correct behavior if "vcpu->arch.hv_clock.flags & PVCLOCK_TSC_STABLE_BIT" (and it will be changed soon to ka->use_masterclock). KVM_CHECK_EXTENSION can still return KVM_CLOCK_TSC_STABLE even if the masterclock is disabled, because KVM_CHECK_EXTENSION only tells you which flags are known for this version of the KVM module.

To see if the masterclock is enabled _now_, you need to check what KVM_GET_CLOCK sets in the flags. From the KVM_CLOCK_TSC_STABLE patch:

		user_ns.flags = kvm->arch.use_master_clock ? KVM_CLOCK_TSC_STABLE : 0;

Thanks,

Paolo

Quoted 9 lines
Quoted 9 lines
Quoted 3 lines

So s->src_use_reliable_get_clock is only used to indicate to the destination that: "you can use KVM_GET_CLOCK value, its safe".

Yes, we agree. I was listing all the points, not just those where we disagree. Actually I'm not sure where we disagree, except on using flags from KVM_CHECK_EXTENSION vs. flags from KVM_GET_CLOCK...

Paolo

#12 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 50 lines · Paolo Bonzini
Quoted 40 lines · Marcelo Tosatti
Quoted 18 lines · Paolo Bonzini
Quoted 15 lines · Marcelo Tosatti

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }
Quoted 8 lines
Quoted 5 lines
    return s->mach_use_reliable_get_clock;
}

Ah, OK, done.

s->src_use_reliable_get_clock should not be set with KVM_CHECK_EXTENSION, but rather from the flags returned by KVM_GET_CLOCK.

Well, thats not right: What matters is the presence of get_kvmclock_ns which returns a value that the guest sees.

get_kernel_monotonic_clock() + kvmclock_offset + (rdtsc() - tsc_timestamp)

IOW what the guest sees. And you changed that in

commit 108b249c453dd7132599ab6dc7e435a7036c193f

Author: Paolo Bonzini <[email protected]>
Date:   Thu Sep 1 14:21:03 2016 +0200
Quoted 6 lines

KVM: x86: introduce get_kvmclock_ns

And the correct behaviour (once KVM_GET_CLOCK is fixed per previous message to return rdtsc - tsc_timestamp for the non masterclock case) depends on this commit above, not on masterclock.

Quoted 6 lines

This commit in turn only gets the correct behavior if "vcpu->arch.hv_clock.flags & PVCLOCK_TSC_STABLE_BIT" (and it will be changed soon to ka->use_masterclock). KVM_CHECK_EXTENSION can still return KVM_CLOCK_TSC_STABLE even if the masterclock is disabled, because KVM_CHECK_EXTENSION only tells you which flags are known for this version of the KVM module.

What QEMU wants is to use KVM_GET_CLOCK at pre_save independently of whether masterclock is enabled or not... it just depends on KVM_GET_CLOCK being correct for the masterclock case (108b249c453dd7132599ab6dc7e435a7036c193f).

So a "reliable KVM_GET_CLOCK" (that does not timebackward when masterclock is enabled) is much simpler to userspace than "whether masterclock is enabled or not".

If you have a reason why that should not be the case, let me know.

Quoted 4 lines

To see if the masterclock is enabled _now_, you need to check what KVM_GET_CLOCK sets in the flags. From the KVM_CLOCK_TSC_STABLE patch:

		user_ns.flags = kvm->arch.use_master_clock ? KVM_CLOCK_TSC_STABLE : 0;

Again, whether masterclock is enable is independent of being able to use KVM_GET_CLOCK at pre_save.

#13 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 70 lines · Marcelo Tosatti
Quoted 50 lines · Paolo Bonzini
Quoted 40 lines · Marcelo Tosatti
Quoted 18 lines · Paolo Bonzini
Quoted 15 lines · Marcelo Tosatti

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }
Quoted 8 lines
Quoted 5 lines
    return s->mach_use_reliable_get_clock;
}

Ah, OK, done.

s->src_use_reliable_get_clock should not be set with KVM_CHECK_EXTENSION, but rather from the flags returned by KVM_GET_CLOCK.

Well, thats not right: What matters is the presence of get_kvmclock_ns which returns a value that the guest sees.

get_kernel_monotonic_clock() + kvmclock_offset + (rdtsc() - tsc_timestamp)

IOW what the guest sees. And you changed that in

commit 108b249c453dd7132599ab6dc7e435a7036c193f

Author: Paolo Bonzini <[email protected]>
Date:   Thu Sep 1 14:21:03 2016 +0200
Quoted 6 lines

KVM: x86: introduce get_kvmclock_ns

And the correct behaviour (once KVM_GET_CLOCK is fixed per previous message to return rdtsc - tsc_timestamp for the non masterclock case) depends on this commit above, not on masterclock.

Quoted 6 lines

This commit in turn only gets the correct behavior if "vcpu->arch.hv_clock.flags & PVCLOCK_TSC_STABLE_BIT" (and it will be changed soon to ka->use_masterclock). KVM_CHECK_EXTENSION can still return KVM_CLOCK_TSC_STABLE even if the masterclock is disabled, because KVM_CHECK_EXTENSION only tells you which flags are known for this version of the KVM module.

What QEMU wants is to use KVM_GET_CLOCK at pre_save independently of whether masterclock is enabled or not... it just depends on KVM_GET_CLOCK being correct for the masterclock case (108b249c453dd7132599ab6dc7e435a7036c193f).

So a "reliable KVM_GET_CLOCK" (that does not timebackward when masterclock is enabled) is much simpler to userspace than "whether masterclock is enabled or not".

If you have a reason why that should not be the case, let me know.

Quoted 7 lines
Quoted 4 lines

To see if the masterclock is enabled _now_, you need to check what KVM_GET_CLOCK sets in the flags. From the KVM_CLOCK_TSC_STABLE patch:

		user_ns.flags = kvm->arch.use_master_clock ? KVM_CLOCK_TSC_STABLE : 0;

Again, whether masterclock is enable is independent of being able to use KVM_GET_CLOCK at pre_save.

Is this point OK ?

Using

                break;

+ case KVM_CAP_ADJUST_CLOCK:
+ r = KVM_CLOCK_TSC_STABLE;
+ break;

To infer whether KVM_GET_CLOCK is fixed for the monotonic case.

maintainer
#14 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 88 lines · Marcelo Tosatti
Quoted 70 lines · Marcelo Tosatti
Quoted 50 lines · Paolo Bonzini
Quoted 40 lines · Marcelo Tosatti
Quoted 18 lines · Paolo Bonzini
Quoted 15 lines · Marcelo Tosatti

static bool kvmclock_src_use_reliable_get_clock(void *opaque)

{
    KVMClockState *s = opaque;

    /*
     * On machine types that support reliable KVM_GET_CLOCK,
     * if host kernel does provide reliable KVM_GET_CLOCK,
     * set src_use_reliable_get_clock=true so that destination
     * avoids reading kvmclock from memory.
     */
    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable())
    {
        s->src_use_reliable_get_clock = true;
    }
Quoted 8 lines
Quoted 5 lines
    return s->mach_use_reliable_get_clock;
}

Ah, OK, done.

s->src_use_reliable_get_clock should not be set with KVM_CHECK_EXTENSION, but rather from the flags returned by KVM_GET_CLOCK.

Well, thats not right: What matters is the presence of get_kvmclock_ns which returns a value that the guest sees.

get_kernel_monotonic_clock() + kvmclock_offset + (rdtsc() - tsc_timestamp)

IOW what the guest sees. And you changed that in

commit 108b249c453dd7132599ab6dc7e435a7036c193f

Author: Paolo Bonzini <[email protected]>
Date:   Thu Sep 1 14:21:03 2016 +0200
Quoted 6 lines

KVM: x86: introduce get_kvmclock_ns

And the correct behaviour (once KVM_GET_CLOCK is fixed per previous message to return rdtsc - tsc_timestamp for the non masterclock case) depends on this commit above, not on masterclock.

Quoted 6 lines

This commit in turn only gets the correct behavior if "vcpu->arch.hv_clock.flags & PVCLOCK_TSC_STABLE_BIT" (and it will be changed soon to ka->use_masterclock). KVM_CHECK_EXTENSION can still return KVM_CLOCK_TSC_STABLE even if the masterclock is disabled, because KVM_CHECK_EXTENSION only tells you which flags are known for this version of the KVM module.

What QEMU wants is to use KVM_GET_CLOCK at pre_save independently of whether masterclock is enabled or not... it just depends on KVM_GET_CLOCK being correct for the masterclock case (108b249c453dd7132599ab6dc7e435a7036c193f).

So a "reliable KVM_GET_CLOCK" (that does not timebackward when masterclock is enabled) is much simpler to userspace than "whether masterclock is enabled or not".

If you have a reason why that should not be the case, let me know.

Quoted 7 lines
Quoted 4 lines

To see if the masterclock is enabled _now_, you need to check what KVM_GET_CLOCK sets in the flags. From the KVM_CLOCK_TSC_STABLE patch:

		user_ns.flags = kvm->arch.use_master_clock ? KVM_CLOCK_TSC_STABLE : 0;

Again, whether masterclock is enable is independent of being able to use KVM_GET_CLOCK at pre_save.

Is this point OK ?

Using

                break;
(quoted diff) +3 -0
+   case KVM_CAP_ADJUST_CLOCK:
+               r = KVM_CLOCK_TSC_STABLE;
+               break;
Quoted 1 line

To infer whether KVM_GET_CLOCK is fixed for the monotonic case.

Yes, I still haven't digested why it is correct (I need to read again what you wrote), but it is indeed correct to use KVM_CAP_ADJUST_CLOCK this way.

Paolo

maintainer
#15 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

In reply to Marcelo Tosatti
Quoted 11 lines · Marcelo Tosatti

What QEMU wants is to use KVM_GET_CLOCK at pre_save independently of whether masterclock is enabled or not... it just depends on KVM_GET_CLOCK being correct for the masterclock case (108b249c453dd7132599ab6dc7e435a7036c193f).

So a "reliable KVM_GET_CLOCK" (that does not timebackward when masterclock is enabled) is much simpler to userspace than "whether masterclock is enabled or not".

If you have a reason why that should not be the case, let me know.

I still cannot understand this case.

If the source has masterclock _disabled_, shouldn't it read kvmclock from memory? But that's not what your patch does. To be clear, what I mean is:

hw/i386/kvm/clock.c +10 -34
index 653b0b4..6f6e2dc 100644
@@ -97,6 +97,7 @@ static uint64_t kvm_get_clock(void)
         fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
                 abort();
     }
+    s->src_use_reliable_get_clock = data.flags & KVM_CLOCK_TSC_STABLE;
     return data.clock;
 }
 
@@ -110,34 +111,19 @@ static void kvmclock_vm_state_change(void *opaque, int running,
 
     if (running) {
         struct kvm_clock_data data = {};
-        uint64_t pvclock_via_mem = 0;
 
-        /* local (running VM) restore */
-        if (s->clock_valid) {
-            /*
-             * if host does not support reliable KVM_GET_CLOCK,
-             * read kvmclock value from memory
-             */
-            if (!kvm_has_adjust_clock_stable()) {
-                pvclock_via_mem = kvmclock_current_nsec(s);
-            }
-        /* migration/savevm/init restore */
-        } else {
-            /*
-             * use s->clock in case machine uses reliable
-             * get clock and source host supported
-             * reliable get clock
-             */
-            if (!s->src_use_reliable_get_clock) {
-                pvclock_via_mem = kvmclock_current_nsec(s);
+        /*
+         * if last KVM_GET_CLOCK did not retrieve a reliable value,
+         * we can't rely on the saved clock value.  Just discard it and
+         * read kvmclock value from memory
+         */
+        if (!s->src_use_reliable_get_clock) {
+            uint64_t pvclock_via_mem = kvmclock_current_nsec(s);
+            if (pvclock_via_mem) {
+                s->clock = pvclock_via_mem;
             }
         }
 
-        /* We can't rely on the saved clock value, just discard it */
-        if (pvclock_via_mem) {
-            s->clock = pvclock_via_mem;
-        }
-
         s->clock_valid = false;
 
         data.clock = s->clock;
@@ -181,16 +168,6 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
 {
     KVMClockState *s = KVM_CLOCK(dev);
 
-    /*
-     * On machine types that support reliable KVM_GET_CLOCK,
-     * if host kernel does provide reliable KVM_GET_CLOCK,
-     * set src_use_reliable_get_clock=true so that destination
-     * avoids reading kvmclock from memory.
-     */
-    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
-        s->src_use_reliable_get_clock = true;
-    }
-
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
 }
 
#16 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 26 lines · Paolo Bonzini
Quoted 11 lines · Marcelo Tosatti

What QEMU wants is to use KVM_GET_CLOCK at pre_save independently of whether masterclock is enabled or not... it just depends on KVM_GET_CLOCK being correct for the masterclock case (108b249c453dd7132599ab6dc7e435a7036c193f).

So a "reliable KVM_GET_CLOCK" (that does not timebackward when masterclock is enabled) is much simpler to userspace than "whether masterclock is enabled or not".

If you have a reason why that should not be the case, let me know.

I still cannot understand this case.

If the source has masterclock _disabled_, shouldn't it read kvmclock from memory? But that's not what your patch does. To be clear, what I mean is:

hw/i386/kvm/clock.c +0 -0
index 653b0b4..6f6e2dc 100644

hw/i386/kvm/clock.c static uint64_t kvm_get_clock(void) · line 100

Quoted 4 lines
hw/i386/kvm/clock.c +1 -0
@@ -97,6 +97,7 @@ static uint64_t kvm_get_clock(void)
         fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
                 abort();
     }
+    s->src_use_reliable_get_clock = data.flags & KVM_CLOCK_TSC_STABLE;

I still don't understand the reasoning behind kvm_has_adjust_clock_stable() vs (flags & KVM_CLOCK_TSC_STABLE), but on either case, updating src_use_reliable_get_clock inside kvm_get_clock() looks like the right thing to do.

Quoted 28 lines
hw/i386/kvm/clock.c +1 -19
     return data.clock;
 }
 
@@ -110,34 +111,19 @@ static void kvmclock_vm_state_change(void *opaque, int running,
 
     if (running) {
         struct kvm_clock_data data = {};
-        uint64_t pvclock_via_mem = 0;
 
-        /* local (running VM) restore */
-        if (s->clock_valid) {
-            /*
-             * if host does not support reliable KVM_GET_CLOCK,
-             * read kvmclock value from memory
-             */
-            if (!kvm_has_adjust_clock_stable()) {
-                pvclock_via_mem = kvmclock_current_nsec(s);
-            }
-        /* migration/savevm/init restore */
-        } else {
-            /*
-             * use s->clock in case machine uses reliable
-             * get clock and source host supported
-             * reliable get clock
-             */
-            if (!s->src_use_reliable_get_clock) {
-                pvclock_via_mem = kvmclock_current_nsec(s);
+        /*

hw/i386/kvm/clock.c static void kvmclock_vm_state_change(void *opaque, int running, · line 125

Quoted 10 lines
hw/i386/kvm/clock.c +8 -0
+         * if last KVM_GET_CLOCK did not retrieve a reliable value,
+         * we can't rely on the saved clock value.  Just discard it and
+         * read kvmclock value from memory
+         */
+        if (!s->src_use_reliable_get_clock) {
+            uint64_t pvclock_via_mem = kvmclock_current_nsec(s);
+            if (pvclock_via_mem) {
+                s->clock = pvclock_via_mem;
             }
         }

This is equivalent to the logic I suggested on my reply to v3. Much simpler.

Quoted 26 lines
hw/i386/kvm/clock.c +0 -15
-        /* We can't rely on the saved clock value, just discard it */
-        if (pvclock_via_mem) {
-            s->clock = pvclock_via_mem;
-        }
-
         s->clock_valid = false;
 
         data.clock = s->clock;
@@ -181,16 +168,6 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
 {
     KVMClockState *s = KVM_CLOCK(dev);
 
-    /*
-     * On machine types that support reliable KVM_GET_CLOCK,
-     * if host kernel does provide reliable KVM_GET_CLOCK,
-     * set src_use_reliable_get_clock=true so that destination
-     * avoids reading kvmclock from memory.
-     */
-    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
-        s->src_use_reliable_get_clock = true;
-    }
-
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
 }
 
Signature · 1 line
Eduardo
maintainer
#17 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 6 lines · Eduardo Habkost
Quoted 1 line

+ s->src_use_reliable_get_clock = data.flags & KVM_CLOCK_TSC_STABLE;

I still don't understand the reasoning behind kvm_has_adjust_clock_stable() vs (flags & KVM_CLOCK_TSC_STABLE), but on either case, updating src_use_reliable_get_clock inside kvm_get_clock() looks like the right thing to do.

There are three possibility: the kernel tells you the clock is stable, the kernel tells you the clock is unstable, the kernel is too old and doesn't tell you anything. Then:

kvm_has_adjust_clock_stable() == true:
if the clock is stable, KVM_CLOCK_TSC_STABLE will be set in "flags" if the clock is unstable, KVM_CLOCK_TSC_STABLE will be unset

kvm_has_adjust_clock_stable() == false:
you cannot know if the clock is stable

Paolo

#18 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

In reply to Paolo Bonzini
Quoted 12 lines · Paolo Bonzini
Quoted 9 lines · Marcelo Tosatti

What QEMU wants is to use KVM_GET_CLOCK at pre_save independently of whether masterclock is enabled or not... it just depends on KVM_GET_CLOCK being correct for the masterclock case (108b249c453dd7132599ab6dc7e435a7036c193f).

So a "reliable KVM_GET_CLOCK" (that does not timebackward when masterclock is enabled) is much simpler to userspace than "whether masterclock is enabled or not".

Quoted 7 lines
Quoted 2 lines

If you have a reason why that should not be the case, let me know.

I still cannot understand this case.

If the source has masterclock _disabled_, shouldn't it read kvmclock from memory?

If the source masterclock is disabled, then the guest does not enable the optimization to not use a global variable to guarantee monotonicity. Therefore there will be no time backwards events (the timer backwards events crashed guests, and are the reason for reading from guest memory).

So if there are no flaws in the reasoning above, no, there is no need to read from memory if masterclock is disabled.

Can you state the reasons why you think it should be enabled?

Quoted 1 line

But that's not what your patch does.

Its on purpose with the data available.

Quoted 76 lines

To be clear, what
I mean is:

hw/i386/kvm/clock.c +10 -34
index 653b0b4..6f6e2dc 100644
@@ -97,6 +97,7 @@ static uint64_t kvm_get_clock(void)
         fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
                 abort();
     }
+    s->src_use_reliable_get_clock = data.flags & KVM_CLOCK_TSC_STABLE;
     return data.clock;
 }
 
@@ -110,34 +111,19 @@ static void kvmclock_vm_state_change(void *opaque, int running,
 
     if (running) {
         struct kvm_clock_data data = {};
-        uint64_t pvclock_via_mem = 0;
 
-        /* local (running VM) restore */
-        if (s->clock_valid) {
-            /*
-             * if host does not support reliable KVM_GET_CLOCK,
-             * read kvmclock value from memory
-             */
-            if (!kvm_has_adjust_clock_stable()) {
-                pvclock_via_mem = kvmclock_current_nsec(s);
-            }
-        /* migration/savevm/init restore */
-        } else {
-            /*
-             * use s->clock in case machine uses reliable
-             * get clock and source host supported
-             * reliable get clock
-             */
-            if (!s->src_use_reliable_get_clock) {
-                pvclock_via_mem = kvmclock_current_nsec(s);
+        /*
+         * if last KVM_GET_CLOCK did not retrieve a reliable value,
+         * we can't rely on the saved clock value.  Just discard it and
+         * read kvmclock value from memory
+         */
+        if (!s->src_use_reliable_get_clock) {
+            uint64_t pvclock_via_mem = kvmclock_current_nsec(s);
+            if (pvclock_via_mem) {
+                s->clock = pvclock_via_mem;
             }
         }
 
-        /* We can't rely on the saved clock value, just discard it */
-        if (pvclock_via_mem) {
-            s->clock = pvclock_via_mem;
-        }
-
         s->clock_valid = false;
 
         data.clock = s->clock;
@@ -181,16 +168,6 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
 {
     KVMClockState *s = KVM_CLOCK(dev);
 
-    /*
-     * On machine types that support reliable KVM_GET_CLOCK,
-     * if host kernel does provide reliable KVM_GET_CLOCK,
-     * set src_use_reliable_get_clock=true so that destination
-     * avoids reading kvmclock from memory.
-     */
-    if (s->mach_use_reliable_get_clock && kvm_has_adjust_clock_stable()) {
-        s->src_use_reliable_get_clock = true;
-    }
-
     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
 }
 
maintainer
#19 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 9 lines · Marcelo Tosatti

If the source masterclock is disabled, then the guest does not enable the optimization to not use a global variable to guarantee monotonicity. Therefore there will be no time backwards events (the timer backwards events crashed guests, and are the reason for reading from guest memory).

So if there are no flaws in the reasoning above, no, there is no need to read from memory if masterclock is disabled.

Yeah, the reasoning is sound. So you go from what Eduardo and I were thinking:

if last KVM_GET_CLOCK was not reliable then
read from memory

to this:

if last KVM_GET_CLOCK was not reliable && masterclock is enabled
read from memory

but:

- on an old kernel, the left side is always true and the right side is unknown (so we must assume it's true and read from memory)

- on a new kernel, the two sides of the "&&" are exactly the opposite, so the result is always false

and then it becomes

if old kernel then
read from memory

Got it finally. :)

Paolo

Quoted 2 lines

Can you state the reasons why you think it should be enabled?

#20 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

In reply to Paolo Bonzini
Quoted 11 lines · Paolo Bonzini

hw/i386/kvm/clock.c line 109

Quoted 8 lines · Marcelo Tosatti
hw/i386/kvm/clock.c +8 -0
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);

Just assign to s->clock here...

Agreed, I just wanted to make so many changes.

Quoted 2 lines

Also, just another small nit: please make your scripts use the "-p" option on diff. :)

YESSSS

I was searching what functions the code belonged for :p

Thanks, Juan.

Acked-by on v1 2/2
#21 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

In reply to Marcelo Tosatti
Quoted 11 lines · Marcelo Tosatti

Check for KVM_CAP_ADJUST_CLOCK capability KVM_CLOCK_TSC_STABLE, which indicates that KVM_GET_CLOCK returns a value as seen by the guest at that moment.

For new machine types, use this value rather than reading from guest memory.

This reduces kvmclock difference on migration from 5s to 0.1s (when max_downtime == 5s).

But, if you have to respin it ....

hw/i386/kvm/clock.c line 44

Quoted 5 lines
hw/i386/kvm/clock.c +5 -0
+    /* whether machine supports reliable KVM_GET_CLOCK */
+    bool mach_use_reliable_get_clock;
+
+    /* whether source host supported reliable KVM_GET_CLOCK */
+    bool src_use_reliable_get_clock;

This two names are really long, but I don't have better suggesitons :-()

hw/i386/kvm/clock.c line 100

Quoted 4 lines
     if (running) {
         struct kvm_clock_data data = {};
hw/i386/kvm/clock.c +1 -1
-        uint64_t time_at_migration = kvmclock_current_nsec(s);
+        uint64_t time_at_migration = 0;

This was not "time_at_migration", it was not already before, but just now it looks really weird. (as it was already faulty, this is why it is only a suggestion.)

Quoted 8 lines
hw/i386/kvm/clock.c +6 -1
-        s->clock_valid = false;
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */

hw/i386/kvm/clock.c line 117

Quoted 10 lines
hw/i386/kvm/clock.c +10 -0
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */

This comment is just weird. Simplifying

    /* If A and B do C */
    if (!A and || !B) {
       then D();
    }

Doing the opposite comment?

Migration code looks rigth.

Once said that, I continue hating clocks.

Later, Juan.

#22 lore raw

Re: [qemu patch 2/2] kvmclock: reduce kvmclock difference on migration

Quoted 54 lines · Juan Quintela
Quoted 11 lines · Marcelo Tosatti

Check for KVM_CAP_ADJUST_CLOCK capability KVM_CLOCK_TSC_STABLE, which indicates that KVM_GET_CLOCK returns a value as seen by the guest at that moment.

For new machine types, use this value rather than reading from guest memory.

This reduces kvmclock difference on migration from 5s to 0.1s (when max_downtime == 5s).

But, if you have to respin it ....

hw/i386/kvm/clock.c line 44

Quoted 5 lines
hw/i386/kvm/clock.c +5 -0
+    /* whether machine supports reliable KVM_GET_CLOCK */
+    bool mach_use_reliable_get_clock;
+
+    /* whether source host supported reliable KVM_GET_CLOCK */
+    bool src_use_reliable_get_clock;

This two names are really long, but I don't have better suggesitons :-()

hw/i386/kvm/clock.c line 100

Quoted 4 lines
     if (running) {
         struct kvm_clock_data data = {};
hw/i386/kvm/clock.c +1 -1
-        uint64_t time_at_migration = kvmclock_current_nsec(s);
+        uint64_t time_at_migration = 0;

This was not "time_at_migration", it was not already before, but just now it looks really weird. (as it was already faulty, this is why it is only a suggestion.)

Quoted 8 lines
hw/i386/kvm/clock.c +6 -1
-        s->clock_valid = false;
+        /* local (running VM) restore */
+        if (s->clock_valid) {
+            /*
+             * if host does not support reliable KVM_GET_CLOCK,
+             * read kvmclock value from memory
+             */

hw/i386/kvm/clock.c line 117

Quoted 10 lines
hw/i386/kvm/clock.c +10 -0
+            if (!kvm_has_adjust_clock_stable()) {
+                time_at_migration = kvmclock_current_nsec(s);
+            }
+        /* migration/savevm/init restore */
+        } else {
+            /*
+             * use s->clock in case machine uses reliable
+             * get clock and host where vm was executing
+             * supported reliable get clock
+             */

This comment is just weird. Simplifying

Quoted 8 lines
    /* If A and B do C */
    if (!A and || !B) {
       then D();
    }

Doing the opposite comment?

Migration code looks rigth.

Fixed those.

Quoted 1 line

Once said that, I continue hating clocks.

Me too, especially the biological one.