hw/riscv/Kconfig | 1 +
hw/riscv/virt-acpi-build.c | 10 ++++++
hw/riscv/virt.c | 35 +++++++++++++++++++++
include/hw/riscv/virt.h | 4 +++
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
5 files changed, 51 insertions(+)
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index fc9c35bd98..f89a6e3672 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 f1406cb683..64fd8aa426 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 17909206c7..a853184105 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 },
@@ -1270,6 +1273,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;
@@ -1428,6 +1447,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,
@@ -1701,6 +1728,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);
+ }
+
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);
@@ -1742,6 +1774,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/qtest/bios-tables-test-allowed-diff.h
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..8e85fcdee9 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/riscv64/virt/DSDT",