]>
Commit | Line | Data |
---|---|---|
30787ff0 | 1 | From 385c66564aad5fbbe303e0d2ee5e8ffd9c10bc23 Mon Sep 17 00:00:00 2001 |
30706ba4 DDAG |
2 | From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> |
3 | Date: Mon, 12 Sep 2016 18:18:35 +0100 | |
30787ff0 | 4 | Subject: [PATCH 04/36] x86/lapic: Load LAPIC state at post_load |
30706ba4 DDAG |
5 | |
6 | Load the LAPIC state during post_load (rather than when the CPU | |
7 | starts). | |
8 | ||
9 | This allows an interrupt to be delivered from the ioapic to | |
10 | the lapic prior to cpu loading, in particular the RTC that starts | |
11 | ticking as soon as we load it's state. | |
12 | ||
13 | Fixes a case where Windows hangs after migration due to RTC interrupts | |
14 | disappearing. | |
15 | ||
16 | Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> | |
17 | Suggested-by: Paolo Bonzini <pbonzini@redhat.com> | |
18 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | |
19 | --- | |
30787ff0 | 20 | hw/i386/kvm/apic.c | 26 ++++++++++++++++++++++++-- |
30706ba4 DDAG |
21 | include/sysemu/kvm.h | 1 - |
22 | target-i386/kvm.c | 17 ----------------- | |
30787ff0 | 23 | 3 files changed, 24 insertions(+), 20 deletions(-) |
30706ba4 DDAG |
24 | |
25 | diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c | |
30787ff0 | 26 | index 2bd0de8..feb0002 100644 |
30706ba4 DDAG |
27 | --- a/hw/i386/kvm/apic.c |
28 | +++ b/hw/i386/kvm/apic.c | |
29 | @@ -28,9 +28,8 @@ static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic, | |
30 | return *((uint32_t *)(kapic->regs + (reg_id << 4))); | |
31 | } | |
32 | ||
33 | -void kvm_put_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic) | |
34 | +static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic) | |
35 | { | |
36 | - APICCommonState *s = APIC_COMMON(dev); | |
37 | int i; | |
38 | ||
39 | memset(kapic, 0, sizeof(*kapic)); | |
30787ff0 | 40 | @@ -125,6 +124,26 @@ static void kvm_apic_vapic_base_update(APICCommonState *s) |
30706ba4 DDAG |
41 | } |
42 | } | |
43 | ||
44 | +static void kvm_apic_put(void *data) | |
45 | +{ | |
46 | + APICCommonState *s = data; | |
47 | + struct kvm_lapic_state kapic; | |
48 | + int ret; | |
49 | + | |
50 | + kvm_put_apic_state(s, &kapic); | |
51 | + | |
52 | + ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_LAPIC, &kapic); | |
53 | + if (ret < 0) { | |
54 | + fprintf(stderr, "KVM_SET_LAPIC failed: %s\n", strerror(ret)); | |
55 | + abort(); | |
56 | + } | |
57 | +} | |
58 | + | |
59 | +static void kvm_apic_post_load(APICCommonState *s) | |
60 | +{ | |
30706ba4 DDAG |
61 | + run_on_cpu(CPU(s->cpu), kvm_apic_put, s); |
62 | +} | |
63 | + | |
64 | static void do_inject_external_nmi(void *data) | |
65 | { | |
66 | APICCommonState *s = data; | |
30787ff0 | 67 | @@ -178,6 +197,8 @@ static void kvm_apic_reset(APICCommonState *s) |
30706ba4 DDAG |
68 | { |
69 | /* Not used by KVM, which uses the CPU mp_state instead. */ | |
70 | s->wait_for_sipi = 0; | |
71 | + | |
72 | + run_on_cpu(CPU(s->cpu), kvm_apic_put, s); | |
73 | } | |
74 | ||
75 | static void kvm_apic_realize(DeviceState *dev, Error **errp) | |
30787ff0 | 76 | @@ -206,6 +227,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data) |
30706ba4 DDAG |
77 | k->set_base = kvm_apic_set_base; |
78 | k->set_tpr = kvm_apic_set_tpr; | |
79 | k->get_tpr = kvm_apic_get_tpr; | |
80 | + k->post_load = kvm_apic_post_load; | |
81 | k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting; | |
82 | k->vapic_base_update = kvm_apic_vapic_base_update; | |
83 | k->external_nmi = kvm_apic_external_nmi; | |
84 | diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h | |
30787ff0 | 85 | index c9c2436..ae5d81b 100644 |
30706ba4 DDAG |
86 | --- a/include/sysemu/kvm.h |
87 | +++ b/include/sysemu/kvm.h | |
30787ff0 | 88 | @@ -372,7 +372,6 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); |
30706ba4 DDAG |
89 | |
90 | void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin); | |
91 | ||
92 | -void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); | |
93 | void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); | |
94 | ||
95 | struct kvm_guest_debug; | |
96 | diff --git a/target-i386/kvm.c b/target-i386/kvm.c | |
97 | index d1a25c5..f1ad805 100644 | |
98 | --- a/target-i386/kvm.c | |
99 | +++ b/target-i386/kvm.c | |
100 | @@ -2416,19 +2416,6 @@ static int kvm_get_apic(X86CPU *cpu) | |
101 | return 0; | |
102 | } | |
103 | ||
104 | -static int kvm_put_apic(X86CPU *cpu) | |
105 | -{ | |
106 | - DeviceState *apic = cpu->apic_state; | |
107 | - struct kvm_lapic_state kapic; | |
108 | - | |
109 | - if (apic && kvm_irqchip_in_kernel()) { | |
110 | - kvm_put_apic_state(apic, &kapic); | |
111 | - | |
112 | - return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_LAPIC, &kapic); | |
113 | - } | |
114 | - return 0; | |
115 | -} | |
116 | - | |
117 | static int kvm_put_vcpu_events(X86CPU *cpu, int level) | |
118 | { | |
119 | CPUState *cs = CPU(cpu); | |
120 | @@ -2670,10 +2657,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level) | |
121 | if (ret < 0) { | |
122 | return ret; | |
123 | } | |
124 | - ret = kvm_put_apic(x86_cpu); | |
125 | - if (ret < 0) { | |
126 | - return ret; | |
127 | - } | |
128 | } | |
129 | ||
130 | ret = kvm_put_tscdeadline_msr(x86_cpu); | |
131 | -- | |
132 | 2.1.4 | |
133 |