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

Vitaly Kuznetsov vkuznets at redhat.com
Thu Jul 25 13:52:16 UTC 2019


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",
+);
+
 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");
                     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;
+                    }
+
+                    for (k = 0; k < VIR_DOMAIN_HYPERV_STIMER_LAST; k++) {
+                        if (def->hyperv_stimer_features[k])
+                            break;
+                    }
+
+                    /* Omit long <stimer></stimer> form when no features are enabled */
+                    if (k == VIR_DOMAIN_HYPERV_STIMER_LAST) {
+                        virBufferAddLit(&childBuf, "/>\n");
                         break;
-                    virBufferAsprintf(&childBuf, " retries='%d'",
-                                      def->hyperv_spinlocks);
+                    }
+
+                    virBufferAddLit(&childBuf, ">\n");
+                    virBufferAdjustIndent(&childBuf, 2);
+
+                    for (k = 0; k < VIR_DOMAIN_HYPERV_STIMER_LAST; k++) {
+                        switch ((virDomainHypervStimer) k) {
+                        case VIR_DOMAIN_HYPERV_STIMER_DIRECT:
+                            if (def->hyperv_stimer_features[k])
+                                virBufferAsprintf(&childBuf, "<%s state='%s'/>\n",
+                                          virDomainHypervStimerTypeToString(k),
+                                          virTristateSwitchTypeToString(
+                                              def->hyperv_stimer_features[k]));
+                            break;
+
+                            /* coverity[dead_error_begin] */
+                        case VIR_DOMAIN_HYPERV_STIMER_LAST:
+                            break;
+                        }
+                    }
+
+                    virBufferAdjustIndent(&childBuf, -2);
+                    virBufferAddLit(&childBuf, "</stimer>\n");
+
+                    break;
+
+                case VIR_DOMAIN_HYPERV_SPINLOCKS:
+                    if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) {
+                        virBufferAsprintf(&childBuf, " retries='%d'",
+                                          def->hyperv_spinlocks);
+                    }
+                    virBufferAddLit(&childBuf, "/>\n");
                     break;
 
                 case VIR_DOMAIN_HYPERV_VENDOR_ID:
-                    if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON)
-                        break;
-                    virBufferEscapeString(&childBuf, " value='%s'",
-                                          def->hyperv_vendor_id);
+                    if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ON) {
+                        virBufferEscapeString(&childBuf, " value='%s'",
+                                              def->hyperv_vendor_id);
+                    }
+                    virBufferAddLit(&childBuf, "/>\n");
                     break;
 
                 /* coverity[dead_error_begin] */
                 case VIR_DOMAIN_HYPERV_LAST:
                     break;
                 }
-
-                virBufferAddLit(&childBuf, "/>\n");
             }
             virBufferAdjustIndent(&childBuf, -2);
             virBufferAddLit(&childBuf, "</hyperv>\n");
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];
     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), \
     }
 
 #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);
 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"
 
 #define VIR_CPU_X86_DATA_INIT { 0 }
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index dff97bd82a..ef8e6cd183 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -418,6 +418,8 @@ virDomainHostdevSubsysTypeToString;
 virDomainHPTResizingTypeToString;
 virDomainHubTypeFromString;
 virDomainHubTypeToString;
+virDomainHypervStimerTypeFromString;
+virDomainHypervStimerTypeToString;
 virDomainHypervTypeFromString;
 virDomainHypervTypeToString;
 virDomainInputBusTypeToString;
-- 
2.20.1




More information about the libvir-list mailing list