Blob Blame History Raw
From f0254b84d490273e922d04b01a7b48f0ac370185 Mon Sep 17 00:00:00 2001
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Date: Tue, 15 May 2018 11:56:32 +0200
Subject: [PATCH 06/10] x86/lapic: Load LAPIC state at post_load

RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: <20180515115634.24469-4-dgilbert@redhat.com>
Patchwork-id: 80273
O-Subject: [RHEL-7.6 qemu-kvm PATCH v2 3/5] x86/lapic: Load LAPIC state at post_load
Bugzilla: 1577680
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

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@redhat.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 78d6a05d2f69cbfa6e95f0a4a24a2c934969913b)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/i386/kvm/apic.c   | 27 ++++++++++++++++++++++++---
 include/sysemu/kvm.h |  1 -
 target-i386/kvm.c    | 18 ------------------
 3 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 6ead17c..0f3a80c 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -25,9 +25,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 *d, struct kvm_lapic_state *kapic)
+static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic)
 {
-    APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
     int i;
 
     memset(kapic, 0, sizeof(*kapic));
@@ -122,6 +121,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;
@@ -173,7 +193,7 @@ static const MemoryRegionOps kvm_apic_io_ops = {
 
 static void kvm_apic_reset(APICCommonState *s)
 {
-    /* This function intentionally left blank, for now */
+    run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
 }
 
 static void kvm_apic_init(APICCommonState *s)
@@ -195,6 +215,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 0c6833f..49cfc42 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -216,7 +216,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 6f3424e..71f1573 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1863,20 +1863,6 @@ static int kvm_get_apic(X86CPU *cpu)
     return 0;
 }
 
-static int kvm_put_apic(X86CPU *cpu)
-{
-    CPUX86State *env = &cpu->env;
-    DeviceState *apic = env->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)
 {
     CPUX86State *env = &cpu->env;
@@ -2058,10 +2044,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);
-- 
1.8.3.1