在 2021/1/13 21:32, Han Han 写道:


On Wed, Jan 13, 2021 at 1:09 AM <huangy81@chinatelecom.cn> wrote:
From: Hyman <huangy81@chinatelecom.cn>

QEMU introduced a dirty ring feature, this patch add a new
KVM feature 'dirty-ring' to set this feature for kvm guests.

To enable the feature, libvirt add "-accel dirty-gfn-count=xxx"
to QEMU command line, the following XML needs to be added to
the guest's domain description:

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

Signed-off-by: Hyman <huangy81@chinatelecom.cn>
---
 docs/formatdomain.rst         | 16 +++++++++-------
 docs/schemas/domaincommon.rng | 10 ++++++++++
 src/conf/domain_conf.c        | 34 ++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h        |  4 ++++
 src/qemu/qemu_command.c       | 13 ++++++++++---
 5 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 6100b88..5bf8517 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -1767,6 +1767,7 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off.
        <hidden state='on'/>
        <hint-dedicated state='on'/>
        <poll-control='on'/>
+       <dirty-ring state='on' size='4096'/>
      </kvm>
      <xen>
        <e820_host state='on'/>
@@ -1849,13 +1850,14 @@ 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)`
-   ============== ============================================================================ ======= ============================
+   ============== ============================================================================ ================================== ============================
+   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)`
+   dirty-ring     Enable dirty ring feature                                                    on, off; size - must be power of 2 :since:`7.0.0 (QEMU 5.2.1)`
Are you sure it will be added in QEMU 5.2.1 ?
I find it has been not merged in qemu yet

indeed, it hasn't been merged.  This patchset base on the following works:

https://lore.kernel.org/qemu-devel/20210108164601.406146-1-peterx@redhat.com/

Maybe the review is under way. I post this patchset for review in advance. Once the qemu patchset is merged, i'll ping the libvir-list and apply for merging.

+   ============== ============================================================================ ================================== ============================

 ``xen``
    Various features to change the behavior of the Xen hypervisor.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 7dc419b..5af4bbe 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -6569,6 +6569,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 349fc28..e617b95 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -186,6 +186,7 @@ VIR_ENUM_IMPL(virDomainKVM,
               "hidden",
               "hint-dedicated",
               "poll-control",
+              "dirty-ring",
 );

 VIR_ENUM_IMPL(virDomainXen,
@@ -18379,6 +18380,7 @@ virDomainFeaturesDefParse(virDomainDefPtr def,
     if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
         int feature;
         int value;
+        node = ctxt->node;
         if ((n = virXPathNodeSet("./features/kvm/*", ctxt, &nodes)) < 0)
             return -1;

@@ -18395,6 +18397,7 @@ virDomainFeaturesDefParse(virDomainDefPtr def,
                 case VIR_DOMAIN_KVM_HIDDEN:
                 case VIR_DOMAIN_KVM_DEDICATED:
                 case VIR_DOMAIN_KVM_POLLCONTROL:
+                case VIR_DOMAIN_KVM_DIRTY_RING:
                     if (!(tmp = virXMLPropString(nodes[i], "state"))) {
                         virReportError(VIR_ERR_XML_ERROR,
                                        _("missing 'state' attribute for "
@@ -18413,6 +18416,26 @@ virDomainFeaturesDefParse(virDomainDefPtr def,

                     VIR_FREE(tmp);
                     def->kvm_features[feature] = value;
+
+                    /* only for dirty ring case */
+                    if (((virDomainKVM) feature) == VIR_DOMAIN_KVM_DIRTY_RING &&
+                          value == VIR_TRISTATE_SWITCH_ON) {
+                        ctxt->node = nodes[i];
+                        if (virXPathUInt("string(./@size)", ctxt,
+                                         &def->dirty_gfn_count) < 0) {
+                            virReportError(VIR_ERR_XML_ERROR, "%s",
+                                           _("invalid number of dirty GFNs"));
+                            return -1;
+                        }
+
+                        if ((def->dirty_gfn_count & (def->dirty_gfn_count - 1)) ||
+                            def->dirty_gfn_count > 65536) {
+                            virReportError(VIR_ERR_XML_ERROR, "%s",
+                                           _("max number of dirty GFNs is 65536 "
+                                             "and must be power of 2"));
+                            return -1;
+                        }
+                    }
                     break;

                 /* coverity[dead_error_begin] */
@@ -18421,6 +18444,7 @@ virDomainFeaturesDefParse(virDomainDefPtr def,
             }
         }
         VIR_FREE(nodes);
+        ctxt->node = node;
     }

     if (def->features[VIR_DOMAIN_FEATURE_XEN] == VIR_TRISTATE_SWITCH_ON) {
@@ -22521,6 +22545,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
             case VIR_DOMAIN_KVM_HIDDEN:
             case VIR_DOMAIN_KVM_DEDICATED:
             case VIR_DOMAIN_KVM_POLLCONTROL:
+            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: "
@@ -28271,6 +28296,15 @@ virDomainDefFormatFeatures(virBufferPtr buf,
                                               def->kvm_features[j]));
                     break;

+                case VIR_DOMAIN_KVM_DIRTY_RING:
+                    if (def->kvm_features[j])
+                        virBufferAsprintf(&childBuf, "<%s state='%s' size='%d'/>\n",
+                                          virDomainKVMTypeToString(j),
+                                          virTristateSwitchTypeToString(
+                                              def->kvm_features[j]),
+                                          def->dirty_gfn_count);
+                    break;
+
                 /* coverity[dead_error_begin] */
                 case VIR_DOMAIN_KVM_LAST:
                     break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ec43bbe..120d490 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1917,6 +1917,7 @@ typedef enum {
     VIR_DOMAIN_KVM_HIDDEN = 0,
     VIR_DOMAIN_KVM_DEDICATED,
     VIR_DOMAIN_KVM_POLLCONTROL,
+    VIR_DOMAIN_KVM_DIRTY_RING,

     VIR_DOMAIN_KVM_LAST
 } virDomainKVM;
@@ -2728,6 +2729,9 @@ struct _virDomainDef {
                              callbacks failed for a non-critical reason
                              (was not able to fill in some data) and thus
                              should be re-run before starting */
+
+    /* Number of dirty GFNs per ring */
+    unsigned int dirty_gfn_count;
 };


diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 0f660aa..31829ba 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6525,6 +6525,9 @@ qemuBuildCpuCommandLine(virCommandPtr cmd,
                     virBufferAddLit(&buf, ",kvm-poll-control=on");
                 break;

+            case VIR_DOMAIN_KVM_DIRTY_RING:
+                break;
+
             /* coverity[dead_error_begin] */
             case VIR_DOMAIN_KVM_LAST:
                 break;
@@ -6959,9 +6962,13 @@ qemuBuildAccelCommandLineTcgOptions(void)


 static void
-qemuBuildAccelCommandLineKvmOptions(void)
+qemuBuildAccelCommandLineKvmOptions(virBuffer *buf,
+                                    const virDomainDef *def)
 {
-    /* implemented in the next patch */
+    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-gfn-count=%d", def->dirty_gfn_count);
+    }
 }


@@ -6982,7 +6989,7 @@ qemuBuildAccelCommandLine(virCommandPtr cmd,

     case VIR_DOMAIN_VIRT_KVM:
         virBufferAddLit(&buf, "kvm");
-        qemuBuildAccelCommandLineKvmOptions();
+        qemuBuildAccelCommandLineKvmOptions(&buf, def);
         break;

     case VIR_DOMAIN_VIRT_KQEMU:
--
1.8.3.1