diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/acpi/generic_event_device.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index 92b931758f..7535d07737 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -12,6 +12,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/pcihp.h" #include "hw/acpi/generic_event_device.h" #include "hw/pci/pci.h" #include "hw/irq.h" @@ -28,6 +29,7 @@ static const uint32_t ged_supported_events[] = { ACPI_GED_PWR_DOWN_EVT, ACPI_GED_NVDIMM_HOTPLUG_EVT, ACPI_GED_CPU_HOTPLUG_EVT, + ACPI_GED_PCI_HOTPLUG_EVT, }; /* @@ -123,6 +125,12 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, aml_notify(aml_name("\\_SB.NVDR"), aml_int(0x80))); break; + case ACPI_GED_PCI_HOTPLUG_EVT: + aml_append(if_ctx, + aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0xFFFF)); + aml_append(if_ctx, aml_call0("\\_SB.PCI0.PCNT")); + aml_append(if_ctx, aml_release(aml_name("\\_SB.PCI0.BLCK"))); + break; default: /* * Please make sure all the events in ged_supported_events[] @@ -316,6 +324,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; } else if (ev & ACPI_CPU_HOTPLUG_STATUS) { sel = ACPI_GED_CPU_HOTPLUG_EVT; + } else if (ev & ACPI_PCI_HOTPLUG_STATUS) { + sel = ACPI_GED_PCI_HOTPLUG_EVT; } else { /* Unknown event. Return without generating interrupt. */ warn_report("GED: Unsupported event %d. No irq injected", ev); @@ -427,9 +437,13 @@ static void acpi_ged_realize(DeviceState *dev, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(dev); AcpiGedState *s = ACPI_GED(dev); + AcpiPciHpState *pcihp_state = &s->pcihp_state; uint32_t ged_events; int i; + if (pcihp_state->use_acpi_hotplug_bridge) { + s->ged_event_bitmap |= ACPI_GED_PCI_HOTPLUG_EVT; + } ged_events = ctpop32(s->ged_event_bitmap); for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { @@ -449,6 +463,13 @@ static void acpi_ged_realize(DeviceState *dev, Error **errp) cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev), &s->cpuhp_state, 0); break; + case ACPI_GED_PCI_HOTPLUG_EVT: + memory_region_init(&s->container_pcihp, OBJECT(dev), + ACPI_PCIHP_REGION_NAME, ACPI_PCIHP_SIZE); + sysbus_init_mmio(sbd, &s->container_pcihp); + acpi_pcihp_init(OBJECT(s), &s->pcihp_state, + &s->container_pcihp, 0); + qbus_set_hotplug_handler(BUS(s->pcihp_state.root), OBJECT(dev)); } ged_events--; } @@ -490,11 +511,22 @@ static void acpi_ged_initfn(Object *obj) sysbus_init_mmio(sbd, &ged_st->regs); } +static void ged_reset_hold(Object *obj, ResetType type) +{ + AcpiGedState *s = ACPI_GED(obj); + + if (s->pcihp_state.use_acpi_hotplug_bridge) { + acpi_pcihp_reset(&s->pcihp_state); + } +} + static void acpi_ged_class_init(ObjectClass *class, const void *data) { DeviceClass *dc = DEVICE_CLASS(class); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class); AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); + ResettableClass *rc = RESETTABLE_CLASS(class); + AcpiGedClass *gedc = ACPI_GED_CLASS(class); dc->desc = "ACPI Generic Event Device"; device_class_set_props(dc, acpi_ged_properties); @@ -505,6 +537,8 @@ static void acpi_ged_class_init(ObjectClass *class, const void *data) hc->plug = acpi_ged_device_plug_cb; hc->unplug_request = acpi_ged_unplug_request_cb; hc->unplug = acpi_ged_unplug_cb; + resettable_class_set_parent_phases(rc, NULL, ged_reset_hold, NULL, + &gedc->parent_phases); adevc->ospm_status = acpi_ged_ospm_status; adevc->send_event = acpi_ged_send_event; @@ -516,6 +550,7 @@ static const TypeInfo acpi_ged_info = { .instance_size = sizeof(AcpiGedState), .instance_init = acpi_ged_initfn, .class_init = acpi_ged_class_init, + .class_size = sizeof(AcpiGedClass), .interfaces = (const InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, { TYPE_ACPI_DEVICE_IF }, |