diff --git a/hw/acpi.c b/hw/acpi.c
index 407949b..7b16716 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -248,6 +248,22 @@ int acpi_table_add(const char *t)
 
 }
 
+static void acpi_notify_wakeup(Notifier *notifier, void *data)
+{
+    ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup);
+    WakeupReason *reason = data;
+
+    switch (*reason) {
+    case QEMU_WAKEUP_REASON_OTHER:
+    default:
+        /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+           Pretend that resume was caused by power button */
+        ar->pm1.evt.sts |=
+            (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
+        break;
+    }
+}
+
 /* ACPI PM1a EVT */
 uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar)
 {
@@ -333,9 +349,10 @@ void acpi_pm_tmr_reset(ACPIREGS *ar)
 }
 
 /* ACPI PM1aCNT */
-void acpi_pm1_cnt_init(ACPIREGS *ar, qemu_irq cmos_s3)
+void acpi_pm1_cnt_init(ACPIREGS *ar)
 {
-    ar->pm1.cnt.cmos_s3 = cmos_s3;
+    ar->wakeup.notify = acpi_notify_wakeup;
+    qemu_register_wakeup_notifier(&ar->wakeup);
 }
 
 void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
@@ -350,12 +367,8 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
             qemu_system_shutdown_request();
             break;
         case 1:
-            /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
-               Pretend that resume was caused by power button */
-            ar->pm1.evt.sts |=
-                (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
-            qemu_system_reset_request();
-            qemu_irq_raise(ar->pm1.cnt.cmos_s3);
+            qemu_system_suspend_request();
+            break;
         default:
             break;
         }
@@ -376,9 +389,6 @@ void acpi_pm1_cnt_update(ACPIREGS *ar,
 void acpi_pm1_cnt_reset(ACPIREGS *ar)
 {
     ar->pm1.cnt.cnt = 0;
-    if (ar->pm1.cnt.cmos_s3) {
-        qemu_irq_lower(ar->pm1.cnt.cmos_s3);
-    }
 }
 
 /* ACPI GPE */
diff --git a/hw/acpi.h b/hw/acpi.h
index 88f8051..fe8cdb4 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -96,7 +96,6 @@ struct ACPIPM1EVT {
 
 struct ACPIPM1CNT {
     uint16_t cnt;
-    qemu_irq cmos_s3;
 };
 
 struct ACPIGPE {
@@ -114,6 +113,7 @@ struct ACPIREGS {
         ACPIPM1EVT  evt;
         ACPIPM1CNT  cnt;
     } pm1;
+    Notifier wakeup;
 };
 
 /* PM_TMR */
@@ -138,7 +138,7 @@ void acpi_pm1_evt_power_down(ACPIREGS *ar);
 void acpi_pm1_evt_reset(ACPIREGS *ar);
 
 /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
-void acpi_pm1_cnt_init(ACPIREGS *ar, qemu_irq cmos_s3);
+void acpi_pm1_cnt_init(ACPIREGS *ar);
 void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val);
 void acpi_pm1_cnt_update(ACPIREGS *ar,
                          bool sci_enable, bool sci_disable);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 9c72e62..f7f0a47 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -372,7 +372,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 cmos_s3, qemu_irq smi_irq,
+                       qemu_irq sci_irq, qemu_irq smi_irq,
                        int kvm_enabled)
 {
     PCIDevice *dev;
@@ -383,7 +383,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     s = DO_UPCAST(PIIX4PMState, dev, dev);
     s->irq = sci_irq;
-    acpi_pm1_cnt_init(&s->ar, cmos_s3);
+    acpi_pm1_cnt_init(&s->ar);
     s->smi_irq = smi_irq;
     s->kvm_enabled = kvm_enabled;
 
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 4a43225..314ed52 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -102,6 +102,7 @@ typedef struct RTCState {
     QEMUTimer *second_timer2;
     Notifier clock_reset_notifier;
     LostTickPolicy lost_tick_policy;
+    Notifier suspend_notifier;
 } RTCState;
 
 static void rtc_set_time(RTCState *s);
@@ -596,6 +597,14 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
 #endif
 }
 
