[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