[PATCH v2 00/29] Introduce hyperv host-model mode
v2 of: https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/DFODX... diff to v1: - Validate dependencies across hv-* enlightenment (per QEMU docs), - Drop introduction of hv-time, since it's already present (as a timer), I've kept mode='host-model' in domain XML and <defaults/> in domcaps XML, since no one objected, yet. Michal Prívozník (29): docs: Fix QEMU version wrt hypervclock src: Drop needless typecast to virDomainTimerNameType conf: Introduce virDomainDefHasTimer() qemuxmlconfdata: Adjust hv-stimer related tests qemu_validate: Reflect dependencies of hv-synic qemu_validate: Reflect dependencies of hv-stimer qemu_validate: Reflect dependencies of hv-tlbflush qemu_validate: Reflect dependencies of hv-ipi qemu_validate: Reflect dependencies of hv-evmcs qemu_validate: Reflect dependencies of hv-tlbflush-direct NEWS: Document Hyper-V enlightenment validation virxml: Introduce virXPathTristateSwitch() virxml: Introduce virXPathTristateBool() qemu: Use virXPathTristateBool() domain_conf: Move format of hyperv features into a function domain_conf: Use virXMLFormatElement() to format hyperv features qemu_caps: Prefer VIR_DOMAIN_CAPS_ENUM_IS_SET() qemu_command: Move hyperv cmd line generation into a function qemu_command: Prefer virBufferAddLit() in qemuBuildCpuHypervCommandLine() libxl: Simplify setting HyperV features conf: More hyperv related members into a single struct docs: Drop remark on now unsupported version of QEMU conf: Report default hyperv values in domain capabilities qemu_capabilities: Format and parse new hyperv domcaps members qemu_capabilities: Fetch new hyperv domcaps qemu_caps: Introduce virQEMUCapsGetHypervCapabilities() conf: Introduce hyperv host-model mode qemu_process: Populate hyperv features for host-model NEWS: Document new host-model hyperv mode NEWS.rst | 11 + docs/formatdomain.rst | 8 +- docs/formatdomaincaps.rst | 9 +- src/conf/domain_capabilities.c | 61 ++++- src/conf/domain_capabilities.h | 11 + src/conf/domain_conf.c | 235 ++++++++++-------- src/conf/domain_conf.h | 20 +- src/conf/schemas/domaincaps.rng | 29 +++ src/conf/schemas/domaincommon.rng | 3 + src/conf/virconftypes.h | 2 + src/libvirt_private.syms | 5 + src/libxl/libxl_conf.c | 70 +++--- src/libxl/xen_common.c | 2 +- src/lxc/lxc_cgroup.c | 2 +- src/lxc/lxc_controller.c | 2 +- src/qemu/qemu_capabilities.c | 107 +++++++- src/qemu/qemu_capabilities.h | 3 + src/qemu/qemu_command.c | 162 ++++++------ src/qemu/qemu_domain.c | 16 +- src/qemu/qemu_process.c | 80 +++++- src/qemu/qemu_validate.c | 74 +++++- src/util/virxml.c | 68 +++++ src/util/virxml.h | 10 + .../qemu_10.0.0-q35.x86_64+amdsev.xml | 7 + .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml | 7 + .../qemu_10.0.0-tcg.x86_64+amdsev.xml | 7 + .../domaincapsdata/qemu_10.0.0-tcg.x86_64.xml | 7 + .../qemu_10.0.0.x86_64+amdsev.xml | 7 + tests/domaincapsdata/qemu_10.0.0.x86_64.xml | 7 + .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 7 + .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 7 + .../qemu_10.1.0-tcg.x86_64+inteltdx.xml | 7 + .../domaincapsdata/qemu_10.1.0-tcg.x86_64.xml | 7 + .../qemu_10.1.0.x86_64+inteltdx.xml | 7 + tests/domaincapsdata/qemu_10.1.0.x86_64.xml | 7 + .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 7 + .../domaincapsdata/qemu_10.2.0-tcg.x86_64.xml | 7 + tests/domaincapsdata/qemu_10.2.0.x86_64.xml | 7 + .../domaincapsdata/qemu_8.0.0-q35.x86_64.xml | 7 + .../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml | 7 + tests/domaincapsdata/qemu_8.0.0.x86_64.xml | 7 + .../domaincapsdata/qemu_8.1.0-q35.x86_64.xml | 7 + .../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml | 7 + tests/domaincapsdata/qemu_8.1.0.x86_64.xml | 7 + .../domaincapsdata/qemu_8.2.0-q35.x86_64.xml | 7 + .../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml | 7 + tests/domaincapsdata/qemu_8.2.0.x86_64.xml | 7 + .../domaincapsdata/qemu_9.0.0-q35.x86_64.xml | 7 + .../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml | 7 + tests/domaincapsdata/qemu_9.0.0.x86_64.xml | 7 + .../domaincapsdata/qemu_9.1.0-q35.x86_64.xml | 7 + .../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml | 7 + tests/domaincapsdata/qemu_9.1.0.x86_64.xml | 7 + .../qemu_9.2.0-q35.x86_64+amdsev.xml | 7 + .../domaincapsdata/qemu_9.2.0-q35.x86_64.xml | 7 + .../qemu_9.2.0-tcg.x86_64+amdsev.xml | 7 + .../domaincapsdata/qemu_9.2.0-tcg.x86_64.xml | 7 + .../qemu_9.2.0.x86_64+amdsev.xml | 7 + tests/domaincapsdata/qemu_9.2.0.x86_64.xml | 7 + .../caps_10.0.0_x86_64+amdsev.xml | 5 + .../caps_10.0.0_x86_64.xml | 5 + .../caps_10.1.0_x86_64+inteltdx.xml | 5 + .../caps_10.1.0_x86_64.xml | 5 + .../caps_10.2.0_x86_64.xml | 5 + .../caps_8.0.0_x86_64.xml | 5 + .../caps_8.1.0_x86_64.xml | 5 + .../caps_8.2.0_x86_64.xml | 5 + .../caps_9.0.0_x86_64.xml | 5 + .../caps_9.1.0_x86_64.xml | 5 + .../caps_9.2.0_x86_64+amdsev.xml | 5 + .../caps_9.2.0_x86_64.xml | 5 + .../hyperv-host-model.x86_64-latest.args | 32 +++ .../hyperv-host-model.x86_64-latest.xml | 33 +++ tests/qemuxmlconfdata/hyperv-host-model.xml | 27 ++ .../hyperv-passthrough.x86_64-latest.xml | 3 +- .../hyperv-stimer-direct.x86_64-latest.args | 2 +- .../hyperv-stimer-direct.x86_64-latest.xml | 4 +- .../qemuxmlconfdata/hyperv-stimer-direct.xml | 4 +- .../qemuxmlconfdata/hyperv.x86_64-latest.args | 2 +- .../qemuxmlconfdata/hyperv.x86_64-latest.xml | 4 +- tests/qemuxmlconfdata/hyperv.xml | 4 +- tests/qemuxmlconftest.c | 1 + 82 files changed, 1151 insertions(+), 267 deletions(-) create mode 100644 tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/hyperv-host-model.xml -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> The hv-time feature was introduced in QEMU commit v2.0.0-rc0~119^2~3 which means the first version the feature is available in is 2.0.0. But our docs say 1.2.2. Fix it. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f50dce477f..fcf3ad8d29 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2437,7 +2437,7 @@ Windows, however, expects it to be in so called 'localtime'. The ``name`` attribute selects which timer is being modified, and can be one of "platform" (currently unsupported), "hpet" (xen, qemu, lxc), "kvmclock" (qemu), "pit" (qemu), "rtc" (qemu, lxc), "tsc" (xen, qemu - - :since:`since 3.2.0` ), "hypervclock" (qemu - :since:`since 1.2.2` ) or + :since:`since 3.2.0` ), "hypervclock" (qemu - :since:`since 2.0.0` ) or "armvtimer" (qemu - :since:`since 6.1.0` ). The ``hypervclock`` timer adds support for the reference time counter and the reference page for iTSC feature for guests running the Microsoft Windows operating system. -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
The hv-time feature was introduced in QEMU commit v2.0.0-rc0~119^2~3 which means the first version the feature is available in is 2.0.0. But our docs say 1.2.2. Fix it.
Those are libvirt versions, "qemu" means it's supported by our qemu driver: commit 600bca592b2352b683856f4b7f2694f366feac36 Author: Peter Krempa <pkrempa@redhat.com> CommitDate: 2014-02-10 11:30:10 +0100 qemu: hyperv: Add support for timer enlightenments git describe: v1.2.1-143-g600bca592b contains: v1.2.2-rc1~149 Jano
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f50dce477f..fcf3ad8d29 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2437,7 +2437,7 @@ Windows, however, expects it to be in so called 'localtime'. The ``name`` attribute selects which timer is being modified, and can be one of "platform" (currently unsupported), "hpet" (xen, qemu, lxc), "kvmclock" (qemu), "pit" (qemu), "rtc" (qemu, lxc), "tsc" (xen, qemu - - :since:`since 3.2.0` ), "hypervclock" (qemu - :since:`since 1.2.2` ) or + :since:`since 3.2.0` ), "hypervclock" (qemu - :since:`since 2.0.0` ) or "armvtimer" (qemu - :since:`since 6.1.0` ). The ``hypervclock`` timer adds support for the reference time counter and the reference page for iTSC feature for guests running the Microsoft Windows operating system. -- 2.49.1
On Wed, Oct 08, 2025 at 03:35:10PM +0200, Ján Tomko via Devel wrote:
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
The hv-time feature was introduced in QEMU commit v2.0.0-rc0~119^2~3 which means the first version the feature is available in is 2.0.0. But our docs say 1.2.2. Fix it.
Those are libvirt versions, "qemu" means it's supported by our qemu driver:
Good point, we should unify how we refer to features available only in some drivers as currently some of the forms can be confusing. But that's work for different series. Pavel
commit 600bca592b2352b683856f4b7f2694f366feac36 Author: Peter Krempa <pkrempa@redhat.com> CommitDate: 2014-02-10 11:30:10 +0100
qemu: hyperv: Add support for timer enlightenments
git describe: v1.2.1-143-g600bca592b contains: v1.2.2-rc1~149
Jano
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f50dce477f..fcf3ad8d29 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2437,7 +2437,7 @@ Windows, however, expects it to be in so called 'localtime'. The ``name`` attribute selects which timer is being modified, and can be one of "platform" (currently unsupported), "hpet" (xen, qemu, lxc), "kvmclock" (qemu), "pit" (qemu), "rtc" (qemu, lxc), "tsc" (xen, qemu - - :since:`since 3.2.0` ), "hypervclock" (qemu - :since:`since 1.2.2` ) or + :since:`since 3.2.0` ), "hypervclock" (qemu - :since:`since 2.0.0` ) or "armvtimer" (qemu - :since:`since 6.1.0` ). The ``hypervclock`` timer adds support for the reference time counter and the reference page for iTSC feature for guests running the Microsoft Windows operating system. -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> This was missed in v8.10.0-rc1~229 which switched the 'name' member of _virDomainTimerDef struct from int to virDomainTimerNameType. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libxl/libxl_conf.c | 2 +- src/libxl/xen_common.c | 2 +- src/lxc/lxc_cgroup.c | 2 +- src/lxc/lxc_controller.c | 2 +- src/qemu/qemu_command.c | 6 +++--- src/qemu/qemu_validate.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 9d8301169b..0cbc09b6b0 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -397,7 +397,7 @@ libxlMakeDomBuildInfo(virDomainDef *def, } for (i = 0; i < clock.ntimers; i++) { - switch ((virDomainTimerNameType) clock.timers[i]->name) { + switch (clock.timers[i]->name) { case VIR_DOMAIN_TIMER_NAME_TSC: switch (clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: diff --git a/src/libxl/xen_common.c b/src/libxl/xen_common.c index a050f0ab6e..666c6cae20 100644 --- a/src/libxl/xen_common.c +++ b/src/libxl/xen_common.c @@ -2093,7 +2093,7 @@ xenFormatHypervisorFeatures(virConf *conf, virDomainDef *def) } for (i = 0; i < def->clock.ntimers; i++) { - switch ((virDomainTimerNameType)def->clock.timers[i]->name) { + switch (def->clock.timers[i]->name) { case VIR_DOMAIN_TIMER_NAME_TSC: switch (def->clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index f566a5468e..1c637be38b 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -335,7 +335,7 @@ static int virLXCCgroupSetupDeviceACL(virDomainDef *def, if (timer->present == VIR_TRISTATE_BOOL_NO) continue; - switch ((virDomainTimerNameType)timer->name) { + switch (timer->name) { case VIR_DOMAIN_TIMER_NAME_PLATFORM: case VIR_DOMAIN_TIMER_NAME_TSC: case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index fb7f8e0bc2..3f4c8efdcf 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1502,7 +1502,7 @@ virLXCControllerSetupTimers(virLXCController *ctrl) if (timer->present == VIR_TRISTATE_BOOL_NO) continue; - switch ((virDomainTimerNameType)timer->name) { + switch (timer->name) { case VIR_DOMAIN_TIMER_NAME_PLATFORM: case VIR_DOMAIN_TIMER_NAME_TSC: case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 08e2a5147d..f7af92fe35 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6047,7 +6047,7 @@ qemuBuildClockCommandLine(virCommand *cmd, } for (i = 0; i < def->clock.ntimers; i++) { - switch ((virDomainTimerNameType)def->clock.timers[i]->name) { + switch (def->clock.timers[i]->name) { case VIR_DOMAIN_TIMER_NAME_PLATFORM: /* qemuDomainDefValidateClockTimers will handle this * error condition */ @@ -6491,7 +6491,7 @@ qemuBuildCpuCommandLine(virCommand *cmd, for (i = 0; i < def->clock.ntimers; i++) { virDomainTimerDef *timer = def->clock.timers[i]; - switch ((virDomainTimerNameType)timer->name) { + switch (timer->name) { case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: if (timer->present != VIR_TRISTATE_BOOL_ABSENT) { /* QEMU expects on/off -> virTristateSwitch. */ @@ -7200,7 +7200,7 @@ qemuBuildMachineCommandLine(virCommand *cmd, } for (i = 0; i < def->clock.ntimers; i++) { - switch ((virDomainTimerNameType)def->clock.timers[i]->name) { + switch (def->clock.timers[i]->name) { case VIR_DOMAIN_TIMER_NAME_HPET: /* qemuBuildClockCommandLine handles the old-style config via '-no-hpet' */ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_HPET) && diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 7f3ffe8bd5..8dac5c76d0 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -477,7 +477,7 @@ qemuValidateDomainDefClockTimers(const virDomainDef *def, for (i = 0; i < def->clock.ntimers; i++) { virDomainTimerDef *timer = def->clock.timers[i]; - switch ((virDomainTimerNameType)timer->name) { + switch (timer->name) { case VIR_DOMAIN_TIMER_NAME_PLATFORM: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported timer type (name) '%1$s'"), -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
This was missed in v8.10.0-rc1~229 which switched the 'name' member of _virDomainTimerDef struct from int to virDomainTimerNameType.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libxl/libxl_conf.c | 2 +- src/libxl/xen_common.c | 2 +- src/lxc/lxc_cgroup.c | 2 +- src/lxc/lxc_controller.c | 2 +- src/qemu/qemu_command.c | 6 +++--- src/qemu/qemu_validate.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Michal Privoznik <mprivozn@redhat.com> This is a simple helper to tell whether domain definition has certain type of timer or not. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 17 +++++++++++++++++ src/conf/domain_conf.h | 4 ++++ src/libvirt_private.syms | 1 + 3 files changed, 22 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 281846dfbe..156e43f5cd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -32517,3 +32517,20 @@ virDomainWatchdogDefFind(const virDomainDef *def, return -1; } + + +bool +virDomainDefHasTimer(const virDomainDef *def, + virDomainTimerNameType name) +{ + size_t i; + + for (i = 0; i < def->clock.ntimers; i++) { + if (def->clock.timers[i]->name == name && + def->clock.timers[i]->present == VIR_TRISTATE_BOOL_YES) { + return true; + } + } + + return false; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 39807b5fe3..9159a69833 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -4727,3 +4727,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainThrottleFilterDef, virDomainThrottleFilte virDomainThrottleFilterDef * virDomainThrottleFilterFind(const virDomainDiskDef *def, const char *name); + +bool +virDomainDefHasTimer(const virDomainDef *def, + virDomainTimerNameType name); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fe72402527..7986ad123c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -346,6 +346,7 @@ virDomainDefHasNVMeDisk; virDomainDefHasOldStyleROUEFI; virDomainDefHasOldStyleUEFI; virDomainDefHasPCIHostdev; +virDomainDefHasTimer; virDomainDefHasUSB; virDomainDefHasVcpusOffline; virDomainDefHasVDPANet; -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
This is a simple helper to tell whether domain definition has certain type of timer or not.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 17 +++++++++++++++++ src/conf/domain_conf.h | 4 ++++ src/libvirt_private.syms | 1 + 3 files changed, 22 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Michal Privoznik <mprivozn@redhat.com> In QEMU, hv-stimer and hv-stimer-direct require hv-time. Reflect this fact in our tests. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.xml | 4 +++- tests/qemuxmlconfdata/hyperv-stimer-direct.xml | 4 +++- tests/qemuxmlconfdata/hyperv.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/hyperv.x86_64-latest.xml | 4 +++- tests/qemuxmlconfdata/hyperv.xml | 4 +++- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.args b/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.args index b665e5365d..0a6d84fbd2 100644 --- a/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.args +++ b/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ -accel tcg \ --cpu qemu64,hv-vpindex=on,hv-synic=on,hv-stimer=on,hv-stimer-direct=on \ +-cpu qemu64,hv-time=on,hv-vpindex=on,hv-synic=on,hv-stimer=on,hv-stimer-direct=on \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.xml b/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.xml index efb9d0072e..5f6223bf3e 100644 --- a/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.xml @@ -21,7 +21,9 @@ <cpu mode='custom' match='exact' check='none'> <model fallback='forbid'>qemu64</model> </cpu> - <clock offset='utc'/> + <clock offset='utc'> + <timer name='hypervclock' present='yes'/> + </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> diff --git a/tests/qemuxmlconfdata/hyperv-stimer-direct.xml b/tests/qemuxmlconfdata/hyperv-stimer-direct.xml index 21163b41ad..4116b7a450 100644 --- a/tests/qemuxmlconfdata/hyperv-stimer-direct.xml +++ b/tests/qemuxmlconfdata/hyperv-stimer-direct.xml @@ -18,7 +18,9 @@ </stimer> </hyperv> </features> - <clock offset='utc'/> + <clock offset='utc'> + <timer name='hypervclock' present='yes'/> + </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> diff --git a/tests/qemuxmlconfdata/hyperv.x86_64-latest.args b/tests/qemuxmlconfdata/hyperv.x86_64-latest.args index 5a32b80e71..30d63bae6b 100644 --- a/tests/qemuxmlconfdata/hyperv.x86_64-latest.args +++ b/tests/qemuxmlconfdata/hyperv.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ -accel tcg \ --cpu 'qemu64,hv-relaxed=on,hv-vapic=on,hv-spinlocks=0x2fff,hv-vpindex=on,hv-runtime=on,hv-synic=on,hv-stimer=on,hv-reset=on,hv-vendor-id=KVM Hv,hv-frequencies=on,hv-reenlightenment=on,hv-tlbflush=on,hv-tlbflush-direct=on,hv-tlbflush-ext=on,hv-ipi=on,hv-evmcs=on,hv-avic=on,hv-emsr-bitmap=on,hv-xmm-input=on' \ +-cpu 'qemu64,hv-time=on,hv-relaxed=on,hv-vapic=on,hv-spinlocks=0x2fff,hv-vpindex=on,hv-runtime=on,hv-synic=on,hv-stimer=on,hv-reset=on,hv-vendor-id=KVM Hv,hv-frequencies=on,hv-reenlightenment=on,hv-tlbflush=on,hv-tlbflush-direct=on,hv-tlbflush-ext=on,hv-ipi=on,hv-evmcs=on,hv-avic=on,hv-emsr-bitmap=on,hv-xmm-input=on' \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/hyperv.x86_64-latest.xml b/tests/qemuxmlconfdata/hyperv.x86_64-latest.xml index 49537188af..ee412164ed 100644 --- a/tests/qemuxmlconfdata/hyperv.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/hyperv.x86_64-latest.xml @@ -36,7 +36,9 @@ <cpu mode='custom' match='exact' check='none'> <model fallback='forbid'>qemu64</model> </cpu> - <clock offset='utc'/> + <clock offset='utc'> + <timer name='hypervclock' present='yes'/> + </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> diff --git a/tests/qemuxmlconfdata/hyperv.xml b/tests/qemuxmlconfdata/hyperv.xml index 8c323f6578..44aec004a8 100644 --- a/tests/qemuxmlconfdata/hyperv.xml +++ b/tests/qemuxmlconfdata/hyperv.xml @@ -33,7 +33,9 @@ <xmm_input state='on'/> </hyperv> </features> - <clock offset='utc'/> + <clock offset='utc'> + <timer name='hypervclock' present='yes'/> + </clock> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
In QEMU, hv-stimer and hv-stimer-direct require hv-time. Reflect this fact in our tests.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/hyperv-stimer-direct.x86_64-latest.xml | 4 +++- tests/qemuxmlconfdata/hyperv-stimer-direct.xml | 4 +++- tests/qemuxmlconfdata/hyperv.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/hyperv.x86_64-latest.xml | 4 +++- tests/qemuxmlconfdata/hyperv.xml | 4 +++- 6 files changed, 14 insertions(+), 6 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Michal Privoznik <mprivozn@redhat.com> Per QEMU documentation (docs/system/i386/hyperv.rst): ``hv-synic`` Enables Hyper-V Synthetic interrupt controller <snip/> Requires: ``hv-vpindex`` Reflect this dependency when validating domain definition. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 42 ++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 8dac5c76d0..279f72f50a 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -88,6 +88,38 @@ qemuValidateDomainDefPSeriesFeature(const virDomainDef *def, } +#define CHECK_HV_FEAT(feat, requires) \ + if (def->hyperv_features[feat] == VIR_TRISTATE_SWITCH_ON && \ + def->hyperv_features[requires] != VIR_TRISTATE_SWITCH_ON) { \ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ + _("'%1$s' hyperv feature requires '%2$s' feature"), \ + virDomainHypervTypeToString(feat), \ + virDomainHypervTypeToString(requires)); \ + return -1; \ + } + +static int +qemuValidateDomainDefHypervFeatures(const virDomainDef *def) +{ + if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_HYPERV_MODE_NONE) + return 0; + + if (!ARCH_IS_X86(def->os.arch) && !qemuDomainIsARMVirt(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Hyperv features are not supported for architecture '%1$s' or machine type '%2$s'"), + virArchToString(def->os.arch), + def->os.machine); + return -1; + } + + CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_SYNIC, VIR_DOMAIN_HYPERV_VPINDEX); + + return 0; +} + +#undef CHECK_HV_FEAT + + static int qemuValidateDomainDefFeatures(const virDomainDef *def, virQEMUCaps *qemuCaps) @@ -187,14 +219,8 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, break; case VIR_DOMAIN_FEATURE_HYPERV: - if (def->features[i] != VIR_DOMAIN_HYPERV_MODE_NONE && - !ARCH_IS_X86(def->os.arch) && !qemuDomainIsARMVirt(def)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Hyperv features are not supported for architecture '%1$s' or machine type '%2$s'"), - virArchToString(def->os.arch), - def->os.machine); - return -1; - } + if (qemuValidateDomainDefHypervFeatures(def) < 0) + return -1; break; case VIR_DOMAIN_FEATURE_PMU: -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Per QEMU documentation (docs/system/i386/hyperv.rst): ``hv-stimer`` Enables Hyper-V synthetic timers. <snip/> Requires: ``hv-vpindex``, ``hv-synic``, ``hv-time`` Reflect these dependencies when validating domain definition. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 279f72f50a..60bf623716 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -114,6 +114,19 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_SYNIC, VIR_DOMAIN_HYPERV_VPINDEX); + if (def->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) { + if (!virDomainDefHasTimer(def, VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("'%1$s' hyperv feature requires '%2$s' timer"), + virDomainHypervTypeToString(VIR_DOMAIN_HYPERV_STIMER), + virDomainTimerNameTypeToString(VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK)); + return -1; + } + } + + CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_STIMER, VIR_DOMAIN_HYPERV_VPINDEX); + CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_STIMER, VIR_DOMAIN_HYPERV_SYNIC); + return 0; } -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Per QEMU documentation (docs/system/i386/hyperv.rst): ``hv-tlbflush`` Enables paravirtualized TLB shoot-down mechanism. <snip/> Requires: ``hv-vpindex`` Reflect this dependency when validating domain definition. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 60bf623716..38cac4dc72 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -127,6 +127,8 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_STIMER, VIR_DOMAIN_HYPERV_VPINDEX); CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_STIMER, VIR_DOMAIN_HYPERV_SYNIC); + CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_TLBFLUSH, VIR_DOMAIN_HYPERV_VPINDEX); + return 0; } -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Per QEMU documentation (docs/system/i386/hyperv.rst): ``hv-ipi`` Enables paravirtualized IPI send mechanism. <snip/> Requires: ``hv-vpindex`` Reflect this dependency when validating domain definition. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 38cac4dc72..f274e4f126 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -129,6 +129,8 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_TLBFLUSH, VIR_DOMAIN_HYPERV_VPINDEX); + CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_IPI, VIR_DOMAIN_HYPERV_VPINDEX); + return 0; } -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Per QEMU documentation (docs/system/i386/hyperv.rst): ``hv-evmcs`` The enlightenment is nested specific, it targets Hyper-V on KVM guests. <snip/> Requires: ``hv-vapic`` Reflect this dependency when validating domain definition. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index f274e4f126..3dbb00c23a 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -131,6 +131,8 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_IPI, VIR_DOMAIN_HYPERV_VPINDEX); + CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_EVMCS, VIR_DOMAIN_HYPERV_VAPIC); + return 0; } -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Per QEMU documentation (docs/system/i386/hyperv.rst): ``hv-tlbflush-direct`` The enlightenment is nested specific, it targets Hyper-V on KVM guests. <snip/> Requires: ``hv-vapic`` Reflect this dependency when validating domain definition. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_validate.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 3dbb00c23a..930ba3543f 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -133,6 +133,17 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_EVMCS, VIR_DOMAIN_HYPERV_VAPIC); + if (def->hyperv_features[VIR_DOMAIN_HYPERV_TLBFLUSH] == VIR_TRISTATE_SWITCH_ON && + def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv_features[VIR_DOMAIN_HYPERV_VAPIC] != VIR_TRISTATE_SWITCH_ON) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("'%1$s' hyperv feature requires '%2$s' feature"), + VIR_CPU_x86_HV_TLBFLUSH_DIRECT, + virDomainHypervTypeToString(VIR_DOMAIN_HYPERV_VAPIC)); + return -1; + } + } + return 0; } -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- NEWS.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 006b2ccf6a..c44203bcc1 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -25,6 +25,11 @@ v11.9.0 (unreleased) Intel-specific USB controllers are relegated to x86 guests, and model selection overall behaves more consistently across architectures. + * qemu: Validate Hyper-V enlightenment dependencies + + Some Hyper-V enlightenments may require some other enlightenments to be + turned on. Libvirt now validates these when defining new domains. + * **Bug fixes** -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- NEWS.rst | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/NEWS.rst b/NEWS.rst index 006b2ccf6a..c44203bcc1 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -25,6 +25,11 @@ v11.9.0 (unreleased) Intel-specific USB controllers are relegated to x86 guests, and model selection overall behaves more consistently across architectures.
+ * qemu: Validate Hyper-V enlightenment dependencies + + Some Hyper-V enlightenments may require some other enlightenments to be + turned on. Libvirt now validates these when defining new domains.
Validation also happens at domain startup. I suggest: s/when defining/for/ And for patches 2-11: Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Michal Privoznik <mprivozn@redhat.com> Similarly to other virXPath* functions, let's have a helper that evaluates an XPath and stores the value into virTristateSwitch. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virxml.c | 34 ++++++++++++++++++++++++++++++++++ src/util/virxml.h | 5 +++++ 3 files changed, 40 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7986ad123c..0b692c038e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3827,6 +3827,7 @@ virXPathLongLong; virXPathNode; virXPathNodeSet; virXPathString; +virXPathTristateSwitch; virXPathUInt; virXPathUIntBase; virXPathULongLong; diff --git a/src/util/virxml.c b/src/util/virxml.c index bb80bb7444..60485c10fa 100644 --- a/src/util/virxml.c +++ b/src/util/virxml.c @@ -284,6 +284,40 @@ virXPathLongLong(const char *xpath, } +/** + * virXPathTristateSwitch: + * @xpath: the XPath string to evaluate + * @ctxt: an XPath context + * @value: the returned virTristateSwitch value + * + * Convenience function to evaluate an XPath tristate value. The @xpath + * expression must ensure that the evaluated value is returned as a + * string (use the 'string()' conversion in the expression). + * + * Returns 0 in case of success in which case @value is set, + * or -1 if the XPath evaluation failed or -2 if the + * value isn't of a virTristateSwitch value. + */ +int +virXPathTristateSwitch(const char *xpath, + xmlXPathContextPtr ctxt, + virTristateSwitch *value) +{ + g_autoptr(xmlXPathObject) obj = NULL; + int rc; + + if (!(obj = virXPathEvalString(xpath, ctxt))) + return -1; + + rc = virTristateSwitchTypeFromString((char *)obj->stringval); + if (rc < 0) + return -2; + + *value = rc; + return 0; +} + + /** * virXMLCheckIllegalChars: * @nodeName: Name of checked node diff --git a/src/util/virxml.h b/src/util/virxml.h index 7cc3f47913..dfec386494 100644 --- a/src/util/virxml.h +++ b/src/util/virxml.h @@ -73,6 +73,11 @@ virXPathLongLong(const char *xpath, xmlXPathContextPtr ctxt, long long *value); +int +virXPathTristateSwitch(const char *xpath, + xmlXPathContextPtr ctxt, + virTristateSwitch *value); + xmlNodePtr virXMLNodeGetSubelement(xmlNodePtr node, const char *name); -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Similarly to other virXPath* functions, let's have a helper that evaluates an XPath and stores the value into virTristateBool. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virxml.c | 34 ++++++++++++++++++++++++++++++++++ src/util/virxml.h | 5 +++++ 3 files changed, 40 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0b692c038e..1a4f47aabc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3827,6 +3827,7 @@ virXPathLongLong; virXPathNode; virXPathNodeSet; virXPathString; +virXPathTristateBool; virXPathTristateSwitch; virXPathUInt; virXPathUIntBase; diff --git a/src/util/virxml.c b/src/util/virxml.c index 60485c10fa..44f11accf3 100644 --- a/src/util/virxml.c +++ b/src/util/virxml.c @@ -318,6 +318,40 @@ virXPathTristateSwitch(const char *xpath, } +/** + * virXPathTristateBool: + * @xpath: the XPath string to evaluate + * @ctxt: an XPath context + * @value: the returned virTristateBool value + * + * Convenience function to evaluate an XPath tristate value. The @xpath + * expression must ensure that the evaluated value is returned as a + * string (use the 'string()' conversion in the expression). + * + * Returns 0 in case of success in which case @value is set, + * or -1 if the XPath evaluation failed or -2 if the + * value isn't of a virTristateBool value. + */ +int +virXPathTristateBool(const char *xpath, + xmlXPathContextPtr ctxt, + virTristateBool *value) +{ + g_autoptr(xmlXPathObject) obj = NULL; + int rc; + + if (!(obj = virXPathEvalString(xpath, ctxt))) + return -1; + + rc = virTristateBoolTypeFromString((char *)obj->stringval); + if (rc < 0) + return -2; + + *value = rc; + return 0; +} + + /** * virXMLCheckIllegalChars: * @nodeName: Name of checked node diff --git a/src/util/virxml.h b/src/util/virxml.h index dfec386494..82218c0539 100644 --- a/src/util/virxml.h +++ b/src/util/virxml.h @@ -78,6 +78,11 @@ virXPathTristateSwitch(const char *xpath, xmlXPathContextPtr ctxt, virTristateSwitch *value); +int +virXPathTristateBool(const char *xpath, + xmlXPathContextPtr ctxt, + virTristateBool *value); + xmlNodePtr virXMLNodeGetSubelement(xmlNodePtr node, const char *name); -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> There are two places in our code base which can use freshly introduced virXPathTristateBool(): qemuStorageSourcePrivateDataParse() and qemuDomainObjPrivateXMLParseBlockjobs(). Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_domain.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b39fabfbb4..d675a5d7ee 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2073,7 +2073,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, g_autofree char *authalias = NULL; g_autofree char *httpcookiealias = NULL; g_autofree char *tlskeyalias = NULL; - g_autofree char *thresholdEventWithIndex = NULL; + virTristateBool thresholdEventWithIndex; bool fdsetPresent = false; unsigned int fdSetID; int enccount; @@ -2139,9 +2139,10 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, if (virStorageSourcePrivateDataParseRelPath(ctxt, src) < 0) return -1; - if ((thresholdEventWithIndex = virXPathString("string(./thresholdEvent/@indexUsed)", ctxt)) && - virTristateBoolTypeFromString(thresholdEventWithIndex) == VIR_TRISTATE_BOOL_YES) - src->thresholdEventWithIndex = true; + if (virXPathTristateBool("string(./thresholdEvent/@indexUsed)", + ctxt, &thresholdEventWithIndex) >= 0) { + virTristateBoolToBool(thresholdEventWithIndex, &src->thresholdEventWithIndex); + } if ((nbdkitnode = virXPathNode("nbdkit", ctxt))) { if (qemuStorageSourcePrivateDataParseNbdkit(nbdkitnode, ctxt, src) < 0) @@ -3210,13 +3211,10 @@ qemuDomainObjPrivateXMLParseBlockjobs(virDomainObj *vm, { g_autofree xmlNodePtr *nodes = NULL; ssize_t nnodes = 0; - g_autofree char *active = NULL; - int tmp; size_t i; - if ((active = virXPathString("string(./blockjobs/@active)", ctxt)) && - (tmp = virTristateBoolTypeFromString(active)) > 0) - priv->reconnectBlockjobs = tmp; + virXPathTristateBool("string(./blockjobs/@active)", + ctxt, &priv->reconnectBlockjobs); if ((nnodes = virXPathNodeSet("./blockjobs/blockjob", ctxt, &nodes)) < 0) return -1; -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
There are two places in our code base which can use freshly introduced virXPathTristateBool(): qemuStorageSourcePrivateDataParse() and qemuDomainObjPrivateXMLParseBlockjobs().
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_domain.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b39fabfbb4..d675a5d7ee 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2073,7 +2073,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, g_autofree char *authalias = NULL; g_autofree char *httpcookiealias = NULL; g_autofree char *tlskeyalias = NULL; - g_autofree char *thresholdEventWithIndex = NULL; + virTristateBool thresholdEventWithIndex; bool fdsetPresent = false; unsigned int fdSetID; int enccount; @@ -2139,9 +2139,10 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, if (virStorageSourcePrivateDataParseRelPath(ctxt, src) < 0) return -1;
- if ((thresholdEventWithIndex = virXPathString("string(./thresholdEvent/@indexUsed)", ctxt)) && - virTristateBoolTypeFromString(thresholdEventWithIndex) == VIR_TRISTATE_BOOL_YES) - src->thresholdEventWithIndex = true; + if (virXPathTristateBool("string(./thresholdEvent/@indexUsed)", + ctxt, &thresholdEventWithIndex) >= 0) { + virTristateBoolToBool(thresholdEventWithIndex, &src->thresholdEventWithIndex); + }
if ((nbdkitnode = virXPathNode("nbdkit", ctxt))) { if (qemuStorageSourcePrivateDataParseNbdkit(nbdkitnode, ctxt, src) < 0) @@ -3210,13 +3211,10 @@ qemuDomainObjPrivateXMLParseBlockjobs(virDomainObj *vm, { g_autofree xmlNodePtr *nodes = NULL; ssize_t nnodes = 0; - g_autofree char *active = NULL; - int tmp; size_t i;
- if ((active = virXPathString("string(./blockjobs/@active)", ctxt)) && - (tmp = virTristateBoolTypeFromString(active)) > 0) - priv->reconnectBlockjobs = tmp;
No need to convert this, it is unused since: commit 542d6c6bf2458bdf6296a4c50e87c67b2eb3f3ac Author: Peter Krempa <pkrempa@redhat.com> CommitDate: 2022-08-11 15:12:20 +0200 qemu: process: Remove pre-blockdev code paths git describe: v8.6.0-149-g542d6c6bf2 contains: v8.7.0-rc1~110 Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
On 10/15/25 03:45, Ján Tomko wrote:
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
There are two places in our code base which can use freshly introduced virXPathTristateBool(): qemuStorageSourcePrivateDataParse() and qemuDomainObjPrivateXMLParseBlockjobs().
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_domain.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b39fabfbb4..d675a5d7ee 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2073,7 +2073,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, g_autofree char *authalias = NULL; g_autofree char *httpcookiealias = NULL; g_autofree char *tlskeyalias = NULL; - g_autofree char *thresholdEventWithIndex = NULL; + virTristateBool thresholdEventWithIndex; bool fdsetPresent = false; unsigned int fdSetID; int enccount; @@ -2139,9 +2139,10 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, if (virStorageSourcePrivateDataParseRelPath(ctxt, src) < 0) return -1;
- if ((thresholdEventWithIndex = virXPathString("string(./ thresholdEvent/@indexUsed)", ctxt)) && - virTristateBoolTypeFromString(thresholdEventWithIndex) == VIR_TRISTATE_BOOL_YES) - src->thresholdEventWithIndex = true; + if (virXPathTristateBool("string(./thresholdEvent/@indexUsed)", + ctxt, &thresholdEventWithIndex) >= 0) { + virTristateBoolToBool(thresholdEventWithIndex, &src-
thresholdEventWithIndex); + }
if ((nbdkitnode = virXPathNode("nbdkit", ctxt))) { if (qemuStorageSourcePrivateDataParseNbdkit(nbdkitnode, ctxt, src) < 0) @@ -3210,13 +3211,10 @@ qemuDomainObjPrivateXMLParseBlockjobs(virDomainObj *vm, { g_autofree xmlNodePtr *nodes = NULL; ssize_t nnodes = 0; - g_autofree char *active = NULL; - int tmp; size_t i;
- if ((active = virXPathString("string(./blockjobs/@active)", ctxt)) && - (tmp = virTristateBoolTypeFromString(active)) > 0) - priv->reconnectBlockjobs = tmp;
No need to convert this, it is unused since:
commit 542d6c6bf2458bdf6296a4c50e87c67b2eb3f3ac Author: Peter Krempa <pkrempa@redhat.com> CommitDate: 2022-08-11 15:12:20 +0200
qemu: process: Remove pre-blockdev code paths
git describe: v8.6.0-149-g542d6c6bf2 contains: v8.7.0-rc1~110
Why wasn't it removed then? I'll post a patch for that. Michal
From: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 158 ++++++++++++++++++++++------------------- 1 file changed, 84 insertions(+), 74 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 156e43f5cd..585546d6fd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -28581,6 +28581,89 @@ virDomainFeatureTCGFormat(virBuffer *buf, } +static void +virDomainFeaturesHyperVDefFormat(virBuffer *buf, + const virDomainDef *def) +{ + virBuffer tmpChildBuf = VIR_BUFFER_INIT_CHILD(buf); + size_t j; + + if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_HYPERV_MODE_NONE) + return; + + virBufferAsprintf(buf, "<hyperv mode='%s'>\n", + virDomainHyperVModeTypeToString(def->features[VIR_DOMAIN_FEATURE_HYPERV])); + + for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) { + g_auto(virBuffer) hypervAttrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) hypervChildBuf = VIR_BUFFER_INIT_CHILD(&tmpChildBuf); + + if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT) + continue; + + virBufferAsprintf(&hypervAttrBuf, " state='%s'", + virTristateSwitchTypeToString(def->hyperv_features[j])); + + switch ((virDomainHyperv) j) { + case VIR_DOMAIN_HYPERV_RELAXED: + case VIR_DOMAIN_HYPERV_VAPIC: + case VIR_DOMAIN_HYPERV_VPINDEX: + case VIR_DOMAIN_HYPERV_RUNTIME: + case VIR_DOMAIN_HYPERV_SYNIC: + case VIR_DOMAIN_HYPERV_RESET: + case VIR_DOMAIN_HYPERV_FREQUENCIES: + case VIR_DOMAIN_HYPERV_REENLIGHTENMENT: + case VIR_DOMAIN_HYPERV_IPI: + case VIR_DOMAIN_HYPERV_EVMCS: + case VIR_DOMAIN_HYPERV_AVIC: + case VIR_DOMAIN_HYPERV_EMSR_BITMAP: + case VIR_DOMAIN_HYPERV_XMM_INPUT: + break; + + case VIR_DOMAIN_HYPERV_SPINLOCKS: + if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) { + virBufferAsprintf(&hypervAttrBuf, + " retries='%d'", def->hyperv_spinlocks); + } + break; + + case VIR_DOMAIN_HYPERV_STIMER: + if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON && + def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON) { + virBufferAddLit(&hypervChildBuf, "<direct state='on'/>\n"); + } + + break; + + case VIR_DOMAIN_HYPERV_VENDOR_ID: + if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) { + virBufferEscapeString(&hypervAttrBuf, " value='%s'", + def->hyperv_vendor_id); + } + break; + + case VIR_DOMAIN_HYPERV_TLBFLUSH: + if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) + break; + + if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) + virBufferAddLit(&hypervChildBuf, "<direct state='on'/>\n"); + if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) + virBufferAddLit(&hypervChildBuf, "<extended state='on'/>\n"); + break; + + case VIR_DOMAIN_HYPERV_LAST: + break; + } + + virXMLFormatElement(&tmpChildBuf, virDomainHypervTypeToString(j), + &hypervAttrBuf, &hypervChildBuf); + } + + virBufferAddBuffer(buf, &tmpChildBuf); + virBufferAddLit(buf, "</hyperv>\n"); +} + static int virDomainDefFormatFeatures(virBuffer *buf, virDomainDef *def) @@ -28678,80 +28761,7 @@ virDomainDefFormatFeatures(virBuffer *buf, break; case VIR_DOMAIN_FEATURE_HYPERV: - if (def->features[i] == VIR_DOMAIN_HYPERV_MODE_NONE) - break; - - virBufferAsprintf(&childBuf, "<hyperv mode='%s'>\n", - virDomainHyperVModeTypeToString(def->features[i])); - - for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) { - g_auto(virBuffer) hypervAttrBuf = VIR_BUFFER_INITIALIZER; - g_auto(virBuffer) hypervChildBuf = VIR_BUFFER_INIT_CHILD(&tmpChildBuf); - - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT) - continue; - - virBufferAsprintf(&hypervAttrBuf, " state='%s'", - virTristateSwitchTypeToString(def->hyperv_features[j])); - - switch ((virDomainHyperv) j) { - case VIR_DOMAIN_HYPERV_RELAXED: - case VIR_DOMAIN_HYPERV_VAPIC: - case VIR_DOMAIN_HYPERV_VPINDEX: - case VIR_DOMAIN_HYPERV_RUNTIME: - case VIR_DOMAIN_HYPERV_SYNIC: - case VIR_DOMAIN_HYPERV_RESET: - case VIR_DOMAIN_HYPERV_FREQUENCIES: - case VIR_DOMAIN_HYPERV_REENLIGHTENMENT: - case VIR_DOMAIN_HYPERV_IPI: - case VIR_DOMAIN_HYPERV_EVMCS: - case VIR_DOMAIN_HYPERV_AVIC: - case VIR_DOMAIN_HYPERV_EMSR_BITMAP: - case VIR_DOMAIN_HYPERV_XMM_INPUT: - break; - - case VIR_DOMAIN_HYPERV_SPINLOCKS: - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) { - virBufferAsprintf(&hypervAttrBuf, - " retries='%d'", def->hyperv_spinlocks); - } - break; - - case VIR_DOMAIN_HYPERV_STIMER: - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON && - def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON) { - virBufferAddLit(&hypervChildBuf, "<direct state='on'/>\n"); - } - - break; - - case VIR_DOMAIN_HYPERV_VENDOR_ID: - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) { - virBufferEscapeString(&hypervAttrBuf, " value='%s'", - def->hyperv_vendor_id); - } - break; - - case VIR_DOMAIN_HYPERV_TLBFLUSH: - if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) - break; - - if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) - virBufferAddLit(&hypervChildBuf, "<direct state='on'/>\n"); - if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) - virBufferAddLit(&hypervChildBuf, "<extended state='on'/>\n"); - break; - - case VIR_DOMAIN_HYPERV_LAST: - break; - } - - virXMLFormatElement(&tmpChildBuf, virDomainHypervTypeToString(j), - &hypervAttrBuf, &hypervChildBuf); - } - - virBufferAddBuffer(&childBuf, &tmpChildBuf); - virBufferAddLit(&childBuf, "</hyperv>\n"); + virDomainFeaturesHyperVDefFormat(&childBuf, def); break; case VIR_DOMAIN_FEATURE_KVM: -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Not only is it more modern that old virBufferAsprintf() of opening and closing tag, it's also aware of child elements buffer and thus formats a singleton properly. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 13 +++++++------ .../hyperv-passthrough.x86_64-latest.xml | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 585546d6fd..d095454283 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -28585,18 +28585,19 @@ static void virDomainFeaturesHyperVDefFormat(virBuffer *buf, const virDomainDef *def) { - virBuffer tmpChildBuf = VIR_BUFFER_INIT_CHILD(buf); + virBuffer childBuf = VIR_BUFFER_INIT_CHILD(buf); + virBuffer attrBuf = VIR_BUFFER_INITIALIZER; size_t j; if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_HYPERV_MODE_NONE) return; - virBufferAsprintf(buf, "<hyperv mode='%s'>\n", + virBufferAsprintf(&attrBuf, " mode='%s'", virDomainHyperVModeTypeToString(def->features[VIR_DOMAIN_FEATURE_HYPERV])); for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) { g_auto(virBuffer) hypervAttrBuf = VIR_BUFFER_INITIALIZER; - g_auto(virBuffer) hypervChildBuf = VIR_BUFFER_INIT_CHILD(&tmpChildBuf); + g_auto(virBuffer) hypervChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf); if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT) continue; @@ -28656,14 +28657,14 @@ virDomainFeaturesHyperVDefFormat(virBuffer *buf, break; } - virXMLFormatElement(&tmpChildBuf, virDomainHypervTypeToString(j), + virXMLFormatElement(&childBuf, virDomainHypervTypeToString(j), &hypervAttrBuf, &hypervChildBuf); } - virBufferAddBuffer(buf, &tmpChildBuf); - virBufferAddLit(buf, "</hyperv>\n"); + virXMLFormatElement(buf, "hyperv", &attrBuf, &childBuf); } + static int virDomainDefFormatFeatures(virBuffer *buf, virDomainDef *def) diff --git a/tests/qemuxmlconfdata/hyperv-passthrough.x86_64-latest.xml b/tests/qemuxmlconfdata/hyperv-passthrough.x86_64-latest.xml index 2cfae8fa4c..0ce5bab605 100644 --- a/tests/qemuxmlconfdata/hyperv-passthrough.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/hyperv-passthrough.x86_64-latest.xml @@ -10,8 +10,7 @@ </os> <features> <acpi/> - <hyperv mode='passthrough'> - </hyperv> + <hyperv mode='passthrough'/> </features> <cpu mode='custom' match='exact' check='none'> <model fallback='forbid'>qemu64</model> -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> While virDomainCapsEnum is in fact a bitmap, we also have a macro to manipulate/query individual bits. Prefer it to make the code more readable. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_capabilities.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 618291e5b6..5b485d7bfb 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -5065,7 +5065,7 @@ virQEMUCapsFormatHypervCapabilities(virQEMUCaps *qemuCaps, size_t i; for (i = 0; i < sizeof(hvcaps->features.values) * CHAR_BIT; i++) { - if (!(hvcaps->features.values & (1U << i))) + if (!VIR_DOMAIN_CAPS_ENUM_IS_SET(hvcaps->features, i)) continue; virBufferAsprintf(&childBuf, "<cap name='%s'/>\n", -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_command.c | 155 ++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 70 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f7af92fe35..542022b889 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6449,6 +6449,89 @@ qemuBuildCpuModelArgStr(virQEMUDriver *driver, return 0; } + +static int +qemuBuildCpuHypervCommandLine(virBuffer *buf, + const virDomainDef *def) +{ + size_t i; + + if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_HYPERV_MODE_NONE) + return 0; + + switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) { + case VIR_DOMAIN_HYPERV_MODE_CUSTOM: + break; + + case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH: + virBufferAsprintf(buf, ",hv-%s=on", "passthrough"); + break; + + case VIR_DOMAIN_HYPERV_MODE_NONE: + case VIR_DOMAIN_HYPERV_MODE_LAST: + default: + virReportEnumRangeError(virDomainHyperVMode, + def->features[VIR_DOMAIN_FEATURE_HYPERV]); + return -1; + } + + for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) { + switch ((virDomainHyperv) i) { + case VIR_DOMAIN_HYPERV_RELAXED: + case VIR_DOMAIN_HYPERV_VAPIC: + case VIR_DOMAIN_HYPERV_VPINDEX: + case VIR_DOMAIN_HYPERV_RUNTIME: + case VIR_DOMAIN_HYPERV_SYNIC: + case VIR_DOMAIN_HYPERV_STIMER: + case VIR_DOMAIN_HYPERV_RESET: + case VIR_DOMAIN_HYPERV_FREQUENCIES: + case VIR_DOMAIN_HYPERV_REENLIGHTENMENT: + case VIR_DOMAIN_HYPERV_TLBFLUSH: + case VIR_DOMAIN_HYPERV_IPI: + case VIR_DOMAIN_HYPERV_EVMCS: + case VIR_DOMAIN_HYPERV_AVIC: + case VIR_DOMAIN_HYPERV_EMSR_BITMAP: + case VIR_DOMAIN_HYPERV_XMM_INPUT: + if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { + const char *name = virDomainHypervTypeToString(i); + g_autofree char *full_name = g_strdup_printf("hv-%s", name); + const char *qemu_name = virQEMUCapsCPUFeatureToQEMU(def->os.arch, + full_name); + virBufferAsprintf(buf, ",%s=on", qemu_name); + } + if ((i == VIR_DOMAIN_HYPERV_STIMER) && + (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON)) + virBufferAsprintf(buf, ",%s=on", VIR_CPU_x86_HV_STIMER_DIRECT); + if (i == VIR_DOMAIN_HYPERV_TLBFLUSH) { + if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) + virBufferAsprintf(buf, ",%s=on", VIR_CPU_x86_HV_TLBFLUSH_DIRECT); + if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) + virBufferAsprintf(buf, ",%s=on", VIR_CPU_x86_HV_TLBFLUSH_EXT); + } + break; + + case VIR_DOMAIN_HYPERV_SPINLOCKS: + if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) + virBufferAsprintf(buf, ",%s=0x%x", + VIR_CPU_x86_HV_SPINLOCKS, + def->hyperv_spinlocks); + break; + + case VIR_DOMAIN_HYPERV_VENDOR_ID: + if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) + virBufferAsprintf(buf, ",hv-vendor-id=%s", + def->hyperv_vendor_id); + break; + + case VIR_DOMAIN_HYPERV_LAST: + break; + } + } + + return 0; +} + + static int qemuBuildCpuCommandLine(virCommand *cmd, virQEMUDriver *driver, @@ -6545,76 +6628,8 @@ qemuBuildCpuCommandLine(virCommand *cmd, VIR_TRISTATE_SWITCH_ON ? "on" : "off"); } - if (def->features[VIR_DOMAIN_FEATURE_HYPERV] != VIR_DOMAIN_HYPERV_MODE_NONE) { - switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) { - case VIR_DOMAIN_HYPERV_MODE_CUSTOM: - break; - - case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH: - virBufferAsprintf(&buf, ",hv-%s=on", "passthrough"); - break; - - case VIR_DOMAIN_HYPERV_MODE_NONE: - case VIR_DOMAIN_HYPERV_MODE_LAST: - default: - virReportEnumRangeError(virDomainHyperVMode, - def->features[VIR_DOMAIN_FEATURE_HYPERV]); - return -1; - } - - for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) { - switch ((virDomainHyperv) i) { - case VIR_DOMAIN_HYPERV_RELAXED: - case VIR_DOMAIN_HYPERV_VAPIC: - case VIR_DOMAIN_HYPERV_VPINDEX: - case VIR_DOMAIN_HYPERV_RUNTIME: - case VIR_DOMAIN_HYPERV_SYNIC: - case VIR_DOMAIN_HYPERV_STIMER: - case VIR_DOMAIN_HYPERV_RESET: - case VIR_DOMAIN_HYPERV_FREQUENCIES: - case VIR_DOMAIN_HYPERV_REENLIGHTENMENT: - case VIR_DOMAIN_HYPERV_TLBFLUSH: - case VIR_DOMAIN_HYPERV_IPI: - case VIR_DOMAIN_HYPERV_EVMCS: - case VIR_DOMAIN_HYPERV_AVIC: - case VIR_DOMAIN_HYPERV_EMSR_BITMAP: - case VIR_DOMAIN_HYPERV_XMM_INPUT: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - const char *name = virDomainHypervTypeToString(i); - g_autofree char *full_name = g_strdup_printf("hv-%s", name); - const char *qemu_name = virQEMUCapsCPUFeatureToQEMU(def->os.arch, - full_name); - virBufferAsprintf(&buf, ",%s=on", qemu_name); - } - if ((i == VIR_DOMAIN_HYPERV_STIMER) && - (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON)) - virBufferAsprintf(&buf, ",%s=on", VIR_CPU_x86_HV_STIMER_DIRECT); - if (i == VIR_DOMAIN_HYPERV_TLBFLUSH) { - if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) - virBufferAsprintf(&buf, ",%s=on", VIR_CPU_x86_HV_TLBFLUSH_DIRECT); - if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) - virBufferAsprintf(&buf, ",%s=on", VIR_CPU_x86_HV_TLBFLUSH_EXT); - } - break; - - case VIR_DOMAIN_HYPERV_SPINLOCKS: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) - virBufferAsprintf(&buf, ",%s=0x%x", - VIR_CPU_x86_HV_SPINLOCKS, - def->hyperv_spinlocks); - break; - - case VIR_DOMAIN_HYPERV_VENDOR_ID: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) - virBufferAsprintf(&buf, ",hv-vendor-id=%s", - def->hyperv_vendor_id); - break; - - case VIR_DOMAIN_HYPERV_LAST: - break; - } - } - } + if (qemuBuildCpuHypervCommandLine(&buf, def) < 0) + return -1; for (i = 0; i < def->npanics; i++) { if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) { -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Using virBufferAsprintf() just to concatenate two literal strings is excessive. Use virBufferAddLit(). Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 542022b889..65b50740ce 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6464,7 +6464,7 @@ qemuBuildCpuHypervCommandLine(virBuffer *buf, break; case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH: - virBufferAsprintf(buf, ",hv-%s=on", "passthrough"); + virBufferAddLit(buf, ",hv-passthrough=on"); break; case VIR_DOMAIN_HYPERV_MODE_NONE: -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Inside of libxlMakeDomBuildInfo() there's a huge switch() for each virDomainHyperv case. Instead of checking whether feature is enabled in each 'case', let's just check it at the beginning of each loop. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/libxl/libxl_conf.c | 67 +++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 0cbc09b6b0..cea4bd801c 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -608,60 +608,49 @@ libxlMakeDomBuildInfo(virDomainDef *def, } for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) { + if (def->hyperv_features[i] != VIR_TRISTATE_SWITCH_ON) + continue; + switch ((virDomainHyperv) i) { case VIR_DOMAIN_HYPERV_VPINDEX: case VIR_DOMAIN_HYPERV_RELAXED: /* Already set by base flag */ break; case VIR_DOMAIN_HYPERV_SYNIC: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC); - } + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC); break; case VIR_DOMAIN_HYPERV_STIMER: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - /* STIMER implies synic and clock features */ - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_STIMER); - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC); - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT); - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC); - } + /* STIMER implies synic and clock features */ + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_STIMER); + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC); + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT); + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC); break; case VIR_DOMAIN_HYPERV_VAPIC: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST); - } + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST); break; case VIR_DOMAIN_HYPERV_FREQUENCIES: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ); - } + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ); break; case VIR_DOMAIN_HYPERV_TLBFLUSH: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_REMOTE_TLB_FLUSH); - } + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_REMOTE_TLB_FLUSH); break; case VIR_DOMAIN_HYPERV_IPI: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - libxl_bitmap_set(&b_info->u.hvm.viridian_enable, - LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_IPI); - } + libxl_bitmap_set(&b_info->u.hvm.viridian_enable, + LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_IPI); break; case VIR_DOMAIN_HYPERV_SPINLOCKS: case VIR_DOMAIN_HYPERV_VENDOR_ID: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - const char *name = virDomainHypervTypeToString(i); - VIR_WARN("Hyper-v flag '%s' specified per-domain but is a global Xen setting and will be ignored.", name); - } + VIR_WARN("Hyper-v flag '%s' specified per-domain but is a global Xen setting and will be ignored.", + virDomainHypervTypeToString(i)); break; case VIR_DOMAIN_HYPERV_RUNTIME: case VIR_DOMAIN_HYPERV_RESET: @@ -670,11 +659,9 @@ libxlMakeDomBuildInfo(virDomainDef *def, case VIR_DOMAIN_HYPERV_AVIC: case VIR_DOMAIN_HYPERV_EMSR_BITMAP: case VIR_DOMAIN_HYPERV_XMM_INPUT: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { - const char *name = virDomainHypervTypeToString(i); - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Hyper-v enlightenment feature '%1$s' is not supported for Xen domains."), name); - } + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Hyper-v enlightenment feature '%1$s' is not supported for Xen domains."), + virDomainHypervTypeToString(i)); break; case VIR_DOMAIN_HYPERV_LAST: break; -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> So far, we have an array of integers (hyperv_features), an uint (hyperv_spinlocks), a string (hyperv_vendor_id) and some tristate switches scattered across virDomainDef. Soon, new knobs will be introduced and keeping the current state would only worsen readability. Introduce virDomainHypervFeatures struct to place hyperv related features there. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/conf/domain_conf.c | 77 ++++++++++++++++++++++------------------ src/conf/domain_conf.h | 15 ++++---- src/conf/virconftypes.h | 2 ++ src/libxl/libxl_conf.c | 2 +- src/qemu/qemu_command.c | 16 ++++----- src/qemu/qemu_process.c | 8 ++--- src/qemu/qemu_validate.c | 12 +++---- 7 files changed, 72 insertions(+), 60 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d095454283..8c42f95af4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4020,6 +4020,13 @@ virDomainOSDefClear(virDomainOSDef *os) } +static void +virDomainHypervFeaturesClear(virDomainHypervFeatures *hv) +{ + g_free(hv->vendor_id); +} + + void virDomainDefFree(virDomainDef *def) { size_t i; @@ -4147,8 +4154,8 @@ void virDomainDefFree(virDomainDef *def) g_free(def->emulator); g_free(def->description); g_free(def->title); + virDomainHypervFeaturesClear(&def->hyperv); g_free(def->kvm_features); - g_free(def->hyperv_vendor_id); g_free(def->tcg_features); virBlkioDeviceArrayClear(def->blkio.devices, @@ -17049,7 +17056,7 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, &value) < 0) return -1; - def->hyperv_features[feature] = value; + def->hyperv.features[feature] = value; switch ((virDomainHyperv) feature) { case VIR_DOMAIN_HYPERV_RELAXED: @@ -17075,11 +17082,11 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, while (child) { if (STREQ((const char *)child->name, "direct")) { if (virXMLPropTristateSwitch(child, "state", VIR_XML_PROP_REQUIRED, - &def->hyperv_tlbflush_direct) < 0) + &def->hyperv.tlbflush_direct) < 0) return -1; } else if (STREQ((const char *)child->name, "extended")) { if (virXMLPropTristateSwitch(child, "state", VIR_XML_PROP_REQUIRED, - &def->hyperv_tlbflush_extended) < 0) + &def->hyperv.tlbflush_extended) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -17106,7 +17113,7 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, } if (virXMLPropTristateSwitch(child, "state", VIR_XML_PROP_REQUIRED, - &def->hyperv_stimer_direct) < 0) + &def->hyperv.stimer_direct) < 0) return -1; child = xmlNextElementSibling(child); @@ -17118,10 +17125,10 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, break; if (virXMLPropUInt(node, "retries", 0, VIR_XML_PROP_REQUIRED, - &def->hyperv_spinlocks) < 0) + &def->hyperv.spinlocks) < 0) return -1; - if (def->hyperv_spinlocks < 0xFFF) { + if (def->hyperv.spinlocks < 0xFFF) { virReportError(VIR_ERR_XML_ERROR, "%s", _("HyperV spinlock retry count must be at least 4095")); return -1; @@ -17132,15 +17139,15 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, if (value != VIR_TRISTATE_SWITCH_ON) break; - g_clear_pointer(&def->hyperv_vendor_id, g_free); + g_clear_pointer(&def->hyperv.vendor_id, g_free); - if (!(def->hyperv_vendor_id = virXMLPropString(node, "value"))) { + if (!(def->hyperv.vendor_id = virXMLPropString(node, "value"))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing 'value' attribute for HyperV feature 'vendor_id'")); return -1; } - if (!STRLIM(def->hyperv_vendor_id, VIR_DOMAIN_HYPERV_VENDOR_ID_MAX)) { + if (!STRLIM(def->hyperv.vendor_id, VIR_DOMAIN_HYPERV_VENDOR_ID_MAX)) { virReportError(VIR_ERR_XML_ERROR, _("HyperV vendor_id value must not be more than %1$d characters."), VIR_DOMAIN_HYPERV_VENDOR_ID_MAX); @@ -17148,7 +17155,7 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, } /* ensure that the string can be passed to qemu */ - if (strchr(def->hyperv_vendor_id, ',')) { + if (strchr(def->hyperv.vendor_id, ',')) { virReportError(VIR_ERR_XML_ERROR, "%s", _("HyperV vendor_id value is invalid")); return -1; @@ -21641,12 +21648,12 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_HYPERV_AVIC: case VIR_DOMAIN_HYPERV_EMSR_BITMAP: case VIR_DOMAIN_HYPERV_XMM_INPUT: - if (src->hyperv_features[i] != dst->hyperv_features[i]) { + if (src->hyperv.features[i] != dst->hyperv.features[i]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of HyperV enlightenment feature '%1$s' differs: source: '%2$s', destination: '%3$s'"), virDomainHypervTypeToString(i), - virTristateSwitchTypeToString(src->hyperv_features[i]), - virTristateSwitchTypeToString(dst->hyperv_features[i])); + virTristateSwitchTypeToString(src->hyperv.features[i]), + virTristateSwitchTypeToString(dst->hyperv.features[i])); return false; } @@ -21654,21 +21661,21 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_HYPERV_SPINLOCKS: /* spinlock count matters! */ - if (src->hyperv_spinlocks != dst->hyperv_spinlocks) { + if (src->hyperv.spinlocks != dst->hyperv.spinlocks) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("HyperV spinlock retry count differs: source: '%1$u', destination: '%2$u'"), - src->hyperv_spinlocks, - dst->hyperv_spinlocks); + src->hyperv.spinlocks, + dst->hyperv.spinlocks); return false; } break; case VIR_DOMAIN_HYPERV_VENDOR_ID: - if (STRNEQ_NULLABLE(src->hyperv_vendor_id, dst->hyperv_vendor_id)) { + if (STRNEQ_NULLABLE(src->hyperv.vendor_id, dst->hyperv.vendor_id)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("HyperV vendor_id differs: source: '%1$s', destination: '%2$s'"), - src->hyperv_vendor_id, - dst->hyperv_vendor_id); + src->hyperv.vendor_id, + dst->hyperv.vendor_id); return false; } break; @@ -21679,12 +21686,12 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, } } - if (src->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) { - if (src->hyperv_stimer_direct != dst->hyperv_stimer_direct) { + if (src->hyperv.features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) { + if (src->hyperv.stimer_direct != dst->hyperv.stimer_direct) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of HyperV stimer direct feature differs: source: '%1$s', destination: '%2$s'"), - virTristateSwitchTypeToString(src->hyperv_stimer_direct), - virTristateSwitchTypeToString(dst->hyperv_stimer_direct)); + virTristateSwitchTypeToString(src->hyperv.stimer_direct), + virTristateSwitchTypeToString(dst->hyperv.stimer_direct)); return false; } } @@ -28599,11 +28606,11 @@ virDomainFeaturesHyperVDefFormat(virBuffer *buf, g_auto(virBuffer) hypervAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) hypervChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf); - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT) + if (def->hyperv.features[j] == VIR_TRISTATE_SWITCH_ABSENT) continue; virBufferAsprintf(&hypervAttrBuf, " state='%s'", - virTristateSwitchTypeToString(def->hyperv_features[j])); + virTristateSwitchTypeToString(def->hyperv.features[j])); switch ((virDomainHyperv) j) { case VIR_DOMAIN_HYPERV_RELAXED: @@ -28622,34 +28629,34 @@ virDomainFeaturesHyperVDefFormat(virBuffer *buf, break; case VIR_DOMAIN_HYPERV_SPINLOCKS: - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[j] == VIR_TRISTATE_SWITCH_ON) { virBufferAsprintf(&hypervAttrBuf, - " retries='%d'", def->hyperv_spinlocks); + " retries='%d'", def->hyperv.spinlocks); } break; case VIR_DOMAIN_HYPERV_STIMER: - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON && - def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[j] == VIR_TRISTATE_SWITCH_ON && + def->hyperv.stimer_direct == VIR_TRISTATE_SWITCH_ON) { virBufferAddLit(&hypervChildBuf, "<direct state='on'/>\n"); } break; case VIR_DOMAIN_HYPERV_VENDOR_ID: - if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[j] == VIR_TRISTATE_SWITCH_ON) { virBufferEscapeString(&hypervAttrBuf, " value='%s'", - def->hyperv_vendor_id); + def->hyperv.vendor_id); } break; case VIR_DOMAIN_HYPERV_TLBFLUSH: - if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.features[j] != VIR_TRISTATE_SWITCH_ON) break; - if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.tlbflush_direct == VIR_TRISTATE_SWITCH_ON) virBufferAddLit(&hypervChildBuf, "<direct state='on'/>\n"); - if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.tlbflush_extended == VIR_TRISTATE_SWITCH_ON) virBufferAddLit(&hypervChildBuf, "<extended state='on'/>\n"); break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9159a69833..5e37ef7b0d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3124,6 +3124,14 @@ struct _virDomainPstoreDef { virDomainDeviceInfo info; }; +struct _virDomainHypervFeatures { + int features[VIR_DOMAIN_HYPERV_LAST]; + unsigned int spinlocks; + virTristateSwitch stimer_direct; + virTristateSwitch tlbflush_direct; + virTristateSwitch tlbflush_extended; + char *vendor_id; +}; #define SCSI_SUPER_WIDE_BUS_MAX_CONT_UNIT 64 #define SCSI_WIDE_BUS_MAX_CONT_UNIT 16 @@ -3195,19 +3203,14 @@ struct _virDomainDef { * See virDomainDefFeaturesCheckABIStability() for details. */ int features[VIR_DOMAIN_FEATURE_LAST]; int caps_features[VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST]; - int hyperv_features[VIR_DOMAIN_HYPERV_LAST]; + virDomainHypervFeatures hyperv; virDomainFeatureKVM *kvm_features; int msrs_features[VIR_DOMAIN_MSRS_LAST]; int xen_features[VIR_DOMAIN_XEN_LAST]; virDomainXenPassthroughMode xen_passthrough_mode; - unsigned int hyperv_spinlocks; - virTristateSwitch hyperv_stimer_direct; - virTristateSwitch hyperv_tlbflush_direct; - virTristateSwitch hyperv_tlbflush_extended; virGICVersion gic_version; virDomainHPTResizing hpt_resizing; unsigned long long hpt_maxpagesize; /* Stored in KiB */ - char *hyperv_vendor_id; virTristateSwitch apic_eoi; virDomainFeatureTCG *tcg_features; diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 93fc9c9217..6e2573035a 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -142,6 +142,8 @@ typedef struct _virDomainHubDef virDomainHubDef; typedef struct _virDomainHugePage virDomainHugePage; +typedef struct _virDomainHypervFeatures virDomainHypervFeatures; + typedef struct _virDomainIOMMUDef virDomainIOMMUDef; typedef struct _virDomainIOThreadIDDef virDomainIOThreadIDDef; diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index cea4bd801c..3962a7dba2 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -608,7 +608,7 @@ libxlMakeDomBuildInfo(virDomainDef *def, } for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) { - if (def->hyperv_features[i] != VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.features[i] != VIR_TRISTATE_SWITCH_ON) continue; switch ((virDomainHyperv) i) { diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 65b50740ce..7a31848d6f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6492,7 +6492,7 @@ qemuBuildCpuHypervCommandLine(virBuffer *buf, case VIR_DOMAIN_HYPERV_AVIC: case VIR_DOMAIN_HYPERV_EMSR_BITMAP: case VIR_DOMAIN_HYPERV_XMM_INPUT: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[i] == VIR_TRISTATE_SWITCH_ON) { const char *name = virDomainHypervTypeToString(i); g_autofree char *full_name = g_strdup_printf("hv-%s", name); const char *qemu_name = virQEMUCapsCPUFeatureToQEMU(def->os.arch, @@ -6500,27 +6500,27 @@ qemuBuildCpuHypervCommandLine(virBuffer *buf, virBufferAsprintf(buf, ",%s=on", qemu_name); } if ((i == VIR_DOMAIN_HYPERV_STIMER) && - (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON)) + (def->hyperv.stimer_direct == VIR_TRISTATE_SWITCH_ON)) virBufferAsprintf(buf, ",%s=on", VIR_CPU_x86_HV_STIMER_DIRECT); if (i == VIR_DOMAIN_HYPERV_TLBFLUSH) { - if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.tlbflush_direct == VIR_TRISTATE_SWITCH_ON) virBufferAsprintf(buf, ",%s=on", VIR_CPU_x86_HV_TLBFLUSH_DIRECT); - if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.tlbflush_extended == VIR_TRISTATE_SWITCH_ON) virBufferAsprintf(buf, ",%s=on", VIR_CPU_x86_HV_TLBFLUSH_EXT); } break; case VIR_DOMAIN_HYPERV_SPINLOCKS: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.features[i] == VIR_TRISTATE_SWITCH_ON) virBufferAsprintf(buf, ",%s=0x%x", VIR_CPU_x86_HV_SPINLOCKS, - def->hyperv_spinlocks); + def->hyperv.spinlocks); break; case VIR_DOMAIN_HYPERV_VENDOR_ID: - if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.features[i] == VIR_TRISTATE_SWITCH_ON) virBufferAsprintf(buf, ",hv-vendor-id=%s", - def->hyperv_vendor_id); + def->hyperv.vendor_id); break; case VIR_DOMAIN_HYPERV_LAST: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 57b14f640e..d42e3f612b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4418,7 +4418,7 @@ qemuProcessVerifyHypervFeatures(virDomainDef *def, i == VIR_DOMAIN_HYPERV_SPINLOCKS) continue; - if (def->hyperv_features[i] != VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.features[i] != VIR_TRISTATE_SWITCH_ON) continue; cpuFeature = g_strdup_printf("hv-%s", virDomainHypervTypeToString(i)); @@ -4429,7 +4429,7 @@ qemuProcessVerifyHypervFeatures(virDomainDef *def, return -1; } else if (rc == 1) { if (i == VIR_DOMAIN_HYPERV_STIMER) { - if (def->hyperv_stimer_direct != VIR_TRISTATE_SWITCH_ON) + if (def->hyperv.stimer_direct != VIR_TRISTATE_SWITCH_ON) continue; rc = virCPUDataCheckFeature(cpu, VIR_CPU_x86_HV_STIMER_DIRECT); @@ -4444,7 +4444,7 @@ qemuProcessVerifyHypervFeatures(virDomainDef *def, return -1; } if (i == VIR_DOMAIN_HYPERV_TLBFLUSH) { - if (def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.tlbflush_direct == VIR_TRISTATE_SWITCH_ON) { rc = virCPUDataCheckFeature(cpu, VIR_CPU_x86_HV_TLBFLUSH_DIRECT); if (rc < 0) return -1; @@ -4455,7 +4455,7 @@ qemuProcessVerifyHypervFeatures(virDomainDef *def, return -1; } } - if (def->hyperv_tlbflush_extended == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.tlbflush_extended == VIR_TRISTATE_SWITCH_ON) { rc = virCPUDataCheckFeature(cpu, VIR_CPU_x86_HV_TLBFLUSH_EXT); if (rc < 0) return -1; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 930ba3543f..3e8fdb2268 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -89,8 +89,8 @@ qemuValidateDomainDefPSeriesFeature(const virDomainDef *def, #define CHECK_HV_FEAT(feat, requires) \ - if (def->hyperv_features[feat] == VIR_TRISTATE_SWITCH_ON && \ - def->hyperv_features[requires] != VIR_TRISTATE_SWITCH_ON) { \ + if (def->hyperv.features[feat] == VIR_TRISTATE_SWITCH_ON && \ + def->hyperv.features[requires] != VIR_TRISTATE_SWITCH_ON) { \ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ _("'%1$s' hyperv feature requires '%2$s' feature"), \ virDomainHypervTypeToString(feat), \ @@ -114,7 +114,7 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_SYNIC, VIR_DOMAIN_HYPERV_VPINDEX); - if (def->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) { if (!virDomainDefHasTimer(def, VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("'%1$s' hyperv feature requires '%2$s' timer"), @@ -133,9 +133,9 @@ qemuValidateDomainDefHypervFeatures(const virDomainDef *def) CHECK_HV_FEAT(VIR_DOMAIN_HYPERV_EVMCS, VIR_DOMAIN_HYPERV_VAPIC); - if (def->hyperv_features[VIR_DOMAIN_HYPERV_TLBFLUSH] == VIR_TRISTATE_SWITCH_ON && - def->hyperv_tlbflush_direct == VIR_TRISTATE_SWITCH_ON) { - if (def->hyperv_features[VIR_DOMAIN_HYPERV_VAPIC] != VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[VIR_DOMAIN_HYPERV_TLBFLUSH] == VIR_TRISTATE_SWITCH_ON && + def->hyperv.tlbflush_direct == VIR_TRISTATE_SWITCH_ON) { + if (def->hyperv.features[VIR_DOMAIN_HYPERV_VAPIC] != VIR_TRISTATE_SWITCH_ON) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("'%1$s' hyperv feature requires '%2$s' feature"), VIR_CPU_x86_HV_TLBFLUSH_DIRECT, -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> In formatdomaincaps.rst under section documenting hyperv features there's a paragraph describing behaviour with QEMU older than 6.1.0. Well, as of v11.2.0-rc1~216 the minimum required version is 6.2.0 rendering the paragraph needless. Drop it. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomaincaps.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index 664194b16d..4eb8211b09 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -871,10 +871,6 @@ are supported. The ``features`` enum corresponds to the ``<hyperv/>`` element (well, its children) as documented in `Hypervisor features <formatdomain.html#hypervisor-features>`__. -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 -not all features were reported by QEMU. - Launch security ^^^^^^^^^^^^^^^ -- 2.49.1
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
From: Michal Privoznik <mprivozn@redhat.com> After previous commit the virDomainCapsFeatureHyperv struct gained new members. Since virQEMUCaps struct holds a pointer to such struct we must format and parse it to/from capabilities XML. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_capabilities.c | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2ccddbfcaa..f571596b30 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4496,6 +4496,7 @@ virQEMUCapsParseHypervCapabilities(virQEMUCaps *qemuCaps, g_autoptr(virDomainCapsFeatureHyperv) hvcaps = NULL; xmlNodePtr n = NULL; g_autofree xmlNodePtr *capNodes = NULL; + int rc; int ncapNodes; size_t i; @@ -4531,6 +4532,28 @@ virQEMUCapsParseHypervCapabilities(virQEMUCaps *qemuCaps, VIR_DOMAIN_CAPS_ENUM_SET(hvcaps->features, val); } + rc = virXPathUInt("string(./hypervCapabilities/spinlocks)", + ctxt, &hvcaps->spinlocks); + if (rc == -2) + return -1; + + rc = virXPathTristateSwitch("string(./hypervCapabilities/stimer_direct)", + ctxt, &hvcaps->stimer_direct); + if (rc == -2) + return -1; + + rc = virXPathTristateSwitch("string(./hypervCapabilities/tlbflush_direct)", + ctxt, &hvcaps->tlbflush_direct); + if (rc == -2) + return -1; + + rc = virXPathTristateSwitch("string(./hypervCapabilities/tlbflush_extended)", + ctxt, &hvcaps->tlbflush_extended); + if (rc == -2) + return -1; + + hvcaps->vendor_id = virXPathString("string(./hypervCapabilities/vendor_id)", ctxt); + qemuCaps->hypervCapabilities = g_steal_pointer(&hvcaps); return 0; } @@ -5070,6 +5093,25 @@ virQEMUCapsFormatHypervCapabilities(virQEMUCaps *qemuCaps, virBufferAsprintf(&childBuf, "<cap name='%s'/>\n", virDomainHypervTypeToString(i)); } + + if (hvcaps->spinlocks != 0) { + virBufferAsprintf(&childBuf, "<spinlocks>%u</spinlocks>\n", + hvcaps->spinlocks); + } + if (hvcaps->stimer_direct != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(&childBuf, "<stimer_direct>%s</stimer_direct>\n", + virTristateSwitchTypeToString(hvcaps->stimer_direct)); + } + if (hvcaps->tlbflush_direct != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(&childBuf, "<tlbflush_direct>%s</tlbflush_direct>\n", + virTristateSwitchTypeToString(hvcaps->tlbflush_direct)); + } + if (hvcaps->tlbflush_extended != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(&childBuf, "<tlbflush_extended>%s</tlbflush_extended>\n", + virTristateSwitchTypeToString(hvcaps->tlbflush_extended)); + } + virBufferEscapeString(&childBuf, "<vendor_id>%s</vendor_id>\n", + hvcaps->vendor_id); } return virXMLFormatElement(buf, "hypervCapabilities", &attrBuf, &childBuf); -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Now that everything is prepared, we can start storing the default values for some hyperv features that are reported in domain capabilities XML later. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_capabilities.c | 44 +++++++++++++++++++ .../qemu_10.0.0-q35.x86_64+amdsev.xml | 7 +++ .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml | 7 +++ .../qemu_10.0.0-tcg.x86_64+amdsev.xml | 7 +++ .../domaincapsdata/qemu_10.0.0-tcg.x86_64.xml | 7 +++ .../qemu_10.0.0.x86_64+amdsev.xml | 7 +++ tests/domaincapsdata/qemu_10.0.0.x86_64.xml | 7 +++ .../qemu_10.1.0-q35.x86_64+inteltdx.xml | 7 +++ .../domaincapsdata/qemu_10.1.0-q35.x86_64.xml | 7 +++ .../qemu_10.1.0-tcg.x86_64+inteltdx.xml | 7 +++ .../domaincapsdata/qemu_10.1.0-tcg.x86_64.xml | 7 +++ .../qemu_10.1.0.x86_64+inteltdx.xml | 7 +++ tests/domaincapsdata/qemu_10.1.0.x86_64.xml | 7 +++ .../domaincapsdata/qemu_10.2.0-q35.x86_64.xml | 7 +++ .../domaincapsdata/qemu_10.2.0-tcg.x86_64.xml | 7 +++ tests/domaincapsdata/qemu_10.2.0.x86_64.xml | 7 +++ .../domaincapsdata/qemu_8.0.0-q35.x86_64.xml | 7 +++ .../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml | 7 +++ tests/domaincapsdata/qemu_8.0.0.x86_64.xml | 7 +++ .../domaincapsdata/qemu_8.1.0-q35.x86_64.xml | 7 +++ .../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml | 7 +++ tests/domaincapsdata/qemu_8.1.0.x86_64.xml | 7 +++ .../domaincapsdata/qemu_8.2.0-q35.x86_64.xml | 7 +++ .../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml | 7 +++ tests/domaincapsdata/qemu_8.2.0.x86_64.xml | 7 +++ .../domaincapsdata/qemu_9.0.0-q35.x86_64.xml | 7 +++ .../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml | 7 +++ tests/domaincapsdata/qemu_9.0.0.x86_64.xml | 7 +++ .../domaincapsdata/qemu_9.1.0-q35.x86_64.xml | 7 +++ .../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml | 7 +++ tests/domaincapsdata/qemu_9.1.0.x86_64.xml | 7 +++ .../qemu_9.2.0-q35.x86_64+amdsev.xml | 7 +++ .../domaincapsdata/qemu_9.2.0-q35.x86_64.xml | 7 +++ .../qemu_9.2.0-tcg.x86_64+amdsev.xml | 7 +++ .../domaincapsdata/qemu_9.2.0-tcg.x86_64.xml | 7 +++ .../qemu_9.2.0.x86_64+amdsev.xml | 7 +++ tests/domaincapsdata/qemu_9.2.0.x86_64.xml | 7 +++ .../caps_10.0.0_x86_64+amdsev.xml | 5 +++ .../caps_10.0.0_x86_64.xml | 5 +++ .../caps_10.1.0_x86_64+inteltdx.xml | 5 +++ .../caps_10.1.0_x86_64.xml | 5 +++ .../caps_10.2.0_x86_64.xml | 5 +++ .../caps_8.0.0_x86_64.xml | 5 +++ .../caps_8.1.0_x86_64.xml | 5 +++ .../caps_8.2.0_x86_64.xml | 5 +++ .../caps_9.0.0_x86_64.xml | 5 +++ .../caps_9.1.0_x86_64.xml | 5 +++ .../caps_9.2.0_x86_64+amdsev.xml | 5 +++ .../caps_9.2.0_x86_64.xml | 5 +++ 49 files changed, 356 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f571596b30..2f4664fce3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3155,6 +3155,50 @@ virQEMUCapsProbeHypervCapabilities(virQEMUCaps *qemuCaps, if (!(name = STRSKIP(prop.name, "hv-"))) continue; + if (STREQ(prop.name, VIR_CPU_x86_HV_SPINLOCKS)) { + if (prop.type != QEMU_MONITOR_CPU_PROPERTY_NUMBER) { + VIR_DEBUG("Unexpected type '%s' for name '%s'", + qemuMonitorCPUPropertyTypeToString(prop.type), prop.name); + continue; + } + + if ((uint32_t)prop.value.number != (uint32_t)-1) + hvcaps->spinlocks = prop.value.number; + } else if (STREQ(prop.name, VIR_CPU_x86_HV_STIMER_DIRECT)) { + if (prop.type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) { + VIR_DEBUG("Unexpected type '%s' for name '%s'", + qemuMonitorCPUPropertyTypeToString(prop.type), prop.name); + } else { + hvcaps->stimer_direct = virTristateSwitchFromBool(prop.value.boolean); + } + continue; + } else if (STREQ(prop.name, VIR_CPU_x86_HV_TLBFLUSH_DIRECT)) { + if (prop.type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) { + VIR_DEBUG("Unexpected type '%s' for name '%s'", + qemuMonitorCPUPropertyTypeToString(prop.type), prop.name); + } else { + hvcaps->tlbflush_direct = virTristateSwitchFromBool(prop.value.boolean); + } + continue; + } else if (STREQ(prop.name, VIR_CPU_x86_HV_TLBFLUSH_EXT)) { + if (prop.type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) { + VIR_DEBUG("Unexpected type '%s' for name '%s'", + qemuMonitorCPUPropertyTypeToString(prop.type), prop.name); + } else { + hvcaps->tlbflush_extended = virTristateSwitchFromBool(prop.value.boolean); + } + continue; + } else if (STREQ(prop.name, "hv-vendor-id")) { + if (prop.type != QEMU_MONITOR_CPU_PROPERTY_STRING) { + VIR_DEBUG("Unexpected type '%s' for name '%s'", + qemuMonitorCPUPropertyTypeToString(prop.type), prop.name); + continue; + } + + if (STRNEQ(prop.value.string, "")) + hvcaps->vendor_id = g_strdup(prop.value.string); + } + hvprop = virDomainHypervTypeFromString(name); if (hvprop < 0) { diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml index 5ef892e1ff..ec2944d380 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64+amdsev.xml @@ -861,6 +861,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml index 60cee93cb6..abe4536c18 100644 --- a/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-q35.x86_64.xml @@ -1716,6 +1716,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml index 6dc5bccfed..481092d7b1 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64+amdsev.xml @@ -1830,6 +1830,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml index de4fbe0dbe..3bec568edf 100644 --- a/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0-tcg.x86_64.xml @@ -1824,6 +1824,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml index 74bc0dc84e..818876eb89 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64+amdsev.xml @@ -861,6 +861,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml index b41e9ae196..c9c89b202b 100644 --- a/tests/domaincapsdata/qemu_10.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.0.0.x86_64.xml @@ -1716,6 +1716,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml index fafa28ecbe..e7b1e4d1ae 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64+inteltdx.xml @@ -773,6 +773,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml index 3479493fca..9c832a7bfd 100644 --- a/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-q35.x86_64.xml @@ -1741,6 +1741,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml index eba8023fc8..b0eb35c6c8 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64+inteltdx.xml @@ -1820,6 +1820,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml index fd4ea39d42..fb6540b94a 100644 --- a/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0-tcg.x86_64.xml @@ -1821,6 +1821,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml index 9ea7d779b5..468dc22ce9 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64+inteltdx.xml @@ -773,6 +773,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml index fc90d0d680..df171bb5d7 100644 --- a/tests/domaincapsdata/qemu_10.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.1.0.x86_64.xml @@ -1741,6 +1741,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml index d81f1632a3..409357d8f4 100644 --- a/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-q35.x86_64.xml @@ -994,6 +994,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml index c439ea0eee..c43f7eb9ce 100644 --- a/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0-tcg.x86_64.xml @@ -1821,6 +1821,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml b/tests/domaincapsdata/qemu_10.2.0.x86_64.xml index 59ac0015ce..65283fb50a 100644 --- a/tests/domaincapsdata/qemu_10.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_10.2.0.x86_64.xml @@ -994,6 +994,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml index 7fd6a8b043..8a5277934d 100644 --- a/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-q35.x86_64.xml @@ -1262,6 +1262,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>off</tlbflush_direct> + <tlbflush_extended>off</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml index 949534b6cc..9348304998 100644 --- a/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0-tcg.x86_64.xml @@ -1755,6 +1755,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>off</tlbflush_direct> + <tlbflush_extended>off</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml b/tests/domaincapsdata/qemu_8.0.0.x86_64.xml index db709b0355..f68a87f2e0 100644 --- a/tests/domaincapsdata/qemu_8.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.0.0.x86_64.xml @@ -1262,6 +1262,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>off</tlbflush_direct> + <tlbflush_extended>off</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml index 5130dd0c6c..a9a113326a 100644 --- a/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-q35.x86_64.xml @@ -1520,6 +1520,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml index 8381303e99..f1f41fbe96 100644 --- a/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0-tcg.x86_64.xml @@ -1776,6 +1776,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml b/tests/domaincapsdata/qemu_8.1.0.x86_64.xml index 705e7be2e7..13541e8421 100644 --- a/tests/domaincapsdata/qemu_8.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.1.0.x86_64.xml @@ -1520,6 +1520,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml index 8e026e2f40..dabdf47c6b 100644 --- a/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-q35.x86_64.xml @@ -1522,6 +1522,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml index 5878c09b14..7538570678 100644 --- a/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0-tcg.x86_64.xml @@ -1743,6 +1743,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml b/tests/domaincapsdata/qemu_8.2.0.x86_64.xml index 921e87a285..ffcfc42b08 100644 --- a/tests/domaincapsdata/qemu_8.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_8.2.0.x86_64.xml @@ -1522,6 +1522,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml index 16f8b46b15..7289d5fbdc 100644 --- a/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-q35.x86_64.xml @@ -1522,6 +1522,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml index 79411ea73f..141edc67f3 100644 --- a/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0-tcg.x86_64.xml @@ -1672,6 +1672,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml b/tests/domaincapsdata/qemu_9.0.0.x86_64.xml index fa378cf372..5a636f06a8 100644 --- a/tests/domaincapsdata/qemu_9.0.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.0.0.x86_64.xml @@ -1522,6 +1522,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml index c7ae480df8..4003af73de 100644 --- a/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-q35.x86_64.xml @@ -1658,6 +1658,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml index 94b530d1e8..2fdeeb143a 100644 --- a/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0-tcg.x86_64.xml @@ -1777,6 +1777,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml b/tests/domaincapsdata/qemu_9.1.0.x86_64.xml index fce0504d60..ba78d5d24d 100644 --- a/tests/domaincapsdata/qemu_9.1.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.1.0.x86_64.xml @@ -1658,6 +1658,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml index 3667417d1b..099c503551 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64+amdsev.xml @@ -861,6 +861,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml index b4437dd3d0..f83af00819 100644 --- a/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-q35.x86_64.xml @@ -1716,6 +1716,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml index d214915a48..28b9647f14 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64+amdsev.xml @@ -1830,6 +1830,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml index 04c13a1335..f3469cdade 100644 --- a/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0-tcg.x86_64.xml @@ -1824,6 +1824,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml index 9b62c679b7..462365ee12 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64+amdsev.xml @@ -861,6 +861,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='yes'> <enum name='sectype'> diff --git a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml index 3d970f53db..756e2cf90a 100644 --- a/tests/domaincapsdata/qemu_9.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_9.2.0.x86_64.xml @@ -1716,6 +1716,13 @@ <value>emsr_bitmap</value> <value>xmm_input</value> </enum> + <defaults> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> + </defaults> </hyperv> <launchSecurity supported='no'/> </features> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml index b83de7cc4d..e410e11dbe 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -3374,5 +3374,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml index 4545de53ef..6b50ff6249 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -4223,5 +4223,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml index 3381f0bafa..3d5d53d3e7 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -3581,5 +3581,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml index 014e0ff44e..9628c5c999 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -4899,5 +4899,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml index 3e5e2cdb08..35d63265f0 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml @@ -3946,5 +3946,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml index 555b078971..f0053a9742 100644 --- a/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml @@ -3453,5 +3453,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>off</tlbflush_direct> + <tlbflush_extended>off</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml index 5e44997c91..c8782763aa 100644 --- a/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml @@ -3782,5 +3782,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml index 232a060750..21f40b7f5a 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml @@ -3756,5 +3756,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index 4953de2247..5ec8321bf2 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -3692,5 +3692,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index df062944e2..4c0d5a28f9 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -3949,5 +3949,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml index 048d1b1462..6caddd450f 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml @@ -3123,5 +3123,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml index dd2d876cad..665b82560c 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml @@ -3930,5 +3930,10 @@ <cap name='avic'/> <cap name='emsr_bitmap'/> <cap name='xmm_input'/> + <spinlocks>4095</spinlocks> + <stimer_direct>on</stimer_direct> + <tlbflush_direct>on</tlbflush_direct> + <tlbflush_extended>on</tlbflush_extended> + <vendor_id>Linux KVM Hv</vendor_id> </hypervCapabilities> </qemuCaps> -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> We'll need to access hypervCapabilities memeber later on. Introduce a getter function. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_capabilities.c | 7 +++++++ src/qemu/qemu_capabilities.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2f4664fce3..83946123be 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2710,6 +2710,13 @@ virQEMUCapsGetSGXCapabilities(virQEMUCaps *qemuCaps) } +virDomainCapsFeatureHyperv * +virQEMUCapsGetHypervCapabilities(virQEMUCaps *qemuCaps) +{ + return qemuCaps->hypervCapabilities; +} + + static int virQEMUCapsProbeQMPObjectTypes(virQEMUCaps *qemuCaps, qemuMonitor *mon) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index c71fc19a03..2b454e0352 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -957,6 +957,9 @@ virQEMUCapsGetSEVCapabilities(virQEMUCaps *qemuCaps); virSGXCapability * virQEMUCapsGetSGXCapabilities(virQEMUCaps *qemuCaps); +virDomainCapsFeatureHyperv * +virQEMUCapsGetHypervCapabilities(virQEMUCaps *qemuCaps); + bool virQEMUCapsGetKVMSupportsSecureGuest(virQEMUCaps *qemuCaps) ATTRIBUTE_MOCKABLE; -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> So far we have two modes for hyperv features: 1) custom, where users have to enable features explicitly, and 2) passthrough, where hypervisor enables features automagically. Problem with 'custom' mode is that some features are not plain on/off switches but expect int/string value. Until very recently, these were not reported in domcaps. And even if they were it's a bit cumbersome. Problem with 'passthrough' mode is that users don't get to see the expanded list of enlightenments enabled. Therefore, mimic what we're already doing with CPUs: have 'host-model' which gets expanded at domain startup and is fixed throughout domain's run. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.rst | 6 ++++ src/conf/domain_conf.c | 4 ++- src/conf/domain_conf.h | 1 + src/conf/schemas/domaincommon.rng | 3 ++ src/libxl/libxl_conf.c | 1 + src/qemu/qemu_command.c | 1 + .../hyperv-host-model.x86_64-latest.args | 32 ++++++++++++++++++ .../hyperv-host-model.x86_64-latest.xml | 33 +++++++++++++++++++ tests/qemuxmlconfdata/hyperv-host-model.xml | 27 +++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/hyperv-host-model.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index fcf3ad8d29..13c624fe5b 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2189,6 +2189,12 @@ are: virtual CPU may or may not contain features which may block migration even to an identical host. + ``host-model`` + Similar to the ``passthrough`` mode, except libvirt detects which + enlightenments are supported by hypervisor and expands them on domain + startup into the live XML. In a sense, this is similar to ``host-model`` + CPU mode (See `CPU model and topology`_). :since:`Since 11.9.0` + The ``mode`` attribute can be omitted and will default to ``custom``. ``pvspinlock`` diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8c42f95af4..4737594487 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -145,6 +145,7 @@ VIR_ENUM_IMPL(virDomainHyperVMode, "none", "custom", "passthrough", + "host-model", ); VIR_ENUM_IMPL(virDomainBoot, @@ -17035,7 +17036,8 @@ virDomainFeaturesHyperVDefParse(virDomainDef *def, def->features[VIR_DOMAIN_FEATURE_HYPERV] = mode; - if (mode == VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH) + if (mode == VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH || + mode == VIR_DOMAIN_HYPERV_MODE_HOST_MODEL) return 0; node = xmlFirstElementChild(node); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5e37ef7b0d..a63d922853 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -164,6 +164,7 @@ typedef enum { VIR_DOMAIN_HYPERV_MODE_NONE = 0, VIR_DOMAIN_HYPERV_MODE_CUSTOM, VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH, + VIR_DOMAIN_HYPERV_MODE_HOST_MODEL, VIR_DOMAIN_HYPERV_MODE_LAST } virDomainHyperVMode; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index b9230a35b4..ace74fee08 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -8030,6 +8030,9 @@ <attribute name="mode"> <value>passthrough</value> </attribute> + <attribute name="mode"> + <value>host-model</value> + </attribute> <group> <optional> <attribute name="mode"> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 3962a7dba2..2b988157fa 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -599,6 +599,7 @@ libxlMakeDomBuildInfo(virDomainDef *def, case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH: libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable); break; + case VIR_DOMAIN_HYPERV_MODE_HOST_MODEL: case VIR_DOMAIN_HYPERV_MODE_NONE: case VIR_DOMAIN_HYPERV_MODE_LAST: default: diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7a31848d6f..609d0677df 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6461,6 +6461,7 @@ qemuBuildCpuHypervCommandLine(virBuffer *buf, switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) { case VIR_DOMAIN_HYPERV_MODE_CUSTOM: + case VIR_DOMAIN_HYPERV_MODE_HOST_MODEL: break; case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH: diff --git a/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args b/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args new file mode 100644 index 0000000000..2ed72fcd1b --- /dev/null +++ b/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args @@ -0,0 +1,32 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 6,sockets=6,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.xml b/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.xml new file mode 100644 index 0000000000..453a43b3c9 --- /dev/null +++ b/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>6</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <features> + <acpi/> + <hyperv mode='host-model'/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/hyperv-host-model.xml b/tests/qemuxmlconfdata/hyperv-host-model.xml new file mode 100644 index 0000000000..fae00d86dd --- /dev/null +++ b/tests/qemuxmlconfdata/hyperv-host-model.xml @@ -0,0 +1,27 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>6</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <features> + <acpi/> + <hyperv mode='host-model'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 55c622176a..e4d80faa99 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1656,6 +1656,7 @@ mymain(void) DO_TEST_CAPS_LATEST("hyperv-panic"); DO_TEST_CAPS_LATEST("hyperv-passthrough"); DO_TEST_CAPS_LATEST("hyperv-stimer-direct"); + DO_TEST_CAPS_LATEST("hyperv-host-model"); DO_TEST_CAPS_LATEST("kvm-features"); DO_TEST_CAPS_LATEST("kvm-features-off"); -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Pretty straightforward. The only "weird" thing here is that 'hv-time' enlightenment is exposed as a <timer/> under <clock/> element. Since it's required by 'hv-stimer' and 'hv-stimer-direct' it needs to be enabled too. Resolves: https://issues.redhat.com/browse/RHEL-114003 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_process.c | 72 +++++++++++++++++++ .../hyperv-host-model.x86_64-latest.args | 2 +- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 609d0677df..fcf5fc1935 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6461,13 +6461,13 @@ qemuBuildCpuHypervCommandLine(virBuffer *buf, switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) { case VIR_DOMAIN_HYPERV_MODE_CUSTOM: - case VIR_DOMAIN_HYPERV_MODE_HOST_MODEL: break; case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH: virBufferAddLit(buf, ",hv-passthrough=on"); break; + case VIR_DOMAIN_HYPERV_MODE_HOST_MODEL: case VIR_DOMAIN_HYPERV_MODE_NONE: case VIR_DOMAIN_HYPERV_MODE_LAST: default: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d42e3f612b..9926998f85 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6835,6 +6835,75 @@ qemuProcessPrepareChardevSource(virDomainDef *def, } +static void +qemuProcessMaybeAddHypervTimer(virDomainDef *def) +{ + g_autofree virDomainTimerDef *timer = NULL; + + if (virDomainDefHasTimer(def, VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK)) + return; + + timer = g_new0(virDomainTimerDef, 1); + timer->name = VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK; + timer->present = VIR_TRISTATE_BOOL_YES; + + VIR_APPEND_ELEMENT(def->clock.timers, def->clock.ntimers, timer); +} + + +static int +qemuProcessEnableDomainFeatures(virDomainObj *vm) +{ + virDomainCapsFeatureHyperv *hv = NULL; + qemuDomainObjPrivate *priv = vm->privateData; + size_t i; + + if (vm->def->features[VIR_DOMAIN_FEATURE_HYPERV] != VIR_DOMAIN_HYPERV_MODE_HOST_MODEL) + return 0; + + hv = virQEMUCapsGetHypervCapabilities(priv->qemuCaps); + if (!hv || hv->supported != VIR_TRISTATE_BOOL_YES) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("host-model hyperv mode unsupported, no hyperv capabilities found")); + return -1; + } + + for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) { + if (!VIR_DOMAIN_CAPS_ENUM_IS_SET(hv->features, i)) + continue; + + vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ON; + + if (i == VIR_DOMAIN_HYPERV_SPINLOCKS) { + if (hv->spinlocks != 0) { + vm->def->hyperv.spinlocks = hv->spinlocks; + } else { + vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ABSENT; + } + } else if (i == VIR_DOMAIN_HYPERV_STIMER) { + vm->def->hyperv.stimer_direct = hv->stimer_direct; + /* Both hv-stimer and hv-stimer-direct require hv-time which is + * expose as a timer. Enable it. */ + qemuProcessMaybeAddHypervTimer(vm->def); + } else if (i == VIR_DOMAIN_HYPERV_TLBFLUSH) { + vm->def->hyperv.tlbflush_direct = hv->tlbflush_direct; + vm->def->hyperv.tlbflush_extended = hv->tlbflush_extended; + } else if (i == VIR_DOMAIN_HYPERV_VENDOR_ID) { + if (hv->vendor_id) { + vm->def->hyperv.vendor_id = g_strdup(hv->vendor_id); + } else { + vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ABSENT; + } + } + } + + vm->def->features[VIR_DOMAIN_FEATURE_HYPERV] = VIR_DOMAIN_HYPERV_MODE_CUSTOM; + + return 0; +} + + + /** * qemuProcessPrepareDomain: * @driver: qemu driver @@ -6948,6 +7017,9 @@ qemuProcessPrepareDomain(virQEMUDriver *driver, VIR_DEBUG("Aligning guest memory"); if (qemuDomainAlignMemorySizes(vm->def) < 0) return -1; + + if (qemuProcessEnableDomainFeatures(vm) < 0) + return -1; } for (i = 0; i < vm->def->nchannels; i++) { diff --git a/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args b/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args index 2ed72fcd1b..58502ff51e 100644 --- a/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args +++ b/tests/qemuxmlconfdata/hyperv-host-model.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \ -accel tcg \ --cpu qemu64 \ +-cpu 'qemu64,hv-time=on,hv-relaxed=on,hv-vapic=on,hv-spinlocks=0xfff,hv-vpindex=on,hv-runtime=on,hv-synic=on,hv-stimer=on,hv-stimer-direct=on,hv-reset=on,hv-vendor-id=Linux KVM Hv,hv-frequencies=on,hv-reenlightenment=on,hv-tlbflush=on,hv-tlbflush-direct=on,hv-tlbflush-ext=on,hv-ipi=on,hv-avic=on,hv-emsr-bitmap=on,hv-xmm-input=on' \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ -- 2.49.1
From: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- NEWS.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index c44203bcc1..5dcc4a1c2f 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,6 +17,12 @@ v11.9.0 (unreleased) * **New features** + * Introduce Hyper-V ``host-model`` mode + + Similarly to CPUs, ``host-model`` mode expands available Hyper-V + enlightenments at domain startup into the live XML so that's obvious which + enlightenments are enabled. + * **Improvements** * qemu: Improvements to USB controller model selection -- 2.49.1
On a Wednesday in 2025, Michal Privoznik via Devel wrote:
v2 of:
https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/DFODX...
diff to v1: - Validate dependencies across hv-* enlightenment (per QEMU docs), - Drop introduction of hv-time, since it's already present (as a timer),
I've kept mode='host-model' in domain XML and <defaults/> in domcaps XML, since no one objected, yet.
Michal Prívozník (29): docs: Fix QEMU version wrt hypervclock
Except for 1/29
src: Drop needless typecast to virDomainTimerNameType conf: Introduce virDomainDefHasTimer() qemuxmlconfdata: Adjust hv-stimer related tests qemu_validate: Reflect dependencies of hv-synic qemu_validate: Reflect dependencies of hv-stimer qemu_validate: Reflect dependencies of hv-tlbflush qemu_validate: Reflect dependencies of hv-ipi qemu_validate: Reflect dependencies of hv-evmcs qemu_validate: Reflect dependencies of hv-tlbflush-direct NEWS: Document Hyper-V enlightenment validation virxml: Introduce virXPathTristateSwitch() virxml: Introduce virXPathTristateBool() qemu: Use virXPathTristateBool() domain_conf: Move format of hyperv features into a function domain_conf: Use virXMLFormatElement() to format hyperv features qemu_caps: Prefer VIR_DOMAIN_CAPS_ENUM_IS_SET() qemu_command: Move hyperv cmd line generation into a function qemu_command: Prefer virBufferAddLit() in qemuBuildCpuHypervCommandLine() libxl: Simplify setting HyperV features conf: More hyperv related members into a single struct docs: Drop remark on now unsupported version of QEMU conf: Report default hyperv values in domain capabilities qemu_capabilities: Format and parse new hyperv domcaps members qemu_capabilities: Fetch new hyperv domcaps qemu_caps: Introduce virQEMUCapsGetHypervCapabilities() conf: Introduce hyperv host-model mode qemu_process: Populate hyperv features for host-model NEWS: Document new host-model hyperv mode
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (4)
-
Ján Tomko -
Michal Privoznik -
Michal Prívozník -
Pavel Hrdina