qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/11] initial suspend support
@ 2012-02-09 17:05 Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 01/11] acpi: move around structs Gerd Hoffmann
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

  Hi,

Next round, this time with a proper acpi integration as auggested by
gleb.  Also features some acpi cleanup bits.  New is pmtimer support,
which is not tested yet though.  Commit messages are still a bit rougth,
but I expect I'll need a v5 anyway so I try to get that one quickly out
of the door for review, especially on the infrastructure bits (patch #5
now).

cheers,
  Gerd

Gerd Hoffmann (11):
  acpi: move around structs
  acpi: add ACPIREGS
  acpi: don't pass overflow_time to acpi_pm1_evt_get_sts
  acpi: add acpi_pm1_evt_write_en
  suspend: add infrastructure
  suspend: switch acpi s3 to new infrastructure.
  suspend: add system_wakeup monitor command
  suspend: make ps/2 devices wakeup the guest
  suspend: make serial ports wakeup the guest.
  suspend: make rtc alarm wakeup the guest.
  suspend: pmtimer s3 wakeup

 hmp-commands.hx  |   14 +++++
 hmp.c            |    5 ++
 hmp.h            |    1 +
 hw/acpi.c        |  172 +++++++++++++++++++++++++++++++-----------------------
 hw/acpi.h        |   93 ++++++++++++++++-------------
 hw/acpi_piix4.c  |   70 ++++++++++------------
 hw/mc146818rtc.c |   13 ++++
 hw/mips_malta.c  |    2 +-
 hw/pc.c          |   11 ----
 hw/pc.h          |    3 +-
 hw/pc_piix.c     |    8 +--
 hw/ps2.c         |    6 ++
 hw/serial.c      |    6 ++
 hw/vt82c686.c    |   42 ++++++-------
 qapi-schema.json |   11 ++++
 qmp-commands.hx  |   21 +++++++
 qmp.c            |    5 ++
 sysemu.h         |   11 ++++
 vl.c             |   49 +++++++++++++++
 xen-all.c        |   11 ++--
 20 files changed, 355 insertions(+), 199 deletions(-)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 01/11] acpi: move around structs
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 02/11] acpi: add ACPIREGS Gerd Hoffmann
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/acpi.h |   48 +++++++++++++++++++++++-------------------------
 1 files changed, 23 insertions(+), 25 deletions(-)

diff --git a/hw/acpi.h b/hw/acpi.h
index c141e65..5c43b7d 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -73,9 +73,11 @@
 /* PM2_CNT */
 #define ACPI_BITMASK_ARB_DISABLE                0x0001
 
-/* PM_TMR */
-struct ACPIPMTimer;
+/* structs */
 typedef struct ACPIPMTimer ACPIPMTimer;
+typedef struct ACPIPM1EVT ACPIPM1EVT;
+typedef struct ACPIPM1CNT ACPIPM1CNT;
+typedef struct ACPIGPE ACPIGPE;
 
 typedef void (*acpi_update_sci_fn)(ACPIPMTimer *tmr);
 
@@ -86,6 +88,25 @@ struct ACPIPMTimer {
     acpi_update_sci_fn update_sci;
 };
 
+struct ACPIPM1EVT {
+    uint16_t sts;
+    uint16_t en;
+};
+
+struct ACPIPM1CNT {
+    uint16_t cnt;
+    qemu_irq cmos_s3;
+};
+
+struct ACPIGPE {
+    uint32_t blk;
+    uint8_t len;
+
+    uint8_t *sts;
+    uint8_t *en;
+};
+
+/* PM_TMR */
 void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable);
 void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr);
 uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr);
@@ -100,26 +121,12 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
 }
 
 /* PM1a_EVT: piix and ich9 don't implement PM1b. */
-struct ACPIPM1EVT
-{
-    uint16_t sts;
-    uint16_t en;
-};
-typedef struct ACPIPM1EVT ACPIPM1EVT;
-
 uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time);
 void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val);
 void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr);
 void acpi_pm1_evt_reset(ACPIPM1EVT *pm1);
 
 /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
-struct ACPIPM1CNT {
-    uint16_t cnt;
-
-    qemu_irq cmos_s3;
-};
-typedef struct ACPIPM1CNT ACPIPM1CNT;
-
 void acpi_pm1_cnt_init(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3);
 void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val);
 void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
@@ -127,15 +134,6 @@ void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
 void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt);
 
 /* GPE0 */
-struct ACPIGPE {
-    uint32_t blk;
-    uint8_t len;
-
-    uint8_t *sts;
-    uint8_t *en;
-};
-typedef struct ACPIGPE ACPIGPE;
-
 void acpi_gpe_init(ACPIGPE *gpe, uint8_t len);
 void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk);
 void acpi_gpe_reset(ACPIGPE *gpe);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 02/11] acpi: add ACPIREGS
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 01/11] acpi: move around structs Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 03/11] acpi: don't pass overflow_time to acpi_pm1_evt_get_sts Gerd Hoffmann
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

bundle acpi structs there, use it everythere pass around acpi state.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/acpi.c       |  130 +++++++++++++++++++++++++++----------------------------
 hw/acpi.h       |   48 ++++++++++++--------
 hw/acpi_piix4.c |   68 +++++++++++++---------------
 hw/vt82c686.c   |   42 ++++++++---------
 4 files changed, 145 insertions(+), 143 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 79b179b..1922e53 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -249,63 +249,61 @@ int acpi_table_add(const char *t)
 }
 
 /* ACPI PM1a EVT */
-uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time)
+uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar, int64_t overflow_time)
 {
     int64_t d = acpi_pm_tmr_get_clock();
     if (d >= overflow_time) {
-        pm1->sts |= ACPI_BITMASK_TIMER_STATUS;
+        ar->pm1.evt.sts |= ACPI_BITMASK_TIMER_STATUS;
     }
-    return pm1->sts;
+    return ar->pm1.evt.sts;
 }
 
-void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val)
+void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
 {
-    uint16_t pm1_sts = acpi_pm1_evt_get_sts(pm1, tmr->overflow_time);
+    uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar, ar->tmr.overflow_time);
     if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
         /* if TMRSTS is reset, then compute the new overflow time */
-        acpi_pm_tmr_calc_overflow_time(tmr);
+        acpi_pm_tmr_calc_overflow_time(ar);
     }
-    pm1->sts &= ~val;
+    ar->pm1.evt.sts &= ~val;
 }
 
-void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr)
+void acpi_pm1_evt_power_down(ACPIREGS *ar)
 {
-    if (!pm1) {
-        qemu_system_shutdown_request();
-    } else if (pm1->en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
-        pm1->sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
-        tmr->update_sci(tmr);
+    if (ar->pm1.evt.en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+        ar->pm1.evt.sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
+        ar->tmr.update_sci(ar);
     }
 }
 
-void acpi_pm1_evt_reset(ACPIPM1EVT *pm1)
+void acpi_pm1_evt_reset(ACPIREGS *ar)
 {
-    pm1->sts = 0;
-    pm1->en = 0;
+    ar->pm1.evt.sts = 0;
+    ar->pm1.evt.en = 0;
 }
 
 /* ACPI PM_TMR */
-void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable)
+void acpi_pm_tmr_update(ACPIREGS *ar, bool enable)
 {
     int64_t expire_time;
 
     /* schedule a timer interruption if needed */
     if (enable) {
-        expire_time = muldiv64(tmr->overflow_time, get_ticks_per_sec(),
+        expire_time = muldiv64(ar->tmr.overflow_time, get_ticks_per_sec(),
                                PM_TIMER_FREQUENCY);
-        qemu_mod_timer(tmr->timer, expire_time);
+        qemu_mod_timer(ar->tmr.timer, expire_time);
     } else {
-        qemu_del_timer(tmr->timer);
+        qemu_del_timer(ar->tmr.timer);
     }
 }
 
-void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr)
+void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar)
 {
     int64_t d = acpi_pm_tmr_get_clock();
-    tmr->overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+    ar->tmr.overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
 }
 
-uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
+uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
 {
     uint32_t d = acpi_pm_tmr_get_clock();
     return d & 0xffffff;
@@ -313,31 +311,31 @@ uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
 
 static void acpi_pm_tmr_timer(void *opaque)
 {
-    ACPIPMTimer *tmr = opaque;
-    tmr->update_sci(tmr);
+    ACPIREGS *ar = opaque;
+    ar->tmr.update_sci(ar);
 }
 
-void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci)
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci)
 {
-    tmr->update_sci = update_sci;
-    tmr->timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, tmr);
+    ar->tmr.update_sci = update_sci;
+    ar->tmr.timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, ar);
 }
 
-void acpi_pm_tmr_reset(ACPIPMTimer *tmr)
+void acpi_pm_tmr_reset(ACPIREGS *ar)
 {
-    tmr->overflow_time = 0;
-    qemu_del_timer(tmr->timer);
+    ar->tmr.overflow_time = 0;
+    qemu_del_timer(ar->tmr.timer);
 }
 
 /* ACPI PM1aCNT */
-void acpi_pm1_cnt_init(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3)
+void acpi_pm1_cnt_init(ACPIREGS *ar, qemu_irq cmos_s3)
 {
-    pm1_cnt->cmos_s3 = cmos_s3;
+    ar->pm1.cnt.cmos_s3 = cmos_s3;
 }
 
-void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val)
+void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
 {
-    pm1_cnt->cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+    ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
 
     if (val & ACPI_BITMASK_SLEEP_ENABLE) {
         /* change suspend type */
@@ -349,62 +347,62 @@ void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val)
         case 1:
             /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
                Pretend that resume was caused by power button */
-            pm1a->sts |=
+            ar->pm1.evt.sts |=
                 (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS);
             qemu_system_reset_request();
-            qemu_irq_raise(pm1_cnt->cmos_s3);
+            qemu_irq_raise(ar->pm1.cnt.cmos_s3);
         default:
             break;
         }
     }
 }
 
-void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
+void acpi_pm1_cnt_update(ACPIREGS *ar,
                          bool sci_enable, bool sci_disable)
 {
     /* ACPI specs 3.0, 4.7.2.5 */
     if (sci_enable) {
-        pm1_cnt->cnt |= ACPI_BITMASK_SCI_ENABLE;
+        ar->pm1.cnt.cnt |= ACPI_BITMASK_SCI_ENABLE;
     } else if (sci_disable) {
-        pm1_cnt->cnt &= ~ACPI_BITMASK_SCI_ENABLE;
+        ar->pm1.cnt.cnt &= ~ACPI_BITMASK_SCI_ENABLE;
     }
 }
 
-void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt)
+void acpi_pm1_cnt_reset(ACPIREGS *ar)
 {
-    pm1_cnt->cnt = 0;
-    if (pm1_cnt->cmos_s3) {
-        qemu_irq_lower(pm1_cnt->cmos_s3);
+    ar->pm1.cnt.cnt = 0;
+    if (ar->pm1.cnt.cmos_s3) {
+        qemu_irq_lower(ar->pm1.cnt.cmos_s3);
     }
 }
 
 /* ACPI GPE */
-void acpi_gpe_init(ACPIGPE *gpe, uint8_t len)
+void acpi_gpe_init(ACPIREGS *ar, uint8_t len)
 {
-    gpe->len = len;
-    gpe->sts = g_malloc0(len / 2);
-    gpe->en = g_malloc0(len / 2);
+    ar->gpe.len = len;
+    ar->gpe.sts = g_malloc0(len / 2);
+    ar->gpe.en = g_malloc0(len / 2);
 }
 
-void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk)
+void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk)
 {
-    gpe->blk = blk;
+    ar->gpe.blk = blk;
 }
 
-void acpi_gpe_reset(ACPIGPE *gpe)
+void acpi_gpe_reset(ACPIREGS *ar)
 {
-    memset(gpe->sts, 0, gpe->len / 2);
-    memset(gpe->en, 0, gpe->len / 2);
+    memset(ar->gpe.sts, 0, ar->gpe.len / 2);
+    memset(ar->gpe.en, 0, ar->gpe.len / 2);
 }
 
-static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
+static uint8_t *acpi_gpe_ioport_get_ptr(ACPIREGS *ar, uint32_t addr)
 {
     uint8_t *cur = NULL;
 
-    if (addr < gpe->len / 2) {
-        cur = gpe->sts + addr;
-    } else if (addr < gpe->len) {
-        cur = gpe->en + addr - gpe->len / 2;
+    if (addr < ar->gpe.len / 2) {
+        cur = ar->gpe.sts + addr;
+    } else if (addr < ar->gpe.len) {
+        cur = ar->gpe.en + addr - ar->gpe.len / 2;
     } else {
         abort();
     }
@@ -412,16 +410,16 @@ static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
     return cur;
 }
 
-void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val)
+void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val)
 {
     uint8_t *cur;
 
-    addr -= gpe->blk;
-    cur = acpi_gpe_ioport_get_ptr(gpe, addr);
-    if (addr < gpe->len / 2) {
+    addr -= ar->gpe.blk;
+    cur = acpi_gpe_ioport_get_ptr(ar, addr);
+    if (addr < ar->gpe.len / 2) {
         /* GPE_STS */
         *cur = (*cur) & ~val;
-    } else if (addr < gpe->len) {
+    } else if (addr < ar->gpe.len) {
         /* GPE_EN */
         *cur = val;
     } else {
@@ -429,13 +427,13 @@ void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val)
     }
 }
 
-uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr)
+uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
 {
     uint8_t *cur;
     uint32_t val;
 
-    addr -= gpe->blk;
-    cur = acpi_gpe_ioport_get_ptr(gpe, addr);
+    addr -= ar->gpe.blk;
+    cur = acpi_gpe_ioport_get_ptr(ar, addr);
     val = 0;
     if (cur != NULL) {
         val = *cur;
diff --git a/hw/acpi.h b/hw/acpi.h
index 5c43b7d..530c86a 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -78,8 +78,9 @@ typedef struct ACPIPMTimer ACPIPMTimer;
 typedef struct ACPIPM1EVT ACPIPM1EVT;
 typedef struct ACPIPM1CNT ACPIPM1CNT;
 typedef struct ACPIGPE ACPIGPE;
+typedef struct ACPIREGS ACPIREGS;
 
-typedef void (*acpi_update_sci_fn)(ACPIPMTimer *tmr);
+typedef void (*acpi_update_sci_fn)(ACPIREGS *ar);
 
 struct ACPIPMTimer {
     QEMUTimer *timer;
@@ -106,12 +107,21 @@ struct ACPIGPE {
     uint8_t *en;
 };
 
+struct ACPIREGS {
+    ACPIPMTimer     tmr;
+    ACPIGPE         gpe;
+    struct {
+        ACPIPM1EVT  evt;
+        ACPIPM1CNT  cnt;
+    } pm1;
+};
+
 /* PM_TMR */
-void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable);
-void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr);
-uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr);
-void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci);
-void acpi_pm_tmr_reset(ACPIPMTimer *tmr);
+void acpi_pm_tmr_update(ACPIREGS *ar, bool enable);
+void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar);
+uint32_t acpi_pm_tmr_get(ACPIREGS *ar);
+void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci);
+void acpi_pm_tmr_reset(ACPIREGS *ar);
 
 #include "qemu-timer.h"
 static inline int64_t acpi_pm_tmr_get_clock(void)
@@ -121,24 +131,24 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
 }
 
 /* PM1a_EVT: piix and ich9 don't implement PM1b. */
-uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time);
-void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val);
-void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr);
-void acpi_pm1_evt_reset(ACPIPM1EVT *pm1);
+uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar, int64_t overflow_time);
+void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val);
+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(ACPIPM1CNT *pm1_cnt, qemu_irq cmos_s3);
-void acpi_pm1_cnt_write(ACPIPM1EVT *pm1a, ACPIPM1CNT *pm1_cnt, uint16_t val);
-void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
+void acpi_pm1_cnt_init(ACPIREGS *ar, qemu_irq cmos_s3);
+void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val);
+void acpi_pm1_cnt_update(ACPIREGS *ar,
                          bool sci_enable, bool sci_disable);
-void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt);
+void acpi_pm1_cnt_reset(ACPIREGS *ar);
 
 /* GPE0 */
-void acpi_gpe_init(ACPIGPE *gpe, uint8_t len);
-void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk);
-void acpi_gpe_reset(ACPIGPE *gpe);
+void acpi_gpe_init(ACPIREGS *ar, uint8_t len);
+void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk);
+void acpi_gpe_reset(ACPIREGS *ar);
 
