[libvirt] [PATCH 4/6] conf: add support for Direct Mode for Hyper-V Synthetic timers

Vitaly Kuznetsov vkuznets at redhat.com
Mon Jul 29 12:38:56 UTC 2019


Ján Tomko <jtomko at redhat.com> writes:

> On Thu, Jul 25, 2019 at 03:52:16PM +0200, Vitaly Kuznetsov wrote:
>>Support 'Direct Mode' for Hyper-V Synthetic Timers in domain config.
>>Make it 'stimer' enlightenment option as it is not a separate thing.
>>
>>Signed-off-by: Vitaly Kuznetsov <vkuznets at redhat.com>
>>---
>> docs/formatdomain.html.in     |  10 ++-
>> docs/schemas/domaincommon.rng |  16 +++-
>> src/conf/domain_conf.c        | 138 +++++++++++++++++++++++++++++++---
>> src/conf/domain_conf.h        |   8 ++
>> src/cpu/cpu_x86.c             |  51 +++++++------
>> src/cpu/cpu_x86_data.h        |   2 +
>> src/libvirt_private.syms      |   2 +
>> 7 files changed, 187 insertions(+), 40 deletions(-)
>>
>>diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
>>index 1aaddb6d9b..a0723edad1 100644
>>--- a/docs/formatdomain.html.in
>>+++ b/docs/formatdomain.html.in
>>@@ -2033,7 +2033,9 @@
>>     <vpindex state='on'/>
>>     <runtime state='on'/>
>>     <synic state='on'/>
>>-    <stimer state='on'/>
>>+    <stimer state='on'>
>>+      <direct state='on'/>
>>+    </stimer>
>>     <reset state='on'/>
>>     <vendor_id state='on' value='KVM Hv'/>
>>     <frequencies state='on'/>
>>@@ -2148,9 +2150,9 @@
>>         </tr>
>>         <tr>
>>           <td>stimer</td>
>>-          <td>Enable SynIC timers</td>
>>-          <td>on, off</td>
>>-          <td><span class="since">1.3.3 (QEMU 2.6)</span></td>
>>+          <td>Enable SynIC timers, optionally with Direct Mode support</td>
>>+          <td>on, off; direct - on,off</td>
>>+          <td><span class="since">1.3.3 (QEMU 2.6), direct mode 5.6.0 (QEMU 4.1)</span></td>
>>         </tr>
>>         <tr>
>>           <td>reset</td>
>>diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
>>index 763480440c..8cf1995748 100644
>>--- a/docs/schemas/domaincommon.rng
>>+++ b/docs/schemas/domaincommon.rng
>>@@ -5896,7 +5896,7 @@
>>         </optional>
>>         <optional>
>>           <element name="stimer">
>>-            <ref name="featurestate"/>
>>+            <ref name="stimer"/>
>>           </element>
>>         </optional>
>>         <optional>
>>@@ -5945,6 +5945,20 @@
>>     </element>
>>   </define>
>>
>>+  <!-- Hyper-V stimer features -->
>>+  <define name="stimer">
>>+    <interleave>
>>+      <optional>
>>+        <ref name="featurestate"/>
>>+      </optional>
>>+      <optional>
>>+        <element name="direct">
>>+          <ref name="featurestate"/>
>>+        </element>
>>+      </optional>
>>+    </interleave>
>>+  </define>
>>+
>>   <!-- Optional KVM features -->
>>   <define name="kvm">
>>     <element name="kvm">
>>diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>>index 0574c69a46..779b4ed880 100644
>>--- a/src/conf/domain_conf.c
>>+++ b/src/conf/domain_conf.c
>>@@ -197,6 +197,11 @@ VIR_ENUM_IMPL(virDomainHyperv,
>>               "evmcs",
>> );
>>
>>+VIR_ENUM_IMPL(virDomainHypervStimer,
>>+              VIR_DOMAIN_HYPERV_STIMER_LAST,
>>+              "direct",
>>+);
>
> Do you anticipate more stimer "sub"-features in the future?
> Having an enum with one value just to loop over an array with one
> element and then switch()-ing across all the possible value seems
> like overkill.
>

