From: Paolo Bonzini <pbonzini@redhat.com>
To: Marcelo Tosatti <mtosatti@redhat.com>, kvm@vger.kernel.org
Cc: qemu-devel@nongnu.org,
Dr David Alan Gilbert <dgilbert@redhat.com>,
Juan Quintela <quintela@redhat.com>,
Radim Krcmar <rkrcmar@redhat.com>,
Eduardo Habkost <ehabkost@redhat.com>
Subject: Re: [Qemu-devel] [qemu patch V4 2/2] kvmclock: reduce kvmclock difference on migration
Date: Fri, 16 Dec 2016 11:03:33 +0100 [thread overview]
Message-ID: <ccb8c6bf-f136-9a6c-fbdc-7e7d4924321e@redhat.com> (raw)
In-Reply-To: <20161210172324.482367805@redhat.com>
I'd like to make a few cleanups and add more documentation:
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index eacc9dc..f767ea9 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -37,7 +37,7 @@ typedef struct KVMClockState {
uint64_t clock;
bool clock_valid;
- /* whether machine type supports reliable get clock */
+ /* whether machine type supports reliable KVM_GET_CLOCK */
bool mach_use_reliable_get_clock;
/* whether the 'clock' value was obtained in a host with
@@ -88,7 +88,7 @@ static uint64_t kvmclock_current_nsec(KVMClockState *s)
return nsec + time.system_time;
}
-static uint64_t kvm_get_clock(void)
+static void kvm_update_clock(void)
{
struct kvm_clock_data data;
int ret;
@@ -98,7 +98,48 @@ static uint64_t kvm_get_clock(void)
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
abort();
}
- return data.clock;
+ s->clock = data.clock;
+
+ /* If kvm_has_adjust_clock_stable() is false, KVM_GET_CLOCK returns
+ * essentially CLOCK_MONOTONIC plus a guest-specific adjustment. This
+ * can drift from the TSC-based value that is computed by the guest,
+ * so we need to go through kvmclock_current_nsec(). If
+ * kvm_has_adjust_clock_stable() is true, and the flags contain
+ * KVM_CLOCK_TSC_STABLE, then KVM_GET_CLOCK returns a TSC-based value
+ * and kvmclock_current_nsec() is not necessary.
+ *
+ * Here, however, we need not check KVM_CLOCK_TSC_STABLE. This is because:
+ *
+ * - if the host has disabled the kvmclock master clock, the guest already
+ * has protection against time going backwards. This "safety net" is only
+ * absent when kvmclock is stable;
+ *
+ * - therefore, we can replace a check like
+ *
+ * if last KVM_GET_CLOCK was not reliable
+ * read from memory
+ *
+ * with
+ *
+ * if last KVM_GET_CLOCK was not reliable && masterclock is enabled
+ * read from memory
+ *
+ * However:
+ *
+ * - if kvm_has_adjust_clock_stable() returns false, the left side is
+ * always true (KVM_GET_CLOCK is never reliable), and the right side is
+ * unknown (because we don't have data.flags). We must assume it's true
+ * and read from memory.
+ *
+ * - if kvm_has_adjust_clock_stable() returns true, the result of the &&
+ * is always false (masterclock is enabled iff KVM_GET_CLOCK is reliable)
+ *
+ * So we can just use this instead:
+ *
+ * if !kvm_has_adjust_clock_stable() then
+ * read from memory
+ */
+ s->clock_is_reliable = kvm_has_adjust_clock_stable();
}
static void kvmclock_vm_state_change(void *opaque, int running,
@@ -111,19 +153,17 @@ static void kvmclock_vm_state_change(void *opaque, int running,
if (running) {
struct kvm_clock_data data = {};
- uint64_t pvclock_via_mem = 0;
/*
* If the host where s->clock was read did not support reliable
* KVM_GET_CLOCK, read kvmclock value from memory.
*/
if (!s->clock_is_reliable) {
- pvclock_via_mem = kvmclock_current_nsec(s);
- }
-
- /* We can't rely on the saved clock value, just discard it */
- if (pvclock_via_mem) {
- s->clock = pvclock_via_mem;
+ uint64_t pvclock_via_mem = kvmclock_current_nsec(s);
+ /* 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;
@@ -155,11 +195,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
kvm_synchronize_all_tsc();
- s->clock = kvm_get_clock();
- /* any code that sets s->clock needs to ensure clock_is_reliable
- * is correctly set.
- */
- s->clock_is_reliable = kvm_has_adjust_clock_stable();
+ kvm_update_clock();
/*
* If the VM is stopped, declare the clock state valid to
* avoid re-reading it on next vmsave (which would return
@@ -173,9 +209,7 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
{
KVMClockState *s = KVM_CLOCK(dev);
- if (kvm_has_adjust_clock_stable()) {
- s->clock_is_reliable = true;
- }
+ kvm_update_clock();
qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
}
@@ -216,7 +250,7 @@ static void kvmclock_pre_save(void *opaque)
{
KVMClockState *s = opaque;
- s->clock = kvm_get_clock();
+ kvm_update_clock();
}
static const VMStateDescription kvmclock_vmsd = {
next prev parent reply other threads:[~2016-12-16 10:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-10 17:21 [Qemu-devel] [qemu patch V4 0/2] improve kvmclock difference on migration Marcelo Tosatti
2016-12-10 17:21 ` [Qemu-devel] [qemu patch V4 1/2] kvm: sync linux headers Marcelo Tosatti
2016-12-10 17:21 ` [Qemu-devel] [qemu patch V4 2/2] kvmclock: reduce kvmclock difference on migration Marcelo Tosatti
2016-12-12 7:36 ` Pankaj Gupta
2016-12-12 11:22 ` Marcelo Tosatti
2016-12-12 14:24 ` Pankaj Gupta
2016-12-13 1:32 ` Pankaj Gupta
2016-12-12 18:01 ` Eduardo Habkost
2016-12-12 19:44 ` Marcelo Tosatti
2016-12-12 19:57 ` Eduardo Habkost
2016-12-16 10:03 ` Paolo Bonzini [this message]
2016-12-16 13:41 ` Eduardo Habkost
2016-12-16 15:59 ` Marcelo Tosatti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ccb8c6bf-f136-9a6c-fbdc-7e7d4924321e@redhat.com \
--to=pbonzini@redhat.com \
--cc=dgilbert@redhat.com \
--cc=ehabkost@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
--cc=rkrcmar@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).