-void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val);
-uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr);
+void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val);
+uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr);
 
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 21484ae..afb37e2 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -54,13 +54,10 @@ struct pci_status {
 typedef struct PIIX4PMState {
     PCIDevice dev;
     IORange ioport;
-    ACPIPM1EVT pm1a;
-    ACPIPM1CNT pm1_cnt;
+    ACPIREGS ar;
 
     APMState apm;
 
-    ACPIPMTimer tmr;
-
     PMSMBus smb;
     uint32_t smb_io_base;
 
@@ -70,7 +67,6 @@ typedef struct PIIX4PMState {
     Notifier machine_ready;
 
     /* for pci hotplug */
-    ACPIGPE gpe;
     struct pci_status pci0_status;
     uint32_t pci0_hotplug_enable;
 } PIIX4PMState;
@@ -84,23 +80,24 @@ static void pm_update_sci(PIIX4PMState *s)
 {
     int sci_level, pmsts;
 
-    pmsts = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
-    sci_level = (((pmsts & s->pm1a.en) &
+    pmsts = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
+    sci_level = (((pmsts & s->ar.pm1.evt.en) &
                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
-        (((s->gpe.sts[0] & s->gpe.en[0]) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
+        (((s->ar.gpe.sts[0] & s->ar.gpe.en[0])
+          & PIIX4_PCI_HOTPLUG_STATUS) != 0);
 
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
-    acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
+    acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 }
 
-static void pm_tmr_timer(ACPIPMTimer *tmr)
+static void pm_tmr_timer(ACPIREGS *ar)
 {
-    PIIX4PMState *s = container_of(tmr, PIIX4PMState, tmr);
+    PIIX4PMState *s = container_of(ar, PIIX4PMState, ar);
     pm_update_sci(s);
 }
 
@@ -116,15 +113,15 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
 
     switch(addr) {
     case 0x00:
-        acpi_pm1_evt_write_sts(&s->pm1a, &s->tmr, val);
+        acpi_pm1_evt_write_sts(&s->ar, val);
         pm_update_sci(s);
         break;
     case 0x02:
-        s->pm1a.en = val;
+        s->ar.pm1.evt.en = val;
         pm_update_sci(s);
         break;
     case 0x04:
-        acpi_pm1_cnt_write(&s->pm1a, &s->pm1_cnt, val);
+        acpi_pm1_cnt_write(&s->ar, val);
         break;
     default:
         break;
@@ -141,16 +138,16 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
 
     switch(addr) {
     case 0x00:
-        val = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
+        val = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
         break;
     case 0x02:
-        val = s->pm1a.en;
+        val = s->ar.pm1.evt.en;
         break;
     case 0x04:
-        val = s->pm1_cnt.cnt;
+        val = s->ar.pm1.cnt.cnt;
         break;
     case 0x08:
-        val = acpi_pm_tmr_get(&s->tmr);
+        val = acpi_pm_tmr_get(&s->ar);
         break;
     default:
         val = 0;
@@ -170,7 +167,7 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
     PIIX4PMState *s = arg;
 
     /* ACPI specs 3.0, 4.7.2.5 */
-    acpi_pm1_cnt_update(&s->pm1_cnt, val == ACPI_ENABLE, val == ACPI_DISABLE);
+    acpi_pm1_cnt_update(&s->ar, val == ACPI_ENABLE, val == ACPI_DISABLE);
 
     if (s->dev.config[0x5b] & (1 << 1)) {
         if (s->smi_irq) {
@@ -258,13 +255,13 @@ static const VMStateDescription vmstate_acpi = {
     .post_load = vmstate_acpi_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
-        VMSTATE_UINT16(pm1a.sts, PIIX4PMState),
-        VMSTATE_UINT16(pm1a.en, PIIX4PMState),
-        VMSTATE_UINT16(pm1_cnt.cnt, PIIX4PMState),
+        VMSTATE_UINT16(ar.pm1.evt.sts, PIIX4PMState),
+        VMSTATE_UINT16(ar.pm1.evt.en, PIIX4PMState),
+        VMSTATE_UINT16(ar.pm1.cnt.cnt, PIIX4PMState),
         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
-        VMSTATE_TIMER(tmr.timer, PIIX4PMState),
-        VMSTATE_INT64(tmr.overflow_time, PIIX4PMState),
-        VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
+        VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
+        VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
+        VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
         VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
                        struct pci_status),
         VMSTATE_END_OF_LIST()
@@ -310,10 +307,9 @@ static void piix4_reset(void *opaque)
 static void piix4_powerdown(void *opaque, int irq, int power_failing)
 {
     PIIX4PMState *s = opaque;
-    ACPIPM1EVT *pm1a = s? &s->pm1a: NULL;
-    ACPIPMTimer *tmr = s? &s->tmr: NULL;
 
-    acpi_pm1_evt_power_down(pm1a, tmr);
+    assert(s != NULL);
+    acpi_pm1_evt_power_down(&s->ar);
 }
 
 static void piix4_pm_machine_ready(Notifier *n, void *opaque)
@@ -361,8 +357,8 @@ static int piix4_pm_initfn(PCIDevice *dev)
     register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
-    acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
-    acpi_gpe_init(&s->gpe, GPE_LEN);
+    acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
+    acpi_gpe_init(&s->ar, GPE_LEN);
 
     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 
@@ -387,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->pm1_cnt, cmos_s3);
+    acpi_pm1_cnt_init(&s->ar, cmos_s3);
     s->smi_irq = smi_irq;
     s->kvm_enabled = kvm_enabled;
 
@@ -436,7 +432,7 @@ device_init(piix4_pm_register);
 static uint32_t gpe_readb(void *opaque, uint32_t addr)
 {
     PIIX4PMState *s = opaque;
-    uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr);
+    uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
 
     PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
     return val;
@@ -446,7 +442,7 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     PIIX4PMState *s = opaque;
 
-    acpi_gpe_ioport_writeb(&s->gpe, addr, val);
+    acpi_gpe_ioport_writeb(&s->ar, addr, val);
     pm_update_sci(s);
 
     PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
@@ -531,7 +527,7 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 
     register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
     register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
-    acpi_gpe_blk(&s->gpe, GPE_BASE);
+    acpi_gpe_blk(&s->ar, GPE_BASE);
 
     register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
     register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
@@ -547,13 +543,13 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 
 static void enable_device(PIIX4PMState *s, int slot)
 {
-    s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
+    s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
     s->pci0_status.up |= (1 << slot);
 }
 
 static void disable_device(PIIX4PMState *s, int slot)
 {
-    s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
+    s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
     s->pci0_status.down |= (1 << slot);
 }
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index aa0954f..8370434 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -159,10 +159,8 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address,
 
 typedef struct VT686PMState {
     PCIDevice dev;
-    ACPIPM1EVT pm1a;
-    ACPIPM1CNT pm1_cnt;
+    ACPIREGS ar;
     APMState apm;
-    ACPIPMTimer tmr;
     PMSMBus smb;
     uint32_t smb_io_base;
 } VT686PMState;
@@ -179,21 +177,21 @@ static void pm_update_sci(VT686PMState *s)
 {
     int sci_level, pmsts;
 
-    pmsts = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
-    sci_level = (((pmsts & s->pm1a.en) &
+    pmsts = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
+    sci_level = (((pmsts & s->ar.pm1.evt.en) &
                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0);
     qemu_set_irq(s->dev.irq[0], sci_level);
     /* schedule a timer interruption if needed */
-    acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
+    acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pmsts & ACPI_BITMASK_TIMER_STATUS));
 }
 
-static void pm_tmr_timer(ACPIPMTimer *tmr)
+static void pm_tmr_timer(ACPIREGS *ar)
 {
-    VT686PMState *s = container_of(tmr, VT686PMState, tmr);
+    VT686PMState *s = container_of(ar, VT686PMState, ar);
     pm_update_sci(s);
 }
 
@@ -204,15 +202,15 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     addr &= 0x0f;
     switch (addr) {
     case 0x00:
-        acpi_pm1_evt_write_sts(&s->pm1a, &s->tmr, val);
+        acpi_pm1_evt_write_sts(&s->ar, val);
         pm_update_sci(s);
         break;
     case 0x02:
-        s->pm1a.en = val;
+        s->ar.pm1.evt.en = val;
         pm_update_sci(s);
         break;
     case 0x04:
-        acpi_pm1_cnt_write(&s->pm1a, &s->pm1_cnt, val);
+        acpi_pm1_cnt_write(&s->ar, val);
         break;
     default:
         break;
@@ -228,13 +226,13 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
     addr &= 0x0f;
     switch (addr) {
     case 0x00:
-        val = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time);
+        val = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
         break;
     case 0x02:
-        val = s->pm1a.en;
+        val = s->ar.pm1.evt.en;
         break;
     case 0x04:
-        val = s->pm1_cnt.cnt;
+        val = s->ar.pm1.cnt.cnt;
         break;
     default:
         val = 0;
@@ -258,7 +256,7 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     addr &= 0x0f;
     switch (addr) {
     case 0x08:
-        val = acpi_pm_tmr_get(&s->tmr);
+        val = acpi_pm_tmr_get(&s->ar);
         break;
     default:
         val = 0;
@@ -309,12 +307,12 @@ static const VMStateDescription vmstate_acpi = {
     .post_load = vmstate_acpi_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, VT686PMState),
-        VMSTATE_UINT16(pm1a.sts, VT686PMState),
-        VMSTATE_UINT16(pm1a.en, VT686PMState),
-        VMSTATE_UINT16(pm1_cnt.cnt, VT686PMState),
+        VMSTATE_UINT16(ar.pm1.evt.sts, VT686PMState),
+        VMSTATE_UINT16(ar.pm1.evt.en, VT686PMState),
+        VMSTATE_UINT16(ar.pm1.cnt.cnt, VT686PMState),
         VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState),
-        VMSTATE_TIMER(tmr.timer, VT686PMState),
-        VMSTATE_INT64(tmr.overflow_time, VT686PMState),
+        VMSTATE_TIMER(ar.tmr.timer, VT686PMState),
+        VMSTATE_INT64(ar.tmr.overflow_time, VT686PMState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -445,8 +443,8 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     apm_init(&s->apm, NULL, s);
 
-    acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
-    acpi_pm1_cnt_init(&s->pm1_cnt, NULL);
+    acpi_pm_tmr_init(&s->ar, pm_tmr_timer);
+    acpi_pm1_cnt_init(&s->ar, NULL);
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 03/11] acpi: don't pass overflow_time to acpi_pm1_evt_get_sts
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 01/11] acpi: move around structs Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 02/11] acpi: add ACPIREGS Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 04/11] acpi: add acpi_pm1_evt_write_en Gerd Hoffmann
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

Pretty pointless, can be reached via ACPIREGS now.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/acpi.c       |    6 +++---
 hw/acpi.h       |    2 +-
 hw/acpi_piix4.c |    4 ++--
 hw/vt82c686.c   |    4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 1922e53..1129335 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -249,10 +249,10 @@ int acpi_table_add(const char *t)
 }
 
 /* ACPI PM1a EVT */
-uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar, int64_t overflow_time)
+uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar)
 {
     int64_t d = acpi_pm_tmr_get_clock();
-    if (d >= overflow_time) {
+    if (d >= ar->tmr.overflow_time) {
         ar->pm1.evt.sts |= ACPI_BITMASK_TIMER_STATUS;
     }
     return ar->pm1.evt.sts;
@@ -260,7 +260,7 @@ uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar, int64_t overflow_time)
 
 void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
 {
-    uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar, ar->tmr.overflow_time);
+    uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar);
     if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
         /* if TMRSTS is reset, then compute the new overflow time */
         acpi_pm_tmr_calc_overflow_time(ar);
diff --git a/hw/acpi.h b/hw/acpi.h
index 530c86a..e1d5e3b 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -131,7 +131,7 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
 }
 
 /* PM1a_EVT: piix and ich9 don't implement PM1b. */
-uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar, int64_t overflow_time);
+uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar);
 void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val);
 void acpi_pm1_evt_power_down(ACPIREGS *ar);
 void acpi_pm1_evt_reset(ACPIREGS *ar);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index afb37e2..b6899f4 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -80,7 +80,7 @@ static void pm_update_sci(PIIX4PMState *s)
 {
     int sci_level, pmsts;
 
-    pmsts = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
+    pmsts = acpi_pm1_evt_get_sts(&s->ar);
     sci_level = (((pmsts & s->ar.pm1.evt.en) &
                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
@@ -138,7 +138,7 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
 
     switch(addr) {
     case 0x00:
-        val = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
+        val = acpi_pm1_evt_get_sts(&s->ar);
         break;
     case 0x02:
         val = s->ar.pm1.evt.en;
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 8370434..10e066b 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -177,7 +177,7 @@ static void pm_update_sci(VT686PMState *s)
 {
     int sci_level, pmsts;
 
-    pmsts = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
+    pmsts = acpi_pm1_evt_get_sts(&s->ar);
     sci_level = (((pmsts & s->ar.pm1.evt.en) &
                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
@@ -226,7 +226,7 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
     addr &= 0x0f;
     switch (addr) {
     case 0x00:
-        val = acpi_pm1_evt_get_sts(&s->ar, s->ar.tmr.overflow_time);
+        val = acpi_pm1_evt_get_sts(&s->ar);
         break;
     case 0x02:
         val = s->ar.pm1.evt.en;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 04/11] acpi: add acpi_pm1_evt_write_en
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 03/11] acpi: don't pass overflow_time to acpi_pm1_evt_get_sts Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure Gerd Hoffmann
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/acpi.c       |    5 +++++
 hw/acpi.h       |    1 +
 hw/acpi_piix4.c |    2 +-
 hw/vt82c686.c   |    2 +-
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 1129335..407949b 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -268,6 +268,11 @@ void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
     ar->pm1.evt.sts &= ~val;
 }
 
+void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
+{
+    ar->pm1.evt.en = val;
+}
+
 void acpi_pm1_evt_power_down(ACPIREGS *ar)
 {
     if (ar->pm1.evt.en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
diff --git a/hw/acpi.h b/hw/acpi.h
index e1d5e3b..88f8051 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -133,6 +133,7 @@ static inline int64_t acpi_pm_tmr_get_clock(void)
 /* PM1a_EVT: piix and ich9 don't implement PM1b. */
 uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar);
 void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val);
+void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val);
 void acpi_pm1_evt_power_down(ACPIREGS *ar);
 void acpi_pm1_evt_reset(ACPIREGS *ar);
 
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index b6899f4..9c72e62 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -117,7 +117,7 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
         pm_update_sci(s);
         break;
     case 0x02:
-        s->ar.pm1.evt.en = val;
+        acpi_pm1_evt_write_en(&s->ar, val);
         pm_update_sci(s);
         break;
     case 0x04:
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 10e066b..d8f4e26 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -206,7 +206,7 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
         pm_update_sci(s);
         break;
     case 0x02:
-        s->ar.pm1.evt.en = val;
+        acpi_pm1_evt_write_en(&s->ar, val);
         pm_update_sci(s);
         break;
     case 0x04:
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 04/11] acpi: add acpi_pm1_evt_write_en Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-13  9:21   ` Gleb Natapov
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 06/11] suspend: switch acpi s3 to new infrastructure Gerd Hoffmann
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

This patch adds some infrastructure to handle suspend and resume to
qemu.  First there are two functions to switch state and second there
is a suspend notifier:

 * qemu_system_suspend_request is supposed to be called when the
   guest asks for being be suspended, for example via ACPI.

 * qemu_system_wakeup_request is supposed to be called on events
   which should wake up the guest.

 * qemu_register_suspend_notifier can be used to register a notifier
   which will be called when the guest is suspended.  Machine types
   and device models can hook in there to modify state if needed.

 * qemu_register_wakeup_notifier can be used to register a notifier
   which will be called when the guest is woken up.  Machine types
   and device models can hook in there to modify state if needed.

 * qemu_system_wakeup_enable can be used to enable/disable wakeup
   events.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 sysemu.h |    9 +++++++++
 vl.c     |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/sysemu.h b/sysemu.h
index 9d5ce33..af73813 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -38,7 +38,16 @@ void vm_start(void);
 void vm_stop(RunState state);
 void vm_stop_force_state(RunState state);
 
+typedef enum WakeupReason {
+    QEMU_WAKEUP_REASON_OTHER = 0,
+} WakeupReason;
+
 void qemu_system_reset_request(void);
+void qemu_system_suspend_request(void);
+void qemu_register_suspend_notifier(Notifier *notifier);
+void qemu_system_wakeup_request(WakeupReason reason);
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled);
+void qemu_register_wakeup_notifier(Notifier *notifier);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
 void qemu_system_debug_request(void);
diff --git a/vl.c b/vl.c
index 63dd725..5095e06 100644
--- a/vl.c
+++ b/vl.c
@@ -1283,6 +1283,12 @@ static int shutdown_requested, shutdown_signal = -1;
 static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
+static bool is_suspended;
+static NotifierList suspend_notifiers =
+    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
+static NotifierList wakeup_notifiers =
+    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
+static uint32_t wakeup_reason_mask = ~0;
 static RunState vmstop_requested = RUN_STATE_MAX;
 
 int qemu_shutdown_requested_get(void)
@@ -1398,6 +1404,49 @@ void qemu_system_reset_request(void)
     qemu_notify_event();
 }
 
+void qemu_system_suspend_request(void)
+{
+    if (is_suspended) {
+        return;
+    }
+    cpu_stop_current();
+    notifier_list_notify(&suspend_notifiers, NULL);
+    is_suspended = true;
+}
+
+void qemu_register_suspend_notifier(Notifier *notifier)
+{
+    notifier_list_add(&suspend_notifiers, notifier);
+}
+
+void qemu_system_wakeup_request(WakeupReason reason)
+{
+    if (!is_suspended) {
+        return;
+    }
+    if (!(wakeup_reason_mask & (1 << reason))) {
+        return;
+    }
+    notifier_list_notify(&wakeup_notifiers, &reason);
+    reset_requested = 1;
+    qemu_notify_event();
+    is_suspended = false;
+}
+
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
+{
+    if (enabled) {
+        wakeup_reason_mask |= (1 << reason);
+    } else {
+        wakeup_reason_mask &= ~(1 << reason);
+    }
+}
+
+void qemu_register_wakeup_notifier(Notifier *notifier)
+{
+    notifier_list_add(&wakeup_notifiers, notifier);
+}
+
 void qemu_system_killed(int signal, pid_t pid)
 {
     shutdown_signal = signal;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 06/11] suspend: switch acpi s3 to new infrastructure.
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 07/11] suspend: add system_wakeup monitor command Gerd Hoffmann
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

This patch switches pc s3 suspend over to the new infrastructure.
The cmos_s3 qemu_irq is killed, the new notifier is used instead.
The xen hack goes away with that too, the hypercall can simply be
done in a notifier function now.

This patch also makes the guest actually stay suspended instead
of leaving suspend instantly, so it is useful for more than just
testing whenever the suspend/resume cycle actually works.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/acpi.c        |   32 +++++++++++++++++++++-----------
 hw/acpi.h        |    4 ++--
 hw/acpi_piix4.c  |    4 ++--
 hw/mc146818rtc.c |   12 ++++++++++++
 hw/mips_malta.c  |    2 +-
 hw/pc.c          |   11 -----------
 hw/pc.h          |    3 +--
 hw/pc_piix.c     |    8 +-------
 hw/vt82c686.c    |    2 +-
 xen-all.c        |   11 ++++++-----
 10 files changed, 47 insertions(+), 42 deletions(-)

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,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 07/11] suspend: add system_wakeup monitor command
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 06/11] suspend: switch acpi s3 to new infrastructure Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 08/11] suspend: make ps/2 devices wakeup the guest Gerd Hoffmann
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

This patch adds the system_wakeup monitor command which will simply
wake up suspended guests.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hmp-commands.hx  |   14 ++++++++++++++
 hmp.c            |    5 +++++
 hmp.h            |    1 +
 qapi-schema.json |   11 +++++++++++
 qmp-commands.hx  |   21 +++++++++++++++++++++
 qmp.c            |    5 +++++
 6 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 573b823..64b3656 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -352,6 +352,20 @@ Resume emulation.
 ETEXI
 
     {
+        .name       = "system_wakeup",
+        .args_type  = "",
+        .params     = "",
+        .help       = "wakeup guest from suspend",
+        .mhandler.cmd = hmp_system_wakeup,
+    },
+
+STEXI
+@item system_wakeup
+@findex system_wakeup
+Wakeup guest from suspend.
+ETEXI
+
+    {
         .name       = "gdbserver",
         .args_type  = "device:s?",
         .params     = "[device]",
diff --git a/hmp.c b/hmp.c
index 8ff8c94..3a54455 100644
--- a/hmp.c
+++ b/hmp.c
@@ -632,6 +632,11 @@ void hmp_cont(Monitor *mon, const QDict *qdict)
     }
 }
 
+void hmp_system_wakeup(Monitor *mon, const QDict *qdict)
+{
+    qmp_system_wakeup(NULL);
+}
+
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
 {
     Error *errp = NULL;
diff --git a/hmp.h b/hmp.h
index 18eecbd..5409464 100644
--- a/hmp.h
+++ b/hmp.h
@@ -41,6 +41,7 @@ void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
+void hmp_system_wakeup(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
diff --git a/qapi-schema.json b/qapi-schema.json
index d02ee86..226c1da 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -999,6 +999,17 @@
 { 'command': 'cont' }
 
 ##
+# @system_wakeup:
+#
+# Wakeup guest from suspend
+#
+# Since:  1.1
+#
+# Returns:  nothing.
+##
+{ 'command': 'system_wakeup' }
+
+##
 # @inject-nmi:
 #
 # Injects an Non-Maskable Interrupt into all guest's VCPUs.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b5e2ab8..f5081e2 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -212,6 +212,27 @@ Example:
 EQMP
 
     {
+        .name       = "system_wakeup",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_system_wakeup,
+    },
+
+SQMP
+system_wakeup
+-------------
+
+Wakeup guest from suspend.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "system_wakeup" }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "system_reset",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_system_reset,
diff --git a/qmp.c b/qmp.c
index 45052cc..15d656f 100644
--- a/qmp.c
+++ b/qmp.c
@@ -164,6 +164,11 @@ void qmp_cont(Error **errp)
     vm_start();
 }
 
+void qmp_system_wakeup(Error **errp)
+{
+    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+}
+
 ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
 {
     Object *obj;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 08/11] suspend: make ps/2 devices wakeup the guest
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 07/11] suspend: add system_wakeup monitor command Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 09/11] suspend: make serial ports " Gerd Hoffmann
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

This patch adds wakeup support to ps/2 emulation.  Any key press on the
ps/2 keyboard will wakeup the guest.  Likewise any mouse button press
will wakeup the guest.  Mouse moves are ignored, so the guest will not
wakeup in case your mouse crosses the vnc window of a suspended guest by
accident.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/ps2.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/ps2.c b/hw/ps2.c
index 1d9057b..b1a67bc 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -24,6 +24,7 @@
 #include "hw.h"
 #include "ps2.h"
 #include "console.h"
+#include "sysemu.h"
 
 /* debug PC keyboard */
 //#define DEBUG_KBD
@@ -154,6 +155,7 @@ static void ps2_put_keycode(void *opaque, int keycode)
 {
     PS2KbdState *s = opaque;
 
+    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
     /* XXX: add support for scancode set 1 */
     if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
         if (keycode & 0x80) {
@@ -368,6 +370,10 @@ static void ps2_mouse_event(void *opaque,
 	return;
     s->mouse_buttons = buttons_state;
 
+    if (buttons_state) {
+        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+    }
+
     if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
         (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
         for(;;) {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 09/11] suspend: make serial ports wakeup the guest.
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 08/11] suspend: make ps/2 devices wakeup the guest Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 10/11] suspend: make rtc alarm " Gerd Hoffmann
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

Add a 'wakeup' property to the serial port.  It is off by default.  When
enabled any incoming character on the serial line will wake up the
guest.  Useful for guests which have a serial console configured.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/serial.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index 82917e2..8224607 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -139,6 +139,7 @@ struct SerialState {
     int it_shift;
     int baudbase;
     int tsr_retry;
+    uint32_t wakeup;
 
     uint64_t last_xmit_ts;              /* Time when the last byte was successfully sent out of the tsr */
     SerialFIFO recv_fifo;
@@ -635,6 +636,10 @@ static int serial_can_receive1(void *opaque)
 static void serial_receive1(void *opaque, const uint8_t *buf, int size)
 {
     SerialState *s = opaque;
+
+    if (s->wakeup) {
+        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+    }
     if(s->fcr & UART_FCR_FE) {
         int i;
         for (i = 0; i < size; i++) {
@@ -884,6 +889,7 @@ static Property serial_isa_properties[] = {
     DEFINE_PROP_HEX32("iobase", ISASerialState, iobase,  -1),
     DEFINE_PROP_UINT32("irq",   ISASerialState, isairq,  -1),
     DEFINE_PROP_CHR("chardev",  ISASerialState, state.chr),
+    DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 10/11] suspend: make rtc alarm wakeup the guest.
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 09/11] suspend: make serial ports " Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 11/11] suspend: pmtimer s3 wakeup Gerd Hoffmann
  2012-02-10 12:43 ` [Qemu-devel] [PATCH 12/11] suspend: add qmp events Gerd Hoffmann
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

Make the rtc wake up the guest when the alarm fires.
Add acpi windup to property support RTC_EN.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/acpi.c        |    7 +++++++
 hw/mc146818rtc.c |    1 +
 sysemu.h         |    1 +
 3 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 7b16716..c05dde6 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -254,6 +254,10 @@ static void acpi_notify_wakeup(Notifier *notifier, void *data)
     WakeupReason *reason = data;
 
     switch (*reason) {
+    case QEMU_WAKEUP_REASON_RTC:
+        ar->pm1.evt.sts |=
+            (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS);
+        break;
     case QEMU_WAKEUP_REASON_OTHER:
     default:
         /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
@@ -287,6 +291,8 @@ void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val)
 void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
 {
     ar->pm1.evt.en = val;
+    qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC,
+                              val & ACPI_BITMASK_RT_CLOCK_ENABLE);
 }
 
 void acpi_pm1_evt_power_down(ACPIREGS *ar)
@@ -301,6 +307,7 @@ void acpi_pm1_evt_reset(ACPIREGS *ar)
 {
     ar->pm1.evt.sts = 0;
     ar->pm1.evt.en = 0;
+    qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, 0);
 }
 
 /* ACPI PM_TMR */
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 314ed52..37adddb 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -437,6 +437,7 @@ static void rtc_update_second2(void *opaque)
 
         s->cmos_data[RTC_REG_C] |= REG_C_AF;
         if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
+            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
             qemu_irq_raise(s->irq);
             s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
         }
diff --git a/sysemu.h b/sysemu.h
index af73813..781bdaf 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -40,6 +40,7 @@ void vm_stop_force_state(RunState state);
 
 typedef enum WakeupReason {
     QEMU_WAKEUP_REASON_OTHER = 0,
+    QEMU_WAKEUP_REASON_RTC,
 } WakeupReason;
 
 void qemu_system_reset_request(void);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH v4 11/11] suspend: pmtimer s3 wakeup
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 10/11] suspend: make rtc alarm " Gerd Hoffmann
@ 2012-02-09 17:05 ` Gerd Hoffmann
  2012-02-10 12:43 ` [Qemu-devel] [PATCH 12/11] suspend: add qmp events Gerd Hoffmann
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-09 17:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, gleb

---
 hw/acpi.c |    8 ++++++++
 sysemu.h  |    1 +
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index c05dde6..5d521e5 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -258,6 +258,10 @@ static void acpi_notify_wakeup(Notifier *notifier, void *data)
         ar->pm1.evt.sts |=
             (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS);
         break;
+    case QEMU_WAKEUP_REASON_PMTIMER:
+        ar->pm1.evt.sts |=
+            (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS);
+        break;
     case QEMU_WAKEUP_REASON_OTHER:
     default:
         /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
@@ -293,6 +297,8 @@ void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val)
     ar->pm1.evt.en = val;
     qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC,
                               val & ACPI_BITMASK_RT_CLOCK_ENABLE);
