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

Fabian Grünbichler f.gruenbichler at proxmox.com
Tue Sep 20 09:26:27 CEST 2016


applied with cleanup

On Mon, Sep 19, 2016 at 01:59:29PM +0200, Wolfgang Link wrote:
> 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
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel




More information about the pve-devel mailing list