]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: Add support for S3/S4 state configuration
authorMartin Kletzander <mkletzan@redhat.com>
Thu, 2 Aug 2012 10:14:39 +0000 (12:14 +0200)
committerMartin Kletzander <mkletzan@redhat.com>
Mon, 3 Sep 2012 07:32:39 +0000 (09:32 +0200)
This patch adds support for running qemu guests with the required
parameters to forcefully enable or disable BIOS advertising of S3 and
S4 states.  The support for this is added to capabilities and there is
also a qemu command parameter parsing implemented.

src/qemu/qemu_capabilities.c
src/qemu/qemu_capabilities.h
src/qemu/qemu_command.c
src/qemu/qemu_driver.c

index 7b29a813a67f2dfb26bdc57b8696c1135cab3bd5..2ba7956e693f37d7b9a5b1902a059b485673f7b4 100644 (file)
@@ -173,7 +173,9 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
               "lsi",
               "virtio-scsi-pci",
               "iolimits",
+              "disable-s3",
 
+              "disable-s4", /* 105 */
     );
 
 struct qemu_feature_flags {
@@ -1404,6 +1406,7 @@ qemuCapsExtractDeviceStr(const char *qemu,
                          "-device", "virtio-blk-pci,?",
                          "-device", "virtio-net-pci,?",
                          "-device", "scsi-disk,?",
+                         "-device", "PIIX4_PM,?",
                          NULL);
     /* qemu -help goes to stdout, but qemu -device ? goes to stderr.  */
     virCommandSetErrorBuffer(cmd, &output);
@@ -1510,6 +1513,10 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags)
     if (strstr(str, ".logical_block_size") &&
         strstr(str, ".physical_block_size"))
         qemuCapsSet(flags, QEMU_CAPS_IOLIMITS);
+    if (strstr(str, "PIIX4_PM.disable_s3="))
+        qemuCapsSet(flags, QEMU_CAPS_DISABLE_S3);
+    if (strstr(str, "PIIX4_PM.disable_s4="))
+        qemuCapsSet(flags, QEMU_CAPS_DISABLE_S4);
 
     return 0;
 }
index b0e41ba49cc1cbe0c1cf05fe4c62a58d960459fa..a7b3a061c4c5704136fa3efa4862f63ae78e695a 100644 (file)
@@ -139,6 +139,8 @@ enum qemuCapsFlags {
     QEMU_CAPS_SCSI_LSI           = 101, /* -device lsi */
     QEMU_CAPS_VIRTIO_SCSI_PCI    = 102, /* -device virtio-scsi-pci */
     QEMU_CAPS_IOLIMITS           = 103, /* -device ...logical_block_size & co */
+    QEMU_CAPS_DISABLE_S3         = 104, /* S3 BIOS Advertisement on/off */
+    QEMU_CAPS_DISABLE_S4         = 105, /* S4 BIOS Advertisement on/off */
 
     QEMU_CAPS_LAST,                   /* this must always be the last item */
 };
index 51a225b2a79c28de69a1e69a1e6929a3bdeffb65..e739f34e3f2ead7af3a8679634315370a5b4d19d 100644 (file)
@@ -4790,6 +4790,28 @@ qemuBuildCommandLine(virConnectPtr conn,
             virCommandAddArg(cmd, "-no-acpi");
     }
 
+    if (def->pm.s3) {
+        if (!qemuCapsGet(qemuCaps, QEMU_CAPS_DISABLE_S3)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           "%s", _("setting ACPI S3 not supported"));
+            goto error;
+        }
+        virCommandAddArg(cmd, "-global");
+        virCommandAddArgFormat(cmd, "PIIX4_PM.disable_s3=%d",
+                               def->pm.s3 == VIR_DOMAIN_PM_STATE_DISABLED);
+    }
+
+    if (def->pm.s4) {
+        if (!qemuCapsGet(qemuCaps, QEMU_CAPS_DISABLE_S4)) {
+         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           "%s", _("setting ACPI S4 not supported"));
+            goto error;
+        }
+        virCommandAddArg(cmd, "-global");
+        virCommandAddArgFormat(cmd, "PIIX4_PM.disable_s4=%d",
+                               def->pm.s4 == VIR_DOMAIN_PM_STATE_DISABLED);
+    }
+
     if (!def->os.bootloader) {
         /*
          * We prefer using explicit bootindex=N parameters for predictable
@@ -8376,6 +8398,42 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
 
                 *monConfig = chr;
             }
+        } else if (STREQ(arg, "-global") &&
+                   STRPREFIX(progargv[i + 1], "PIIX4_PM.disable_s3=")) {
+            /* We want to parse only the known "-global" parameters,
+             * so the ones that we don't know are still added to the
+             * namespace */
+            WANT_VALUE();
+
+            val += strlen("PIIX4_PM.disable_s3=");
+            if (STREQ(val, "0"))
+                def->pm.s3 = VIR_DOMAIN_PM_STATE_ENABLED;
+            else if (STREQ(val, "1"))
+                def->pm.s3 = VIR_DOMAIN_PM_STATE_DISABLED;
+            else {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("invalid value for disable_s3 parameter: "
+                                 "'%s'"), val);
+                goto error;
+            }
+
+        } else if (STREQ(arg, "-global") &&
+                   STRPREFIX(progargv[i + 1], "PIIX4_PM.disable_s4=")) {
+
+            WANT_VALUE();
+
+            val += strlen("PIIX4_PM.disable_s4=");
+            if (STREQ(val, "0"))
+                def->pm.s4 = VIR_DOMAIN_PM_STATE_ENABLED;
+            else if (STREQ(val, "1"))
+                def->pm.s4 = VIR_DOMAIN_PM_STATE_DISABLED;
+            else {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("invalid value for disable_s4 parameter: "
+                                 "'%s'"), val);
+                goto error;
+            }
+
         } else if (STREQ(arg, "-S")) {
             /* ignore, always added by libvirt */
         } else {
index 53d6e5b56e45d8327dcdd82d27328f40b4f9942a..b12d9bcd24c44838a9a920068d8a2ba241da14ec 100644 (file)
@@ -13722,6 +13722,23 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
         goto cleanup;
     }
 
+    if (vm->def->pm.s3 || vm->def->pm.s4) {
+        if (vm->def->pm.s3 == VIR_DOMAIN_PM_STATE_DISABLED &&
+            (target == VIR_NODE_SUSPEND_TARGET_MEM ||
+             target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("S3 state is disabled for this domain"));
+            goto cleanup;
+        }
+
+        if (vm->def->pm.s4 == VIR_DOMAIN_PM_STATE_DISABLED &&
+            target == VIR_NODE_SUSPEND_TARGET_DISK) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("S4 state is disabled for this domain"));
+            goto cleanup;
+        }
+    }
+
     if (priv->agentError) {
         virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                        _("QEMU guest agent is not "