diff --git a/docs/specs/acpi_pci_hotplug.txt b/docs/specs/acpi_pci_hotplug.txt
index a839434..951b99a 100644
--- a/docs/specs/acpi_pci_hotplug.txt
+++ b/docs/specs/acpi_pci_hotplug.txt
@@ -43,3 +43,11 @@ PCI removability status (IO port 0xae0c-0xae0f, 4-byte access):
 
 Used by ACPI BIOS _RMV method to indicate removability status to OS. One
 bit per slot.  Read-only
+
+PCI bus selector (IO port 0xae10-0xae13, 4-byte access):
+-----------------------------------------------
+
+Used by ACPI BIOS methods to select the current PCI bus.
+When written, makes all the other PCI registers (0xae00 - 0xae0f)
+to refer to the appropriate bus.
+0 selects PCI root bus (default).
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index c077a7a..bc7df06 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -29,6 +29,7 @@
 #include "exec/ioport.h"
 #include "hw/nvram/fw_cfg.h"
 #include "exec/address-spaces.h"
+#include "hw/pci/pci_bus.h"
 
 //#define DEBUG
 
@@ -42,11 +43,12 @@
 #define GPE_LEN 4
 
 #define PCI_HOTPLUG_ADDR 0xae00
-#define PCI_HOTPLUG_SIZE 0x000f
+#define PCI_HOTPLUG_SIZE 0x0014
 #define PCI_UP_BASE 0xae00
 #define PCI_DOWN_BASE 0xae04
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
+#define PCI_SEL_BASE 0xae10
 
 #define PIIX4_PROC_BASE 0xaf00
 #define PIIX4_PROC_LEN 32
@@ -57,6 +59,8 @@
 struct pci_status {
     uint32_t up; /* deprecated, maintained for migration compatibility */
     uint32_t down;
+    uint32_t hotplug_enable;
+    uint32_t device_present;
 };
 
 typedef struct CPUStatus {
@@ -84,9 +88,8 @@ typedef struct PIIX4PMState {
     Notifier powerdown_notifier;
 
     /* for pci hotplug */
-    struct pci_status pci0_status;
-    uint32_t pci0_hotplug_enable;
-    uint32_t pci0_slot_device_present;
+    struct pci_status pci_status[GUEST_INFO_MAX_HOTPLUG_BUS];
+    uint32_t hotplug_select;
 
     uint8_t disable_s3;
     uint8_t disable_s4;
@@ -98,6 +101,17 @@ typedef struct PIIX4PMState {
     PcGuestInfo *guest_info;
 } PIIX4PMState;
 
+static int piix4_find_hotplug_bus(PcGuestInfo *guest_info, PCIBus *bus)
+{
+    int i;
+    for (i = 0; i < GUEST_INFO_MAX_HOTPLUG_BUS; ++i) {
+        if (guest_info->hotplug_buses[i] == bus) {
+            return i;
+        }
+    }
+    return -1;
+}
+
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                            PCIBus *bus, PIIX4PMState *s);
 
@@ -181,15 +195,35 @@ static void pm_write_config(PCIDevice *d,
     }
 }
 
-static void vmstate_pci_status_pre_save(void *opaque)
+static bool piix4_acpi_bridge_hotplug(PIIX4PMState *s)
+{
+    return s->guest_info && s->guest_info->has_acpi_bridge_hotplug;
+}
+
+static bool vmstate_test_bridge_hotplug(void *opaque, int version_id)
+{
+    return piix4_acpi_bridge_hotplug(opaque);
+}
+
+static bool vmstate_test_no_bridge_hotplug(void *opaque, int version_id)
+{
+    return !piix4_acpi_bridge_hotplug(opaque);
+}
+
+static void vmstate_pci_status_pre_save_compat(void *opaque)
 {
     struct pci_status *pci0_status = opaque;
-    PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status);
+    PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci_status[0]);
+
+    /* Bridge hotplug enabled - no need for compat hacks */
+    if (piix4_acpi_bridge_hotplug(s)) {
+        return;
+    }
 
     /* We no longer track up, so build a safe value for migrating
      * to a version that still does... of course these might get lost
      * by an old buggy implementation, but we try. */
-    pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
+    pci0_status->up = pci0_status->device_present & pci0_status->hotplug_enable;
 }
 
 static int vmstate_acpi_post_load(void *opaque, int version_id)
@@ -227,7 +261,7 @@ static const VMStateDescription vmstate_pci_status = {
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .pre_save = vmstate_pci_status_pre_save,
+    .pre_save = vmstate_pci_status_pre_save_compat,
     .fields      = (VMStateField []) {
         VMSTATE_UINT32(up, struct pci_status),
         VMSTATE_UINT32(down, struct pci_status),
@@ -267,7 +301,8 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
         qemu_get_be16s(f, &temp);
     }
 
-    ret = vmstate_load_state(f, &vmstate_pci_status, &s->pci0_status, 1);
+    ret = vmstate_load_state(f, &vmstate_pci_status,
+                             &s->pci_status, 1);
     return ret;
 }
 
