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 | 7 +++
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 103 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_driver.c | 17 +++++++
4 files changed, 129 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 85c49a2..b4a662f 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -169,6 +169,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"virtio-s390",
"balloon-event",
+ "disable-s3", /* 100 */
+ "disable-s4",
);
struct qemu_feature_flags {
@@ -1396,6 +1398,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);
@@ -1487,6 +1490,10 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags)
qemuCapsSet(flags, QEMU_CAPS_SCSI_CD);
if (strstr(str, "ide-cd"))
qemuCapsSet(flags, QEMU_CAPS_IDE_CD);
+ 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;
}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index e8251dc..a909f67 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -135,6 +135,8 @@ enum qemuCapsFlags {
QEMU_CAPS_NEC_USB_XHCI = 97, /* -device nec-usb-xhci */
QEMU_CAPS_VIRTIO_S390 = 98, /* -device virtio-*-s390 */
QEMU_CAPS_BALLOON_EVENT = 99, /* Async event for balloon changes */
+ QEMU_CAPS_DISABLE_S3 = 100, /* S3 BIOS Advertisement on/off */
+ QEMU_CAPS_DISABLE_S4 = 101, /* S4 BIOS Advertisement on/off */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6ad65a6..a30c2f1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4692,6 +4692,48 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArg(cmd, "-no-acpi");
}
+ if (def->pm.s3) {
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_DISABLE_S3)) {
+ if (def->pm.s3 == VIR_DOMAIN_PM_STATE_ON)
+ virCommandAddArgList(cmd,
+ "-global",
+ "PIIX4_PM.disable_s3=0",
+ NULL);
+
+ else if (def->pm.s3 == VIR_DOMAIN_PM_STATE_OFF)
+ virCommandAddArgList(cmd,
+ "-global",
+ "PIIX4_PM.disable_s3=1",
+ NULL);
+
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("setting ACPI S3 not
supported"));
+ goto error;
+ }
+ }
+
+ if (def->pm.s4) {
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_DISABLE_S4)) {
+ if (def->pm.s4 == VIR_DOMAIN_PM_STATE_ON)
+ virCommandAddArgList(cmd,
+ "-global",
+ "PIIX4_PM.disable_s4=0",
+ NULL);
+
+ else if (def->pm.s4 == VIR_DOMAIN_PM_STATE_OFF)
+ virCommandAddArgList(cmd,
+ "-global",
+ "PIIX4_PM.disable_s4=1",
+ NULL);
+
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("setting ACPI S4 not
supported"));
+ goto error;
+ }
+ }
+
if (!def->os.bootloader) {
/*
* We prefer using explicit bootindex=N parameters for predictable
@@ -8199,6 +8241,67 @@ 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 (strlen(val) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid value for disable_s3 parameter: "
+ "'%s'"), val);
+ goto error;
+ }
+
+ switch (*val) {
+ case '0':
+ def->pm.s3 = VIR_DOMAIN_PM_STATE_ON;
+ break;
+
+ case '1':
+ def->pm.s3 = VIR_DOMAIN_PM_STATE_OFF;
+ break;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("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 (strlen(val) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid value for disable_s4 parameter: "
+ "'%s'"), val);
+ goto error;
+ }
+
+ switch (*val) {
+ case '0':
+ def->pm.s4 = VIR_DOMAIN_PM_STATE_ON;
+ break;
+
+ case '1':
+ def->pm.s4 = VIR_DOMAIN_PM_STATE_OFF;
+ break;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid value for disable_s4 parameter: "
+ "'%s'"), val);
+ goto error;
+ }
+
} else if (STREQ(arg, "-S")) {
/* ignore, always added by libvirt */
} else {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b3f946c..24712ce 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13066,6 +13066,23 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
goto cleanup;
}
+ if (vm->def->pm.s3 || vm->def->pm.s4) {
+ if (!vm->def->pm.s3 == VIR_DOMAIN_PM_STATE_OFF &&
+ (target == VIR_NODE_SUSPEND_TARGET_MEM ||
+ target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("S3 signals are disabled for this domain"));
+ goto cleanup;
+ }
+
+ if (vm->def->pm.s4 == VIR_DOMAIN_PM_STATE_OFF &&
+ target == VIR_NODE_SUSPEND_TARGET_DISK) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("S4 signals are disabled for this domain"));
+ goto cleanup;
+ }
+ }
+
if (priv->agentError) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("QEMU guest agent is not available due to an
error"));
--
1.7.8.6