+    qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER,
+                              val & ACPI_BITMASK_TIMER_ENABLE);
 }
 
 void acpi_pm1_evt_power_down(ACPIREGS *ar)
@@ -308,6 +314,7 @@ void acpi_pm1_evt_reset(ACPIREGS *ar)
     ar->pm1.evt.sts = 0;
     ar->pm1.evt.en = 0;
     qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, 0);
+    qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, 0);
 }
 
 /* ACPI PM_TMR */
@@ -340,6 +347,7 @@ uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
 static void acpi_pm_tmr_timer(void *opaque)
 {
     ACPIREGS *ar = opaque;
+    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER);
     ar->tmr.update_sci(ar);
 }
 
diff --git a/sysemu.h b/sysemu.h
index 781bdaf..98118cc 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -41,6 +41,7 @@ void vm_stop_force_state(RunState state);
 typedef enum WakeupReason {
     QEMU_WAKEUP_REASON_OTHER = 0,
     QEMU_WAKEUP_REASON_RTC,
+    QEMU_WAKEUP_REASON_PMTIMER,
 } WakeupReason;
 
 void qemu_system_reset_request(void);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 12/11] suspend: add qmp events
  2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 11/11] suspend: pmtimer s3 wakeup Gerd Hoffmann
@ 2012-02-10 12:43 ` Gerd Hoffmann
  11 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-10 12:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Send qmp events on suspend and wakeup so libvirt
has a chance to track the vm state.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 monitor.c |    6 ++++++
 monitor.h |    2 ++
 vl.c      |   15 +++++++++++++++
 3 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/monitor.c b/monitor.c
index aadbdcb..e6f5fad 100644
--- a/monitor.c
+++ b/monitor.c
@@ -485,6 +485,12 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
         case QEVENT_BLOCK_JOB_CANCELLED:
             event_name = "BLOCK_JOB_CANCELLED";
             break;
+        case QEVENT_SUSPEND:
+            event_name = "SUSPEND";
+            break;
+        case QEVENT_WAKEUP:
+            event_name = "WAKEUP";
+            break;
         default:
             abort();
             break;
diff --git a/monitor.h b/monitor.h
index b72ea07..9df3bab 100644
--- a/monitor.h
+++ b/monitor.h
@@ -38,6 +38,8 @@ typedef enum MonitorEvent {
     QEVENT_SPICE_DISCONNECTED,
     QEVENT_BLOCK_JOB_COMPLETED,
     QEVENT_BLOCK_JOB_CANCELLED,
+    QEVENT_SUSPEND,
+    QEVENT_WAKEUP,
     QEVENT_MAX,
 } MonitorEvent;
 
diff --git a/vl.c b/vl.c
index 5095e06..28ca323 100644
--- a/vl.c
+++ b/vl.c
@@ -1411,6 +1411,7 @@ void qemu_system_suspend_request(void)
     }
     cpu_stop_current();
     notifier_list_notify(&suspend_notifiers, NULL);
+    monitor_protocol_event(QEVENT_SUSPEND, NULL);
     is_suspended = true;
 }
 
@@ -1421,12 +1422,26 @@ void qemu_register_suspend_notifier(Notifier *notifier)
 
 void qemu_system_wakeup_request(WakeupReason reason)
 {
+    static const char *names[] = {
+        [QEMU_WAKEUP_REASON_OTHER]   = "other",
+        [QEMU_WAKEUP_REASON_RTC]     = "rtc",
+        [QEMU_WAKEUP_REASON_PMTIMER] = "pmtimer",
+    };
+    const char *name;
+    QObject *data;
+
     if (!is_suspended) {
         return;
     }
     if (!(wakeup_reason_mask & (1 << reason))) {
         return;
     }
+
+    name = (reason < ARRAY_SIZE(names)) ? names[reason] : "unknown";
+    data = qobject_from_jsonf("{ 'reason': %s }", name);
+    monitor_protocol_event(QEVENT_WAKEUP, data);
+    qobject_decref(data);
+
     notifier_list_notify(&wakeup_notifiers, &reason);
     reset_requested = 1;
     qemu_notify_event();
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure Gerd Hoffmann
@ 2012-02-13  9:21   ` Gleb Natapov
  2012-02-14  8:18     ` Gerd Hoffmann
  0 siblings, 1 reply; 19+ messages in thread
From: Gleb Natapov @ 2012-02-13  9:21 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Thu, Feb 09, 2012 at 06:05:37PM +0100, Gerd Hoffmann wrote:
> This patch adds some infrastructure to handle suspend and resume to
> qemu.  First there are two functions to switch state and second there
> is a suspend notifier:
> 
>  * qemu_system_suspend_request is supposed to be called when the
>    guest asks for being be suspended, for example via ACPI.
> 
>  * qemu_system_wakeup_request is supposed to be called on events
>    which should wake up the guest.
> 
>  * qemu_register_suspend_notifier can be used to register a notifier
>    which will be called when the guest is suspended.  Machine types
>    and device models can hook in there to modify state if needed.
> 
>  * qemu_register_wakeup_notifier can be used to register a notifier
>    which will be called when the guest is woken up.  Machine types
>    and device models can hook in there to modify state if needed.
> 
>  * qemu_system_wakeup_enable can be used to enable/disable wakeup
>    events.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  sysemu.h |    9 +++++++++
>  vl.c     |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+), 0 deletions(-)
> 
> diff --git a/sysemu.h b/sysemu.h
> index 9d5ce33..af73813 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -38,7 +38,16 @@ void vm_start(void);
>  void vm_stop(RunState state);
>  void vm_stop_force_state(RunState state);
>  
> +typedef enum WakeupReason {
> +    QEMU_WAKEUP_REASON_OTHER = 0,
> +} WakeupReason;
> +
>  void qemu_system_reset_request(void);
> +void qemu_system_suspend_request(void);
> +void qemu_register_suspend_notifier(Notifier *notifier);
> +void qemu_system_wakeup_request(WakeupReason reason);
> +void qemu_system_wakeup_enable(WakeupReason reason, bool enabled);
> +void qemu_register_wakeup_notifier(Notifier *notifier);
>  void qemu_system_shutdown_request(void);
>  void qemu_system_powerdown_request(void);
>  void qemu_system_debug_request(void);
> diff --git a/vl.c b/vl.c
> index 63dd725..5095e06 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1283,6 +1283,12 @@ static int shutdown_requested, shutdown_signal = -1;
>  static pid_t shutdown_pid;
>  static int powerdown_requested;
>  static int debug_requested;
> +static bool is_suspended;
> +static NotifierList suspend_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
> +static NotifierList wakeup_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
> +static uint32_t wakeup_reason_mask = ~0;
>  static RunState vmstop_requested = RUN_STATE_MAX;
>  
>  int qemu_shutdown_requested_get(void)
> @@ -1398,6 +1404,49 @@ void qemu_system_reset_request(void)
>      qemu_notify_event();
>  }
>  
> +void qemu_system_suspend_request(void)
> +{
> +    if (is_suspended) {
> +        return;
> +    }
> +    cpu_stop_current();
> +    notifier_list_notify(&suspend_notifiers, NULL);
> +    is_suspended = true;
> +}
> +
Shouldn't we stop the whole VM at some point, not only vcpu that
does ACPI IO? May be I missed where it is done in the patch series.

> +void qemu_register_suspend_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&suspend_notifiers, notifier);
> +}
> +
> +void qemu_system_wakeup_request(WakeupReason reason)
> +{
> +    if (!is_suspended) {
> +        return;
> +    }
> +    if (!(wakeup_reason_mask & (1 << reason))) {
> +        return;
> +    }
> +    notifier_list_notify(&wakeup_notifiers, &reason);
> +    reset_requested = 1;
> +    qemu_notify_event();
> +    is_suspended = false;
> +}
> +
> +void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
> +{
> +    if (enabled) {
> +        wakeup_reason_mask |= (1 << reason);
> +    } else {
> +        wakeup_reason_mask &= ~(1 << reason);
> +    }
> +}
> +
> +void qemu_register_wakeup_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&wakeup_notifiers, notifier);
> +}
> +
>  void qemu_system_killed(int signal, pid_t pid)
>  {
>      shutdown_signal = signal;
> -- 
> 1.7.1

--
			Gleb.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-13  9:21   ` Gleb Natapov