@@ -293,28 +328,64 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
         VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
         VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
-        VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
-                       struct pci_status),
+        VMSTATE_STRUCT_TEST(pci_status[0], PIIX4PMState,
+                            vmstate_test_no_bridge_hotplug, 1,
+                            vmstate_pci_status,
+                            struct pci_status),
+        VMSTATE_UINT32_TEST(hotplug_select, PIIX4PMState,
+                            vmstate_test_bridge_hotplug),
+        VMSTATE_STRUCT_ARRAY_TEST(pci_status, PIIX4PMState,
+                                  GUEST_INFO_MAX_HOTPLUG_BUS,
+                                  vmstate_test_bridge_hotplug, 1,
+                                  vmstate_pci_status,
+                                  struct pci_status),
         VMSTATE_END_OF_LIST()
     }
 };
 
-static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
+static bool acpi_piix_pc_no_hotplug(PIIX4PMState *s, PCIDevice *dev)
+{
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+    /* No ACPI hotplug? Assume native hotplug. In theory it
+     * can handle hot-unplug of bridge devices.
+     */
+    if (!piix4_acpi_bridge_hotplug(s))
+        return pc->no_hotplug;
+    /*
+     * ACPI doesn't allow hotplug of bridge devices.  Don't allow
+     * hot-unplug of bridge devices unless they were added by hotplug
+     * (and so, not described by acpi).
+     */
+    return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug;
+}
+
+static PCIBus *piix4_acpi_hotplug_bus(PIIX4PMState *s, unsigned bsel)
+{
+    if (!piix4_acpi_bridge_hotplug(s))
+        return bsel == 0 ? pci_device_root_bus(&s->dev) : NULL;
+    return s->guest_info->hotplug_buses[bsel];
+}
+
+static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned bsel, unsigned slots)
 {
     BusChild *kid, *next;
-    BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
+    BusState *bus;
     int slot = ffs(slots) - 1;
     bool slot_free = true;
 
+    if (!piix4_acpi_hotplug_bus(s, bsel)) {
+        return;
+    }
+    bus = &piix4_acpi_hotplug_bus(s, bsel)->qbus;
+
     /* Mark request as complete */
-    s->pci0_status.down &= ~(1U << slot);
+    s->pci_status[bsel].down &= ~(1U << slot);
 
     QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
         DeviceState *qdev = kid->child;
         PCIDevice *dev = PCI_DEVICE(qdev);
-        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
         if (PCI_SLOT(dev->devfn) == slot) {
-            if (pc->no_hotplug) {
+            if (acpi_piix_pc_no_hotplug(s, dev)) {
                 slot_free = false;
             } else {
                 qdev_free(qdev);
@@ -322,35 +393,37 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
         }
     }
     if (slot_free) {
-        s->pci0_slot_device_present &= ~(1U << slot);
+        s->pci_status[bsel].device_present &= ~(1U << slot);
     }
 }
 
-static void piix4_update_hotplug(PIIX4PMState *s)
+static void piix4_update_hotplug(PIIX4PMState *s, unsigned bsel)
 {
-    PCIDevice *dev = &s->dev;
-    BusState *bus = qdev_get_parent_bus(&dev->qdev);
     BusChild *kid, *next;
+    BusState *bus;
 
+    if (!piix4_acpi_hotplug_bus(s, bsel)) {
+        return;
+    }
+    bus = &piix4_acpi_hotplug_bus(s, bsel)->qbus;
     /* Execute any pending removes during reset */
-    while (s->pci0_status.down) {
-        acpi_piix_eject_slot(s, s->pci0_status.down);
+    while (s->pci_status[bsel].down) {
+        acpi_piix_eject_slot(s, bsel, s->pci_status[bsel].down);
     }
 
-    s->pci0_hotplug_enable = ~0;
-    s->pci0_slot_device_present = 0;
+    s->pci_status[bsel].hotplug_enable = ~0;
+    s->pci_status[bsel].device_present = 0;
 
     QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
         DeviceState *qdev = kid->child;
         PCIDevice *pdev = PCI_DEVICE(qdev);
-        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
         int slot = PCI_SLOT(pdev->devfn);
 
-        if (pc->no_hotplug) {
-            s->pci0_hotplug_enable &= ~(1U << slot);
+        if (acpi_piix_pc_no_hotplug(s, pdev)) {
+            s->pci_status[bsel].hotplug_enable &= ~(1U << slot);
         }
 
-        s->pci0_slot_device_present |= (1U << slot);
+        s->pci_status[bsel].device_present |= (1U << slot);
     }
 }
 
@@ -358,6 +431,7 @@ static void piix4_reset(void *opaque)
 {
     PIIX4PMState *s = opaque;
     uint8_t *pci_conf = s->dev.config;
+    int i;
 
     pci_conf[0x58] = 0;
     pci_conf[0x59] = 0;
@@ -371,7 +445,9 @@ static void piix4_reset(void *opaque)
         /* Mark SMM as already inited (until KVM supports SMM). */
         pci_conf[0x5B] = 0x02;
     }
-    piix4_update_hotplug(s);
+    for (i = 0; i < GUEST_INFO_MAX_HOTPLUG_BUS; ++i) {
+        piix4_update_hotplug(s, i);
+    }
 }
 
 static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
@@ -382,25 +458,47 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
     acpi_pm1_evt_power_down(&s->ar);
 }
 
