169b9a
From f0254b84d490273e922d04b01a7b48f0ac370185 Mon Sep 17 00:00:00 2001
6e672b
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
169b9a
Date: Tue, 15 May 2018 11:56:32 +0200
169b9a
Subject: [PATCH 06/10] x86/lapic: Load LAPIC state at post_load
6e672b
6e672b
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
6e672b
Message-id: <20180515115634.24469-4-dgilbert@redhat.com>
6e672b
Patchwork-id: 80273
6e672b
O-Subject: [RHEL-7.6 qemu-kvm PATCH v2 3/5] x86/lapic: Load LAPIC state at post_load
169b9a
Bugzilla: 1577680
6e672b
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
6e672b
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
6e672b
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
6e672b
6e672b
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
6e672b
6e672b
Load the LAPIC state during post_load (rather than when the CPU
6e672b
starts).
6e672b
6e672b
This allows an interrupt to be delivered from the ioapic to
6e672b
the lapic prior to cpu loading, in particular the RTC that starts
6e672b
ticking as soon as we load it's state.
6e672b
6e672b
Fixes a case where Windows hangs after migration due to RTC interrupts
6e672b
disappearing.
6e672b
6e672b
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
6e672b
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
6e672b
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6e672b
(cherry picked from commit 78d6a05d2f69cbfa6e95f0a4a24a2c934969913b)
6e672b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
6e672b
---
6e672b
 hw/i386/kvm/apic.c   | 27 ++++++++++++++++++++++++---
6e672b
 include/sysemu/kvm.h |  1 -
6e672b
 target-i386/kvm.c    | 18 ------------------
6e672b
 3 files changed, 24 insertions(+), 22 deletions(-)
6e672b
6e672b
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
6e672b
index 6ead17c..0f3a80c 100644
6e672b
--- a/hw/i386/kvm/apic.c
6e672b
+++ b/hw/i386/kvm/apic.c
6e672b
@@ -25,9 +25,8 @@ static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic,
6e672b
     return *((uint32_t *)(kapic->regs + (reg_id << 4)));
6e672b
 }
6e672b
 
6e672b
-void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
6e672b
+static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic)
6e672b
 {
6e672b
-    APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
6e672b
     int i;
6e672b
 
6e672b
     memset(kapic, 0, sizeof(*kapic));
6e672b
@@ -122,6 +121,27 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
6e672b
     }
6e672b
 }
6e672b
 
6e672b
+static void kvm_apic_put(void *data)
6e672b
+{
6e672b
+    APICCommonState *s = data;
6e672b
+    struct kvm_lapic_state kapic;
6e672b
+    int ret;
6e672b
+
6e672b
+    kvm_put_apic_state(s, &kapic);
6e672b
+
6e672b
+    ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_LAPIC, &kapic);
6e672b
+    if (ret < 0) {
6e672b
+        fprintf(stderr, "KVM_SET_LAPIC failed: %s\n", strerror(ret));
6e672b
+        abort();
6e672b
+    }
6e672b
+}
6e672b
+
6e672b
+static void kvm_apic_post_load(APICCommonState *s)
6e672b
+{
6e672b
+    fprintf(stderr, "%s: Yeh\n", __func__);
6e672b
+    run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
6e672b
+}
6e672b
+
6e672b
 static void do_inject_external_nmi(void *data)
6e672b
 {
6e672b
     APICCommonState *s = data;
6e672b
@@ -173,7 +193,7 @@ static const MemoryRegionOps kvm_apic_io_ops = {
6e672b
 
6e672b
 static void kvm_apic_reset(APICCommonState *s)
6e672b
 {
6e672b
-    /* This function intentionally left blank, for now */
6e672b
+    run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
6e672b
 }
6e672b
 
6e672b
 static void kvm_apic_init(APICCommonState *s)
6e672b
@@ -195,6 +215,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data)
6e672b
     k->set_base = kvm_apic_set_base;
6e672b
     k->set_tpr = kvm_apic_set_tpr;
6e672b
     k->get_tpr = kvm_apic_get_tpr;
6e672b
+    k->post_load = kvm_apic_post_load;
6e672b
     k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting;
6e672b
     k->vapic_base_update = kvm_apic_vapic_base_update;
6e672b
     k->external_nmi = kvm_apic_external_nmi;
6e672b
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
6e672b
index 0c6833f..49cfc42 100644
6e672b
--- a/include/sysemu/kvm.h
6e672b
+++ b/include/sysemu/kvm.h
6e672b
@@ -216,7 +216,6 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
6e672b
 
6e672b
 void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin);
6e672b
 
6e672b
-void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
6e672b
 void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
6e672b
 
6e672b
 struct kvm_guest_debug;
6e672b
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
169b9a
index 6f3424e..71f1573 100644
6e672b
--- a/target-i386/kvm.c
6e672b
+++ b/target-i386/kvm.c
169b9a
@@ -1863,20 +1863,6 @@ static int kvm_get_apic(X86CPU *cpu)
6e672b
     return 0;
6e672b
 }
6e672b
 
6e672b
-static int kvm_put_apic(X86CPU *cpu)
6e672b
-{
6e672b
-    CPUX86State *env = &cpu->env;
6e672b
-    DeviceState *apic = env->apic_state;
6e672b
-    struct kvm_lapic_state kapic;
6e672b
-
6e672b
-    if (apic && kvm_irqchip_in_kernel()) {
6e672b
-        kvm_put_apic_state(apic, &kapic);
6e672b
-
6e672b
-        return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_LAPIC, &kapic);
6e672b
-    }
6e672b
-    return 0;
6e672b
-}
6e672b
-
6e672b
 static int kvm_put_vcpu_events(X86CPU *cpu, int level)
6e672b
 {
6e672b
     CPUX86State *env = &cpu->env;
169b9a
@@ -2058,10 +2044,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
6e672b
         if (ret < 0) {
6e672b
             return ret;
6e672b
         }
6e672b
-        ret = kvm_put_apic(x86_cpu);
6e672b
-        if (ret < 0) {
6e672b
-            return ret;
6e672b
-        }
6e672b
     }
6e672b
 
6e672b
     ret = kvm_put_tscdeadline_msr(x86_cpu);
6e672b
-- 
6e672b
1.8.3.1
6e672b