From: Hyman <huang...@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 <huang...@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 | 16 ++++++++++++++++ 5 files changed, 73 insertions(+), 7 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 6100b88..16338be 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:`6.10.1 (QEMU 5.2.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 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 9a64473..58651fe 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; @@ -6911,6 +6914,18 @@ qemuBuildMachineCommandLine(virCommandPtr cmd, return 0; } +static void +qemuBuildAccelCommandLineKvmOptions(virCommandPtr cmd, + const virDomainDef *def) +{ + if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON && + def->kvm_features[VIR_DOMAIN_KVM_DIRTY_RING] == VIR_TRISTATE_SWITCH_ON) { + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + virBufferAsprintf(&buf, ",dirty_gfn_count=%d", def->dirty_gfn_count); + virCommandAddArgBuffer(cmd, &buf); + } +} + static int qemuBuildAccelCommandLine(virCommandPtr cmd, const virDomainDef *def) @@ -6927,6 +6942,7 @@ qemuBuildAccelCommandLine(virCommandPtr cmd, case VIR_DOMAIN_VIRT_KVM: virBufferAddLit(&buf, "kvm"); + qemuBuildAccelCommandLineKvmOptions(cmd, def); break; case VIR_DOMAIN_VIRT_KQEMU: -- 1.8.3.1