-static void piix4_update_guest_info(PIIX4PMState *s)
+static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
+                                PCIHotplugState state);
+
+static void piix4_update_bus_guest_info(PCIBus *pci_bus, void *opaque)
 {
-    PCIDevice *dev = &s->dev;
-    BusState *bus = qdev_get_parent_bus(&dev->qdev);
+    PIIX4PMState *s = opaque;
+    PcGuestInfo *guest_info = s->guest_info;
     BusChild *kid, *next;
+    BusState *bus = &pci_bus->qbus;
+
+    int i = piix4_find_hotplug_bus(guest_info, NULL);
+    assert(i >= 0);
 
-    memset(s->guest_info->slot_hotplug_enable, 0xff,
-           DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE));
+    guest_info->hotplug_buses[i] = pci_bus;
 
     QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
         DeviceState *qdev = kid->child;
         PCIDevice *pdev = PCI_DEVICE(qdev);
-        PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
         int slot = PCI_SLOT(pdev->devfn);
 
-        if (pc->no_hotplug) {
-            clear_bit(slot, s->guest_info->slot_hotplug_enable);
+        if (acpi_piix_pc_no_hotplug(s, pdev)) {
+            clear_bit(slot, guest_info->hotplug_enable[i]);
         }
     }
+
+    pci_bus_hotplug(pci_bus, piix4_device_hotplug, &s->dev.qdev);
+}
+
+static void piix4_update_guest_info(PIIX4PMState *s)
+{
+    PCIDevice *dev = &s->dev;
+
+    memset(s->guest_info->hotplug_enable, 0xff,
+           sizeof s->guest_info->hotplug_enable);
+
+    if (s->guest_info->has_acpi_bridge_hotplug) {
+        pci_for_each_bus(dev->bus, piix4_update_bus_guest_info,
+                         s);
+    } else {
+        piix4_update_bus_guest_info(dev->bus, s);
+    }
 }
 
 static void piix4_pm_machine_ready(Notifier *n, void *opaque)
@@ -589,16 +687,22 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
 {
     PIIX4PMState *s = opaque;
     uint32_t val = 0;
+    int bsel = s->hotplug_select;
+
+    if (bsel > GUEST_INFO_MAX_HOTPLUG_BUS) {
+        return 0;
+    }
 
     switch (addr) {
     case PCI_UP_BASE - PCI_HOTPLUG_ADDR:
         /* Manufacture an "up" value to cause a device check on any hotplug
          * slot with a device.  Extra device checks are harmless. */
-        val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
+        val = s->pci_status[bsel].device_present &
+            s->pci_status[bsel].hotplug_enable;
         PIIX4_DPRINTF("pci_up_read %" PRIu32 "\n", val);
         break;
     case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
-        val = s->pci0_status.down;
+        val = s->pci_status[bsel].down;
         PIIX4_DPRINTF("pci_down_read %" PRIu32 "\n", val);
         break;
     case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
@@ -606,8 +710,10 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
         PIIX4_DPRINTF("pci_features_read %" PRIu32 "\n", val);
         break;
     case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
-        val = s->pci0_hotplug_enable;
+        val = s->pci_status[bsel].hotplug_enable;
         break;
+    case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
+        val = s->hotplug_select;
     default:
         break;
     }
@@ -618,12 +724,18 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
 static void pci_write(void *opaque, hwaddr addr, uint64_t data,
                       unsigned int size)
 {
+    PIIX4PMState *s = opaque;
     switch (addr) {
     case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
-        acpi_piix_eject_slot(opaque, (uint32_t)data);
+        if (s->hotplug_select >= GUEST_INFO_MAX_HOTPLUG_BUS) {
+            break;
+        }
+        acpi_piix_eject_slot(s, s->hotplug_select, data);
         PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
                       addr, data);
         break;
+    case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
+        s->hotplug_select = data;
     default:
         break;
     }
@@ -706,9 +818,6 @@ static void piix4_init_cpu_status(CPUState *cpu, void *data)
     g->sts[id / 8] |= (1 << (id % 8));
 }
 
-static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
-                                PCIHotplugState state);
-
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                            PCIBus *bus, PIIX4PMState *s)
 {
@@ -720,8 +829,6 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                           PCI_HOTPLUG_SIZE);
     memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
                                 &s->io_pci);
-    pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
-
     qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu);
     memory_region_init_io(&s->io_cpu, &cpu_hotplug_ops, s, "apci-cpu-hotplug",
                           PIIX4_PROC_LEN);
@@ -730,16 +837,16 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
     qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
 }
 
-static void enable_device(PIIX4PMState *s, int slot)
+static void enable_device(PIIX4PMState *s, unsigned bsel, int slot)
 {
     s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
-    s->pci0_slot_device_present |= (1U << slot);
+    s->pci_status[bsel].device_present |= (1U << slot);
 }
 