+/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
+   BIOS will read it and start S3 resume at POST Entry */
+static void rtc_notify_suspend(Notifier *notifier, void *data)
+{
+    RTCState *s = container_of(notifier, RTCState, suspend_notifier);
+    rtc_set_memory(&s->dev, 0xF, 0xFE);
+}
+
 static void rtc_reset(void *opaque)
 {
     RTCState *s = opaque;
@@ -676,6 +685,9 @@ static int rtc_initfn(ISADevice *dev)
     s->clock_reset_notifier.notify = rtc_notify_clock_reset;
     qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
 
+    s->suspend_notifier.notify = rtc_notify_suspend;
+    qemu_register_suspend_notifier(&s->suspend_notifier);
+
     s->next_second_time =
         qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
     qemu_mod_timer(s->second_timer2, s->next_second_time);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index d232630..fe02c93 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -966,7 +966,7 @@ void mips_malta_init (ram_addr_t ram_size,
     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
-                          isa_get_irq(NULL, 9), NULL, NULL, 0);
+                          isa_get_irq(NULL, 9), NULL, 0);
     /* TODO: Populate SPD eeprom data.  */
     smbus_eeprom_init(smbus, 8, NULL, 0);
     pit = pit_init(isa_bus, 0x40, 0);
diff --git a/hw/pc.c b/hw/pc.c
index 7f3aa65..7b93aee 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -915,17 +915,6 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
     return dev;
 }
 
-/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
-   BIOS will read it and start S3 resume at POST Entry */
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
-{
-    ISADevice *s = opaque;
-
-    if (level) {
-        rtc_set_memory(s, 0xF, 0xFE);
-    }
-}
-
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 {
     CPUState *s = opaque;
diff --git a/hw/pc.h b/hw/pc.h
index c666ec9..571c915 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -128,7 +128,6 @@ void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out);
 extern int fd_bootchk;
 
 void pc_register_ferr_irq(qemu_irq irq);
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model);
@@ -167,7 +166,7 @@ int acpi_table_add(const char *table_desc);
 /* acpi_piix.c */
 
 i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
-                       qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
+                       qemu_irq sci_irq, qemu_irq smi_irq,
                        int kvm_enabled);
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index c06f1b5..918f5ac 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -139,7 +139,6 @@ static void pc_init1(MemoryRegion *system_memory,
     qemu_irq *cpu_irq;
     qemu_irq *gsi;
     qemu_irq *i8259;
-    qemu_irq *cmos_s3;
     qemu_irq *smi_irq;
     GSIState *gsi_state;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
@@ -291,15 +290,10 @@ static void pc_init1(MemoryRegion *system_memory,
     if (pci_enabled && acpi_enabled) {
         i2c_bus *smbus;
 
-        if (!xen_enabled()) {
-            cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
-        } else {
-            cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
-        }
         smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
         /* TODO: Populate SPD eeprom data.  */
         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                              gsi[9], *cmos_s3, *smi_irq,
+                              gsi[9], *smi_irq,
                               kvm_enabled());
         smbus_eeprom_init(smbus, 8, NULL, 0);
     }
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index d8f4e26..75e29f8 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -444,7 +444,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
     apm_init(&s->apm, NULL, s);
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
-    acpi_pm1_cnt_init(&s->ar, NULL);
+    acpi_pm1_cnt_init(&s->ar);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
 
diff --git a/xen-all.c b/xen-all.c
index fd39168..b0ed1ed 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -89,6 +89,7 @@ typedef struct XenIOState {
     const XenPhysmap *log_for_dirtybit;
 
     Notifier exit;
+    Notifier suspend;
 } XenIOState;
 
 /* Xen specific function for piix pci */
@@ -121,12 +122,9 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
     }
 }
 
-void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
+static void xen_suspend_notifier(Notifier *notifier, void *data)
 {
-    pc_cmos_set_s3_resume(opaque, irq, level);
-    if (level) {
-        xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
-    }
+    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
 }
 
 /* Xen Interrupt Controller */
@@ -936,6 +934,9 @@ int xen_hvm_init(void)
     state->exit.notify = xen_exit_notifier;
     qemu_add_exit_notifier(&state->exit);
 
+    state->suspend.notify = xen_suspend_notifier;
+    qemu_register_suspend_notifier(&state->suspend);
+
     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
     DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
     state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
