From: Michal Privoznik <mprivozn@redhat.com>
So far the set of available Hyper-V enlightenments are reported
in domain capabilities. Well, some enlightenments are more than
just simple on/off switch. For instance, the 'spinlocks'
enlightenment expects a number, or 'vendor_id' expects a string.
All of these have some default values (at least in QEMU) and are
used when the passthrough mode is set.
Allow querying these defaults in domain capabilities XML.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
docs/formatdomaincaps.rst | 5 ++-
src/conf/domain_capabilities.c | 61 ++++++++++++++++++++++++++++++++-
src/conf/domain_capabilities.h | 11 ++++++
src/conf/schemas/domaincaps.rng | 29 ++++++++++++++++
src/libvirt_private.syms | 2 ++
src/qemu/qemu_capabilities.c | 12 +++----
6 files changed, 111 insertions(+), 9 deletions(-)
diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst
index 4eb8211b09..32dc09d41e 100644
--- a/docs/formatdomaincaps.rst
+++ b/docs/formatdomaincaps.rst
@@ -869,7 +869,10 @@ Hyper-V Enlightenments
Report which features improving behavior of guests running Microsoft Windows
are supported. The ``features`` enum corresponds to the ``<hyperv/>`` element
(well, its children) as documented in `Hypervisor features
-<formatdomain.html#hypervisor-features>`__.
+<formatdomain.html#hypervisor-features>`__. The ``defaults`` element then
+contains child elements describing default values as reported by hypervisor,
+e.h. whether direct or extended TLB flushes are available. :since:`(since
+11.9.0)`
Launch security
^^^^^^^^^^^^^^^
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index f29c4e0515..422b68c085 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -92,6 +92,32 @@ virSGXCapabilitiesFree(virSGXCapability *cap)
}
+void
+virDomainCapsFeatureHypervFree(virDomainCapsFeatureHyperv *cap)
+{
+ if (!cap)
+ return;
+
+ g_free(cap->vendor_id);
+ g_free(cap);
+}
+
+
+virDomainCapsFeatureHyperv *
+virDomainCapsFeatureHypervCopy(virDomainCapsFeatureHyperv *cap)
+{
+ virDomainCapsFeatureHyperv *ret = NULL;
+
+ if (!cap)
+ return NULL;
+
+ ret = g_memdup2(cap, sizeof(virDomainCapsFeatureHyperv));
+ ret->vendor_id = g_strdup(cap->vendor_id);
+
+ return ret;
+}
+
+
static void
virDomainCapsDispose(void *obj)
{
@@ -105,7 +131,7 @@ virDomainCapsDispose(void *obj)
virCPUDefFree(caps->cpu.hostModel);
virSEVCapabilitiesFree(caps->sev);
virSGXCapabilitiesFree(caps->sgx);
- g_free(caps->hyperv);
+ virDomainCapsFeatureHypervFree(caps->hyperv);
values = &caps->os.loader.values;
for (i = 0; i < values->nvalues; i++)
@@ -791,6 +817,8 @@ static void
virDomainCapsFeatureHypervFormat(virBuffer *buf,
const virDomainCapsFeatureHyperv *hyperv)
{
+ virBuffer defaults = VIR_BUFFER_INIT_CHILD(buf);
+
if (!hyperv)
return;
@@ -798,6 +826,37 @@ virDomainCapsFeatureHypervFormat(virBuffer *buf,
ENUM_PROCESS(hyperv, features, virDomainHypervTypeToString);
+ virBufferAdjustIndent(&defaults, 2);
+
+ if (VIR_DOMAIN_CAPS_ENUM_IS_SET(hyperv->features, VIR_DOMAIN_HYPERV_SPINLOCKS) &&
+ hyperv->spinlocks != 0) {
+ virBufferAsprintf(&defaults, "<spinlocks>%u</spinlocks>\n", hyperv->spinlocks);
+ }
+
+ if (VIR_DOMAIN_CAPS_ENUM_IS_SET(hyperv->features, VIR_DOMAIN_HYPERV_STIMER) &&
+ hyperv->stimer_direct != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&defaults, "<stimer_direct>%s</stimer_direct>\n",
+ virTristateSwitchTypeToString(hyperv->stimer_direct));
+ }
+
+ if (VIR_DOMAIN_CAPS_ENUM_IS_SET(hyperv->features, VIR_DOMAIN_HYPERV_TLBFLUSH)) {
+ if (hyperv->tlbflush_direct != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&defaults, "<tlbflush_direct>%s</tlbflush_direct>\n",
+ virTristateSwitchTypeToString(hyperv->tlbflush_direct));
+ }
+
+ if (hyperv->tlbflush_extended != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&defaults, "<tlbflush_extended>%s</tlbflush_extended>\n",
+ virTristateSwitchTypeToString(hyperv->tlbflush_extended));
+ }
+ }
+
+ if (VIR_DOMAIN_CAPS_ENUM_IS_SET(hyperv->features, VIR_DOMAIN_HYPERV_VENDOR_ID)) {
+ virBufferEscapeString(&defaults, "<vendor_id>%s</vendor_id>\n", hyperv->vendor_id);
+ }
+
+ virXMLFormatElement(buf, "defaults", NULL, &defaults);
+
FORMAT_EPILOGUE(hyperv);
}
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 43141dbdd5..437981c711 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -163,6 +163,11 @@ typedef struct _virDomainCapsFeatureHyperv virDomainCapsFeatureHyperv;
struct _virDomainCapsFeatureHyperv {
virTristateBool supported;
virDomainCapsEnum features; /* Info about supported virDomainHyperv features */
+ unsigned int spinlocks;
+ virTristateSwitch stimer_direct;
+ virTristateSwitch tlbflush_direct;
+ virTristateSwitch tlbflush_extended;
+ char *vendor_id;
};
STATIC_ASSERT_ENUM(VIR_DOMAIN_LAUNCH_SECURITY_LAST);
@@ -378,3 +383,9 @@ void
virSGXCapabilitiesFree(virSGXCapability *capabilities);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSGXCapability, virSGXCapabilitiesFree);
+
+void virDomainCapsFeatureHypervFree(virDomainCapsFeatureHyperv *capabilities);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainCapsFeatureHyperv, virDomainCapsFeatureHypervFree);
+
+virDomainCapsFeatureHyperv *
+virDomainCapsFeatureHypervCopy(virDomainCapsFeatureHyperv *cap);
diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng
index 7edae54931..8d0380951d 100644
--- a/src/conf/schemas/domaincaps.rng
+++ b/src/conf/schemas/domaincaps.rng
@@ -509,6 +509,35 @@
<element name="hyperv">
<ref name="supported"/>
<ref name="enum"/>
+ <optional>
+ <element name="defaults">
+ <optional>
+ <element name="spinlocks">
+ <ref name="unsignedInt"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="stimer_direct">
+ <ref name="virOnOff"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="tlbflush_direct">
+ <ref name="virOnOff"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="tlbflush_extended">
+ <ref name="virOnOff"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="vendor_id">
+ <text/>
+ </element>
+ </optional>
+ </element>
+ </optional>
</element>
</define>
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1a4f47aabc..26776dff2a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -217,6 +217,8 @@ virDomainCapsCPUUsableTypeFromString;
virDomainCapsCPUUsableTypeToString;
virDomainCapsEnumClear;
virDomainCapsEnumSet;
+virDomainCapsFeatureHypervCopy;
+virDomainCapsFeatureHypervFree;
virDomainCapsFormat;
virDomainCapsNew;
virSEVCapabilitiesFree;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5b485d7bfb..2ccddbfcaa 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2070,8 +2070,7 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps)
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC))
virQEMUCapsSGXInfoCopy(&ret->sgxCapabilities, qemuCaps->sgxCapabilities);
- ret->hypervCapabilities = g_memdup2(qemuCaps->hypervCapabilities,
- sizeof(virDomainCapsFeatureHyperv));
+ ret->hypervCapabilities = virDomainCapsFeatureHypervCopy(qemuCaps->hypervCapabilities);
return g_steal_pointer(&ret);
}
@@ -2113,7 +2112,7 @@ void virQEMUCapsDispose(void *obj)
virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
virSGXCapabilitiesFree(qemuCaps->sgxCapabilities);
- g_free(qemuCaps->hypervCapabilities);
+ virDomainCapsFeatureHypervFree(qemuCaps->hypervCapabilities);
virQEMUCapsAccelClear(&qemuCaps->kvm);
virQEMUCapsAccelClear(&qemuCaps->hvf);
@@ -3138,7 +3137,7 @@ static int
virQEMUCapsProbeHypervCapabilities(virQEMUCaps *qemuCaps,
qemuMonitorCPUModelInfo *fullQEMU)
{
- g_autofree virDomainCapsFeatureHyperv *hvcaps = NULL;
+ g_autoptr(virDomainCapsFeatureHyperv) hvcaps = NULL;
size_t i;
if (!fullQEMU)
@@ -4494,7 +4493,7 @@ static int
virQEMUCapsParseHypervCapabilities(virQEMUCaps *qemuCaps,
xmlXPathContextPtr ctxt)
{
- g_autofree virDomainCapsFeatureHyperv *hvcaps = NULL;
+ g_autoptr(virDomainCapsFeatureHyperv) hvcaps = NULL;
xmlNodePtr n = NULL;
g_autofree xmlNodePtr *capNodes = NULL;
int ncapNodes;
@@ -6930,8 +6929,7 @@ static void
virQEMUCapsFillDomainFeatureHypervCaps(virQEMUCaps *qemuCaps,
virDomainCaps *domCaps)
{
- domCaps->hyperv = g_memdup2(qemuCaps->hypervCapabilities,
- sizeof(virDomainCapsFeatureHyperv));
+ domCaps->hyperv = virDomainCapsFeatureHypervCopy(qemuCaps->hypervCapabilities);
}
--
2.49.1