-static void disable_device(PIIX4PMState *s, int slot)
+static void disable_device(PIIX4PMState *s, unsigned bsel, int slot)
 {
     s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
-    s->pci0_status.down |= (1U << slot);
+    s->pci_status[bsel].down |= (1U << slot);
 }
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
@@ -748,19 +855,23 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
     int slot = PCI_SLOT(dev->devfn);
     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
                                 PCI_DEVICE(qdev));
+    int bsel = piix4_find_hotplug_bus(s->guest_info, dev->bus);
+    if (bsel < 0) {
+        return -1;
+    }
 
     /* Don't send event when device is enabled during qemu machine creation:
      * it is present on boot, no hotplug event is necessary. We do send an
      * event when the device is disabled later. */
     if (state == PCI_COLDPLUG_ENABLED) {
-        s->pci0_slot_device_present |= (1U << slot);
+        s->pci_status[bsel].device_present |= (1U << slot);
         return 0;
     }
 
     if (state == PCI_HOTPLUG_ENABLED) {
-        enable_device(s, slot);
+        enable_device(s, bsel, slot);
     } else {
-        disable_device(s, slot);
+        disable_device(s, bsel, slot);
     }
 
     pm_update_sci(s);
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 2ab2572..c2e74e9 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -6,7 +6,7 @@ obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
 obj-y += bios-linker-loader.o
-hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex hw/i386/q35-acpi-dsdt.hex
+hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex hw/i386/ssdt-proc.hex hw/i386/ssdt-misc.hex hw/i386/q35-acpi-dsdt.hex
 hw/i386/pc_piix.o: hw/i386/pc_piix.c hw/i386/acpi-dsdt.hex
 hw/i386/pc_q35.o: hw/i386/pc_q35.c hw/i386/q35-acpi-dsdt.hex
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index bc44f95..2b3900a 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -35,6 +35,7 @@
 #include "hw/nvram/fw_cfg.h"
 #include "hw/i386/bios-linker-loader.h"
 #include "hw/loader.h"
+#include "hw/pci/pci_bus.h"
 
 #define ACPI_BUILD_APPNAME  "Bochs"
 #define ACPI_BUILD_APPNAME6 "BOCHS "
@@ -259,23 +260,372 @@ acpi_encode_len(uint8_t *ssdt_ptr, int length, int bytes)
 #define ACPI_PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
 #define ACPI_PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
 
-/* 0x5B 0x82 DeviceOp PkgLength NameString */
-#define ACPI_PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
-#define ACPI_PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
-#define ACPI_PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
-#define ACPI_PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
-#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
-#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
-
 #define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
 #define ACPI_SSDT_HEADER_LENGTH 36
 
 #include "hw/i386/ssdt-misc.hex"
