diff options
author | Jiaxun Yang <jiaxun.yang@flygoat.com> | 2024-05-08 10:31:09 +0100 |
---|---|---|
committer | Philippe Mathieu-Daudé <philmd@linaro.org> | 2024-05-09 00:07:21 +0200 |
commit | 5b1a3b9f8c0fbcd2420977678601948d7573c809 (patch) | |
tree | 5b8cc0f07f4b71c8d49ad10e86aa8af3ceef0202 /hw/mips | |
parent | d804ad98f51cc6ae795ff9c9890db66bae513214 (diff) | |
download | qemu-5b1a3b9f8c0fbcd2420977678601948d7573c809.zip qemu-5b1a3b9f8c0fbcd2420977678601948d7573c809.tar.gz qemu-5b1a3b9f8c0fbcd2420977678601948d7573c809.tar.bz2 |
hw/mips/loongson3_virt: Emulate suspend function
Suspend function is emulated as what hardware actually do.
Doorbell register fields are updates to include suspend value,
suspend vector is encoded in firmware blob and fw_cfg is updated
to include S3 bits as what x86 did.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Message-ID: <20240508-loongson3v-suspend-v1-1-186725524a39@flygoat.com>
[PMD: Use g_memdup2(), constify suspend array]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Diffstat (limited to 'hw/mips')
-rw-r--r-- | hw/mips/loongson3_bootp.c | 1 | ||||
-rw-r--r-- | hw/mips/loongson3_virt.c | 20 |
2 files changed, 21 insertions, 0 deletions
diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c index f99af22..03a10b6 100644 --- a/hw/mips/loongson3_bootp.c +++ b/hw/mips/loongson3_bootp.c @@ -148,4 +148,5 @@ void init_reset_system(struct efi_reset_system_t *reset) reset->Shutdown = cpu_to_le64(0xffffffffbfc000a8); reset->ResetCold = cpu_to_le64(0xffffffffbfc00080); reset->ResetWarm = cpu_to_le64(0xffffffffbfc00080); + reset->DoSuspend = cpu_to_le64(0xffffffffbfc000d0); } diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index b10a611..440268a 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -127,6 +127,9 @@ static void loongson3_pm_write(void *opaque, hwaddr addr, case 0x00: qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; + case 0x01: + qemu_system_suspend_request(); + return; case 0xff: qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); return; @@ -250,6 +253,17 @@ static void init_boot_rom(void) 0x240D00FF, /* li t1, 0xff */ 0xA18D0000, /* sb t1, (t0) */ 0x1000FFFF, /* 1: b 1b */ + 0x00000000, /* nop */ + /* Suspend */ + 0x3C0C9000, /* dli t0, 0x9000000010080010 */ + 0x358C0000, + 0x000C6438, + 0x358C1008, + 0x000C6438, + 0x358C0010, + 0x240D0001, /* li t1, 0x01 */ + 0xA18D0000, /* sb t1, (t0) */ + 0x03e00008, /* jr ra */ 0x00000000 /* nop */ }; @@ -265,6 +279,7 @@ static void fw_cfg_boot_set(void *opaque, const char *boot_device, static void fw_conf_init(unsigned long ram_size) { + static const uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; FWCfgState *fw_cfg; hwaddr cfg_addr = virt_memmap[VIRT_FW_CFG].base; @@ -274,6 +289,10 @@ static void fw_conf_init(unsigned long ram_size) fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz()); + + fw_cfg_add_file(fw_cfg, "etc/system-states", + g_memdup2(suspend, sizeof(suspend)), sizeof(suspend)); + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } @@ -553,6 +572,7 @@ static void mips_loongson3_virt_init(MachineState *machine) machine->ram, 0, virt_memmap[VIRT_LOWMEM].size); memory_region_init_io(iomem, NULL, &loongson3_pm_ops, NULL, "loongson3_pm", virt_memmap[VIRT_PM].size); + qemu_register_wakeup_support(); memory_region_add_subregion(address_space_mem, virt_memmap[VIRT_LOWMEM].base, ram); |