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^
> >

Reply via email to