@ 2012-02-14  8:18     ` Gerd Hoffmann
  2012-02-14  8:37       ` Gleb Natapov
  0 siblings, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-14  8:18 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: qemu-devel

  Hi,

> Shouldn't we stop the whole VM at some point, not only vcpu that
> does ACPI IO? May be I missed where it is done in the patch series.

It isn't hidden elsewhere, qemu doesn't do it.   The code was like that
before, and I think the reason is that the guest has to stop the other
cpus before entering s3.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-14  8:18     ` Gerd Hoffmann
@ 2012-02-14  8:37       ` Gleb Natapov
  2012-02-14  8:57         ` Gerd Hoffmann
  0 siblings, 1 reply; 19+ messages in thread
From: Gleb Natapov @ 2012-02-14  8:37 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Tue, Feb 14, 2012 at 09:18:34AM +0100, Gerd Hoffmann wrote:
>   Hi,
> 
> > Shouldn't we stop the whole VM at some point, not only vcpu that
> > does ACPI IO? May be I missed where it is done in the patch series.
> 
> It isn't hidden elsewhere, qemu doesn't do it.   The code was like that
> before, and I think the reason is that the guest has to stop the other
> cpus before entering s3.
> 
Current code calls qemu_system_reset_request() which takes care of
stopping (and reseting) all vcpus (and rest of the machine) by setting
reset_requested flag immediately on suspend. We cannot just stop
current cpu on S3 and delay reset till wakeup since guest can leave
other vcpus in spinning state and they will take 100% of host cpu while
guest is suspended. I think it is also important to reset all device
immediately to ensure that no device will do DMA into main memory after
suspend. Technically if this happens it would be a guest bug since
guest should make sure that devices are stopped before entering S3,
but I wouldn't want to debug such bug report :)

--
			Gleb.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-14  8:37       ` Gleb Natapov
