[PATCH 0/4] Enable mshv support for Qemu domains

"[PATCH v3 00/26] Implementing a MSHV (Microsoft Hypervisor) accelerator" patchset in qemu-devel mailing list introduces MSHV support within Qemu. With above patchset, Qemu guests can be started with `-accel mshv` option to use Microsoft Hypervisor (/dev/mshv) as the hypervisor. Retaining Libvirt's naming convention, this translates to `hyperv` domains. Below is an excerpt of the xml to use with this patcset: ``` <domain type='hyperv'> <name>qemu_msh_testv</name> <cpu mode='host-model'/> <os> <type machine='q35'>hvm</type> </os> ... ``` This patch set introduces the necessary changes within libvirt to support Qemu guest with hyperv (mshv) hypervisor. Known issue: ``` abs_builddir=/home/user/QEMU_MSHV/libvirt/build/tests abs_top_srcdir=/home/user/QEMU_MSHV/libvirt LD_LIBRARY_PATH=/home/user/QEMU_MSHV/libvirt/build/tests:/home/user/QEMU_MSHV/libvirt/build/src abs_srcdir=/home/user/QEMU_MSHV/libvirt/tests VIR_TEST_EXPENSIVE=0 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 LC_ALL=C LIBVIRT_AUTOSTART=0 G_DEBUG=fatal-warnings MALLOC_PERTURB_=255 abs_top_builddir=/home/user/QEMU_MSHV/libvirt/build /home/user/QEMU_MSHV/libvirt/build/tests/qemucapabilitiestest TEST: qemucapabilitiestest wrong expected command in /home/user/QEMU_MSHV/libvirt/tests/qemucapabilitiesdata/caps_9.2.0_s390x.replies:23538: : {"execute":"query-mshv","id":"libvirt-6"} expected {"execute":"qom-list-types","id":"libvirt-6"} ``` Could someone point me to the steps to regenerate the replies files to fix above issue? Praveen K Paladugu (4): qemu: introduce mshv capabilities qemu: probe mshv capabilities qemu: use mshv accel for hyperv domains qemu_cgroup: add /dev/mshv to default devices src/qemu/qemu_capabilities.c | 71 +++++++++++++++++++++++++++++++----- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_cgroup.c | 2 +- src/qemu/qemu_command.c | 4 +- src/qemu/qemu_monitor.c | 9 +++-- src/qemu/qemu_monitor.h | 8 ++-- src/qemu/qemu_monitor_json.c | 13 ++++--- src/qemu/qemu_monitor_json.h | 10 ++--- 8 files changed, 88 insertions(+), 30 deletions(-) -- 2.50.1

From: Praveen K Paladugu <prapal@linux.microsoft.com> Add /dev/mshv to default set of devices to pass to domain cgroup. Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index f10976c2b0..b9b68d38d5 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -41,7 +41,7 @@ VIR_LOG_INIT("qemu.qemu_cgroup"); const char *const defaultDeviceACL[] = { "/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", - "/dev/ptmx", "/dev/kvm", + "/dev/ptmx", "/dev/kvm", "/dev/mshv", "/dev/userfaultfd", NULL, }; -- 2.50.1

