286 lines
10 KiB
Diff
286 lines
10 KiB
Diff
From 7dc415a0708f4389bfb470c36cfaa3886882419f Mon Sep 17 00:00:00 2001
|
|
Message-ID: <7dc415a0708f4389bfb470c36cfaa3886882419f.1763133105.git.jdenemar@redhat.com>
|
|
From: Michal Privoznik <mprivozn@redhat.com>
|
|
Date: Tue, 30 Sep 2025 15:05:10 +0200
|
|
Subject: [PATCH] conf: Report default hyperv values in domain capabilities
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
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>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
(cherry picked from commit 57d2f4a0f0cbdb8006e99a3271bf363582843e91)
|
|
|
|
Conflicts:
|
|
- src/qemu/qemu_capabilities.c: Since
|
|
48f04627c8faf505a98e07e542729c135a615dcc is not backported yet,
|
|
the original code had g_memdup() but the bacported patch
|
|
expected g_memdup2().
|
|
|
|
Additionally, virDomainCapsFeatureHypervCopy() inside of
|
|
domain_capabilities.c had to be changed to use g_memdup() since
|
|
g_memdup2() wasn't introduced until glib-2.68.
|
|
|
|
Resolves: https://issues.redhat.com/browse/RHEL-122930
|
|
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 664194b16d..aee0af1045 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)`
|
|
|
|
Please note that depending on the QEMU version some capabilities might be
|
|
missing even though QEMU does support them. This is because prior to QEMU-6.1.0
|
|
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
|
|
index b8f17e6d2f..5f1e1e7100 100644
|
|
--- a/src/conf/domain_capabilities.c
|
|
+++ b/src/conf/domain_capabilities.c
|
|
@@ -91,6 +91,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_memdup(cap, sizeof(virDomainCapsFeatureHyperv));
|
|
+ ret->vendor_id = g_strdup(cap->vendor_id);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
static void
|
|
virDomainCapsDispose(void *obj)
|
|
{
|
|
@@ -104,7 +130,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++)
|
|
@@ -779,6 +805,8 @@ static void
|
|
virDomainCapsFeatureHypervFormat(virBuffer *buf,
|
|
const virDomainCapsFeatureHyperv *hyperv)
|
|
{
|
|
+ virBuffer defaults = VIR_BUFFER_INIT_CHILD(buf);
|
|
+
|
|
if (!hyperv)
|
|
return;
|
|
|
|
@@ -786,6 +814,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 eacbd6b6b3..5421c8cfce 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);
|
|
@@ -370,3 +375,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 850e7d63a0..9e1a80e22e 100644
|
|
--- a/src/conf/schemas/domaincaps.rng
|
|
+++ b/src/conf/schemas/domaincaps.rng
|
|
@@ -494,6 +494,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 bbe1e252af..d609064a19 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 28d3a78d8c..b54bcbd527 100644
|
|
--- a/src/qemu/qemu_capabilities.c
|
|
+++ b/src/qemu/qemu_capabilities.c
|
|
@@ -2051,8 +2051,7 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps)
|
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC))
|
|
virQEMUCapsSGXInfoCopy(&ret->sgxCapabilities, qemuCaps->sgxCapabilities);
|
|
|
|
- ret->hypervCapabilities = g_memdup(qemuCaps->hypervCapabilities,
|
|
- sizeof(virDomainCapsFeatureHyperv));
|
|
+ ret->hypervCapabilities = virDomainCapsFeatureHypervCopy(qemuCaps->hypervCapabilities);
|
|
|
|
return g_steal_pointer(&ret);
|
|
}
|
|
@@ -2094,7 +2093,7 @@ void virQEMUCapsDispose(void *obj)
|
|
virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
|
|
virSGXCapabilitiesFree(qemuCaps->sgxCapabilities);
|
|
|
|
- g_free(qemuCaps->hypervCapabilities);
|
|
+ virDomainCapsFeatureHypervFree(qemuCaps->hypervCapabilities);
|
|
|
|
virQEMUCapsAccelClear(&qemuCaps->kvm);
|
|
virQEMUCapsAccelClear(&qemuCaps->hvf);
|
|
@@ -3116,7 +3115,7 @@ static int
|
|
virQEMUCapsProbeHypervCapabilities(virQEMUCaps *qemuCaps,
|
|
qemuMonitorCPUModelInfo *fullQEMU)
|
|
{
|
|
- g_autofree virDomainCapsFeatureHyperv *hvcaps = NULL;
|
|
+ g_autoptr(virDomainCapsFeatureHyperv) hvcaps = NULL;
|
|
size_t i;
|
|
|
|
if (!fullQEMU)
|
|
@@ -4555,7 +4554,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;
|
|
@@ -6965,8 +6964,7 @@ static void
|
|
virQEMUCapsFillDomainFeatureHypervCaps(virQEMUCaps *qemuCaps,
|
|
virDomainCaps *domCaps)
|
|
{
|
|
- domCaps->hyperv = g_memdup(qemuCaps->hypervCapabilities,
|
|
- sizeof(virDomainCapsFeatureHyperv));
|
|
+ domCaps->hyperv = virDomainCapsFeatureHypervCopy(qemuCaps->hypervCapabilities);
|
|
}
|
|
|
|
|
|
--
|
|
2.51.1
|