@ 2012-02-14  8:57         ` Gerd Hoffmann
  2012-02-14  9:08           ` Gleb Natapov
  0 siblings, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-14  8:57 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: qemu-devel

On 02/14/12 09:37, Gleb Natapov wrote:
> On Tue, Feb 14, 2012 at 09:18:34AM +0100, Gerd Hoffmann wrote:
>>   Hi,
>>
>>> Shouldn't we stop the whole VM at some point, not only vcpu that
>>> does ACPI IO? May be I missed where it is done in the patch series.
>>
>> It isn't hidden elsewhere, qemu doesn't do it.   The code was like that
>> before, and I think the reason is that the guest has to stop the other
>> cpus before entering s3.
>>
> Current code calls qemu_system_reset_request() which takes care of
> stopping (and reseting) all vcpus (and rest of the machine) by setting
> reset_requested flag immediately on suspend.

No.  The current code simply has no separate suspend and wakeup steps.

> We cannot just stop
> current cpu on S3 and delay reset till wakeup since guest can leave
> other vcpus in spinning state and they will take 100% of host cpu while
> guest is suspended.

I see.  I've expeced the the guest os putting them into a hlt loop or
some simliar idle state.  Play save and expliticly pausing them all is
certainly good from a robustness perspective.

> I think it is also important to reset all device
> immediately to ensure that no device will do DMA into main memory after
> suspend.