-#include "hw/i386/ssdt-pcihp.hex"
+
+static inline GArray *build_alloc_array(void)
+{
+        return g_array_new(false, true /* clear */, 1);
+}
+
+static inline void build_free_array(GArray *array)
+{
+        g_array_free(array, true);
+}
+
+static inline void build_prepend_byte(GArray *array, uint8_t val)
+{
+    g_array_prepend_val(array, val);
+}
+
+static inline void build_append_byte(GArray *array, uint8_t val)
+{
+    g_array_append_val(array, val);
+}
+
+static inline void build_prepend_array(GArray *array, GArray *val)
+{
+    g_array_prepend_vals(array, val->data, val->len);
+}
+
+static inline void build_append_array(GArray *array, GArray *val)
+{
+    g_array_append_vals(array, val->data, val->len);
+}
+
+static void build_append_nameseg(GArray *array, const char *format, ...)
+{
+    GString *s = g_string_new("");
+    va_list args;
+
+    va_start(args, format);
+    g_string_vprintf(s, format, args);
+    va_end(args);
+
+    assert(s->len == 4);
+    g_array_append_vals(array, s->str, s->len);
+    g_string_free(s, true);
+}
+
+static void build_prepend_nameseg(GArray *array, const char *format, ...)
+{
+    GString *s = g_string_new("");
+    va_list args;
+
+    va_start(args, format);
+    g_string_vprintf(s, format, args);
+    va_end(args);
+
+    assert(s->len == 4);
+    g_array_prepend_vals(array, s->str, s->len);
+    g_string_free(s, true);
+}
+
+static void build_prepend_devfn(GArray *name, uint8_t devfn)
+{
+    build_prepend_nameseg(name, "S%0.02X_", devfn);
+}
+
+static void build_append_devfn(GArray *name, uint8_t devfn)
+{
+    GArray *array = build_alloc_array();
+    build_prepend_devfn(array, devfn);
+    build_append_array(name, array);
+    build_free_array(array);
+}
+
+static void build_prepend_name_string(GArray *name, PCIBus *bus)
+{
+    int segcount;
+
+    for (;!pci_bus_is_root(bus); bus = bus->parent_dev->bus) {
+        build_prepend_devfn(name, bus->parent_dev->devfn);
+    }
+    g_array_prepend_vals(name, "PCI0", 4);
+    g_array_prepend_vals(name, "_SB_", 4);
+    /* Name segment length is a multiple of 4 */
+    assert(name->len % 4 == 0);
+    segcount = name->len / 4;
+    build_prepend_byte(name, segcount);
+    build_prepend_byte(name, 0x2f); /* MultiNamePrefix */
+    build_prepend_byte(name, '\\'); /* RootChar */
+}
+
+static void build_append_name_string(GArray *name, PCIBus *bus)
+{
+    GArray *append = build_alloc_array();
+    build_prepend_name_string(append, bus);
+    build_append_array(name, append);
+    build_free_array(append);
+}
+
+/* 5.4 Definition Block Encoding */
+enum {
+    PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
+    PACKAGE_LENGTH_2BYTE_SHIFT = 4,
+    PACKAGE_LENGTH_3BYTE_SHIFT = 12,
+    PACKAGE_LENGTH_4BYTE_SHIFT = 20,
+};
+
+static void build_prepend_package_length(GArray *package)
+{
+    uint8_t byte;
+    unsigned length = package->len;
+    unsigned length_bytes;
+
+    if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
+        length_bytes = 1;
+    } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
+        length_bytes = 2;
+    } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
+        length_bytes = 3;
+    } else {
+        length_bytes = 4;
+    }
+
+    /* PkgLength is the length of the inclusive length of the data. */
+    length += length_bytes;
+
+    switch (length_bytes) {
+    case 1:
+        byte = length;
+        build_prepend_byte(package, byte);
+        return;
+    case 4:
+        byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
+        /* fall through */
+    case 3:
+        byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
+        /* fall through */
+    case 2:
+        byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
+        build_prepend_byte(package, byte);
+        length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
+        /* fall through */
+    }
+    /*
+     * Most significant two bits of byte zero indicate how many following bytes
+     * are in PkgLength encoding.
+     */
+    byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
+    build_prepend_byte(package, byte);
+}
+
+static void build_package(GArray *package, uint8_t op)
+{
+    build_prepend_package_length(package);
+    build_prepend_byte(package, op);
+}
+
+static void build_extop_package(GArray *package, uint8_t op)
+{
+    build_package(package, op);
+    build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
+}
+
+static void build_append_notify(GArray *method, GArray *target_name,
+                                uint16_t value)
+{
+    GArray *notify = build_alloc_array();
+    uint8_t op = 0xA0; /* IfOp */
+
+    build_append_byte(notify, 0x93); /* LEqualOp */
+    build_append_byte(notify, 0x68); /* Arg0Op */
+    build_append_byte(notify, 0x0B); /* WordPrefix */
+    build_append_byte(notify, value);
+    build_append_byte(notify, value >> 8);
+    build_append_byte(notify, 0x86); /* NotifyOp */
+    build_append_array(notify, target_name);
+    build_append_byte(notify, 0x69); /* Arg1Op */
+
+    /* Pack it up */
+    build_package(notify, op);
+
+    build_append_array(method, notify);
+
+    build_free_array(notify);
+}
+
+static void
+build_append_notify_slots(GArray *method, PCIBus *bus,
+                          unsigned bus_select,
+                          DECLARE_BITMAP(hotplug_enable, PCI_SLOT_MAX))
+{
+    int i;
+
+    if (!bus) {
+        return;
+    }
+
+    for (i = 0; i < PCI_SLOT_MAX; i++) {
+        GArray *target;
+        if (!test_bit(i, hotplug_enable)) {
+            continue;
+        }
+        target = build_alloc_array();
+        build_prepend_devfn(target, PCI_DEVFN(i, 0));
+        build_prepend_name_string(target, bus);
+        /* *32 matches Multiply in PCNF */
+        build_append_notify(method, target, bus_select * 32 + i);
+        build_free_array(target);
+    }
+}
+
+static void build_append_notify_buses(GArray *table, PcGuestInfo *guest_info)
+{
+    int i;
+    GArray *method = build_alloc_array();
+
+    uint8_t op = 0x14; /* MethodOp */
+
+    build_append_nameseg(method, "PCNT");
+    build_append_byte(method, 0x02); /* MethodFlags: ArgCount */
+    for (i = 0; i < ARRAY_SIZE(guest_info->hotplug_buses); ++i) {
+        build_append_notify_slots(method, guest_info->hotplug_buses[i], i,
+                                  guest_info->hotplug_enable[i]);
+    }
+    build_package(method, op);
+
+    build_append_array(table, method);
+    build_free_array(method);
+}
+
+static void build_append_device(GArray *table, unsigned devfn)
+{
+    uint8_t op, ej0_op;
+
+    GArray *device = build_alloc_array();
+    GArray *ej0 = build_alloc_array();
+
+    op = 0x82; /* DeviceOp */
+
+    build_append_devfn(device, devfn);
+
+    build_append_byte(device, 0x08); /* NameOp */
+    build_append_nameseg(device, "_SUN");
+    build_append_byte(device, 0x0A); /* BytePrefix */
+    build_append_byte(device, PCI_SLOT(devfn));
+    build_append_byte(device, 0x08); /* NameOp */
+    build_append_nameseg(device, "_ADR");
+    build_append_byte(device, 0x0C); /* DWordPrefix */
+    build_append_byte(device, PCI_FUNC(devfn));
+    build_append_byte(device, 0x00);
+    build_append_byte(device, PCI_SLOT(devfn));
+    build_append_byte(device, 0x00);
+
+    ej0_op = 0x14;  /* MethodOp */
+    build_append_nameseg(ej0, "_EJ0");
+    build_append_byte(ej0, 0x01); /* MethodFlags: ArgCount */
+    build_append_byte(ej0, 0xA4); /* ReturnOp */
+    build_append_nameseg(ej0, "PCEJ");
+    build_append_nameseg(ej0, "_SUN");
+    build_append_nameseg(ej0, "BNUM");
+    build_package(ej0, ej0_op);
+    build_append_array(device, ej0);
+
+    build_extop_package(device, op);
+
+    build_append_array(table, device);
+    build_free_array(device);
+    build_free_array(ej0);
+}
+
+static bool build_find_device_bus(PCIBus *buses[GUEST_INFO_MAX_HOTPLUG_BUS],
+                                  PCIBus *bus, unsigned devfn)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(buses); ++i) {
+        if (buses[i] && buses[i]->parent_dev &&
+            buses[i]->parent_dev->bus == bus &&
+            buses[i]->parent_dev->devfn == devfn) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void
+build_append_bus(GArray *table,  int bnum, PcGuestInfo *guest_info)
+{
+    uint8_t op;
+    int slot;
+    unsigned devfn;
+    GArray *device;
+    PCIBus *bus = guest_info->hotplug_buses[bnum];
+
+    if (!bus) {
+        return;
+    }
+
+    device = build_alloc_array();
+
+    /* Root device described in DSDT */
+    if (bnum) {
+        devfn = bus->parent_dev->devfn;
+
+        op = 0x82; /* DeviceOp */
+
+        build_append_name_string(device, bus);
+
+        build_append_byte(device, 0x08); /* NameOp */
+        build_append_nameseg(device, "_SUN");
+        build_append_byte(device, 0x0A); /* BytePrefix */
+        build_append_byte(device, PCI_SLOT(devfn));
+        build_append_byte(device, 0x08); /* NameOp */
+        build_append_nameseg(device, "BNUM");
+        build_append_byte(device, 0x0A); /* BytePrefix */
+        build_append_byte(device, bnum);
+        build_append_byte(device, 0x08); /* NameOp */
+        build_append_nameseg(device, "_ADR");
+        build_append_byte(device, 0x0C); /* DWordPrefix */
+        build_append_byte(device, PCI_FUNC(devfn));
+        build_append_byte(device, 0x00);
+        build_append_byte(device, PCI_SLOT(devfn));
+        build_append_byte(device, 0x00);
+    } else {
+        op = 0x10; /* ScopeOp */
+        build_append_nameseg(device, "PCI0");
+    }
+
+    for (slot = 0; slot < PCI_SLOT_MAX; ++slot) {
+        if (!test_bit(slot, guest_info->hotplug_enable[bnum])) {
+            continue;
+        }
+        /* Bus device? We'll add it later */
+        if (build_find_device_bus(guest_info->hotplug_buses,
+                                  bus, PCI_DEVFN(slot, 0))) {
+            continue;
+        }
+        build_append_device(device, PCI_DEVFN(slot, 0));
+    }
+
+    if (bnum) {
+        build_extop_package(device, op);
+    } else {
+        build_package(device, op);
+    }
+
+    build_append_array(table, device);
+    build_free_array(device);
+}
+
+static void build_append_device_buses(GArray *table, PcGuestInfo *guest_info)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(guest_info->hotplug_buses); ++i) {
+        build_append_bus(table, i, guest_info);
+    }
+}
 
 static uint8_t*
 build_notify(uint8_t *ssdt_ptr, const char *name, int skip, int count,
-             const char *target, int ofs)
+             const char *target, int ofs, int step)
 {
     int i;
 
@@ -296,31 +646,14 @@ build_notify(uint8_t *ssdt_ptr, const char *name, int skip, int count,
         *(ssdt_ptr++) = i;
         *(ssdt_ptr++) = 0x86; /* NotifyOp */
         memcpy(ssdt_ptr, target, 4);
-        ssdt_ptr[ofs] = acpi_get_hex(i >> 4);
-        ssdt_ptr[ofs + 1] = acpi_get_hex(i);
+        ssdt_ptr[ofs] = acpi_get_hex((i * step) >> 4);
+        ssdt_ptr[ofs + 1] = acpi_get_hex(i * step);
         ssdt_ptr += 4;
         *(ssdt_ptr++) = 0x69; /* Arg1Op */
     }
     return ssdt_ptr;
 }
 
