"lsi",
"virtio-scsi-pci",
"iolimits",
+ "disable-s3",
+ "disable-s4", /* 105 */
);
struct qemu_feature_flags {
"-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);
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;
}
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 */
};
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
*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 {
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 "