I don't anticipate any sub-features for stimer for the time being,
however, I wanted to make code look like what we already have
(e.g. virDomainKVM). We can, of course, simplify things if we consider
'direct' being the one and only.

>>+
>> VIR_ENUM_IMPL(virDomainKVM,
>>               VIR_DOMAIN_KVM_LAST,
>>               "hidden",
>>@@ -20359,6 +20364,51 @@ virDomainDefParseXML(xmlDocPtr xml,
>>         ctxt->node = node;
>>     }
>>
>>+    if (def->features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) {
>>+        int feature;
>>+        int value;
>>+        if ((n = virXPathNodeSet("./features/hyperv/stimer/*", ctxt, &nodes)) < 0)
>>+            goto error;
>>+
>>+        for (i = 0; i < n; i++) {
>>+            feature = virDomainHypervStimerTypeFromString((const char *)nodes[i]->name);
>>+            if (feature < 0) {
>>+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>>+                               _("unsupported Hyper-V stimer feature: %s"),
>>+                               nodes[i]->name);
>>+                goto error;
>>+            }
>>+
>>+            switch ((virDomainHypervStimer) feature) {
>>+                case VIR_DOMAIN_HYPERV_STIMER_DIRECT:
>>+                    if (!(tmp = virXMLPropString(nodes[i], "state"))) {
>>+                        virReportError(VIR_ERR_XML_ERROR,
>>+                                       _("missing 'state' attribute for "
>>+                                         "Hyper-V stimer feature '%s'"),
>>+                                       nodes[i]->name);
>>+                        goto error;
>>+                    }
>>+
>>+                    if ((value = virTristateSwitchTypeFromString(tmp)) < 0) {
>>+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>>+                                       _("invalid value of state argument "
>>+                                         "for Hyper-V stimer feature '%s'"),
>>+                                       nodes[i]->name);
>>+                        goto error;
>>+                    }
>>+
>>+                    VIR_FREE(tmp);
>>+                    def->hyperv_stimer_features[feature] = value;
>>+                    break;
>>+
>>+                /* coverity[dead_error_begin] */
>>+                case VIR_DOMAIN_HYPERV_STIMER_LAST:
>>+                    break;
>>+            }
>>+        }
>>+        VIR_FREE(nodes);
>>+    }
>>+
>>     if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
>>         int feature;
>>         int value;
>>@@ -22583,6 +22633,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
>>         }
>>     }
>>
>>+    if (src->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) {
>>+        for (i = 0; i < VIR_DOMAIN_HYPERV_STIMER_LAST; i++) {
>>+            switch ((virDomainHypervStimer) i) {
>>+            case VIR_DOMAIN_HYPERV_STIMER_DIRECT:
>>+                if (src->hyperv_stimer_features[i] != dst->hyperv_stimer_features[i]) {
>>+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>>+                                   _("State of HyperV stimer feature '%s' differs: "
>>+                                     "source: '%s', destination: '%s'"),
>>+                                   virDomainHypervStimerTypeToString(i),
>>+                                   virTristateSwitchTypeToString(src->hyperv_stimer_features[i]),
>>+                                   virTristateSwitchTypeToString(dst->hyperv_stimer_features[i]));
>>+                    return false;
>>+                }
>>+
>>+                break;
>>+
>>+                /* coverity[dead_error_begin] */
>>+            case VIR_DOMAIN_HYPERV_STIMER_LAST:
>>+                break;
>>+            }
>>+        }
>>+    }
>>+
>>     /* kvm */
>>     if (src->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
>>         for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
>>@@ -28017,6 +28090,8 @@ virDomainDefFormatFeatures(virBufferPtr buf,
>>             virBufferAddLit(&childBuf, "<hyperv>\n");
>>             virBufferAdjustIndent(&childBuf, 2);
>>             for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) {
>>+                size_t k;
>>+
>>                 if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT)
>>                     continue;
>>
>>@@ -28031,35 +28106,76 @@ virDomainDefFormatFeatures(virBufferPtr buf,
>>                 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:
>>+                    virBufferAddLit(&childBuf, "/>\n");
>
> Changing all the cases to print the ending tag themselves in a separate
> commit first would make this one look nicer.

Ok.

>
>>                     break;
>>
>>-                case VIR_DOMAIN_HYPERV_SPINLOCKS:
>>-                    if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON)
>>+                case VIR_DOMAIN_HYPERV_STIMER:
>>+                    if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
>>+                        virBufferAddLit(&childBuf, "/>\n");
>>+                        break;
>>+                    }
>>+
>>diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
>>index 48b0af4b04..fc12887fc3 100644
>>--- a/src/conf/domain_conf.h
>>+++ b/src/conf/domain_conf.h
>>@@ -1762,6 +1762,12 @@ typedef enum {
>>     VIR_DOMAIN_HYPERV_LAST
>> } virDomainHyperv;
>>
>>+typedef enum {
>>+    VIR_DOMAIN_HYPERV_STIMER_DIRECT = 0,
>>+
>>+    VIR_DOMAIN_HYPERV_STIMER_LAST
>>+} virDomainHypervStimer;
>>+
>> typedef enum {
>>     VIR_DOMAIN_KVM_HIDDEN = 0,
>>
>>@@ -2400,6 +2406,7 @@ struct _virDomainDef {
>>     int kvm_features[VIR_DOMAIN_KVM_LAST];
>>     int msrs_features[VIR_DOMAIN_MSRS_LAST];
>>     unsigned int hyperv_spinlocks;
>>+    int hyperv_stimer_features[VIR_DOMAIN_HYPERV_STIMER_LAST];
>
> How about:
>     int hyperv_stimer_direct;
>

Yes, if we decide to drop the virDomainHypervStimer.

>>     virGICVersion gic_version;
>>     virDomainHPTResizing hpt_resizing;
>>     unsigned long long hpt_maxpagesize; /* Stored in KiB */
>>@@ -3420,6 +3427,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode);
>> VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode);
>> VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy);
>> VIR_ENUM_DECL(virDomainHyperv);
>>+VIR_ENUM_DECL(virDomainHypervStimer);
>> VIR_ENUM_DECL(virDomainKVM);
>> VIR_ENUM_DECL(virDomainMsrsUnknown);
>> VIR_ENUM_DECL(virDomainRNGModel);
>>diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
>>index 55b55da784..4fb9e6a4df 100644
>>--- a/src/cpu/cpu_x86.c
>>+++ b/src/cpu/cpu_x86.c
>>@@ -59,9 +59,9 @@ struct _virCPUx86Feature {
>>     { .type = VIR_CPU_X86_DATA_CPUID, \
>>       .data = { .cpuid = {__VA_ARGS__} } }
>>
>>-#define KVM_FEATURE_DEF(Name, Eax_in, Eax) \
>>+#define KVM_FEATURE_DEF(Name, Eax_in, Eax, Edx) \
>>     static virCPUx86DataItem Name ## _data[] = { \
>>-        CPUID(.eax_in = Eax_in, .eax = Eax), \
>>+        CPUID(.eax_in = Eax_in, .eax = Eax, .edx = Edx), \
>
> Another change that can be separated.
>

Yes if we still need it) I haven't looked at Jirka's series to check if
we still check CPUID for Hyper-V features or we only check QEMU command
line now.