On Thu, Aug 07, 2025 at 03:48:43PM -0500, Praveen K Paladugu wrote:
From: Praveen K Paladugu <prapal@linux.microsoft.com>
Add /dev/mshv to default set of devices to pass to domain cgroup.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, Aug 07, 2025 at 03:48:43PM -0500, Praveen K Paladugu wrote:
From: Praveen K Paladugu <prapal@linux.microsoft.com>
Add /dev/mshv to default set of devices to pass to domain cgroup.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index f10976c2b0..b9b68d38d5 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -41,7 +41,7 @@ VIR_LOG_INIT("qemu.qemu_cgroup"); const char *const defaultDeviceACL[] = { "/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", - "/dev/ptmx", "/dev/kvm", + "/dev/ptmx", "/dev/kvm", "/dev/mshv",
Oh should update src/qemu/qemu.conf.in and src/qemu/test_libvirtd_qemu.aug.in to match this too.
"/dev/userfaultfd", NULL, }; -- 2.50.1
With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Praveen K Paladugu <prapal@linux.microsoft.com> Probe mshv capabilities from qemu with QMP commands. Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_capabilities.c | 31 ++++++++++++++++++++++++------- src/qemu/qemu_monitor.c | 9 +++++---- src/qemu/qemu_monitor.h | 8 +++++--- src/qemu/qemu_monitor_json.c | 13 +++++++------ src/qemu/qemu_monitor_json.h | 10 +++++----- 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 1e069eb0e5..02dbae8e00 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3473,17 +3473,31 @@ virQEMUCapsProbeQMPTPM(virQEMUCaps *qemuCaps, static int -virQEMUCapsProbeQMPKVMState(virQEMUCaps *qemuCaps, - qemuMonitor *mon) +virQEMUCapsProbeQMPHypervisorState(virQEMUCaps *qemuCaps, + qemuMonitor *mon, + virQEMUCapsFlags flag) { bool enabled = false; bool present = false; - if (qemuMonitorGetKVMState(mon, &enabled, &present) < 0) - return -1; + if (flag == QEMU_CAPS_KVM) { + if (qemuMonitorGetHypervisorState(mon, "query-kvm", + &enabled, &present) < 0) + return -1; + if (present && enabled) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + } else if (flag == QEMU_CAPS_MSHV) { - if (present && enabled) - virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + if (qemuMonitorGetHypervisorState(mon, "query-mshv", + &enabled, &present) < 0) + return -1; + if (present && enabled) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_MSHV); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid Hypervisor type specified for qemu")); + return -1; + } return 0; } @@ -5792,7 +5806,10 @@ virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps, return -1; /* Some capabilities may differ depending on KVM state */ - if (virQEMUCapsProbeQMPKVMState(qemuCaps, mon) < 0) + if (virQEMUCapsProbeQMPHypervisorState(qemuCaps, mon, QEMU_CAPS_KVM) < 0) + return -1; + + if (virQEMUCapsProbeQMPHypervisorState(qemuCaps, mon, QEMU_CAPS_MSHV) < 0) return -1; if (virQEMUCapsProbeHVF(qemuCaps)) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c1fef8d5de..3d01844074 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3423,15 +3423,16 @@ qemuMonitorGetCommandLineOptions(qemuMonitor *mon) int -qemuMonitorGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present) +qemuMonitorGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present) { VIR_DEBUG("enabled=%p present=%p", enabled, present); QEMU_CHECK_MONITOR(mon); - return qemuMonitorJSONGetKVMState(mon, enabled, present); + return qemuMonitorJSONGetHypervisorState(mon, query_cmd, enabled, present); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 755f347e17..8bb0919a00 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1220,9 +1220,11 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig); GHashTable *qemuMonitorGetCommandLineOptions(qemuMonitor *mon); -int qemuMonitorGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present); +int +qemuMonitorGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present); int qemuMonitorGetObjectTypes(qemuMonitor *mon, char ***types); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 9f51421478..18ca124e46 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5520,9 +5520,10 @@ qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon) } -int qemuMonitorJSONGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present) +int qemuMonitorJSONGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; @@ -5531,7 +5532,7 @@ int qemuMonitorJSONGetKVMState(qemuMonitor *mon, /* Safe defaults */ *enabled = *present = false; - if (!(cmd = qemuMonitorJSONMakeCommand("query-kvm", NULL))) + if (!(cmd = qemuMonitorJSONMakeCommand(query_cmd, NULL))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -5542,8 +5543,8 @@ int qemuMonitorJSONGetKVMState(qemuMonitor *mon, if (virJSONValueObjectGetBoolean(data, "enabled", enabled) < 0 || virJSONValueObjectGetBoolean(data, "present", present) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("query-kvm replied unexpected data")); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%1$s replied unexpected data"), query_cmd); return -1; } diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index bd437f7938..2de17e3d75 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -451,11 +451,11 @@ qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon, GHashTable * qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon); -int -qemuMonitorJSONGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present) - ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int qemuMonitorJSONGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); int qemuMonitorJSONGetObjectTypes(qemuMonitor *mon, -- 2.50.1

On Thu, Aug 07, 2025 at 03:48:41PM -0500, Praveen K Paladugu wrote:
From: Praveen K Paladugu <prapal@linux.microsoft.com>
Probe mshv capabilities from qemu with QMP commands.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_capabilities.c | 31 ++++++++++++++++++++++++------- src/qemu/qemu_monitor.c | 9 +++++---- src/qemu/qemu_monitor.h | 8 +++++--- src/qemu/qemu_monitor_json.c | 13 +++++++------ src/qemu/qemu_monitor_json.h | 10 +++++----- 5 files changed, 46 insertions(+), 25 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 1e069eb0e5..02dbae8e00 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3473,17 +3473,31 @@ virQEMUCapsProbeQMPTPM(virQEMUCaps *qemuCaps,
static int -virQEMUCapsProbeQMPKVMState(virQEMUCaps *qemuCaps, - qemuMonitor *mon) +virQEMUCapsProbeQMPHypervisorState(virQEMUCaps *qemuCaps, + qemuMonitor *mon, + virQEMUCapsFlags flag) { bool enabled = false; bool present = false;
- if (qemuMonitorGetKVMState(mon, &enabled, &present) < 0) - return -1; + if (flag == QEMU_CAPS_KVM) { + if (qemuMonitorGetHypervisorState(mon, "query-kvm", + &enabled, &present) < 0) + return -1; + if (present && enabled) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + } else if (flag == QEMU_CAPS_MSHV) {
- if (present && enabled) - virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + if (qemuMonitorGetHypervisorState(mon, "query-mshv", + &enabled, &present) < 0) + return -1; + if (present && enabled) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_MSHV); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Invalid Hypervisor type specified for qemu")); + return -1; + }
return 0; } @@ -5792,7 +5806,10 @@ virQEMUCapsInitQMPMonitor(virQEMUCaps *qemuCaps, return -1;
/* Some capabilities may differ depending on KVM state */ - if (virQEMUCapsProbeQMPKVMState(qemuCaps, mon) < 0) + if (virQEMUCapsProbeQMPHypervisorState(qemuCaps, mon, QEMU_CAPS_KVM) < 0) + return -1; + + if (virQEMUCapsProbeQMPHypervisorState(qemuCaps, mon, QEMU_CAPS_MSHV) < 0) return -1;
if (virQEMUCapsProbeHVF(qemuCaps)) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c1fef8d5de..3d01844074 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3423,15 +3423,16 @@ qemuMonitorGetCommandLineOptions(qemuMonitor *mon)
int -qemuMonitorGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present) +qemuMonitorGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present) { VIR_DEBUG("enabled=%p present=%p", enabled, present);
QEMU_CHECK_MONITOR(mon);
- return qemuMonitorJSONGetKVMState(mon, enabled, present); + return qemuMonitorJSONGetHypervisorState(mon, query_cmd, enabled, present); }
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 755f347e17..8bb0919a00 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1220,9 +1220,11 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig);
GHashTable *qemuMonitorGetCommandLineOptions(qemuMonitor *mon);
-int qemuMonitorGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present); +int +qemuMonitorGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present);
int qemuMonitorGetObjectTypes(qemuMonitor *mon, char ***types); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 9f51421478..18ca124e46 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5520,9 +5520,10 @@ qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon) }
-int qemuMonitorJSONGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present) +int qemuMonitorJSONGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; @@ -5531,7 +5532,7 @@ int qemuMonitorJSONGetKVMState(qemuMonitor *mon, /* Safe defaults */ *enabled = *present = false;
- if (!(cmd = qemuMonitorJSONMakeCommand("query-kvm", NULL))) + if (!(cmd = qemuMonitorJSONMakeCommand(query_cmd, NULL))) return -1;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) @@ -5542,8 +5543,8 @@ int qemuMonitorJSONGetKVMState(qemuMonitor *mon,
if (virJSONValueObjectGetBoolean(data, "enabled", enabled) < 0 || virJSONValueObjectGetBoolean(data, "present", present) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("query-kvm replied unexpected data")); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%1$s replied unexpected data"), query_cmd); return -1; }
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index bd437f7938..2de17e3d75 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -451,11 +451,11 @@ qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon, GHashTable * qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon);
-int -qemuMonitorJSONGetKVMState(qemuMonitor *mon, - bool *enabled, - bool *present) - ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int qemuMonitorJSONGetHypervisorState(qemuMonitor *mon, + const char *query_cmd, + bool *enabled, + bool *present) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
We don't really want QMP command names to leak into callers. I'd suggest making this an internal helper function with qemuMonitorJSONGetKVMState & qemuMonitorJSONGetMSHVState being thin wrappers that specify the command name, and similar qemuMonitorGetKVMState & qemuMonitorGetMSHVState wrappers in qemu_monitor.h With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Praveen K Paladugu <prapal@linux.microsoft.com> Add mshv acceleration (-accel mshv) flag to hyperv domains Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_command.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4e4f1e87eb..3aafacb14d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7321,6 +7321,9 @@ qemuBuildAccelCommandLine(virCommand *cmd, virBufferAddLit(&buf, "hvf"); break; + case VIR_DOMAIN_VIRT_HYPERV: + virBufferAddLit(&buf, "mshv"); + break; case VIR_DOMAIN_VIRT_KQEMU: case VIR_DOMAIN_VIRT_XEN: case VIR_DOMAIN_VIRT_LXC: @@ -7328,7 +7331,6 @@ qemuBuildAccelCommandLine(virCommand *cmd, case VIR_DOMAIN_VIRT_OPENVZ: case VIR_DOMAIN_VIRT_TEST: case VIR_DOMAIN_VIRT_VMWARE: - case VIR_DOMAIN_VIRT_HYPERV: case VIR_DOMAIN_VIRT_VBOX: case VIR_DOMAIN_VIRT_PHYP: case VIR_DOMAIN_VIRT_PARALLELS: -- 2.50.1

On Thu, Aug 07, 2025 at 03:48:42PM -0500, Praveen K Paladugu wrote:
From: Praveen K Paladugu <prapal@linux.microsoft.com>
Add mshv acceleration (-accel mshv) flag to hyperv domains
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_command.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> nb, this patch & the next ought to be /before/ patch 2, as the patch 2 changes will unlock the ability for users to specify type=hyperv in XML which will then be broken until this patch & next patch are applied.
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4e4f1e87eb..3aafacb14d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7321,6 +7321,9 @@ qemuBuildAccelCommandLine(virCommand *cmd, virBufferAddLit(&buf, "hvf"); break;
+ case VIR_DOMAIN_VIRT_HYPERV: + virBufferAddLit(&buf, "mshv"); + break; case VIR_DOMAIN_VIRT_KQEMU: case VIR_DOMAIN_VIRT_XEN: case VIR_DOMAIN_VIRT_LXC: @@ -7328,7 +7331,6 @@ qemuBuildAccelCommandLine(virCommand *cmd, case VIR_DOMAIN_VIRT_OPENVZ: case VIR_DOMAIN_VIRT_TEST: case VIR_DOMAIN_VIRT_VMWARE: - case VIR_DOMAIN_VIRT_HYPERV: case VIR_DOMAIN_VIRT_VBOX: case VIR_DOMAIN_VIRT_PHYP: case VIR_DOMAIN_VIRT_PARALLELS: -- 2.50.1
With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Praveen K Paladugu <prapal@linux.microsoft.com> Qemu with mshv capabilities can launch domains of type hyperv. Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com> --- src/qemu/qemu_capabilities.c | 40 +++++++++++++++++++++++++++++++++--- src/qemu/qemu_capabilities.h | 1 + 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index af238894b5..1e069eb0e5 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -742,6 +742,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "amd-iommu.pci-id", /* QEMU_CAPS_AMD_IOMMU_PCI_ID */ "usb-bot", /* QEMU_CAPS_DEVICE_USB_BOT */ "tdx-guest", /* QEMU_CAPS_TDX_GUEST */ + "mshv", /* QEMU_CAPS_MSHV */ ); @@ -833,6 +834,7 @@ struct _virQEMUCaps { virQEMUCapsAccel kvm; virQEMUCapsAccel hvf; virQEMUCapsAccel tcg; + virQEMUCapsAccel mshv; }; static virClass *virQEMUCapsClass; @@ -930,7 +932,8 @@ virQEMUCapsTypeIsAccelerated(virDomainVirtType type) bool virQEMUCapsHaveAccel(virQEMUCaps *qemuCaps) { - return virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) || + return virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV) || virQEMUCapsGet(qemuCaps, QEMU_CAPS_HVF); } @@ -942,6 +945,8 @@ virQEMUCapsAccelStr(virDomainVirtType type) return "kvm"; else if (type == VIR_DOMAIN_VIRT_HVF) return "hvf"; + else if (type == VIR_DOMAIN_VIRT_HYPERV) + return "mshv"; return "tcg"; } @@ -955,6 +960,8 @@ virQEMUCapsGetAccel(virQEMUCaps *qemuCaps, return &qemuCaps->kvm; else if (type == VIR_DOMAIN_VIRT_HVF) return &qemuCaps->hvf; + else if (type == VIR_DOMAIN_VIRT_HYPERV) + return &qemuCaps->mshv; return &qemuCaps->tcg; } @@ -1062,6 +1069,8 @@ virQEMUCapsGetMachineTypesCaps(virQEMUCaps *qemuCaps, accel = &qemuCaps->kvm; else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_HVF)) accel = &qemuCaps->hvf; + else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) + accel = &qemuCaps->mshv; else accel = &qemuCaps->tcg; @@ -1170,6 +1179,10 @@ virQEMUCapsInitGuestFromBinary(virCaps *caps, virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_HVF, NULL, NULL, 0, NULL); } + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) { + virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_HYPERV, + NULL, NULL, 0, NULL); + } if (ARCH_IS_X86(guestarch) || guestarch == VIR_ARCH_AARCH64 || ARCH_IS_LOONGARCH(guestarch)) @@ -2049,6 +2062,7 @@ virQEMUCaps *virQEMUCapsNewCopy(virQEMUCaps *qemuCaps) virQEMUCapsAccelCopy(&ret->kvm, &qemuCaps->kvm); virQEMUCapsAccelCopy(&ret->hvf, &qemuCaps->hvf); virQEMUCapsAccelCopy(&ret->tcg, &qemuCaps->tcg); + virQEMUCapsAccelCopy(&ret->mshv, &qemuCaps->mshv); ret->gicCapabilities = g_new0(virGICCapability, qemuCaps->ngicCapabilities); ret->ngicCapabilities = qemuCaps->ngicCapabilities; @@ -2109,6 +2123,7 @@ void virQEMUCapsDispose(void *obj) virQEMUCapsAccelClear(&qemuCaps->kvm); virQEMUCapsAccelClear(&qemuCaps->hvf); virQEMUCapsAccelClear(&qemuCaps->tcg); + virQEMUCapsAccelClear(&qemuCaps->mshv); } void @@ -2331,6 +2346,10 @@ virQEMUCapsIsVirtTypeSupported(virQEMUCaps *qemuCaps, virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) return true; + if (virtType == VIR_DOMAIN_VIRT_HYPERV && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) + return true; + return false; } @@ -2894,8 +2913,9 @@ bool virQEMUCapsHasMachines(virQEMUCaps *qemuCaps) { - return !!qemuCaps->kvm.nmachineTypes || - !!qemuCaps->hvf.nmachineTypes || + return !!qemuCaps->kvm.nmachineTypes || + !!qemuCaps->hvf.nmachineTypes || + !!qemuCaps->mshv.nmachineTypes || !!qemuCaps->tcg.nmachineTypes; } @@ -4873,6 +4893,10 @@ virQEMUCapsLoadCache(virArch hostArch, virQEMUCapsLoadAccel(qemuCaps, ctxt, VIR_DOMAIN_VIRT_HVF) < 0) { return -1; } + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV) && + virQEMUCapsLoadAccel(qemuCaps, ctxt, VIR_DOMAIN_VIRT_HYPERV) < 0) { + return -1; + } if (virQEMUCapsLoadAccel(qemuCaps, ctxt, VIR_DOMAIN_VIRT_QEMU) < 0) return -1; @@ -4892,6 +4916,8 @@ virQEMUCapsLoadCache(virArch hostArch, virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_HVF)) virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_HVF); + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) + virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_HYPERV); virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU); if (virXPathBoolean("boolean(./kvmSupportsNesting)", ctxt) > 0) @@ -5209,6 +5235,8 @@ virQEMUCapsFormatCache(virQEMUCaps *qemuCaps) virQEMUCapsFormatAccel(qemuCaps, &buf, VIR_DOMAIN_VIRT_KVM); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_HVF)) virQEMUCapsFormatAccel(qemuCaps, &buf, VIR_DOMAIN_VIRT_HVF); + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) + virQEMUCapsFormatAccel(qemuCaps, &buf, VIR_DOMAIN_VIRT_HYPERV); virQEMUCapsFormatAccel(qemuCaps, &buf, VIR_DOMAIN_VIRT_QEMU); for (i = 0; i < qemuCaps->ngicCapabilities; i++) { @@ -5719,6 +5747,9 @@ virQEMUCapsGetVirtType(virQEMUCaps *qemuCaps) if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_TCG)) return VIR_DOMAIN_VIRT_QEMU; + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) + return VIR_DOMAIN_VIRT_HYPERV; + return VIR_DOMAIN_VIRT_NONE; } @@ -5951,6 +5982,8 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch, virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_HVF)) virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_HVF); + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSHV)) + virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_HYPERV); virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU); if (virQEMUCapsHaveAccel(qemuCaps)) { @@ -7160,4 +7193,5 @@ virQEMUCapsStripMachineAliases(virQEMUCaps *qemuCaps) virQEMUCapsStripMachineAliasesForVirtType(qemuCaps, VIR_DOMAIN_VIRT_KVM); virQEMUCapsStripMachineAliasesForVirtType(qemuCaps, VIR_DOMAIN_VIRT_HVF); virQEMUCapsStripMachineAliasesForVirtType(qemuCaps, VIR_DOMAIN_VIRT_QEMU); + virQEMUCapsStripMachineAliasesForVirtType(qemuCaps, VIR_DOMAIN_VIRT_HYPERV); } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 55b05bea84..3aee25ab0e 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -723,6 +723,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_AMD_IOMMU_PCI_ID, /* amd-iommu.pci-id */ QEMU_CAPS_DEVICE_USB_BOT, /* -device usb-bot */ QEMU_CAPS_TDX_GUEST, /* -object tdx-guest,... */ + QEMU_CAPS_MSHV, /* Whether MSHV is usable / was used during probing */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; -- 2.50.1

