134 lines
4.0 KiB
Diff
134 lines
4.0 KiB
Diff
From 385c66564aad5fbbe303e0d2ee5e8ffd9c10bc23 Mon Sep 17 00:00:00 2001
|
|
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
|
Date: Mon, 12 Sep 2016 18:18:35 +0100
|
|
Subject: [PATCH 04/36] 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@redhat.com>
|
|
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
---
|
|
hw/i386/kvm/apic.c | 26 ++++++++++++++++++++++++--
|
|
include/sysemu/kvm.h | 1 -
|
|
target-i386/kvm.c | 17 -----------------
|
|
3 files changed, 24 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
|
|
index 2bd0de8..feb0002 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,26 @@ 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)
|
|
+{
|
|
+ run_on_cpu(CPU(s->cpu), kvm_apic_put, s);
|
|
+}
|
|
+
|
|
static void do_inject_external_nmi(void *data)
|
|
{
|
|
APICCommonState *s = data;
|
|
@@ -178,6 +197,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 +227,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 c9c2436..ae5d81b 100644
|
|
--- a/include/sysemu/kvm.h
|
|
+++ b/include/sysemu/kvm.h
|
|
@@ -372,7 +372,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
|
|
|