>>     }
>>
>> #define KVM_FEATURE(Name) \
>>@@ -74,49 +74,51 @@ struct _virCPUx86Feature {
>>     }
>>
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_CLOCKSOURCE,
>>-                0x40000001, 0x00000001);
>>+                0x40000001, 0x00000001, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_NOP_IO_DELAY,
>>-                0x40000001, 0x00000002);
>>+                0x40000001, 0x00000002, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_MMU_OP,
>>-                0x40000001, 0x00000004);
>>+                0x40000001, 0x00000004, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_CLOCKSOURCE2,
>>-                0x40000001, 0x00000008);
>>+                0x40000001, 0x00000008, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_ASYNC_PF,
>>-                0x40000001, 0x00000010);
>>+                0x40000001, 0x00000010, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_STEAL_TIME,
>>-                0x40000001, 0x00000020);
>>+                0x40000001, 0x00000020, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_PV_EOI,
>>-                0x40000001, 0x00000040);
>>+                0x40000001, 0x00000040, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_PV_UNHALT,
>>-                0x40000001, 0x00000080);
>>+                0x40000001, 0x00000080, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_CLOCKSOURCE_STABLE_BIT,
>>-                0x40000001, 0x01000000);
>>+                0x40000001, 0x01000000, 0x0);
>
> Take a look at Jirka's series which removes most of these.
>
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_RUNTIME,
>>-                0x40000003, 0x00000001);
>>+                0x40000003, 0x00000001, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_SYNIC,
>>-                0x40000003, 0x00000004);
>>+                0x40000003, 0x00000004, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_STIMER,
>>-                0x40000003, 0x00000008);
>>+                0x40000003, 0x00000008, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_RELAXED,
>>-                0x40000003, 0x00000020);
>>+                0x40000003, 0x00000020, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_SPINLOCKS,
>>-                0x40000003, 0x00000022);
>>+                0x40000003, 0x00000022, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_VAPIC,
>>-                0x40000003, 0x00000030);
>>+                0x40000003, 0x00000030, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_VPINDEX,
>>-                0x40000003, 0x00000040);
>>+                0x40000003, 0x00000040, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_RESET,
>>-                0x40000003, 0x00000080);
>>+                0x40000003, 0x00000080, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_FREQUENCIES,
>>-                0x40000003, 0x00000800);
>>+                0x40000003, 0x00000800, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_REENLIGHTENMENT,
>>-                0x40000003, 0x00002000);
>>+                0x40000003, 0x00002000, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_TLBFLUSH,
>>-                0x40000004, 0x00000004);
>>+                0x40000004, 0x00000004, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_IPI,
>>-                0x40000004, 0x00000400);
>>+                0x40000004, 0x00000400, 0x0);
>> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_EVMCS,
>>-                0x40000004, 0x00004000);
>>+                0x40000004, 0x00004000, 0x0);
>>+KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_STIMER_DIRECT,
>>+                0x40000003, 0x0, 0x00080000);
>>
>> static virCPUx86Feature x86_kvm_features[] =
>> {
>>@@ -142,6 +144,7 @@ static virCPUx86Feature x86_kvm_features[] =
>>     KVM_FEATURE(VIR_CPU_x86_KVM_HV_TLBFLUSH),
>>     KVM_FEATURE(VIR_CPU_x86_KVM_HV_IPI),
>>     KVM_FEATURE(VIR_CPU_x86_KVM_HV_EVMCS),
>>+    KVM_FEATURE(VIR_CPU_x86_KVM_HV_STIMER_DIRECT),
>> };
>>
>> typedef struct _virCPUx86Model virCPUx86Model;
>>diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
>>index f3f4d7ab9c..198f19e037 100644
>>--- a/src/cpu/cpu_x86_data.h
>>+++ b/src/cpu/cpu_x86_data.h
>>@@ -72,6 +72,8 @@ struct _virCPUx86MSR {
>> #define VIR_CPU_x86_KVM_HV_IPI       "__kvm_hv_ipi"
>> #define VIR_CPU_x86_KVM_HV_EVMCS     "__kvm_hv_evmcs"
>>
>>+/* Hyper-V Synthetic Timer (virDomainHypervStimer) features */
>>+#define VIR_CPU_x86_KVM_HV_STIMER_DIRECT "__kvm_hv_stimer_direct"
>
> "hv-stimer-direct"
>
> to correctly detect its availability
>

Yes, I'll rebase on top of Jirka's series. Thanks!

>>
>> #define VIR_CPU_X86_DATA_INIT { 0 }
>>
>
> Jano

-- 
Vitaly




More information about the libvir-list mailing list