Skip to content

Commit

Permalink
hw/isa/piix3: Create power management controller in host device
Browse files Browse the repository at this point in the history
The power management controller is an integral part of PIIX3 (function 3). So
create it as part of the south bridge.

Note that the ACPI function is optional in QEMU. This is why it gets
object_initialize_child()'ed in realize rather than in instance_init.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20231007123843.127151-14-shentey@gmail.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
shentok authored and mstsirkin committed Oct 18, 2023
1 parent 3dc8926 commit be5b66b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 13 deletions.
24 changes: 11 additions & 13 deletions hw/i386/pc_piix.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
#include "hw/i2c/smbus_eeprom.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"
Expand Down Expand Up @@ -115,7 +114,7 @@ static void pc_init1(MachineState *machine,
MemoryRegion *system_io = get_system_io();
PCIBus *pci_bus = NULL;
ISABus *isa_bus;
int piix3_devfn = -1;
Object *piix4_pm = NULL;
qemu_irq smi_irq;
GSIState *gsi_state;
BusState *idebus[MAX_IDE_BUS];
Expand Down Expand Up @@ -266,6 +265,13 @@ static void pc_init1(MachineState *machine,
pci_dev = pci_new_multifunction(-1, TYPE_PIIX3_DEVICE);
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);
qdev_prop_set_uint32(DEVICE(pci_dev), "smb_io_base", 0xb100);
object_property_set_bool(OBJECT(pci_dev), "smm-enabled",
x86_machine_is_smm_enabled(x86ms),
&error_abort);
dev = DEVICE(pci_dev);
for (i = 0; i < ISA_NUM_IRQS; i++) {
qdev_connect_gpio_out_named(dev, "isa-irqs", i, x86ms->gsi[i]);
Expand All @@ -286,10 +292,10 @@ static void pc_init1(MachineState *machine,
XEN_IOAPIC_NUM_PIRQS);
}

piix3_devfn = pci_dev->devfn;
isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0"));
rtc_state = ISA_DEVICE(object_resolve_path_component(OBJECT(pci_dev),
"rtc"));
piix4_pm = object_resolve_path_component(OBJECT(pci_dev), "pm");
dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide"));
pci_ide_create_devs(PCI_DEVICE(dev));
idebus[0] = qdev_get_child_bus(dev, "ide.0");
Expand Down Expand Up @@ -360,17 +366,9 @@ 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);
pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c"));
/* TODO: Populate SPD eeprom data. */
Expand All @@ -382,7 +380,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) {
Expand Down
1 change: 1 addition & 0 deletions hw/isa/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ config PC87312

config PIIX3
bool
select ACPI_PIIX4
select I8257
select IDE_PIIX
select ISA_BUS
Expand Down
15 changes: 15 additions & 0 deletions hw/isa/piix3.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,18 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
return;
}
}

/* Power Management */
if (d->has_acpi) {
object_initialize_child(OBJECT(d), "pm", &d->pm, TYPE_PIIX4_PM);
qdev_prop_set_int32(DEVICE(&d->pm), "addr", dev->devfn + 3);
qdev_prop_set_uint32(DEVICE(&d->pm), "smb_io_base", d->smb_io_base);
qdev_prop_set_bit(DEVICE(&d->pm), "smm-enabled", d->smm_enabled);
if (!qdev_realize(DEVICE(&d->pm), BUS(pci_bus), errp)) {
return;
}
qdev_connect_gpio_out(DEVICE(&d->pm), 0, d->isa_irqs_in[9]);
}
}

static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
Expand Down Expand Up @@ -343,7 +355,10 @@ static void pci_piix3_init(Object *obj)
}

static Property pci_piix3_props[] = {
DEFINE_PROP_UINT32("smb_io_base", PIIX3State, smb_io_base, 0),
DEFINE_PROP_BOOL("has-acpi", PIIX3State, has_acpi, true),
DEFINE_PROP_BOOL("has-usb", PIIX3State, has_usb, true),
DEFINE_PROP_BOOL("smm-enabled", PIIX3State, smm_enabled, false),
DEFINE_PROP_END_OF_LIST(),
};

Expand Down
6 changes: 6 additions & 0 deletions include/hw/southbridge/piix.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define HW_SOUTHBRIDGE_PIIX_H

#include "hw/pci/pci_device.h"
#include "hw/acpi/piix4.h"
#include "hw/ide/pci.h"
#include "hw/rtc/mc146818rtc.h"
#include "hw/usb/hcd-uhci.h"
Expand Down Expand Up @@ -56,14 +57,19 @@ struct PIIXState {
MC146818RtcState rtc;
PCIIDEState ide;
UHCIState uhci;
PIIX4PMState pm;

uint32_t smb_io_base;

/* Reset Control Register contents */
uint8_t rcr;

/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
MemoryRegion rcr_mem;

bool has_acpi;
bool has_usb;
bool smm_enabled;
};
typedef struct PIIXState PIIX3State;

Expand Down

0 comments on commit be5b66b

Please sign in to comment.