[libvirt] [PATCH v3 2/4] qemu: Add support for S3/S4 state configuration

Michal Privoznik mprivozn at redhat.com
Wed Aug 22 13:37:40 UTC 2012


On 09.08.2012 10:26, Martin Kletzander wrote:
> 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 5472267..b8160b6 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -172,6 +172,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
>                "bridge", /* 100 */
>                "lsi",
>                "virtio-scsi-pci",
> +              "disable-s3",
> +              "disable-s4",
> 
>      );
> 
> @@ -1403,6 +1405,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);
> @@ -1499,6 +1502,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 d606890..e49424a 100644
> --- a/src/qemu/qemu_capabilities.h
> +++ b/src/qemu/qemu_capabilities.h
> @@ -138,6 +138,8 @@ enum qemuCapsFlags {
>      QEMU_CAPS_NETDEV_BRIDGE      = 100, /* bridge helper support */
>      QEMU_CAPS_SCSI_LSI           = 101, /* -device lsi */
>      QEMU_CAPS_VIRTIO_SCSI_PCI    = 102, /* -device virtio-scsi-pci */
> +    QEMU_CAPS_DISABLE_S3         = 103, /* S3 BIOS Advertisement on/off */
> +    QEMU_CAPS_DISABLE_S4         = 104, /* 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 9383530..34ee00e 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -4761,6 +4761,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)

Redundant if. After the first condition def->pm.s3 can be either _ON or
_OFF. Nothing else.

> +                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)

ditto

> +                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
> @@ -8279,6 +8321,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,

it's not an internal error really.
s/VIR_ERR_INTERNAL_ERROR/VIR_ERR_CONFIG_UNSUPPORTED/

I know we misuse VIR_INTERNAL_ERROR in much places, but that should be
fixed too.

> +                               _("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,

s/VIR_ERR_INTERNAL_ERROR/VIR_ERR_CONFIG_UNSUPPORTED/

btw: what about optimizing this a bit? My intent is to join this and
previous virReportError() into one:

  val += strlen("PIIX4_PM.disable_s3=");
  if (STREQ(val, "0"))
    def->pm.s3 = VIR_DOMAIN_PM_STATE_ON;
  else if (STREQ(val, "1"))
    def->pm.s3 = VIR_DOMAIN_PM_STATE_OFF;
  else
    virReportError();

This apply for s4 as well.
> +                               _("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 dee1268..13d5917 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -13097,6 +13097,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"));

s/signals are/state is/

> +            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"));

ditto

> +            goto cleanup;
> +        }
> +    }
> +
>      if (priv->agentError) {
>          virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>                         _("QEMU guest agent is not available due to an error"));
> 

Otherwise looking good.

Michal




More information about the libvir-list mailing list