aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMaciej S. Szmigiero <maciej.szmigiero@oracle.com>2022-09-30 17:52:03 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2022-10-18 13:58:04 +0200
commitec19444a53ef221954128e36e1387592a2273dc2 (patch)
treeff409bba0e40fed8fc92bf4c99931800927f01ed /hw
parent8b5335e381e7fd7554a65c6d591875ade1cea062 (diff)
downloadqemu-ec19444a53ef221954128e36e1387592a2273dc2.zip
qemu-ec19444a53ef221954128e36e1387592a2273dc2.tar.gz
qemu-ec19444a53ef221954128e36e1387592a2273dc2.tar.bz2
hyperv: fix SynIC SINT assertion failure on guest reset
Resetting a guest that has Hyper-V VMBus support enabled triggers a QEMU assertion failure: hw/hyperv/hyperv.c:131: synic_reset: Assertion `QLIST_EMPTY(&synic->sint_routes)' failed. This happens both on normal guest reboot or when using "system_reset" HMP command. The failing assertion was introduced by commit 64ddecc88bcf ("hyperv: SControl is optional to enable SynIc") to catch dangling SINT routes on SynIC reset. The root cause of this problem is that the SynIC itself is reset before devices using SINT routes have chance to clean up these routes. Since there seems to be no existing mechanism to force reset callbacks (or methods) to be executed in specific order let's use a similar method that is already used to reset another interrupt controller (APIC) after devices have been reset - by invoking the SynIC reset from the machine reset handler via a new x86_cpu_after_reset() function co-located with the existing x86_cpu_reset() in target/i386/cpu.c. Opportunistically move the APIC reset handler there, too. Fixes: 64ddecc88bcf ("hyperv: SControl is optional to enable SynIc") # exposed the bug Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com> Message-Id: <cb57cee2e29b20d06f81dce054cbcea8b5d497e8.1664552976.git.maciej.szmigiero@oracle.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/i386/microvm.c4
-rw-r--r--hw/i386/pc.c5
2 files changed, 3 insertions, 6 deletions
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 7fe8cce..52f9aa9 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -485,9 +485,7 @@ static void microvm_machine_reset(MachineState *machine)
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
- if (cpu->apic_state) {
- device_legacy_reset(cpu->apic_state);
- }
+ x86_cpu_after_reset(cpu);
}
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 566accf..768982a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -92,6 +92,7 @@
#include "hw/virtio/virtio-mem-pci.h"
#include "hw/mem/memory-device.h"
#include "sysemu/replay.h"
+#include "target/i386/cpu.h"
#include "qapi/qmp/qerror.h"
#include "e820_memory_layout.h"
#include "fw_cfg.h"
@@ -1859,9 +1860,7 @@ static void pc_machine_reset(MachineState *machine)
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
- if (cpu->apic_state) {
- device_legacy_reset(cpu->apic_state);
- }
+ x86_cpu_after_reset(cpu);
}
}