On Thu, Aug 07, 2025 at 03:48:40PM -0500, Praveen K Paladugu wrote:
From: Praveen K Paladugu <prapal@linux.microsoft.com>
Qemu with mshv capabilities can launch domains of type hyperv.
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com> Signed-off-by: Praveen K Paladugu <praveenkpaladugu@gmail.com>
You probably don't need both of these lines, unless perhaps you're trying to indicate this work was a mixture of stuff done as personal effort vs business working time ? Assuming not, then pick whichever you consider to be your primary OSS contributor identity.
--- src/qemu/qemu_capabilities.c | 40 +++++++++++++++++++++++++++++++++--- src/qemu/qemu_capabilities.h | 1 + 2 files changed, 38 insertions(+), 3 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, Aug 07, 2025 at 15:48:39 -0500, Praveen K Paladugu wrote:
"[PATCH v3 00/26] Implementing a MSHV (Microsoft Hypervisor) accelerator"
[...]
Known issue:
``` abs_builddir=/home/user/QEMU_MSHV/libvirt/build/tests abs_top_srcdir=/home/user/QEMU_MSHV/libvirt LD_LIBRARY_PATH=/home/user/QEMU_MSHV/libvirt/build/tests:/home/user/QEMU_MSHV/libvirt/build/src abs_srcdir=/home/user/QEMU_MSHV/libvirt/tests VIR_TEST_EXPENSIVE=0 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 LC_ALL=C LIBVIRT_AUTOSTART=0 G_DEBUG=fatal-warnings MALLOC_PERTURB_=255 abs_top_builddir=/home/user/QEMU_MSHV/libvirt/build /home/user/QEMU_MSHV/libvirt/build/tests/qemucapabilitiestest TEST: qemucapabilitiestest
wrong expected command in /home/user/QEMU_MSHV/libvirt/tests/qemucapabilitiesdata/caps_9.2.0_s390x.replies:23538: : {"execute":"query-mshv","id":"libvirt-6"} expected {"execute":"qom-list-types","id":"libvirt-6"} ``` Could someone point me to the steps to regenerate the replies files to fix above issue?
There are two possibilities how to approach this. First one is that you move this probe slightly further which will allow you to probe available commands first. You then can avoid the probe in cases when qemu doesn't yet support that command preventing you from the need to modify the old replies files. The test files can't really be re-generated as in some cases the old qemu versions no longer compile and parts of the file depend on the host setup. Nevertheless, we do have a tool to programatically modify those. The scripts/qemu-replies-tool.py has provisions which allow you to write code to add/remove sections in the .replies files. look for the 'modify_replies' method which already has an example adding some device data based on the version of qemu. You modify that code to put the json at the appropriate place and then either re-run the testsuite with VIR_TEST_REGENERATE_OUTPUT or run the tool with: ./scripts/qemu-replies-tool.py --regenerate --repliesdir tests/qemucapabilitiesdata/ Beware that you must run it exactly once, and then commit the changes and disable the modification code again, otherwise it'll likely try to re-add the stuff.

