On 7/1/25 2:00 AM, dbarb...@ventanamicro.com wrote: > > From: Xuemei Liu <liu.xuem...@zte.com.cn> > > > > This adds powerdown support by implementing the ACPI GED. > > > > Signed-off-by: Xuemei Liu <liu.xuem...@zte.com.cn> > > Co-authored-by: Björn Töpel <bj...@rivosinc.com> > > > > --- > > Changes in v3: > > - Added missing param to virt_is_acpi_enabled > > - Fixed failure of bios-tables-test > > > > hw/riscv/Kconfig | 1 + > > hw/riscv/virt-acpi-build.c | 10 +++++++++ > > hw/riscv/virt.c | 35 ++++++++++++++++++++++++++++++ > > include/hw/riscv/virt.h | 4 ++++ > > tests/data/acpi/riscv64/virt/DSDT | Bin 3576 -> 3719 bytes > > 5 files changed, 50 insertions(+) > > > > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig > > index e6a0ac1fa1..16837e0e8f 100644 > > --- a/hw/riscv/Kconfig > > +++ b/hw/riscv/Kconfig > > @@ -68,6 +68,7 @@ config RISCV_VIRT > > select PLATFORM_BUS > > select ACPI > > select ACPI_PCI > > + select ACPI_HW_REDUCED > > > > config SHAKTI_C > > bool > > diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c > > index 8b5683dbde..163533f9b8 100644 > > --- a/hw/riscv/virt-acpi-build.c > > +++ b/hw/riscv/virt-acpi-build.c > > @@ -27,6 +27,7 @@ > > #include "hw/acpi/acpi-defs.h" > > #include "hw/acpi/acpi.h" > > #include "hw/acpi/aml-build.h" > > +#include "hw/acpi/generic_event_device.h" > > #include "hw/acpi/pci.h" > > #include "hw/acpi/utils.h" > > #include "hw/intc/riscv_aclint.h" > > @@ -498,6 +499,15 @@ static void build_dsdt(GArray *table_data, > > acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + > > VIRT_IRQCHIP_NUM_SOURCES * 2); > > } > > > > + if (s->acpi_ged) { > > + build_ged_aml(scope, "\\_SB."GED_DEVICE, > > + HOTPLUG_HANDLER(s->acpi_ged), > > + ACPI_GED_IRQ, AML_SYSTEM_MEMORY, > > + s->memmap[VIRT_ACPI_GED].base); > > + } > > + > > + acpi_dsdt_add_power_button(scope); > > + > > aml_append(dsdt, scope); > > > > /* copy AML table into ACPI tables blob and patch header there */ > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > > index cf280a92e5..43b4ab0dc1 100644 > > --- a/hw/riscv/virt.c > > +++ b/hw/riscv/virt.c > > @@ -51,10 +51,12 @@ > > #include "system/kvm.h" > > #include "system/tpm.h" > > #include "system/qtest.h" > > +#include "system/runstate.h" > > #include "hw/pci/pci.h" > > #include "hw/pci-host/gpex.h" > > #include "hw/display/ramfb.h" > > #include "hw/acpi/aml-build.h" > > +#include "hw/acpi/generic_event_device.h" > > #include "qapi/qapi-visit-common.h" > > #include "hw/virtio/virtio-iommu.h" > > #include "hw/uefi/var-service-api.h" > > @@ -95,6 +97,7 @@ static const MemMapEntry virt_memmap[] = { > > [VIRT_UART0] = { 0x10000000, 0x100 }, > > [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, > > [VIRT_FW_CFG] = { 0x10100000, 0x18 }, > > + [VIRT_ACPI_GED] = { 0x10101000, ACPI_GED_EVT_SEL_LEN }, > > [VIRT_FLASH] = { 0x20000000, 0x4000000 }, > > [VIRT_IMSIC_M] = { 0x24000000, VIRT_IMSIC_MAX_SIZE }, > > [VIRT_IMSIC_S] = { 0x28000000, VIRT_IMSIC_MAX_SIZE }, > > @@ -1272,6 +1275,22 @@ static inline DeviceState > > *gpex_pcie_init(MemoryRegion *sys_mem, > > return dev; > > } > > > > +static DeviceState *create_acpi_ged(RISCVVirtState *s, DeviceState > > *irqchip) > > +{ > > + DeviceState *dev; > > + uint32_t event = ACPI_GED_PWR_DOWN_EVT; > > + > > + dev = qdev_new(TYPE_ACPI_GED); > > + qdev_prop_set_uint32(dev, "ged-event", event); > > + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); > > + > > + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, s->memmap[VIRT_ACPI_GED].base); > > + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, > > + qdev_get_gpio_in(irqchip, ACPI_GED_IRQ)); > > + > > + return dev; > > +} > > + > > static FWCfgState *create_fw_cfg(const MachineState *ms, hwaddr base) > > { > > FWCfgState *fw_cfg; > > @@ -1430,6 +1449,14 @@ static void virt_build_smbios(RISCVVirtState *s) > > } > > } > > > > +static void virt_powerdown_req(Notifier *notifier, void *opaque) > > +{ > > + RISCVVirtState *s; > > + > > + s = container_of(notifier, RISCVVirtState, powerdown_notifier); > > + acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS); > > +} > > + > > static void virt_machine_done(Notifier *notifier, void *data) > > { > > RISCVVirtState *s = container_of(notifier, RISCVVirtState, > > @@ -1703,6 +1730,11 @@ static void virt_machine_init(MachineState *machine) > > > > create_platform_bus(s, mmio_irqchip); > > > > + /* acpi ged */ > > + if (virt_is_acpi_enabled(s)) { > > + s->acpi_ged = create_acpi_ged(s, mmio_irqchip); > > + } > > + > > Is there a reason to create this ACPI device here at machine_init() instead of > machine_done() time, before virt_acpi_setup()? > > > if (virt_is_acpi_enabled(s)) { > > + s->acpi_ged = create_acpi_ged(s, mmio_irqchip); > virt_acpi_setup(s); > } > > > Thanks, > > Daniel >
Hi Daniel, I think it's necessary to create acpi_ged device at virt_machine_init() rather than virt_machine_down(), as I think this better aligns with QEMU's design. Best regards, Jessica > > > serial_mm_init(system_memory, s->memmap[VIRT_UART0].base, > > 0, qdev_get_gpio_in(mmio_irqchip, UART0_IRQ), 399193, > > serial_hd(0), DEVICE_LITTLE_ENDIAN); > > @@ -1744,6 +1776,9 @@ static void virt_machine_init(MachineState *machine) > > sysbus_realize_and_unref(SYS_BUS_DEVICE(iommu_sys), &error_fatal); > > } > > > > + s->powerdown_notifier.notify = virt_powerdown_req; > > + qemu_register_powerdown_notifier(&s->powerdown_notifier); > > + > > s->machine_done.notify = virt_machine_done; > > qemu_add_machine_init_done_notifier(&s->machine_done); > > } > > diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h > > index 7b4c2c8b7d..9422b45d0c 100644 > > --- a/include/hw/riscv/virt.h > > +++ b/include/hw/riscv/virt.h > > @@ -47,6 +47,8 @@ struct RISCVVirtState { > > > > /*< public >*/ > > Notifier machine_done; > > + Notifier powerdown_notifier; > > + DeviceState *acpi_ged; > > DeviceState *platform_bus_dev; > > RISCVHartArrayState soc[VIRT_SOCKETS_MAX]; > > DeviceState *irqchip[VIRT_SOCKETS_MAX]; > > @@ -88,9 +90,11 @@ enum { > > VIRT_PLATFORM_BUS, > > VIRT_PCIE_ECAM, > > VIRT_IOMMU_SYS, > > + VIRT_ACPI_GED, > > }; > > > > enum { > > + ACPI_GED_IRQ = 9, > > UART0_IRQ = 10, > > RTC_IRQ = 11, > > VIRTIO_IRQ = 1, /* 1 to 8 */ > > diff --git a/tests/data/acpi/riscv64/virt/DSDT > > b/tests/data/acpi/riscv64/virt/DSDT > > index > > 6a33f5647ddd6de3a0f000f718b58f6fff44f0fd..b167a850026d392eaa6da85562c442945e238208 > > 100644 > > GIT binary patch > > delta 170 > > zcmew%-7d@J66_Mv&d0#O<T;T`n#t+eM)ixl_0dgE>@j-r!A|k+t}gK$@gANoypGNR > > zo(2Yn#ta<sp+GKB0?2X>3Krz!;_hT)U}ofGU|^_Zh;DEVa&>3mVGs}y;9`kx<OXq_ > > zU4vbH6hvg>UBf~+3qYKN1p<?+6S$ZdxR}}k!h@W+8lsydK@5;(0xrA(egOu~2F?)6 > > F7y$P$D2D(5 > > > > delta 25 > > gcmZpd{UOce66_N4gO`DUsc0gXG?Vk)jp`S90cJM`_y7O^ > >