]> git.proxmox.com Git - mirror_qemu.git/commitdiff
x86/lapic: Load LAPIC state at post_load
authorDr. David Alan Gilbert <dgilbert@redhat.com>
Mon, 12 Sep 2016 17:18:35 +0000 (18:18 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 13 Sep 2016 17:09:44 +0000 (19:09 +0200)
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>
hw/i386/kvm/apic.c
include/sysemu/kvm.h
target-i386/kvm.c

index 2bd0de82b40eeed29aa1a55307b4759dcf24e5f4..5d140b93411ae34c32b04f9906ce58949ad1ead9 100644 (file)
@@ -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;
index 4938f65c7a4cbbd8b0b53ca2eda687222c3e3982..f2a7b3b8fe2c86358d673b28a2f18c14eb1ab896 100644 (file)
@@ -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;
index d1a25c54654670b10c8b49bd864d5d96f7f813fc..f1ad805665adf518d3a7bf92d6f9d5a18b9abe34 100644 (file)
@@ -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);