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>
</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"));
+ goto error;
+ }
+
+ if (def->hyperv_spinlocks < 0xFFF) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("HyperV spinlock retry count must be
"
+ "at least 0xFFF"));
+ 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),
+ def->hyperv_spinlocks,
+ virDomainHypervTypeToString(i));
+ 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 HyperV spinlock retry count"));
+ goto cleanup;
+ }
+
+ if (virStrToLong_ui(value, NULL, 0, &dom->hyperv_spinlocks) <
0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("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'/>
--
1.8.1.5