On Mon, 16 Jun 2025 11:46:49 +0200 Eric Auger <eric.au...@redhat.com> wrote:
> QEMU will notify the OS about PCI hotplug/hotunplug events through > GED interrupts. Let the GED device handle a new PCI hotplug event. > On its occurrence it calls the \\_SB.PCI0.PCNT method with the BLCK > mutex held. > > The GED device uses a dedicated MMIO region that will be mapped > by the machine code. > At this point the GED still does not support PCI device hotplug in > its TYPE_HOTPLUG_HANDLER implementation. This will come in a > subsequent patch. looks out of order, perhaps it should be before this patch > > Signed-off-by: Eric Auger <eric.au...@redhat.com> > > --- > v2 -> v3: > - pcihp_init and reset are put in ged code instead of machine code > (Igor) > > v1 -> v2: > - Introduce ACPI_PCIHP_REGION_NAME > --- > include/hw/acpi/generic_event_device.h | 4 ++++ > hw/acpi/generic_event_device.c | 26 ++++++++++++++++++++++++++ > hw/acpi/pcihp.c | 1 - > 3 files changed, 30 insertions(+), 1 deletion(-) > > diff --git a/include/hw/acpi/generic_event_device.h > b/include/hw/acpi/generic_event_device.h > index f5ffa67a39..ec8e1abe0a 100644 > --- a/include/hw/acpi/generic_event_device.h > +++ b/include/hw/acpi/generic_event_device.h > @@ -102,6 +102,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) > #define ACPI_GED_PWR_DOWN_EVT 0x2 > #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 > #define ACPI_GED_CPU_HOTPLUG_EVT 0x8 > +#define ACPI_GED_PCI_HOTPLUG_EVT 0x10 > > typedef struct GEDState { > MemoryRegion evt; > @@ -109,6 +110,8 @@ typedef struct GEDState { > uint32_t sel; > } GEDState; > > +#define ACPI_PCIHP_REGION_NAME "pcihp container" > + > struct AcpiGedState { > SysBusDevice parent_obj; > MemHotplugState memhp_state; > @@ -116,6 +119,7 @@ struct AcpiGedState { > CPUHotplugState cpuhp_state; > MemoryRegion container_cpuhp; > AcpiPciHpState pcihp_state; > + MemoryRegion container_pcihp; > GEDState ged_state; > uint32_t ged_event_bitmap; > qemu_irq irq; > diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c > index ef1c1ec51f..b4eefb0106 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" > @@ -27,6 +28,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, > }; > > /* > @@ -122,6 +124,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[] > @@ -300,6 +308,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); > @@ -433,6 +443,12 @@ 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->pcihp_state.root, &s->container_pcihp, 0); > } > ged_events--; > } > @@ -474,6 +490,15 @@ static void acpi_ged_initfn(Object *obj) > sysbus_init_mmio(sbd, &ged_st->regs); > } > > +static void ged_reset(DeviceState *dev) > +{ > + AcpiGedState *s = ACPI_GED(dev); > + > + 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); > @@ -488,6 +513,7 @@ 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; > + device_class_set_legacy_reset(dc, ged_reset); > > adevc->ospm_status = acpi_ged_ospm_status; > adevc->send_event = acpi_ged_send_event; > diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c > index e79a24b821..36492aa0d9 100644 > --- a/hw/acpi/pcihp.c > +++ b/hw/acpi/pcihp.c > @@ -43,7 +43,6 @@ > #include "qobject/qnum.h" > #include "trace.h" > > -#define ACPI_PCIHP_SIZE 0x0018 > #define PCI_UP_BASE 0x0000 > #define PCI_DOWN_BASE 0x0004 > #define PCI_EJ_BASE 0x0008