[pve-devel] [PATCH pve-qemu-kvm] fix Bug #615 Windows guests suddenly hangs after couple times of migration

Wolfgang Link w.link at proxmox.com
Mon Sep 19 13:59:29 CEST 2016


From: "Dr. David Alan Gilbert" <address at hidden>

Load the LAPIC state during post_load (rather than when the CPU
starts).

This allows an interrupt to be delivered from the ioapic to
the lapic prior to cpu loading, in particular the RTC that starts
ticking as soon as we load it's state.

Partially fixes a case where Windows hangs after migration due to RTC interrupts
disappearing; it survived ~30 iterations of my test where as
---
 debian/patches/series                              |   1 +
 .../x86-lapic-Load-LAPIC-state-at-post_load.patch  | 134 +++++++++++++++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 debian/patches/x86-lapic-Load-LAPIC-state-at-post_load.patch

diff --git a/debian/patches/series b/debian/patches/series
index d1470ba..4d50eef 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -74,3 +74,4 @@ extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch
 extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch
 extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch
 extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch
+x86-lapic-Load-LAPIC-state-at-post_load.patch
diff --git a/debian/patches/x86-lapic-Load-LAPIC-state-at-post_load.patch b/debian/patches/x86-lapic-Load-LAPIC-state-at-post_load.patch
new file mode 100644
index 0000000..b7fe250
--- /dev/null
+++ b/debian/patches/x86-lapic-Load-LAPIC-state-at-post_load.patch
@@ -0,0 +1,134 @@
+From 78d6a05d2f69cbfa6e95f0a4a24a2c934969913b Mon Sep 17 00:00:00 2001
+From: "Dr. David Alan Gilbert" <dgilbert at redhat.com>
+Date: Mon, 12 Sep 2016 18:18:35 +0100
+Subject: [PATCH] x86/lapic: Load LAPIC state at post_load
+
+Load the LAPIC state during post_load (rather than when the CPU
+starts).
+
+This allows an interrupt to be delivered from the ioapic to
+the lapic prior to cpu loading, in particular the RTC that starts
+ticking as soon as we load it's state.
+
+Fixes a case where Windows hangs after migration due to RTC interrupts
+disappearing.
+
+Signed-off-by: Dr. David Alan Gilbert <dgilbert at redhat.com>
+Suggested-by: Paolo Bonzini <pbonzini at redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+---
+ hw/i386/kvm/apic.c   | 27 +++++++++++++++++++++++++--
+ include/sysemu/kvm.h |  1 -
+ target-i386/kvm.c    | 17 -----------------
+ 3 files changed, 25 insertions(+), 20 deletions(-)
+
+diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
+index 2bd0de8..5d140b9 100644
+--- a/hw/i386/kvm/apic.c
++++ b/hw/i386/kvm/apic.c
+@@ -28,9 +28,8 @@ static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic,
+     return *((uint32_t *)(kapic->regs + (reg_id << 4)));
+ }
+ 
+-void kvm_put_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic)
++static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic)
+ {
+-    APICCommonState *s = APIC_COMMON(dev);
+     int i;
+ 
+     memset(kapic, 0, sizeof(*kapic));
+@@ -125,6 +124,27 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
+     }
+ }
+ 
++static void kvm_apic_put(void *data)
++{
++    APICCommonState *s = data;
++    struct kvm_lapic_state kapic;
++    int ret;
++
++    kvm_put_apic_state(s, &kapic);
++
++    ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_LAPIC, &kapic);
++    if (ret < 0) {
++        fprintf(stderr, "KVM_SET_LAPIC failed: %s\n", strerror(ret));
++        abort();
++    }
++}
++
++static void kvm_apic_post_load(APICCommonState *s)
++{
++    fprintf(stderr, "%s: Yeh\n", __func__);
++    run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
++}
++
+ static void do_inject_external_nmi(void *data)
+ {
+     APICCommonState *s = data;
+@@ -178,6 +198,8 @@ static void kvm_apic_reset(APICCommonState *s)
+ {
+     /* Not used by KVM, which uses the CPU mp_state instead.  */
+     s->wait_for_sipi = 0;
++
++    run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
+ }
+ 
+ static void kvm_apic_realize(DeviceState *dev, Error **errp)
+@@ -206,6 +228,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data)
+     k->set_base = kvm_apic_set_base;
+     k->set_tpr = kvm_apic_set_tpr;
+     k->get_tpr = kvm_apic_get_tpr;
++    k->post_load = kvm_apic_post_load;
+     k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting;
+     k->vapic_base_update = kvm_apic_vapic_base_update;
+     k->external_nmi = kvm_apic_external_nmi;
+diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
+index 4938f65..f2a7b3b 100644
+--- a/include/sysemu/kvm.h
++++ b/include/sysemu/kvm.h
+@@ -371,7 +371,6 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
+ 
+ void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin);
+ 
+-void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
+ void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
+ 
+ struct kvm_guest_debug;
+diff --git a/target-i386/kvm.c b/target-i386/kvm.c
+index d1a25c5..f1ad805 100644
+--- a/target-i386/kvm.c
++++ b/target-i386/kvm.c
+@@ -2416,19 +2416,6 @@ static int kvm_get_apic(X86CPU *cpu)
+     return 0;
+ }
+ 
+-static int kvm_put_apic(X86CPU *cpu)
+-{
+-    DeviceState *apic = cpu->apic_state;
+-    struct kvm_lapic_state kapic;
+-
+-    if (apic && kvm_irqchip_in_kernel()) {
+-        kvm_put_apic_state(apic, &kapic);
+-
+-        return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_LAPIC, &kapic);
+-    }
+-    return 0;
+-}
+-
+ static int kvm_put_vcpu_events(X86CPU *cpu, int level)
+ {
+     CPUState *cs = CPU(cpu);
+@@ -2670,10 +2657,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
+         if (ret < 0) {
+             return ret;
+         }
+-        ret = kvm_put_apic(x86_cpu);
+-        if (ret < 0) {
+-            return ret;
+-        }
+     }
+ 
+     ret = kvm_put_tscdeadline_msr(x86_cpu);
+-- 
+2.1.4
+
-- 
2.1.4





More information about the pve-devel mailing list