@@ -44,11 +44,11 @@
#include "sysemu/kvm.h"
#include "hw/kvm/clock.h"
#include "hw/sysbus.h"
+#include "hw/i2c/i2c.h"
#include "hw/i2c/smbus_eeprom.h"
#include "hw/xen/xen-x86.h"
#include "exec/memory.h"
#include "hw/acpi/acpi.h"
-#include "hw/acpi/piix4.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/xen.h"
@@ -83,6 +83,7 @@ static void pc_init1(MachineState *machine,
MemoryRegion *system_io = get_system_io();
PCIBus *pci_bus;
ISABus *isa_bus;
+ Object *piix4_pm;
int piix3_devfn = -1;
qemu_irq smi_irq;
GSIState *gsi_state;
@@ -212,13 +213,21 @@ static void pc_init1(MachineState *machine,
pci_dev = pci_new_multifunction(-1, true, type);
object_property_set_bool(OBJECT(pci_dev), "has-usb",
machine_usb(machine), &error_abort);
+ object_property_set_bool(OBJECT(pci_dev), "has-acpi",
+ x86_machine_is_acpi_enabled(x86ms),
+ &error_abort);
+ object_property_set_bool(OBJECT(pci_dev), "smm-enabled",
+ x86_machine_is_smm_enabled(x86ms),
+ &error_abort);
pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
piix3 = PIIX3_PCI_DEVICE(pci_dev);
piix3->pic = x86ms->gsi;
piix3_devfn = piix3->dev.devfn;
isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
+ piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
} else {
pci_bus = NULL;
+ piix4_pm = NULL;
isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
&error_abort);
i8257_dma_init(isa_bus, 0);
@@ -283,15 +292,8 @@ static void pc_init1(MachineState *machine,
}
#endif
- if (pcmc->pci_enabled && x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) {
- PCIDevice *piix4_pm;
-
+ if (piix4_pm) {
smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
- piix4_pm = pci_new(piix3_devfn + 3, TYPE_PIIX4_PM);
- qdev_prop_set_uint32(DEVICE(piix4_pm), "smb_io_base", 0xb100);
- qdev_prop_set_bit(DEVICE(piix4_pm), "smm-enabled",
- x86_machine_is_smm_enabled(x86ms));
- pci_realize_and_unref(piix4_pm, pci_bus, &error_fatal);
qdev_connect_gpio_out(DEVICE(piix4_pm), 0, x86ms->gsi[9]);
qdev_connect_gpio_out_named(DEVICE(piix4_pm), "smi-irq", 0, smi_irq);
@@ -305,7 +307,7 @@ static void pc_init1(MachineState *machine,
object_property_allow_set_link,
OBJ_PROP_LINK_STRONG);
object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
- OBJECT(piix4_pm), &error_abort);
+ piix4_pm, &error_abort);
}
if (machine->nvdimms_state->is_enabled) {
@@ -324,6 +324,16 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
} else {
object_unparent(OBJECT(&d->uhci));
}
+
+ /* ACPI */
+ if (d->has_acpi) {
+ qdev_prop_set_int32(DEVICE(&d->pm), "addr", dev->devfn + 3);
+ if (!qdev_realize(DEVICE(&d->pm), BUS(pci_bus), errp)) {
+ return;
+ }
+ } else {
+ object_unparent(OBJECT(&d->pm));
+ }
}
static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
@@ -344,9 +354,15 @@ static void pci_piix3_init(Object *obj)
PIIX3State *d = PIIX3_PCI_DEVICE(obj);
object_initialize_child(obj, "uhci", &d->uhci, "piix3-usb-uhci");
+
+ object_initialize_child(obj, "pm", &d->pm, TYPE_PIIX4_PM);
+ qdev_prop_set_uint32(DEVICE(&d->pm), "smb_io_base", 0xb100);
+ object_property_add_alias(obj, "smm-enabled",
+ OBJECT(&d->pm), "smm-enabled");
}
static Property pci_piix3_props[] = {
+ DEFINE_PROP_BOOL("has-acpi", PIIX3State, has_acpi, true),
DEFINE_PROP_BOOL("has-usb", PIIX3State, has_usb, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -14,6 +14,7 @@
#include "hw/pci/pci.h"
#include "qom/object.h"
+#include "hw/acpi/piix4.h"
#include "hw/usb/hcd-uhci.h"
/* PIRQRC[A:D]: PIRQx Route Control Registers */
@@ -54,6 +55,7 @@ struct PIIXState {
int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
UHCIState uhci;
+ PIIX4PMState pm;
/* Reset Control Register contents */
uint8_t rcr;
@@ -61,6 +63,7 @@ struct PIIXState {
/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
MemoryRegion rcr_mem;
+ bool has_acpi;
bool has_usb;
};
typedef struct PIIXState PIIX3State;
The ACPI controller is an integral part of PIIX3 (function 3). So create it as part of the southbridge. Note that the ACPI function is optional in QEMU. This is why it gets unparented if it is disabled, otherwiese QEMU will abort with: src/hw/core/qdev.c:357: qdev_assert_realized_properly_cb: Assertion `dev->realized' failed Signed-off-by: Bernhard Beschow <shentey@gmail.com> --- hw/i386/pc_piix.c | 22 ++++++++++++---------- hw/isa/piix3.c | 16 ++++++++++++++++ include/hw/southbridge/piix.h | 3 +++ 3 files changed, 31 insertions(+), 10 deletions(-)