From debbda1c67eac6c4b44d07fe4301ff9b57c82afa Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 12 Jan 2023 15:02:44 +0100 Subject: [PATCH] x86: pcihp: fix invalid AML PCNT calls to hotplugged bridges When QEMU is started with hotplugged bridges (think migration): QEMU -S -monitor stdio \ -device pci-bridge,chassis_nr=1 \ -device pci-bridge,bus=pci.1,addr=1.0,chassis_nr=2 (qemu) device_add pci-bridge,id=hpbr,bus=pci.1,addr=2.0,chassis_nr=3 (qemu) cont it will generate AML calls to hpbr's PCNT, which doesn't exists since it's hotplugged bridge. As result DSDT becomes malformed, with consequences that hotplug might stop working at best or crash guest OS at worst, when it attempts to call non existing PCNT method or during OS guest reboot when parsing DSDT again. IASL de-compiles malformed AML of above config DSDT as: + External (_SB_.PCI0.S18_.S10_.PCNT, MethodObj) // Warning: Unknown method, guessing 1 arguments + External (_SB_.PCI0.S18_.S19_.PCNT, MethodObj) // Warning: Unknown method, guessing 2 arguments ... BNUM = One DVNT (PCIU, One) DVNT (PCID, 0x03) - ^S08.PCNT () + ^S19.PCNT (^S10.PCNT (^S08.PCNT ())) } } With BSEL assignment limited only to coldplugged bridges [1], it should be possible to add PCNT call to a child bridge only if the child has BSEL property, otherwise ignore it since it's hotplugged. Which should fix the issue. 1) ("pci: acpihp: assign BSEL only to coldplugged bridges") Signed-off-by: Igor Mammedov Message-Id: <20230112140312.3096331-13-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 8ba34d8fde..1c51ab01fc 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -515,7 +515,8 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, /* Notify about child bus events in any case */ if (pcihp_bridge_en) { QLIST_FOREACH(sec, &bus->child, sibling) { - if (pci_bus_is_root(sec)) { + if (pci_bus_is_root(sec) || + !object_property_find(OBJECT(sec), ACPI_PCIHP_PROP_BSEL)) { continue; }