aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/acpi/generic_event_device.c6
-rw-r--r--hw/loongarch/meson.build2
-rw-r--r--hw/loongarch/virt.c39
-rw-r--r--include/hw/acpi/generic_event_device.h7
-rw-r--r--include/hw/loongarch/virt.h1
-rw-r--r--target/loongarch/arch_dump.c6
6 files changed, 49 insertions, 12 deletions
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 15b4c3e..d00f5a6 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -201,9 +201,9 @@ static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data,
switch (addr) {
case ACPI_GED_REG_SLEEP_CTL:
- slp_typ = (data >> 2) & 0x07;
- slp_en = (data >> 5) & 0x01;
- if (slp_en && slp_typ == 5) {
+ slp_typ = (data >> ACPI_GED_SLP_TYP_POS) & ACPI_GED_SLP_TYP_MASK;
+ slp_en = !!(data & ACPI_GED_SLP_EN);
+ if (slp_en && slp_typ == ACPI_GED_SLP_TYP_S5) {
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
}
return;
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index bce7eba..005f017 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -1,8 +1,8 @@
loongarch_ss = ss.source_set()
loongarch_ss.add(files(
- 'fw_cfg.c',
'boot.c',
))
+common_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('fw_cfg.c'))
loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('virt.c'))
loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index ddd886f..9a635d1 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -280,6 +280,44 @@ static void fdt_add_rtc_node(LoongArchVirtMachineState *lvms,
g_free(nodename);
}
+static void fdt_add_ged_reset(LoongArchVirtMachineState *lvms)
+{
+ char *name;
+ uint32_t ged_handle;
+ MachineState *ms = MACHINE(lvms);
+ hwaddr base = VIRT_GED_REG_ADDR;
+ hwaddr size = ACPI_GED_REG_COUNT;
+
+ ged_handle = qemu_fdt_alloc_phandle(ms->fdt);
+ name = g_strdup_printf("/ged@%" PRIx64, base);
+ qemu_fdt_add_subnode(ms->fdt, name);
+ qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon");
+ qemu_fdt_setprop_cells(ms->fdt, name, "reg", 0x0, base, 0x0, size);
+ /* 8 bit registers */
+ qemu_fdt_setprop_cell(ms->fdt, name, "reg-shift", 0);
+ qemu_fdt_setprop_cell(ms->fdt, name, "reg-io-width", 1);
+ qemu_fdt_setprop_cell(ms->fdt, name, "phandle", ged_handle);
+ ged_handle = qemu_fdt_get_phandle(ms->fdt, name);
+ g_free(name);
+
+ name = g_strdup_printf("/reboot");
+ qemu_fdt_add_subnode(ms->fdt, name);
+ qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-reboot");
+ qemu_fdt_setprop_cell(ms->fdt, name, "regmap", ged_handle);
+ qemu_fdt_setprop_cell(ms->fdt, name, "offset", ACPI_GED_REG_RESET);
+ qemu_fdt_setprop_cell(ms->fdt, name, "value", ACPI_GED_RESET_VALUE);
+ g_free(name);
+
+ name = g_strdup_printf("/poweroff");
+ qemu_fdt_add_subnode(ms->fdt, name);
+ qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-poweroff");
+ qemu_fdt_setprop_cell(ms->fdt, name, "regmap", ged_handle);
+ qemu_fdt_setprop_cell(ms->fdt, name, "offset", ACPI_GED_REG_SLEEP_CTL);
+ qemu_fdt_setprop_cell(ms->fdt, name, "value", ACPI_GED_SLP_EN |
+ (ACPI_GED_SLP_TYP_S5 << ACPI_GED_SLP_TYP_POS));
+ g_free(name);
+}
+
static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
uint32_t *pch_pic_phandle, hwaddr base,
int irq, bool chosen)
@@ -737,6 +775,7 @@ static void virt_devices_init(DeviceState *pch_pic,
qdev_get_gpio_in(pch_pic,
VIRT_RTC_IRQ - VIRT_GSI_BASE));
fdt_add_rtc_node(lvms, pch_pic_phandle);
+ fdt_add_ged_reset(lvms);
/* acpi ged */
lvms->acpi_ged = create_acpi_ged(pch_pic, lvms);
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 40af355..d2dac87 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -81,8 +81,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
/* ACPI_GED_REG_RESET value for reset*/
#define ACPI_GED_RESET_VALUE 0x42
-/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */
-#define ACPI_GED_SLP_TYP_S5 0x05
+/* [ACPI 5.0 Chapter 4.8.3.7] Sleep Control and Status Register */
+#define ACPI_GED_SLP_TYP_POS 0x2 /* SLP_TYPx Bit Offset */
+#define ACPI_GED_SLP_TYP_MASK 0x07 /* SLP_TYPx 3-bit mask */
+#define ACPI_GED_SLP_TYP_S5 0x05 /* System _S5 State (Soft Off) */
+#define ACPI_GED_SLP_EN 0x20 /* SLP_EN write-only bit */
#define GED_DEVICE "GED"
#define AML_GED_EVT_REG "EREG"
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index c373e48..9ba4779 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -8,7 +8,6 @@
#ifndef HW_LOONGARCH_H
#define HW_LOONGARCH_H
-#include "target/loongarch/cpu.h"
#include "hw/boards.h"
#include "qemu/queue.h"
#include "hw/block/flash.h"
diff --git a/target/loongarch/arch_dump.c b/target/loongarch/arch_dump.c
index 4986db9..d9e1120 100644
--- a/target/loongarch/arch_dump.c
+++ b/target/loongarch/arch_dump.c
@@ -97,11 +97,7 @@ static int loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f,
loongarch_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu));
note.fpu.fcsr = cpu_to_dump64(s, env->fcsr0);
-
- for (i = 0; i < 8; i++) {
- note.fpu.fcc |= env->cf[i] << (8 * i);
- }
- note.fpu.fcc = cpu_to_dump64(s, note.fpu.fcc);
+ note.fpu.fcc = cpu_to_dump64(s, read_fcc(env));
for (i = 0; i < 32; ++i) {
note.fpu.fpr[i] = cpu_to_dump64(s, env->fpr[i].vreg.UD[0]);