Didn't investigate yet, but I suspect this could break wakeup from pci
devices (nic, usb-tablet via uhci) ...

> Technically if this happens it would be a guest bug since
> guest should make sure that devices are stopped before entering S3,
> but I wouldn't want to debug such bug report :)

... and it shouldn't be needed.  Although I agree that bugs in that area
are nasty to debug ...

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-14  8:57         ` Gerd Hoffmann
@ 2012-02-14  9:08           ` Gleb Natapov
  2012-02-14 14:49             ` Gerd Hoffmann
  0 siblings, 1 reply; 19+ messages in thread
From: Gleb Natapov @ 2012-02-14  9:08 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Tue, Feb 14, 2012 at 09:57:01AM +0100, Gerd Hoffmann wrote:
> On 02/14/12 09:37, Gleb Natapov wrote:
> > On Tue, Feb 14, 2012 at 09:18:34AM +0100, Gerd Hoffmann wrote:
> >>   Hi,
> >>
> >>> Shouldn't we stop the whole VM at some point, not only vcpu that
> >>> does ACPI IO? May be I missed where it is done in the patch series.
> >>
> >> It isn't hidden elsewhere, qemu doesn't do it.   The code was like that
> >> before, and I think the reason is that the guest has to stop the other
> >> cpus before entering s3.
> >>
> > Current code calls qemu_system_reset_request() which takes care of
> > stopping (and reseting) all vcpus (and rest of the machine) by setting
> > reset_requested flag immediately on suspend.
> 
> No.  The current code simply has no separate suspend and wakeup steps.
> 
Nod.

> > We cannot just stop
> > current cpu on S3 and delay reset till wakeup since guest can leave
> > other vcpus in spinning state and they will take 100% of host cpu while
> > guest is suspended.
> 
> I see.  I've expeced the the guest os putting them into a hlt loop or
> some simliar idle state.  Play save and expliticly pausing them all is
> certainly good from a robustness perspective.
Yes. We should not trust a guest to do the "right thing".

> 
> > I think it is also important to reset all device
> > immediately to ensure that no device will do DMA into main memory after
> > suspend.
> 
> Didn't investigate yet, but I suspect this could break wakeup from pci
> devices (nic, usb-tablet via uhci) ...

Yes. Can't say I fully understand how this works on real HW. I know
that there are separate "power planes" for different system sates
(this is defined in ACPI spec). So in S3 some devices (or even part of
a device?) may be powered down, but others still have power. Not sure
we should dive into emulating that in this patch series.

> 
> > Technically if this happens it would be a guest bug since
> > guest should make sure that devices are stopped before entering S3,
> > but I wouldn't want to debug such bug report :)
> 
> ... and it shouldn't be needed.  Although I agree that bugs in that area
> are nasty to debug ...
> 
> cheers,
>   Gerd

--
			Gleb.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure
  2012-02-14  9:08           ` Gleb Natapov
