[PATCH v7 1/2] qemu: support dirty ring feature

huangy81 at chinatelecom.cn huangy81 at chinatelecom.cn
Tue Nov 23 14:36:58 UTC 2021


From: Hyman Huang(黄勇) <huangy81 at chinatelecom.cn>

Dirty ring feature was introduced in qemu-6.1.0, this patch
add the corresponding feature named 'dirty-ring', which enable
dirty ring feature when starting vm.

To implement the dirty-ring feature, dirty_ring_size in struct
"_virDomainDef" is introduced to hold the dirty ring size
configured in xml, and it will be used as dirty-ring-size
property of kvm accelerator when building qemu commandline,
it is something like "-accel dirty-ring-size=xxx".

To enable the feature, the following XML needs to be added to
the guest's domain description:

<features>
   <kvm>
     <dirty-ring state='on' size='xxx'>
   </kvm>
</features>

If property "state=on", property "size" must be specified, which
should be power of 2 and range in [1024, 65526].

Signed-off-by: Hyman Huang(黄勇) <huangy81 at chinatelecom.cn>
---
 docs/formatdomain.rst         | 18 ++++++------
 docs/schemas/domaincommon.rng | 10 +++++++
 src/conf/domain_conf.c        | 54 +++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h        |  4 +++
 src/qemu/qemu_command.c       | 12 ++++++++
 5 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index eb8c973cf1..ea69b61c70 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -1843,6 +1843,7 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off.
        <hint-dedicated state='on'/>
        <poll-control state='on'/>
        <pv-ipi state='off'/>
+       <dirty-ring state='on' size='4096'/>
      </kvm>
      <xen>
        <e820_host state='on'/>
@@ -1925,14 +1926,15 @@ are:
 ``kvm``
    Various features to change the behavior of the KVM hypervisor.
 
-   ============== ============================================================================ ======= ============================
-   Feature        Description                                                                  Value   Since
-   ============== ============================================================================ ======= ============================
-   hidden         Hide the KVM hypervisor from standard MSR based discovery                    on, off :since:`1.2.8 (QEMU 2.1.0)`
-   hint-dedicated Allows a guest to enable optimizations when running on dedicated vCPUs       on, off :since:`5.7.0 (QEMU 2.12.0)`
-   poll-control   Decrease IO completion latency by introducing a grace period of busy waiting on, off :since:`6.10.0 (QEMU 4.2)`
-   pv-ipi         Paravirtualized send IPIs                                                    on, off :since:`7.10.0 (QEMU 3.1)`
-   ============== ============================================================================ ======= ============================
+   ============== ============================================================================ ====================================================== ============================
+   Feature        Description                                                                  Value                                                  Since
+   ============== ============================================================================ ====================================================== ============================
+   hidden         Hide the KVM hypervisor from standard MSR based discovery                    on, off                                                :since:`1.2.8 (QEMU 2.1.0)`
+   hint-dedicated Allows a guest to enable optimizations when running on dedicated vCPUs       on, off                                                :since:`5.7.0 (QEMU 2.12.0)`
+   poll-control   Decrease IO completion latency by introducing a grace period of busy waiting on, off                                                :since:`6.10.0 (QEMU 4.2)`
+   pv-ipi         Paravirtualized send IPIs                                                    on, off                                                :since:`7.10.0 (QEMU 3.1)`
+   dirty-ring     Enable dirty ring feature                                                    on, off; size - must be power of 2, range [1024,65536] :since:`7.10.0 (QEMU 6.1)`
+   ============== ============================================================================ ====================================================== ============================
 
 ``xen``
    Various features to change the behavior of the Xen hypervisor.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index f01b7a6470..5f9fe3cc58 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -7212,6 +7212,16 @@
             <ref name="featurestate"/>
           </element>
         </optional>
+        <optional>
+          <element name="dirty-ring">
+            <ref name="featurestate"/>
+            <optional>
+              <attribute name="size">
+                <data type="unsignedInt"/>
+              </attribute>
+            </optional>
+          </element>
+        </optional>
       </interleave>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 552d43b845..6f3c925b55 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -205,6 +205,7 @@ VIR_ENUM_IMPL(virDomainKVM,
               "hint-dedicated",
               "poll-control",
               "pv-ipi",
+              "dirty-ring",
 );
 
 VIR_ENUM_IMPL(virDomainXen,
@@ -17589,6 +17590,25 @@ virDomainFeaturesKVMDefParse(virDomainDef *def,
 
         def->kvm_features[feature] = value;
 
+        /* dirty ring feature should parse size property */
+        if (((virDomainKVM) feature == VIR_DOMAIN_KVM_DIRTY_RING) &&
+             (value == VIR_TRISTATE_SWITCH_ON))  {
+
+            if (virXMLPropUInt(node, "size", 0, VIR_XML_PROP_REQUIRED,
+                               &def->dirty_ring_size) < 0) {
+                return -1;
+            }
+
+            if ((def->dirty_ring_size != VIR_ROUND_UP_POWER_OF_TWO(def->dirty_ring_size)) ||
+                def->dirty_ring_size < 1024 ||
+                def->dirty_ring_size > 65536) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("dirty ring must be power of 2 and ranges [1024, 65536]"));
+
+                return -1;
+            }
+        }
+
         node = xmlNextElementSibling(node);
     }
 
