diff --git a/hw/acpi.c b/hw/acpi.c
index 5d521e5..effc7ec 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 fe8cdb4..7337f41 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 585da4e..ce1f5af 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;
@@ -421,7 +426,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, uint16_t fw_cfg_key)
 {
     PCIDevice *dev;
     PIIX4PMState *s;
@@ -437,11 +442,23 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     qdev_init_nofail(&dev->qdev);
 
+    if (fw_cfg_key != FW_CFG_INVALID) {
+        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_bytes(fw_cfg_key, 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 4752bb2..5f0f5b6 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -48,6 +48,7 @@
 #include "blockdev.h"
 #include "exec-memory.h"
 #include "sysbus.h"             /* SysBusDevice */
+#include "fw_cfg.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -954,7 +955,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, FW_CFG_INVALID);
     /* 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 5d28d3b..3a2c2d2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -29,7 +29,6 @@
 #include "pci.h"
 #include "vmware_vga.h"
 #include "monitor.h"
-#include "fw_cfg.h"
 #include "hpet_emul.h"
 #include "smbios.h"
 #include "loader.h"
@@ -64,11 +63,6 @@
 /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
 #define ACPI_DATA_SIZE       0x10000
 #define BIOS_CFG_IOPORT 0x510
-#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
-#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
-#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
-#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
-#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
 
 #define MSI_ADDR_BASE 0xfee00000
 
diff --git a/hw/pc.h b/hw/pc.h
index 74d3369..4d23712 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -9,6 +9,7 @@
 #include "net.h"
 #include "memory.h"
 #include "ioapic.h"
+#include "fw_cfg.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -142,7 +143,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, uint16_t fw_cfg_key);
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 
 /* hpet.c */
@@ -227,4 +228,11 @@ void pc_system_firmware_init(MemoryRegion *rom_memory);
 
 int e820_add_entry(uint64_t, uint64_t, uint32_t);
 
+#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
+#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
+#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
+#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
+#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
+#define FW_CFG_SYSTEM_STATES (FW_CFG_ARCH_LOCAL + 5)
+
 #endif
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 6a75718..6bd2791 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -280,7 +280,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_SYSTEM_STATES);
         smbus_eeprom_init(smbus, 8, NULL, 0);
     }
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 6fb7950..5d7c00c 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;