@ 2012-02-14 14:49             ` Gerd Hoffmann
  0 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2012-02-14 14:49 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 954 bytes --]

  Hi,

>> I see.  I've expeced the the guest os putting them into a hlt loop or
>> some simliar idle state.  Play save and expliticly pausing them all is
>> certainly good from a robustness perspective.
> Yes. We should not trust a guest to do the "right thing".

Updated patch attached.

>>> I think it is also important to reset all device
>>> immediately to ensure that no device will do DMA into main memory after
>>> suspend.
>>
>> Didn't investigate yet, but I suspect this could break wakeup from pci
>> devices (nic, usb-tablet via uhci) ...
> 
> Yes. Can't say I fully understand how this works on real HW. I know
> that there are separate "power planes" for different system sates
> (this is defined in ACPI spec). So in S3 some devices (or even part of
> a device?) may be powered down, but others still have power. Not sure
> we should dive into emulating that in this patch series.

We'll do that later, one step at a time.

cheers,
  Gerd


[-- Attachment #2: 0001-suspend-add-infrastructure.patch --]
[-- Type: text/plain, Size: 4515 bytes --]

>From fa91a3c496e1a3795622b91079dd588d38fe59b4 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 11 Jan 2012 13:09:38 +0100
Subject: [PATCH] suspend: add infrastructure

This patch adds some infrastructure to handle suspend and resume to
qemu.  First there are two functions to switch state and second there
is a suspend notifier:

 * qemu_system_suspend_request is supposed to be called when the
   guest asks for being be suspended, for example via ACPI.

 * qemu_system_wakeup_request is supposed to be called on events
   which should wake up the guest.

 * qemu_register_suspend_notifier can be used to register a notifier
   which will be called when the guest is suspended.  Machine types
   and device models can hook in there to modify state if needed.

 * qemu_register_wakeup_notifier can be used to register a notifier
   which will be called when the guest is woken up.  Machine types
   and device models can hook in there to modify state if needed.

 * qemu_system_wakeup_enable can be used to enable/disable wakeup
   events.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 sysemu.h |    9 ++++++++
 vl.c     |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/sysemu.h b/sysemu.h
index 9d5ce33..af73813 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -38,7 +38,16 @@ void vm_start(void);
 void vm_stop(RunState state);
 void vm_stop_force_state(RunState state);
 
+typedef enum WakeupReason {
+    QEMU_WAKEUP_REASON_OTHER = 0,
+} WakeupReason;
+
 void qemu_system_reset_request(void);
+void qemu_system_suspend_request(void);
+void qemu_register_suspend_notifier(Notifier *notifier);
+void qemu_system_wakeup_request(WakeupReason reason);
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled);
+void qemu_register_wakeup_notifier(Notifier *notifier);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
 void qemu_system_debug_request(void);
diff --git a/vl.c b/vl.c
index 63dd725..bfdcb7c 100644
--- a/vl.c
+++ b/vl.c
@@ -1283,6 +1283,13 @@ static int shutdown_requested, shutdown_signal = -1;
 static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
+static int suspend_requested;
+static bool is_suspended;
+static NotifierList suspend_notifiers =
+    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
+static NotifierList wakeup_notifiers =
+    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
+static uint32_t wakeup_reason_mask = ~0;
 static RunState vmstop_requested = RUN_STATE_MAX;
 
 int qemu_shutdown_requested_get(void)
@@ -1325,6 +1332,13 @@ int qemu_reset_requested(void)
     return r;
 }
 
+static int qemu_suspend_requested(void)
+{
+    int r = suspend_requested;
+    suspend_requested = 0;
+    return r;
+}
+
 int qemu_powerdown_requested(void)
 {
     int r = powerdown_requested;
@@ -1398,6 +1412,56 @@ void qemu_system_reset_request(void)
     qemu_notify_event();
 }
 
+static void qemu_system_suspend(void)
+{
+    pause_all_vcpus();
+    notifier_list_notify(&suspend_notifiers, NULL);
+    is_suspended = true;
+}
+
+void qemu_system_suspend_request(void)
+{
+    if (is_suspended) {
+        return;
+    }
+    suspend_requested = 1;
+    cpu_stop_current();
+    qemu_notify_event();
+}
+
+void qemu_register_suspend_notifier(Notifier *notifier)
+{
+    notifier_list_add(&suspend_notifiers, notifier);
+}
+
+void qemu_system_wakeup_request(WakeupReason reason)
+{
+    if (!is_suspended) {
+        return;
+    }
+    if (!(wakeup_reason_mask & (1 << reason))) {
+        return;
+    }
+    notifier_list_notify(&wakeup_notifiers, &reason);
+    reset_requested = 1;
+    qemu_notify_event();
+    is_suspended = false;
+}
+
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
+{
+    if (enabled) {
+        wakeup_reason_mask |= (1 << reason);
+    } else {
+        wakeup_reason_mask &= ~(1 << reason);
+    }
+}
+
+void qemu_register_wakeup_notifier(Notifier *notifier)
+{
+    notifier_list_add(&wakeup_notifiers, notifier);
+}
+
 void qemu_system_killed(int signal, pid_t pid)
 {
     shutdown_signal = signal;
@@ -1438,6 +1502,9 @@ static bool main_loop_should_exit(void)
     if (qemu_debug_requested()) {
         vm_stop(RUN_STATE_DEBUG);
     }
+    if (qemu_suspend_requested()) {
+        qemu_system_suspend();
+    }
     if (qemu_shutdown_requested()) {
         qemu_kill_report();
         monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-02-14 14:49 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-09 17:05 [Qemu-devel] [PATCH v4 00/11] initial suspend support Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 01/11] acpi: move around structs Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 02/11] acpi: add ACPIREGS Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 03/11] acpi: don't pass overflow_time to acpi_pm1_evt_get_sts Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 04/11] acpi: add acpi_pm1_evt_write_en Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure Gerd Hoffmann
2012-02-13  9:21   ` Gleb Natapov
2012-02-14  8:18     ` Gerd Hoffmann
2012-02-14  8:37       ` Gleb Natapov
2012-02-14  8:57         ` Gerd Hoffmann
2012-02-14  9:08           ` Gleb Natapov
2012-02-14 14:49             ` Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 06/11] suspend: switch acpi s3 to new infrastructure Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 07/11] suspend: add system_wakeup monitor command Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 08/11] suspend: make ps/2 devices wakeup the guest Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 09/11] suspend: make serial ports " Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 10/11] suspend: make rtc alarm " Gerd Hoffmann
2012-02-09 17:05 ` [Qemu-devel] [PATCH v4 11/11] suspend: pmtimer s3 wakeup Gerd Hoffmann
2012-02-10 12:43 ` [Qemu-devel] [PATCH 12/11] suspend: add qmp events Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).