-static void patch_pcihp(int slot, uint8_t *ssdt_ptr, uint32_t eject)
-{
-    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(slot >> 4);
-    ssdt_ptr[ACPI_PCIHP_OFFSET_HEX+1] = acpi_get_hex(slot);
-    ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
-    ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
-
-    /* Runtime patching of ACPI_EJ0: to disable hotplug for a slot,
-     * replace the method name: _EJ0 by ACPI_EJ0_. */
-    /* Sanity check */
-    assert (!memcmp(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "_EJ0", 4));
-
-    if (!eject) {
-        memcpy(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "EJ0_", 4);
-    }
-}
-
 static void
 build_ssdt(GArray *table_data, GArray *linker,
            FWCfgState *fw_cfg, PcGuestInfo *guest_info)
@@ -331,11 +664,20 @@ build_ssdt(GArray *table_data, GArray *linker,
                   + (acpi_cpus * ACPI_PROC_SIZEOF)               /* procs */
                   + (1+2+5+(12*acpi_cpus))                  /* NTFY */
                   + (6+2+1+(1*acpi_cpus))                   /* CPON */
-                  + (1+3+4)                                 /* Scope(PCI0) */
-                  + ((PCI_SLOT_MAX - 1) * ACPI_PCIHP_SIZEOF)        /* slots */
-                  + (1+2+5+(12*(PCI_SLOT_MAX - 1))));          /* PCNT */
-    uint8_t *ssdt = acpi_data_push(table_data, length);
-    uint8_t *ssdt_ptr = ssdt;
+                 );
+    uint8_t *ssdt;
+    uint8_t *ssdt_ptr;
+    GArray *devices = build_alloc_array();
+    GArray *notify = build_alloc_array();
+
+    /* TODO: rewrite this function using glib */
+    build_append_device_buses(devices, guest_info);
+    length += devices->len;
+    build_append_notify_buses(notify, guest_info);
+    length += notify->len;
+
+    ssdt = acpi_data_push(table_data, length);
+    ssdt_ptr = ssdt;
 
     /* Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages */
     memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