On Wed, Aug 20, 2025 at 14:24:19 +0200, Peter Krempa via Devel wrote:
On Thu, Aug 07, 2025 at 15:48:39 -0500, Praveen K Paladugu wrote:
"[PATCH v3 00/26] Implementing a MSHV (Microsoft Hypervisor) accelerator"
[...]
Known issue:
``` abs_builddir=/home/user/QEMU_MSHV/libvirt/build/tests abs_top_srcdir=/home/user/QEMU_MSHV/libvirt LD_LIBRARY_PATH=/home/user/QEMU_MSHV/libvirt/build/tests:/home/user/QEMU_MSHV/libvirt/build/src abs_srcdir=/home/user/QEMU_MSHV/libvirt/tests VIR_TEST_EXPENSIVE=0 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 LC_ALL=C LIBVIRT_AUTOSTART=0 G_DEBUG=fatal-warnings MALLOC_PERTURB_=255 abs_top_builddir=/home/user/QEMU_MSHV/libvirt/build /home/user/QEMU_MSHV/libvirt/build/tests/qemucapabilitiestest TEST: qemucapabilitiestest
wrong expected command in /home/user/QEMU_MSHV/libvirt/tests/qemucapabilitiesdata/caps_9.2.0_s390x.replies:23538: : {"execute":"query-mshv","id":"libvirt-6"} expected {"execute":"qom-list-types","id":"libvirt-6"} ``` Could someone point me to the steps to regenerate the replies files to fix above issue?
There are two possibilities how to approach this.
First one is that you move this probe slightly further which will allow you to probe available commands first. You then can avoid the probe in cases when qemu doesn't yet support that command preventing you from the need to modify the old replies files.
The test files can't really be re-generated as in some cases the old qemu versions no longer compile and parts of the file depend on the host setup.
Nevertheless, we do have a tool to programatically modify those. The scripts/qemu-replies-tool.py has provisions which allow you to write code to add/remove sections in the .replies files. look for the 'modify_replies' method which already has an example adding some device data based on the version of qemu. You modify that code to put the json at the appropriate place and then either re-run the testsuite with VIR_TEST_REGENERATE_OUTPUT or run the tool with:
./scripts/qemu-replies-tool.py --regenerate --repliesdir tests/qemucapabilitiesdata/
Beware that you must run it exactly once, and then commit the changes and disable the modification code again, otherwise it'll likely try to re-add the stuff.
One more detail. You'll likely want to also add capabilities captured on an MSHV-enabled machine to see that the probing works. To do that you'll have to add a 'variant' of the capability dump. See tests/qemucapabilitiesdata/README.rst on how to do that.
participants (1)
-
Daniel P. Berrangé
-
Peter Krempa
-
Praveen K Paladugu