From 8458bb521ea4bb7b50d8d5f6ffea4e2d2fe8f0f5 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Mon, 29 Sep 2025 14:54:23 +0200 Subject: [PATCH] qemu_process: Populate hyperv features for host-model MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Pretty straightforward. The only "weird" thing here is that 'hv-time' enlightenment is exposed as a under 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 Reviewed-by: Ján Tomko --- 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.47.3