From 7068b56c8526667750d8cb91116e9b40382422f3 Mon Sep 17 00:00:00 2001 From: Maxim Nestratov Date: Thu, 10 Mar 2016 15:43:49 +0300 Subject: [PATCH] conf: qemu: Add support for more HyperV Enlightenment features This patch adds support for "vpindex", "runtime", "synic", "stimer", and "vendor_id" features available in qemu 2.5+. - When Hyper-V "vpindex" is on, guest can use MSR HV_X64_MSR_VP_INDEX to get virtual processor ID. - Hyper-V "runtime" enlightement feature allows to use MSR HV_X64_MSR_VP_RUNTIME to get the time the virtual processor consumes running guest code, as well as the time the hypervisor spends running code on behalf of that guest. - Hyper-V "synic" stands for Synthetic Interrupt Controller, which is lapic extension controlled via MSRs. - Hyper-V "stimer" switches on Hyper-V SynIC timers MSR's support. Guest can setup and use fired by host events (SynIC interrupt and appropriate timer expiration message) as guest clock events - Hyper-V "reset" allows guest to reset VM. - Hyper-V "vendor_id" exposes hypervisor vendor id to guest. Signed-off-by: Nikolay Shirokovskiy Signed-off-by: John Ferlan --- docs/formatdomain.html.in | 41 +++++++++++ docs/schemas/domaincommon.rng | 37 ++++++++++ src/conf/domain_conf.c | 69 ++++++++++++++++++- src/conf/domain_conf.h | 9 +++ src/qemu/qemu_command.c | 11 +++ src/qemu/qemu_parse_command.c | 18 +++++ .../qemuxml2argv-hyperv-off.xml | 6 ++ .../qemuxml2argvdata/qemuxml2argv-hyperv.args | 3 +- .../qemuxml2argvdata/qemuxml2argv-hyperv.xml | 6 ++ .../qemuxml2xmlout-hyperv-off.xml | 6 ++ .../qemuxml2xmlout-hyperv.xml | 6 ++ 11 files changed, 210 insertions(+), 2 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 71ffe75045..630c682a6f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1460,6 +1460,11 @@ <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='4096'/> + <vpindex state='on'/> + <runtime state='on'/> + <synic state='on'/> + <reset state='on'/> + <vendor_id state='on' value='KVM Hv'/> </hyperv> <kvm> <hidden state='on'/> @@ -1537,6 +1542,42 @@ on, off; retries - at least 4095 1.1.0 (QEMU only) + + vpindex + Virtual processor index + on, off + 1.3.3 (QEMU 2.5) + + + runtime + Processor time spent on running guest code and on behalf of guest code + on, off + 1.3.3 (QEMU 2.5) + + + synic + Enable Synthetic Interrupt Controller (SyNIC) + on, off + 1.3.3 (QEMU 2.5) + + + stimer + Enable SyNIC timers + on, off + 1.3.3 (QEMU 2.5) + + + reset + Enable hypervisor reset + on, off + 1.3.3 (QEMU 2.5) + + + vendor_id + Set hypervisor vendor id + on, off; value - string, up to 12 characters + 1.3.3 (QEMU 2.5) +
pvspinlock
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index da6de40f87..46137ec4ca 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4902,6 +4902,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [^,]{0,12} + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 797570a42f..771ab4568e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -145,7 +145,13 @@ VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, VIR_DOMAIN_CAPABILITIES_POLICY_LAST, VIR_ENUM_IMPL(virDomainHyperv, VIR_DOMAIN_HYPERV_LAST, "relaxed", "vapic", - "spinlocks") + "spinlocks", + "vpindex", + "runtime", + "synic", + "stimer", + "reset", + "vendor_id") VIR_ENUM_IMPL(virDomainKVM, VIR_DOMAIN_KVM_LAST, "hidden") @@ -2599,6 +2605,7 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->emulator); VIR_FREE(def->description); VIR_FREE(def->title); + VIR_FREE(def->hyperv_vendor_id); virBlkioDeviceArrayClear(def->blkio.devices, def->blkio.ndevices); @@ -15605,6 +15612,11 @@ virDomainDefParseXML(xmlDocPtr xml, switch ((virDomainHyperv) feature) { 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: break; case VIR_DOMAIN_HYPERV_SPINLOCKS: @@ -15626,6 +15638,33 @@ virDomainDefParseXML(xmlDocPtr xml, } break; + case VIR_DOMAIN_HYPERV_VENDOR_ID: + if (value != VIR_TRISTATE_SWITCH_ON) + break; + + if (!(def->hyperv_vendor_id = virXPathString("string(./@value)", + ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing 'value' attribute for " + "HyperV feature 'vendor_id'")); + goto error; + } + + if (strlen(def->hyperv_vendor_id) > VIR_DOMAIN_HYPERV_VENDOR_ID_MAX) { + virReportError(VIR_ERR_XML_ERROR, + _("HyperV vendor_id value must not be more " + "than %d characters."), + VIR_DOMAIN_HYPERV_VENDOR_ID_MAX); + goto error; + } + + /* ensure that the string can be passed to qemu */ + if (strchr(def->hyperv_vendor_id, ',')) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("HyperV vendor_id value is invalid")); + goto error; + } + /* coverity[dead_error_begin] */ case VIR_DOMAIN_HYPERV_LAST: break; @@ -17628,6 +17667,11 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src, 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: if (src->hyperv_features[i] != dst->hyperv_features[i]) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("State of HyperV enlightenment " @@ -17653,6 +17697,17 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src, } break; + case VIR_DOMAIN_HYPERV_VENDOR_ID: + if (STRNEQ_NULLABLE(src->hyperv_vendor_id, dst->hyperv_vendor_id)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("HyperV vendor_id differs: " + "source: '%s', destination: '%s'"), + src->hyperv_vendor_id, + dst->hyperv_vendor_id); + return false; + } + break; + /* coverity[dead_error_begin] */ case VIR_DOMAIN_HYPERV_LAST: break; @@ -22342,6 +22397,11 @@ virDomainDefFormatInternal(virDomainDefPtr def, 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_STIMER: + case VIR_DOMAIN_HYPERV_RESET: break; case VIR_DOMAIN_HYPERV_SPINLOCKS: @@ -22351,6 +22411,13 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->hyperv_spinlocks); break; + case VIR_DOMAIN_HYPERV_VENDOR_ID: + if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) + break; + virBufferEscapeString(buf, " value='%s'", + def->hyperv_vendor_id); + break; + /* coverity[dead_error_begin] */ case VIR_DOMAIN_HYPERV_LAST: break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 83bdd67dec..639fac5376 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1701,10 +1701,18 @@ typedef enum { VIR_DOMAIN_FEATURE_LAST } virDomainFeature; +# define VIR_DOMAIN_HYPERV_VENDOR_ID_MAX 12 + typedef enum { VIR_DOMAIN_HYPERV_RELAXED = 0, VIR_DOMAIN_HYPERV_VAPIC, VIR_DOMAIN_HYPERV_SPINLOCKS, + VIR_DOMAIN_HYPERV_VPINDEX, + VIR_DOMAIN_HYPERV_RUNTIME, + VIR_DOMAIN_HYPERV_SYNIC, + VIR_DOMAIN_HYPERV_STIMER, + VIR_DOMAIN_HYPERV_RESET, + VIR_DOMAIN_HYPERV_VENDOR_ID, VIR_DOMAIN_HYPERV_LAST } virDomainHyperv; @@ -2240,6 +2248,7 @@ struct _virDomainDef { int kvm_features[VIR_DOMAIN_KVM_LAST]; unsigned int hyperv_spinlocks; virGICVersion gic_version; + char *hyperv_vendor_id; /* These options are of type virTristateSwitch: ON = keep, OFF = drop */ int caps_features[VIR_DOMAIN_CAPS_FEATURE_LAST]; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 0331789b6b..45c5398ad8 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6505,6 +6505,11 @@ qemuBuildCpuCommandLine(virCommandPtr cmd, 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: if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) virBufferAsprintf(&buf, ",hv_%s", virDomainHypervTypeToString(i)); @@ -6516,6 +6521,12 @@ qemuBuildCpuCommandLine(virCommandPtr cmd, 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; + /* coverity[dead_error_begin] */ case VIR_DOMAIN_HYPERV_LAST: break; diff --git a/src/qemu/qemu_parse_command.c b/src/qemu/qemu_parse_command.c index 60e3d69162..8b294a7df0 100644 --- a/src/qemu/qemu_parse_command.c +++ b/src/qemu/qemu_parse_command.c @@ -1539,6 +1539,11 @@ qemuParseCommandLineCPU(virDomainDefPtr dom, switch ((virDomainHyperv) f) { 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: if (value) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("HyperV feature '%s' should not " @@ -1566,6 +1571,19 @@ qemuParseCommandLineCPU(virDomainDefPtr dom, dom->hyperv_spinlocks = 0xFFF; break; + case VIR_DOMAIN_HYPERV_VENDOR_ID: + dom->hyperv_features[f] = VIR_TRISTATE_SWITCH_ON; + if (!value) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("missing HyperV vendor_id value")); + goto cleanup; + } + + if (VIR_STRDUP(dom->hyperv_vendor_id, value) < 0) + goto cleanup; + + break; + case VIR_DOMAIN_HYPERV_LAST: break; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hyperv-off.xml b/tests/qemuxml2argvdata/qemuxml2argv-hyperv-off.xml index 1067f64e80..fe084636fd 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-hyperv-off.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-hyperv-off.xml @@ -14,6 +14,12 @@ + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args index 141844a4b7..32846a2707 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.args @@ -8,7 +8,8 @@ QEMU_AUDIO_DRV=none \ -name QEMUGuest1 \ -S \ -M pc \ --cpu qemu32,hv_relaxed,hv_vapic,hv_spinlocks=0x2fff \ +-cpu 'qemu32,hv_relaxed,hv_vapic,hv_spinlocks=0x2fff,hv_vpindex,hv_runtime,\ +hv_synic,hv_stimer,hv_reset,hv_vendor_id=KVM Hv' \ -m 214 \ -smp 6 \ -uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml index 2b8f332a6b..a47013bc24 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml @@ -14,6 +14,12 @@ + + + + + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv-off.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv-off.xml index b09c447869..6163a5d6d9 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv-off.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv-off.xml @@ -14,6 +14,12 @@ + + + + + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv.xml index a79115ceb9..c11c27393b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hyperv.xml @@ -14,6 +14,12 @@ + + + + + + -- 2.39.5