From b8216ec91703423bdeaba9319b2ad59c0d4addde Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Thu, 2 Aug 2012 12:14:39 +0200 Subject: [PATCH] qemu: Add support for S3/S4 state configuration 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 | 58 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_driver.c | 17 +++++++++++ 4 files changed, 84 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 7b29a813a6..2ba7956e69 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -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; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index b0e41ba49c..a7b3a061c4 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -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 */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 51a225b2a7..e739f34e3f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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 { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 53d6e5b56e..b12d9bcd24 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -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 " -- 2.47.2