On Tue, Aug 20, 2024 at 17:10:00 +0200, Anthony Harivel wrote:
Add the support in libvirt to activate the RAPL feature in QEMU.
This feature is activated with -accel kvm,rapl=true,path=/path/sock.sock
in QEMU.
The feature is activated in libvirt with the following XML
configuration:
<kvm>
[...]
<rapl state ='on' socket='/run/qemu-vmsr-helper.sock'/>
[...]
</kvm>
See:
https://gitlab.com/qemu-project/qemu/-/commit/0418f90809aea5b375c859e744c...
So based on how we've implemented other features configured similarly
this makes sense. Although the documentation states that this works only
on Intel hosts I don't think it makes sense for libvirt do do any
checking.
Signed-off-by: Anthony Harivel <aharivel(a)redhat.com>
---
docs/formatdomain.rst | 2 ++
src/conf/domain_conf.c | 30 +++++++++++++++++++
src/conf/domain_conf.h | 2 ++
src/conf/schemas/domaincommon.rng | 10 +++++++
src/qemu/qemu_command.c | 7 +++++
tests/qemuxmlconfdata/kvm-features-off.xml | 1 +
.../kvm-features.x86_64-latest.args | 2 +-
tests/qemuxmlconfdata/kvm-features.xml | 1 +
8 files changed, 54 insertions(+), 1 deletion(-)
[...]
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d950921667a2..06fbcac4aad1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -220,6 +220,7 @@ VIR_ENUM_IMPL(virDomainKVM,
"poll-control",
"pv-ipi",
"dirty-ring",
+ "rapl"
Missing comma at the end, making the next person add one.
);
VIR_ENUM_IMPL(virDomainXen,
@@ -16693,6 +16694,14 @@ virDomainFeaturesKVMDefParse(virDomainDef *def,
return -1;
}
}
+
+ /* rapl feature should parse socket property */
+ if (feature == VIR_DOMAIN_KVM_RAPL && value == VIR_TRISTATE_SWITCH_ON)
{
+ kvm->socket = virXMLPropString(feat, "socket");
+ if (kvm->socket == NULL) {
+ return -1;
'virXMLPropString' returns NULL only if the property is missing. With
code like this you'd not report an error, so the user will not know
what's wrong.
If you want to make the field mandatory you'll need to use either
virXMLPropStringRequired or provide your own error.
Or drop the NULL check if 'socket' is optional.
Also since it's a socket path you should check that the user provided an
absolute path (g_path_is_absolute) and report error if not.
def->features[VIR_DOMAIN_FEATURE_KVM] =
VIR_TRISTATE_SWITCH_ON;
@@ -21108,6 +21117,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src,
case VIR_DOMAIN_KVM_POLLCONTROL:
case VIR_DOMAIN_KVM_PVIPI:
case VIR_DOMAIN_KVM_DIRTY_RING:
+ case VIR_DOMAIN_KVM_RAPL:
if (src->kvm_features->features[i] !=
dst->kvm_features->features[i]) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("State of KVM feature '%1$s' differs:
source: '%2$s', destination: '%3$s'"),
@@ -21132,6 +21142,15 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src,
dst->kvm_features->dirty_ring_size);
return false;
}
+
+ if (src->kvm_features->socket != dst->kvm_features->socket) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("rapl helper socket of KVM feature '%1$s'
differs: source: '%2$s', destination: '%3$s'"),
+ virDomainKVMTypeToString(i),
+ src->kvm_features->socket,
+ dst->kvm_features->socket);
+ return false;
+ }
The socket path doesn't look like guest OS ABI to me. (The guest OS
doesn't care where you are pointing the socket to, and on the remote
side of the migration it seems as if this should be possible to change.
Thus this check should be dropped.
(If it's not dropped, you must use NULLSTR around them. Also you most
likely want to use STREQ?)
}
/* smm */
@@ -27840,6 +27859,17 @@ virDomainDefFormatFeatures(virBuffer *buf,
}
break;
+ case VIR_DOMAIN_KVM_RAPL:
+ if (def->kvm_features->features[j] !=
VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&childBuf, "<%s
state='%s'",
+ virDomainKVMTypeToString(j),
+
virTristateSwitchTypeToString(def->kvm_features->features[j]));
+
+ virBufferEscapeString(&childBuf, "
socket='%s'", def->kvm_features->socket);
+ 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 eae621f900b9..aa777850ec72 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2213,6 +2213,7 @@ typedef enum {
VIR_DOMAIN_KVM_POLLCONTROL,
VIR_DOMAIN_KVM_PVIPI,
VIR_DOMAIN_KVM_DIRTY_RING,
+ VIR_DOMAIN_KVM_RAPL,
VIR_DOMAIN_KVM_LAST
} virDomainKVM;
@@ -2400,6 +2401,7 @@ struct _virDomainFeatureKVM {
int features[VIR_DOMAIN_KVM_LAST];
unsigned int dirty_ring_size; /* size of dirty ring for each vCPU, no units */
+ char *socket; /* rapl helper socket */
Name the variable 'rapl_helper_socket', that way it will be obvious
everywhere and not only here at the comment.
};
typedef struct _virDomainFeatureTCG virDomainFeatureTCG;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 05ba69792470..1883bb115ee5 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -8016,6 +8016,16 @@
</optional>
</element>
</optional>
+ <optional>
+ <element name="rapl">
+ <ref name="featurestate"/>
+ <optional>
+ <attribute name="socket">
+ <data type="string"/>
We have a type for a local path named 'absFilePath'.
+ </attribute>
+ </optional>
+ </element>
+ </optional>
</interleave>
</element>
</define>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 28914c9c346a..d20fb6df5e8e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6562,6 +6562,9 @@ qemuBuildCpuCommandLine(virCommand *cmd,
case VIR_DOMAIN_KVM_DIRTY_RING:
break;
+ case VIR_DOMAIN_KVM_RAPL:
+ break;
+
case VIR_DOMAIN_KVM_LAST:
break;
}
@@ -7176,6 +7179,10 @@ qemuBuildAccelCommandLine(virCommand *cmd,
def->kvm_features->features[VIR_DOMAIN_KVM_DIRTY_RING] ==
VIR_TRISTATE_SWITCH_ON) {
virBufferAsprintf(&buf, ",dirty-ring-size=%d",
def->kvm_features->dirty_ring_size);
}
+ if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON
&&
+ def->kvm_features->features[VIR_DOMAIN_KVM_RAPL] ==
VIR_TRISTATE_SWITCH_ON) {
+ virBufferAsprintf(&buf, ",rapl=true,rapl-helper-socket=%s",
def->kvm_features->socket);
Okay, so socket is mandatory.
Also should we honour also '_OFF' state?
+ }
break;
case VIR_DOMAIN_VIRT_HVF:
diff --git a/tests/qemuxmlconfdata/kvm-features-off.xml
b/tests/qemuxmlconfdata/kvm-features-off.xml
index 3cd4ff18f283..3e8dbea4b177 100644
--- a/tests/qemuxmlconfdata/kvm-features-off.xml
+++ b/tests/qemuxmlconfdata/kvm-features-off.xml
@@ -16,6 +16,7 @@
<poll-control state='off'/>
<pv-ipi state='off'/>
<dirty-ring state='off'/>
+ <rapl state='off'/>
</kvm>
</features>
<cpu mode='host-passthrough' check='none'
migratable='off'/>
diff --git a/tests/qemuxmlconfdata/kvm-features.x86_64-latest.args
b/tests/qemuxmlconfdata/kvm-features.x86_64-latest.args
index 955db67eb4b7..2dd613ab338d 100644
--- a/tests/qemuxmlconfdata/kvm-features.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/kvm-features.x86_64-latest.args
@@ -11,7 +11,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-S \
-object
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}'
\
-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=on \
--accel kvm,dirty-ring-size=4096 \
+-accel kvm,dirty-ring-size=4096,rapl=true,rapl-helper-socket=/run/qemu-vmsr-helper.sock
\
-cpu host,migratable=off,kvm=off,kvm-hint-dedicated=on,kvm-poll-control=on \
-m size=219136k \
-object
'{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}'
\
diff --git a/tests/qemuxmlconfdata/kvm-features.xml
b/tests/qemuxmlconfdata/kvm-features.xml
index 78091064b109..ee601e06de75 100644
--- a/tests/qemuxmlconfdata/kvm-features.xml
+++ b/tests/qemuxmlconfdata/kvm-features.xml
@@ -16,6 +16,7 @@
<poll-control state='on'/>
<pv-ipi state='on'/>
<dirty-ring state='on' size='4096'/>
+ <rapl state='on' socket='/run/qemu-vmsr-helper.sock'/>
</kvm>
</features>
<cpu mode='host-passthrough' check='none'
migratable='off'/>
The rest looks good to me but I'll leave the possibility for others to
chime in even after you post a fixed version.