@@ -21824,7 +21844,27 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src,
                                    virTristateSwitchTypeToString(dst->kvm_features[i]));
                     return false;
                 }
+                break;
 
+            case VIR_DOMAIN_KVM_DIRTY_RING:
+                if (src->kvm_features[i] != dst->kvm_features[i]) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("State of KVM feature '%s' differs: "
+                                     "source: '%s', destination: '%s'"),
+                                   virDomainKVMTypeToString(i),
+                                   virTristateSwitchTypeToString(src->kvm_features[i]),
+                                   virTristateSwitchTypeToString(dst->kvm_features[i]));
+                    return false;
+                }
+
+                if (src->dirty_ring_size != dst->dirty_ring_size) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("dirty ring size of KVM feature '%s' differs: "
+                                     "source: '%d', destination: '%d'"),
+                                   virDomainKVMTypeToString(i),
+                                   src->dirty_ring_size, dst->dirty_ring_size);
+                    return false;
+                }
                 break;
 
             case VIR_DOMAIN_KVM_LAST:
@@ -27872,6 +27912,20 @@ virDomainDefFormatFeatures(virBuffer *buf,
                                               def->kvm_features[j]));
                     break;
 
+                case VIR_DOMAIN_KVM_DIRTY_RING:
+                    if (def->kvm_features[j] != VIR_TRISTATE_SWITCH_ABSENT) {
+                        virBufferAsprintf(&childBuf, "<%s state='%s'",
+                                          virDomainKVMTypeToString(j),
+                                          virTristateSwitchTypeToString(def->kvm_features[j]));
+                        if (def->dirty_ring_size) {
+                            virBufferAsprintf(&childBuf, " size='%d'/>\n",
+                                              def->dirty_ring_size);
+                        } else {
+                            virBufferAddLit(&childBuf, "/>\n");
+                        }
+                    }
+                    break;
+
                 case VIR_DOMAIN_KVM_LAST:
                     break;
                 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8634960313..026edde88f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2084,6 +2084,7 @@ typedef enum {
     VIR_DOMAIN_KVM_DEDICATED,
     VIR_DOMAIN_KVM_POLLCONTROL,
     VIR_DOMAIN_KVM_PVIPI,
+    VIR_DOMAIN_KVM_DIRTY_RING,
 
     VIR_DOMAIN_KVM_LAST
 } virDomainKVM;
@@ -2933,6 +2934,9 @@ struct _virDomainDef {
                              should be re-run before starting */
 
     unsigned int scsiBusMaxUnit;
+
+    /* size of dirty ring for each vcpu */
+    unsigned int dirty_ring_size;
 };
 
 
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7a185061d8..18a72a79a8 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6860,6 +6860,9 @@ qemuBuildCpuCommandLine(virCommand *cmd,
                     virBufferAddLit(&buf, ",kvm-pv-ipi=off");
                 break;
 
+            case VIR_DOMAIN_KVM_DIRTY_RING:
+                break;
+
             case VIR_DOMAIN_KVM_LAST:
                 break;
             }
@@ -7280,6 +7283,15 @@ qemuBuildAccelCommandLine(virCommand *cmd,
 
     case VIR_DOMAIN_VIRT_KVM:
         virBufferAddLit(&buf, "kvm");
+        /*
+         * only handle the kvm case, tcg case use the legacy style
+         * not that either kvm or tcg can be specified by libvirt
+         * so do not worry about the conflict of specifying both
+         * */
+        if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON &&
+            def->kvm_features[VIR_DOMAIN_KVM_DIRTY_RING] == VIR_TRISTATE_SWITCH_ON) {
+            virBufferAsprintf(&buf, ",dirty-ring-size=%d", def->dirty_ring_size);
+        }
         break;
 
     case VIR_DOMAIN_VIRT_KQEMU:
-- 
2.27.0





More information about the libvir-list mailing list