[libvirt] [PATCH v3 2/2] qemu: add hv_vapic and hv_spinlocks support

Peter Krempa pkrempa at redhat.com
Thu Jun 6 09:01:18 UTC 2013


On 06/05/13 17:50, Ján Tomko wrote:
> Add new CPU flags for HyperV:
> hv_vapic for virtual APIC support
> hv_spinlocks for spinlock support
>
> XML:
> <features>
>    <hyperv>
>      <vapic state='on'/>
>      <spinlocks>0xFFFF</spinlocks>

Is the Microsoft documentation for this feature use hex values?

>    </hyperv>
> </features>
>
> results in the following QEMU command line:
> qemu -cpu <cpu_model>,hv_vapic,hv_spinlocks=0xffff
>
> https://bugzilla.redhat.com/show_bug.cgi?id=784836
> ---
>   docs/formatdomain.html.in                       | 17 ++++++++-
>   docs/schemas/domaincommon.rng                   | 12 +++++++
>   src/conf/domain_conf.c                          | 40 ++++++++++++++++++++-
>   src/conf/domain_conf.h                          |  3 ++
>   src/qemu/qemu_command.c                         | 48 ++++++++++++++++++++++++-
>   tests/qemuxml2argvdata/qemuxml2argv-hyperv.args |  2 +-
>   tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml  |  2 ++
>   7 files changed, 120 insertions(+), 4 deletions(-)
>
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index 755d084..983e070 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -1147,6 +1147,8 @@
>       <privnet/>
>       <hyperv>
>         <relaxed state='on'/>
> +      <vapic state='on'/>
> +      <spinlocks>0xFFFF</spinlocks>
>       </hyperv>
>
>     </features>
> @@ -1197,14 +1199,27 @@
>             <th>Feature</th>
>             <th>Description</th>
>             <th>Value</th>
> +          <th>Since</th>
>           </tr>
>           <tr>
>             <td>relaxed</td>
>             <td>Relax contstraints on timers</td>
>             <td> on, off</td>
> +          <td><span class="since">1.0.0 (QEMU only)</span></td>
> +        </tr>
> +        <tr>
> +          <td>vapic</td>
> +          <td>Enable virtual APIC</td>
> +          <td>on, off</td>
> +          <td><span class="since">1.0.6 (QEMU only)</span></td>
> +        </tr>
> +        <tr>
> +          <td>spinlocks</td>
> +          <td>Enable spinlock support</td>
> +          <td>hexadecimal number of retries, at least 0xFFF</td>
> +          <td><span class="since">1.0.6 (QEMU only)</span></td>
>           </tr>
>         </table>
> -      <span class="since">Since 1.0.0 (QEMU only)</span>
>         </dd>
>       </dl>
>
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 3cace35..ff14f34 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -4017,6 +4017,18 @@
>               <ref name="hypervtristate"/>
>             </element>
>           </optional>
> +        <optional>
> +          <element name="vapic">
> +            <ref name="hypervtristate"/>
> +          </element>
> +        </optional>
> +        <optional>
> +          <element name="spinlocks">
> +            <data type="string">
> +              <param name="pattern">0x[0-9a-fA-F]{0,8}</param>
> +            </data>
> +          </element>
> +        </optional>
>         </interleave>
>       </element>
>     </define>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index a16ebd1..3d231a5 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -148,7 +148,9 @@ VIR_ENUM_IMPL(virDomainFeatureState, VIR_DOMAIN_FEATURE_STATE_LAST,
>                 "off")
>
>   VIR_ENUM_IMPL(virDomainHyperv, VIR_DOMAIN_HYPERV_LAST,
> -              "relaxed")
> +              "relaxed",
> +              "vapic",
> +              "spinlocks")
>
>   VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
>                 "destroy",
> @@ -11061,6 +11063,7 @@ virDomainDefParseXML(xmlDocPtr xml,
>
>               switch ((enum virDomainHyperv) feature) {
>                   case VIR_DOMAIN_HYPERV_RELAXED:
> +                case VIR_DOMAIN_HYPERV_VAPIC:
>                       if (!(tmp = virXPathString("string(./@state)", ctxt))) {
>                           virReportError(VIR_ERR_XML_ERROR,
>                                          _("missing 'state' attribute for "
> @@ -11081,6 +11084,32 @@ virDomainDefParseXML(xmlDocPtr xml,
>                       def->hyperv_features[feature] = value;
>                       break;
>
> +                case VIR_DOMAIN_HYPERV_SPINLOCKS:
> +                    if (!(tmp = virXPathString("string(.)", ctxt))) {
> +                        virReportError(VIR_ERR_XML_ERROR,
> +                                       _("missing HyperV spinlock retry count"));
> +                        goto error;
> +                    }
> +
> +                    if (virStrToLong_ui(tmp, NULL, 0,
> +                                        &def->hyperv_spinlocks) < 0) {
> +                        virReportError(VIR_ERR_XML_ERROR,
> +                                       _("Cannot parse HyperV spinlock retry "
> +                                         "count"));

Missing formatting literal "%s" (breaks syntax-check)

> +                        goto error;
> +                    }
> +
> +                    if (def->hyperv_spinlocks < 0xFFF) {
> +                        virReportError(VIR_ERR_XML_ERROR,
> +                                       _("HyperV spinlock retry count must be "
> +                                         "at least 0xFFF"));

Missing formatting literal "%s" (breaks syntax-check)

> +                        goto error;
> +                    }
> +                    VIR_FREE(tmp);
> +                    def->hyperv_features[VIR_DOMAIN_HYPERV_SPINLOCKS] =
> +                        VIR_DOMAIN_FEATURE_STATE_ON;
> +                    break;
> +
>                   case VIR_DOMAIN_HYPERV_LAST:
>                       break;
>               }
> @@ -16175,12 +16204,21 @@ virDomainDefFormatInternal(virDomainDefPtr def,
>               for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
>                   switch ((enum virDomainHyperv) i) {
>                   case VIR_DOMAIN_HYPERV_RELAXED:
> +                case VIR_DOMAIN_HYPERV_VAPIC:
>                       if (def->hyperv_features[i])
>                           virBufferAsprintf(buf, "      <%s state='%s'/>\n",
>                                             virDomainHypervTypeToString(i),
>                                             virDomainFeatureStateTypeToString(def->hyperv_features[i]));
>                       break;
>
> +                case VIR_DOMAIN_HYPERV_SPINLOCKS:
> +                    if (def->hyperv_features[i])
> +                        virBufferAsprintf(buf, "      <%s>0x%x</%s>\n",
> +                                          virDomainHypervTypeToString(i),

The spinlocks case statement doesn't seem to be universal. You can avoid 
a function call by directly using the XML field name instead of doing 
virDomainHypervTypeToString().

> +                                          def->hyperv_spinlocks,
> +                                          virDomainHypervTypeToString(i));

Twice.

> +                    break;
> +
>                   case VIR_DOMAIN_HYPERV_LAST:
>                       break;
>                   }
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 3a71d6c..cce1189 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1583,6 +1583,8 @@ enum virDomainFeatureState {
>
>   enum virDomainHyperv {
>       VIR_DOMAIN_HYPERV_RELAXED = 0,
> +    VIR_DOMAIN_HYPERV_VAPIC,
> +    VIR_DOMAIN_HYPERV_SPINLOCKS,
>
>       VIR_DOMAIN_HYPERV_LAST
>   };
> @@ -1920,6 +1922,7 @@ struct _virDomainDef {
>       int apic_eoi;
>       /* These options are of type virDomainFeatureState */
>       int hyperv_features[VIR_DOMAIN_HYPERV_LAST];
> +    unsigned int hyperv_spinlocks;
>
>       virDomainClockDef clock;
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 5513e28..b0119d8 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -5782,11 +5782,18 @@ qemuBuildCpuArgStr(const virQEMUDriverPtr driver,
>           for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
>               switch ((enum virDomainHyperv) i) {
>               case VIR_DOMAIN_HYPERV_RELAXED:
> +            case VIR_DOMAIN_HYPERV_VAPIC:
>                   if (def->hyperv_features[i] == VIR_DOMAIN_FEATURE_STATE_ON)
>                       virBufferAsprintf(&buf, ",hv_%s",
>                                         virDomainHypervTypeToString(i));
>                   break;
>
> +            case VIR_DOMAIN_HYPERV_SPINLOCKS:
> +                if (def->hyperv_features[i] == VIR_DOMAIN_FEATURE_STATE_ON)
> +                    virBufferAsprintf(&buf,",hv_spinlocks=0x%x",
> +                                      def->hyperv_spinlocks);
> +                break;
> +
>               case VIR_DOMAIN_HYPERV_LAST:
>                   break;
>               }
> @@ -9623,6 +9630,7 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
>   {
>       virCPUDefPtr cpu = NULL;
>       char **tokens;
> +    char **hv_tokens = NULL;
>       char *model = NULL;
>       int ret = -1;
>       int i;
> @@ -9702,9 +9710,19 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
>                       goto cleanup;
>               }
>           } else if (STRPREFIX(tokens[i], "hv_")) {
> -            const char *feature = tokens[i] + 3; /* "hv_" */
> +            const char *token = tokens[i] + 3; /* "hv_" */
> +            const char *feature, *value;
>               int f;
>
> +            if (*token == '\0')
> +                goto syntax;
> +
> +            if (!(hv_tokens = virStringSplit(token, "=", 2)))
> +                goto cleanup;
> +
> +            feature = hv_tokens[0];
> +            value = hv_tokens[1];
> +
>               if (*feature == '\0')
>                   goto syntax;
>
> @@ -9719,12 +9737,39 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
>
>               switch ((enum virDomainHyperv) f) {
>               case VIR_DOMAIN_HYPERV_RELAXED:
> +            case VIR_DOMAIN_HYPERV_VAPIC:
> +                if (value) {
> +                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                                   _("HyperV feature '%s' should not "
> +                                     "have a value"), feature);
> +                    goto cleanup;
> +                }
>                   dom->hyperv_features[f] = VIR_DOMAIN_FEATURE_STATE_ON;
>                   break;
>
> +            case VIR_DOMAIN_HYPERV_SPINLOCKS:
> +                dom->hyperv_features[f] = VIR_DOMAIN_FEATURE_STATE_ON;
> +                if (!hv_tokens[1]) {
> +                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,

Missing formatting literal "%s" (breaks syntax-check)

> +                                   _("missing HyperV spinlock retry count"));
> +                    goto cleanup;
> +                }
> +
> +                if (virStrToLong_ui(value, NULL, 0, &dom->hyperv_spinlocks) < 0) {
> +                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,

Missing formatting literal "%s" (breaks syntax-check)

> +                                   _("cannot parse HyperV spinlock retry count"));
> +                    goto cleanup;
> +                }
> +
> +                if (dom->hyperv_spinlocks < 0xFFF)
> +                    dom->hyperv_spinlocks = 0xFFF;
> +                break;
> +
>               case VIR_DOMAIN_HYPERV_LAST:
>                   break;
>               }
> +            virStringFreeList(hv_tokens);
> +            hv_tokens = NULL;
>           }
>       }
>
> @@ -9752,6 +9797,7 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
>   cleanup:
>       VIR_FREE(model);
>       virStringFreeList(tokens);
> +    virStringFreeList(hv_tokens);
>       return ret;
>
>   syntax:
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args
> index fac4d5f..df6b207 100644
> --- a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args
> @@ -1,4 +1,4 @@
>   LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \
> --cpu qemu32,hv_relaxed -m 214 -smp 6 -nographic -monitor \
> +-cpu qemu32,hv_relaxed,hv_vapic,hv_spinlocks=0x2fff -m 214 -smp 6 -nographic -monitor \
>   unix:/tmp/test-monitor,server,nowait -boot n -usb -net none -serial none \
>   -parallel none
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml
> index 0d5d0c7..9601645 100644
> --- a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml
> @@ -12,6 +12,8 @@
>       <acpi/>
>       <hyperv>
>         <relaxed state='on'/>
> +      <vapic state='on'/>
> +      <spinlocks>0x2fff</spinlocks>
>       </hyperv>
>     </features>
>     <clock offset='utc'/>
>

Peter




More information about the libvir-list mailing list