KVM supports the ability to use ACPI to shutdown guests.  In order to enable
this requires some fixes to be able to generate the SCI interrupt and the
appropriate plumbing.

This patch hasn't changed since v1.

Index: qemu/hw/acpi.c
===================================================================
--- qemu.orig/hw/acpi.c 2008-02-01 10:00:45.000000000 -0600
+++ qemu/hw/acpi.c      2008-02-01 11:12:46.000000000 -0600
@@ -49,6 +49,7 @@
     uint8_t smb_data1;
     uint8_t smb_data[32];
     uint8_t smb_index;
+    qemu_irq irq;
 } PIIX4PMState;
 
 #define RTC_EN (1 << 10)
@@ -71,6 +72,8 @@
 #define SMBHSTDAT1 0x06
 #define SMBBLKDAT 0x07
 
+PIIX4PMState *pm_state;
+
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
@@ -97,11 +100,12 @@
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) &
                   (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
-    qemu_set_irq(s->dev.irq[0], sci_level);
+    qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
     if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
         expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
         qemu_mod_timer(s->tmr_timer, expire_time);
+        s->tmr_overflow_time += 0x800000;
     } else {
         qemu_del_timer(s->tmr_timer);
     }
@@ -467,7 +471,8 @@
     return 0;
 }
 
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+                       qemu_irq sci_irq)
 {
     PIIX4PMState *s;
     uint8_t *pci_conf;
@@ -475,6 +480,7 @@
     s = (PIIX4PMState *)pci_register_device(bus,
                                          "PM", sizeof(PIIX4PMState),
                                          devfn, NULL, pm_write_config);
+    pm_state = s;
     pci_conf = s->dev.config;
     pci_conf[0x00] = 0x86;
     pci_conf[0x01] = 0x80;
@@ -514,5 +520,16 @@
     register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
 
     s->smbus = i2c_init_bus();
+    s->irq = sci_irq;
     return s->smbus;
 }
+
+#if defined(TARGET_I386)
+void qemu_system_powerdown(void)
+{
+    if(pm_state->pmen & PWRBTN_EN) {
+        pm_state->pmsts |= PWRBTN_EN;
+       pm_update_sci(pm_state);
+    }
+}
+#endif
Index: qemu/hw/mips_malta.c
===================================================================
--- qemu.orig/hw/mips_malta.c   2008-02-01 11:06:54.000000000 -0600
+++ qemu/hw/mips_malta.c        2008-02-01 11:12:46.000000000 -0600
@@ -905,7 +905,7 @@
     piix4_devfn = piix4_init(pci_bus, 80);
     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
-    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
+    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, i8259[9]);
     eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
     for (i = 0; i < 8; i++) {
         /* TODO: Populate SPD eeprom data.  */
Index: qemu/hw/pc.c
===================================================================
--- qemu.orig/hw/pc.c   2008-02-01 11:07:04.000000000 -0600
+++ qemu/hw/pc.c        2008-02-01 11:12:46.000000000 -0600
@@ -1006,7 +1006,7 @@
         i2c_bus *smbus;
 
         /* TODO: Populate SPD eeprom data.  */
-        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100);
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]);
         for (i = 0; i < 8; i++) {
             smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
         }
Index: qemu/hw/pc.h
===================================================================
--- qemu.orig/hw/pc.h   2008-02-01 10:00:45.000000000 -0600
+++ qemu/hw/pc.h        2008-02-01 11:12:46.000000000 -0600
@@ -88,7 +88,8 @@
 
 /* acpi.c */
 extern int acpi_enabled;
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+                       qemu_irq sci_irq);
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 void acpi_bios_init(void);
 
Index: qemu/hw/piix_pci.c
===================================================================
--- qemu.orig/hw/piix_pci.c     2008-02-01 10:00:45.000000000 -0600
+++ qemu/hw/piix_pci.c  2008-02-01 11:12:46.000000000 -0600
@@ -220,7 +220,6 @@
 {
     int i, pic_irq, pic_level;
 
-    piix3_dev->config[0x60 + irq_num] &= ~0x80;   // enable bit
     pci_irq_levels[irq_num] = level;
 
     /* now we change the pic irq level according to the piix irq mappings */
Index: qemu/sysemu.h
===================================================================
--- qemu.orig/sysemu.h  2008-02-01 11:06:54.000000000 -0600
+++ qemu/sysemu.h       2008-02-01 11:12:46.000000000 -0600
@@ -31,12 +31,16 @@
 void qemu_system_reset_request(void);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
-#if !defined(TARGET_SPARC)
+int qemu_shutdown_requested(void);
+int qemu_reset_requested(void);
+int qemu_powerdown_requested(void);
+#if !defined(TARGET_SPARC) && !defined(TARGET_I386)
 // Please implement a power failure function to signal the OS
 #define qemu_system_powerdown() do{}while(0)
 #else
 void qemu_system_powerdown(void);
 #endif
+void qemu_system_reset(void);
 
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
Index: qemu/vl.c
===================================================================
--- qemu.orig/vl.c      2008-02-01 11:11:39.000000000 -0600
+++ qemu/vl.c   2008-02-01 11:12:46.000000000 -0600
@@ -7262,6 +7262,27 @@
 static int shutdown_requested;
 static int powerdown_requested;
 
+int qemu_shutdown_requested(void)
+{
+    int r = shutdown_requested;
+    shutdown_requested = 0;
+    return r;
+}
+
+int qemu_reset_requested(void)
+{
+    int r = reset_requested;
+    reset_requested = 0;
+    return r;
+}
+
+int qemu_powerdown_requested(void)
+{
+    int r = powerdown_requested;
+    powerdown_requested = 0;
+    return r;
+}
+
 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
 {
     QEMUResetEntry **pre, *re;
@@ -7276,7 +7297,7 @@
     *pre = re;
 }
 
-static void qemu_system_reset(void)
+void qemu_system_reset(void)
 {
     QEMUResetEntry *re;
 


Reply via email to