@@ -393,7 +735,7 @@ build_ssdt(GArray *table_data, GArray *linker,
 
     /* build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}" */
     /* Arg0 = Processor ID = APIC ID */
-    ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2);
+    ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2, 1);
 
     /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
     *(ssdt_ptr++) = 0x08; /* NameOp */
@@ -415,15 +757,10 @@ build_ssdt(GArray *table_data, GArray *linker,
     *(ssdt_ptr++) = 'I';
     *(ssdt_ptr++) = '0';
 
-    /* build Device object for each slot */
-    for (i = 1; i < PCI_SLOT_MAX; i++) {
-        bool eject = test_bit(i, guest_info->slot_hotplug_enable);
-        memcpy(ssdt_ptr, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
-        patch_pcihp(i, ssdt_ptr, eject);
-        ssdt_ptr += ACPI_PCIHP_SIZEOF;
-    }
-
-    ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOT_MAX, "S00_", 1);
+    memcpy(ssdt_ptr, devices->data, devices->len);
+    ssdt_ptr += devices->len;
+    memcpy(ssdt_ptr, notify->data, notify->len);
+    ssdt_ptr += notify->len;
 
     build_header(linker, table_data,
                  (void*)ssdt, ACPI_SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index 90efce0..dc05668 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -133,11 +133,18 @@ DefinitionBlock (
             B0EJ, 32,
         }
 
+        OperationRegion(SEL, SystemIO, 0xae10, 0x04)
+        Field(SEL, DWordAcc, NoLock, WriteAsZeros) {
+            BSEL, 32,
+        }
+
         /* Methods called by bulk generated PCI devices below */
+        Name(BNUM, 0x00)
 
         /* Methods called by hotplug devices */
-        Method(PCEJ, 1, NotSerialized) {
+        Method(PCEJ, 2, NotSerialized) {
             // _EJ0 method - eject callback
+            Store(Arg1, BSEL)
             Store(ShiftLeft(1, Arg0), B0EJ)
             Return (0x0)
         }
@@ -147,16 +154,25 @@ DefinitionBlock (
 
         /* PCI hotplug notify method */
         Method(PCNF, 0) {
-            // Local0 = iterator
+            // Local0 = bridge selector
             Store(Zero, Local0)
-            While (LLess(Local0, 31)) {
-                Increment(Local0)
-                If (And(PCIU, ShiftLeft(1, Local0))) {
-                    PCNT(Local0, 1)
-                }
-                If (And(PCID, ShiftLeft(1, Local0))) {
-                    PCNT(Local0, 3)
-                }
+            While (LLess(Local0, 255)) {
+                    Store(Local0, BSEL)
+                    // Local1 = slot iterator
+                    Store(Zero, Local1)
+
+                    Store(PCIU, Local2)
+                    Store(PCID, Local3)
+                    While (LLess(Local1, 31)) {
+                        Increment(Local1)
+                        If (And(Local2, ShiftLeft(1, Local1))) {
+                            PCNT(Add(Local1, Multiply(Local0, 32)), 1)
+                        }
+                        If (And(Local3, ShiftLeft(1, Local1))) {
+                            PCNT(Add(Local1, Multiply(Local0, 32)), 3)
+                        }
+                    }
+                    Increment(Local0)
             }
         }
     }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 77e4260..9183acc 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -61,6 +61,7 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 static bool has_pvpanic = true;
 static bool has_pci_info = true;
 static bool has_acpi_build = true;
+static bool has_acpi_bridge_hotplug = true;
 
 /* PC hardware initialisation */
 static void pc_init1(MemoryRegion *system_memory,
@@ -131,6 +132,7 @@ static void pc_init1(MemoryRegion *system_memory,
 
     guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
 
+    guest_info->has_acpi_bridge_hotplug = has_acpi_bridge_hotplug;
     guest_info->has_acpi_build = has_acpi_build;
     guest_info->dsdt_code = AcpiDsdtAmlCode;
     guest_info->dsdt_size = sizeof AcpiDsdtAmlCode;
@@ -277,6 +279,7 @@ static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
 {
     has_pci_info = false;
     has_acpi_build = false;
+    has_acpi_bridge_hotplug = false;
     pc_init_pci(args);
 }
 
diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl
deleted file mode 100644
index d29a5b9..0000000
--- a/hw/i386/ssdt-pcihp.dsl
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
-
-DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
-{
-
-/****************************************************************
- * PCI hotplug
- ****************************************************************/
-
-    /* Objects supplied by DSDT */
-    External(\_SB.PCI0, DeviceObj)
-    External(\_SB.PCI0.PCEJ, MethodObj)
-
-    Scope(\_SB.PCI0) {
-
-        /* Bulk generated PCI hotplug devices */
-        ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
-        ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
-        ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
-
-        // Method _EJ0 can be patched by BIOS to EJ0_
-        // at runtime, if the slot is detected to not support hotplug.
-        // Extract the offset of the address dword and the
-        // _EJ0 name to allow this patching.
-        Device(SAA) {
-            ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
-            Name(_SUN, 0xAA)
-            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
-            Name(_ADR, 0xAA0000)
-            ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
-            Method(_EJ0, 1) {
-                Return (PCEJ(_SUN))
-            }
-        }
-    }
-}
diff --git a/hw/i386/ssdt-pcihp.hex.generated b/hw/i386/ssdt-pcihp.hex.generated
deleted file mode 100644
index 0d32a27..0000000
--- a/hw/i386/ssdt-pcihp.hex.generated
+++ /dev/null
@@ -1,108 +0,0 @@
-static unsigned char ssdt_pcihp_name[] = {
-0x33
-};
-static unsigned char ssdt_pcihp_adr[] = {
-0x44
-};
-static unsigned char ssdt_pcihp_end[] = {
-0x58
-};
-static unsigned char ssdp_pcihp_aml[] = {
-0x53,
-0x53,
-0x44,
-0x54,
-0x58,
-0x0,
-0x0,
-0x0,
-0x1,
-0x77,
-0x42,
-0x58,
-0x50,
-0x43,
-0x0,
-0x0,
-0x42,
-0x58,
-0x53,
-0x53,
-0x44,
-0x54,
-0x50,
-0x43,
-0x1,
-0x0,
-0x0,
-0x0,
-0x49,
-0x4e,
-0x54,
-0x4c,
-0x28,
-0x5,
-0x10,
-0x20,
-0x10,
-0x33,
-0x5c,
-0x2e,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x5b,
-0x82,
-0x26,
-0x53,
-0x41,
-0x41,
-0x5f,
-0x8,
-0x5f,
-0x53,
-0x55,
-0x4e,
-0xa,
-0xaa,
-0x8,
-0x5f,
-0x41,
-0x44,
-0x52,
-0xc,
-0x0,
-0x0,
-0xaa,
-0x0,
-0x14,
-0xf,
-0x5f,
-0x45,
-0x4a,
-0x30,
-0x1,
-0xa4,
-0x50,
-0x43,
-0x45,
-0x4a,
-0x5f,
-0x53,
-0x55,
-0x4e
-};
-static unsigned char ssdt_pcihp_start[] = {
-0x30
-};
-static unsigned char ssdt_pcihp_id[] = {
-0x3d
-};
-static unsigned char ssdt_pcihp_ej0[] = {
-0x4a
-};
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 2ac97d3..051f423 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -38,7 +38,9 @@ struct PcGuestInfo {
     bool s3_disabled;
     bool s4_disabled;
     uint8_t s4_val;
-    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
+#define GUEST_INFO_MAX_HOTPLUG_BUS 256
+    PCIBus *hotplug_buses[GUEST_INFO_MAX_HOTPLUG_BUS];
+    DECLARE_BITMAP(hotplug_enable[GUEST_INFO_MAX_HOTPLUG_BUS], PCI_SLOT_MAX);
     uint16_t sci_int;
     uint8_t acpi_enable_cmd;
     uint8_t acpi_disable_cmd;
@@ -52,6 +54,7 @@ struct PcGuestInfo {
     uint16_t pvpanic_port;
     FWCfgState *fw_cfg;
     bool has_acpi_build;
+    bool has_acpi_bridge_hotplug;
 };
 
 /* parallel.c */
