diff --git a/hw/acpi.c b/hw/acpi.c index 5d521e51331e5a5b83e0a9aea404da00181c83e0..effc7ec23ebccb17ae782a656e76a1c2e792d7c9 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -370,7 +370,7 @@ void acpi_pm1_cnt_init(ACPIREGS *ar) qemu_register_wakeup_notifier(&ar->wakeup); } -void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) +void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4) { ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); @@ -385,6 +385,9 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) qemu_system_suspend_request(); break; default: + if (sus_typ == s4) { /* S4 request */ + qemu_system_shutdown_request(); + } break; } } diff --git a/hw/acpi.h b/hw/acpi.h index fe8cdb48e09d036c156f8c4cc295820d7c3fca77..7337f418577415c2652cb09b95e0720cda97abef 100644 --- a/hw/acpi.h +++ b/hw/acpi.h @@ -139,7 +139,7 @@ void acpi_pm1_evt_reset(ACPIREGS *ar); /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */ void acpi_pm1_cnt_init(ACPIREGS *ar); -void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val); +void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4); void acpi_pm1_cnt_update(ACPIREGS *ar, bool sci_enable, bool sci_disable); void acpi_pm1_cnt_reset(ACPIREGS *ar); diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index a11c8e7ae05eadfcf67993daa02d58a9c9bab121..0aace60f24febff284b9e60f1490185287385e1b 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -27,6 +27,7 @@ #include "sysemu.h" #include "range.h" #include "ioport.h" +#include "fw_cfg.h" //#define DEBUG @@ -71,6 +72,10 @@ typedef struct PIIX4PMState { struct pci_status pci0_status; uint32_t pci0_hotplug_enable; uint32_t pci0_slot_device_present; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; } PIIX4PMState; static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s); @@ -123,7 +128,7 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, pm_update_sci(s); break; case 0x04: - acpi_pm1_cnt_write(&s->ar, val); + acpi_pm1_cnt_write(&s->ar, val, s->s4_val); break; default: break; @@ -424,7 +429,7 @@ static int piix4_pm_initfn(PCIDevice *dev) i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled) + int kvm_enabled, void *fw_cfg) { PCIDevice *dev; PIIX4PMState *s; @@ -440,11 +445,22 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qdev_init_nofail(&dev->qdev); + if (fw_cfg) { + uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; + suspend[3] = 1 | ((!s->disable_s3) << 7); + suspend[4] = s->s4_val | ((!s->disable_s4) << 7); + + fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); + } + return s->smb.smbus; } static Property piix4_pm_properties[] = { DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), + DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0), + DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0), + DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/mips_malta.c b/hw/mips_malta.c index dfd7b6b11369e30465fbc6dac663b1ae50526bd4..351c88ebca3153d3e3ef6a636651bb0ce76e34ef 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -959,7 +959,7 @@ void mips_malta_init (ram_addr_t ram_size, pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, - isa_get_irq(NULL, 9), NULL, 0); + isa_get_irq(NULL, 9), NULL, 0, NULL); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(smbus, 8, NULL, 0); pit = pit_init(isa_bus, 0x40, 0, NULL); diff --git a/hw/pc.c b/hw/pc.c index 8368701efb8100be63e542a9385cadb9a79ba1af..c7e9ab3ee139666c645cfead073f521b557ff8d2 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -970,7 +970,7 @@ void pc_cpus_init(const char *cpu_model) } } -void pc_memory_init(MemoryRegion *system_memory, +void *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, @@ -1029,6 +1029,7 @@ void pc_memory_init(MemoryRegion *system_memory, for (i = 0; i < nb_option_roms; i++) { rom_add_option(option_rom[i].name, option_rom[i].bootindex); } + return fw_cfg; } qemu_irq *pc_allocate_cpu_irq(void) diff --git a/hw/pc.h b/hw/pc.h index 74d3369a1272bc7f466ec527c1413b8f6fae6886..31ccb6f49527ae955fc2f831b394d2fe61ed436f 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -106,7 +106,7 @@ void pc_register_ferr_irq(qemu_irq irq); void pc_acpi_smi_interrupt(void *opaque, int irq, int level); void pc_cpus_init(const char *cpu_model); -void pc_memory_init(MemoryRegion *system_memory, +void *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, @@ -142,7 +142,7 @@ int acpi_table_add(const char *table_desc); i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled); + int kvm_enabled, void *fw_cfg); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); /* hpet.c */ diff --git a/hw/pc_piix.c b/hw/pc_piix.c index d68f77a9c04fb6f48d0819df743f8f6a6753b488..b7e90a82989d3041c0471d67f8d129e7ec87eca3 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -147,6 +147,7 @@ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *ram_memory; MemoryRegion *pci_memory; MemoryRegion *rom_memory; + void *fw_cfg = NULL; pc_cpus_init(cpu_model); @@ -173,7 +174,7 @@ static void pc_init1(MemoryRegion *system_memory, /* allocate ram and load rom/bios */ if (!xen_enabled()) { - pc_memory_init(system_memory, + fw_cfg = pc_memory_init(system_memory, kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, pci_enabled ? rom_memory : system_memory, &ram_memory); @@ -277,7 +278,7 @@ static void pc_init1(MemoryRegion *system_memory, /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, - kvm_enabled()); + kvm_enabled(), fw_cfg); smbus_eeprom_init(smbus, 8, NULL, 0); } diff --git a/hw/vt82c686.c b/hw/vt82c686.c index 6fb7950fa6f53a0f8ef9dc3e1286d01089db3972..5d7c00cf4b91a2733e0e3ba668107cbb1611a9ef 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -210,7 +210,7 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) pm_update_sci(s); break; case 0x04: - acpi_pm1_cnt_write(&s->ar, val); + acpi_pm1_cnt_write(&s->ar, val, 0); break; default: break;