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