[QEMU] acpiphp: hack to send BusCheck to missing device on root bus

Message ID 20230731124649.2601384-1-imammedo@redhat.com
State New
Headers
Series [QEMU] acpiphp: hack to send BusCheck to missing device on root bus |

Commit Message

Igor Mammedov July 31, 2023, 12:46 p.m. UTC
  A reproducer for [1], faking a missing device (supposedly root port)
on root bus, and ability to send BusCheck to it.

Usage:
./qemu-system-x86_64 -monitor stdio -M q35 -cpu host -smp 4 -enable-kvm  -m 4G
   -nographic
   -monitor stdio
   -snapshot
   -serial file:/tmp/s
   -kernel ~/builds/linux-2.6/arch/x86/boot/bzImage
   -append 'root=/dev/sda1 console=ttyS0'
   -device pcie-root-port,id=rp1,bus=pcie.0,chassis=0,addr=8
   vm_disk_image

wait till it boots and then at monitor prompt hotplug a device
(no hotplug will happen since hacked AML code will send only
notify to missing device, but it's sufficient to reproduce kernel crash
at commit [2]):

(qemu)  device_add e1000e,bus=rp1

observe in guest logs:
[  612.277651] BUG: kernel NULL pointer dereference, address: 0000000000000018
[...]
[  612.277798]  ? pci_assign_unassigned_bridge_resources+0x1f/0x260
[  612.277804]  ? pcibios_allocate_dev_resources+0x3c/0x2a0
[  612.277809]  enable_slot+0x21f/0x3e0
[  612.277816]  acpiphp_hotplug_notify+0x13d/0x260
[  612.277822]  ? __pfx_acpiphp_hotplug_notify+0x10/0x10
[  612.277827]  acpi_device_hotplug+0xbc/0x540
[  612.277834]  acpi_hotplug_work_fn+0x15/0x20
[  612.277839]  process_one_work+0x1f7/0x370
[  612.277845]  worker_thread+0x45/0x3b0
[  612.277850]  ? __pfx_worker_thread+0x10/0x10
[  612.277854]  kthread+0xdc/0x110
[  612.277860]  ? __pfx_kthread+0x10/0x10
[  612.277866]  ret_from_fork+0x28/0x40
[  612.277871]  ? __pfx_kthread+0x10/0x10
[  612.277876]  ret_from_fork_asm+0x1b/0x30

1)
  Link: https://lore.kernel.org/r/11fc981c-af49-ce64-6b43-3e282728bd1a@gmail.com
2)
  commit 40613da52b13fb ("PCI: acpiphp: Reassign resources on bridge if necessary")
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/i386/acpi-build.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
  

Patch

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9c74fa17ad..f6c2584289 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1784,11 +1784,18 @@  build_dsdt(GArray *table_data, BIOSLinker *linker,
         if (pci_host) {
             PCIBus *bus = PCI_HOST_BRIDGE(pci_host)->bus;
             Aml *scope = aml_scope("PCI0");
+            Aml *dev;
             /* Scan all PCI buses. Generate tables to support hotplug. */
             build_append_pci_bus_devices(scope, bus);
             if (object_property_find(OBJECT(bus), ACPI_PCIHP_PROP_BSEL)) {
                 build_append_pcihp_slots(scope, bus);
             }
+
+            /* nonexisting PCI device */
+            dev = aml_device("RPX");
+            aml_append(dev, aml_name_decl("_ADR", aml_int(0x100000)));
+            aml_append(scope, dev);
+
             aml_append(sb_scope, scope);
         }
     }
@@ -1852,12 +1859,8 @@  build_dsdt(GArray *table_data, BIOSLinker *linker,
         scope =  aml_scope("_GPE");
         {
             method = aml_method("_E01", 0, AML_NOTSERIALIZED);
-            if (has_pcnt) {
-                aml_append(method,
-                    aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0xFFFF));
-                aml_append(method, aml_call0("\\_SB.PCI0.PCNT"));
-                aml_append(method, aml_release(aml_name("\\_SB.PCI0.BLCK")));
-            }
+            /* send BusCheck to non-present PCI device */
+            aml_append(method, aml_notify(aml_name("\\_SB.PCI0.RPX"), aml_int(0)));
             aml_append(scope, method);
         }
         aml_append(dsdt, scope);