On 5/14/26 16:41, Jedrzej Wasiukiewicz wrote:
> Added energy reporting from resctrl PERF_PK_MON through domstats:
> cpu.energy.monitor.count=1
> cpu.energy.monitor.0.name=vcpus_0
> cpu.energy.monitor.0.vcpus=0
> cpu.energy.monitor.0.pkg.count=2
> cpu.energy.monitor.0.pkg.0.id=0
> cpu.energy.monitor.0.pkg.0.core_energy=0.000000
> cpu.energy.monitor.0.pkg.0.activity=0.000000
> cpu.energy.monitor.0.pkg.1.id=1
> cpu.energy.monitor.0.pkg.1.core_energy=2.888203
> cpu.energy.monitor.0.pkg.1.activity=1.718601
>
> Changes:
> - Added VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_* macros to libvirt-domain.h
> - Added qemuDomainGetStatsEnergy() to qemu_driver.c
>
> Signed-off-by: Jedrzej Wasiukiewicz <[email protected]>
> Signed-off-by: Christopher M. Cantalupo <[email protected]>
> ---
> include/libvirt/libvirt-domain.h | 65 +++++++++++++++++++++++++++++++
> src/qemu/qemu_driver.c | 66 ++++++++++++++++++++++++++++++--
> 2 files changed, 127 insertions(+), 4 deletions(-)
>
> diff --git a/include/libvirt/libvirt-domain.h
> b/include/libvirt/libvirt-domain.h
> index cf05bfe2b7..1066a0b3f1 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -4420,6 +4420,71 @@ struct _virDomainStatsRecord {
> # define
> VIR_DOMAIN_STATS_MEMORY_BANDWIDTH_MONITOR_SUFFIX_NODE_SUFFIX_BYTES_TOTAL
> ".bytes.total"
>
>
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_COUNT:
> + *
> + * The number of energy monitors for this domain, as an unsigned int.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_COUNT "cpu.energy.monitor.count"
> +
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX:
> + *
> + * Prefix for an individual energy monitor group. Concatenate
> + * with the monitor index and one of the "cpu.energy.monitor.<i>." suffix
> + * macros below to form a full parameter name.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX "cpu.energy.monitor."
> +
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_NAME:
> + *
> + * Name of the monitor group as a string.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_NAME ".name"
> +
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_VCPUS:
> + *
> + * vCPU set covered by the monitor group as a string.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_VCPUS ".vcpus"
> +
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_COUNT:
> + *
> + * Number of PERF_PKG nodes the monitor group exposes, as an unsigned int.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_COUNT ".pkg.count"
> +
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_PREFIX:
> + *
> + * Prefix for a single mon_PERF_PKG node inside a monitor group.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_PREFIX ".pkg."
> +
> +/**
> + * VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_SUFFIX_ID:
> + *
> + * Kernel-assigned mon_PERF_PKG node id, as an unsigned int.
> + *
> + * Since: 12.4.0
> + */
> +# define VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_SUFFIX_ID ".id"
> +
> /**
> * VIR_DOMAIN_STATS_DIRTYRATE_CALC_STATUS:
> *
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index a3d648e268..596e6ee7f3 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -17051,11 +17051,11 @@ qemuDomainFreeResctrlMonData(virQEMUResctrlMonData
> *resdata)
> * returns an error, the caller is also required to call
> * qemuDomainFreeResctrlMonData to free each element in the
> * *@resdata array and then the array itself.
> - * @tag: Could be VIR_RESCTRL_MONITOR_TYPE_CACHE for getting cache statistics
> - * from @dom cache monitors. VIR_RESCTRL_MONITOR_TYPE_MEMBW for
> - * getting memory bandwidth statistics from memory bandwidth monitors.
> + * @tag: VIR_RESCTRL_MONITOR_TYPE_CACHE for getting cache statistics.
> + * VIR_RESCTRL_MONITOR_TYPE_MEMBW for getting memory bandwidth
> statistics.
> + * VIR_RESCTRL_MONITOR_TYPE_ENERGY for getting energy statistics.
> *
> - * Get cache or memory bandwidth statistics from @dom monitors.
> + * Get cache, memory bandwidth or energy statistics from @dom monitors.
> *
> * Returns -1 on failure, or 0 on success.
> */
> @@ -17204,6 +17204,62 @@ qemuDomainGetStatsMemoryBandwidth(virQEMUDriver
> *driver,
> }
>
>
> +static void
> +qemuDomainGetStatsEnergy(virQEMUDriver *driver,
> + virDomainObj *dom,
> + virTypedParamList *params)
> +{
> + g_autofree virQEMUResctrlMonData **resdata = NULL;
> + size_t nresdata = 0;
> + size_t i = 0;
> + size_t j = 0;
> + size_t k = 0;
We tend to declare variables in their smallest possible scope.
IOW, these (j, and k) could be declared inside for() loops.
> +
> + if (!virDomainObjIsActive(dom))
> + return;
> +
> + if (qemuDomainGetResctrlMonData(driver, dom, &resdata, &nresdata,
> + VIR_RESCTRL_MONITOR_TYPE_ENERGY) < 0) {
> + virResetLastError();
> + return;
> + }
> +
> + if (nresdata == 0)
> + return;
> +
> + virTypedParamListAddUInt(params, nresdata,
> + VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_COUNT);
> +
> + for (i = 0; i < nresdata; i++) {
> + virTypedParamListAddString(params, resdata[i]->name,
> +
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX "%zu"
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_NAME, i);
> + virTypedParamListAddString(params, resdata[i]->vcpus,
> +
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX "%zu"
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_VCPUS, i);
> + virTypedParamListAddUInt(params, resdata[i]->nstats,
> + VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX
> "%zu" VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_COUNT, i);
> +
> + for (j = 0; j < resdata[i]->nstats; j++) {
> + char **features = resdata[i]->stats[j]->features;
> +
> + virTypedParamListAddUInt(params, resdata[i]->stats[j]->id,
> +
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX "%zu"
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_PREFIX "%zu"
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_SUFFIX_ID, i, j);
> +
> + for (k = 0; features[k]; k++) {
> + if (k >= resdata[i]->stats[j]->ndvals)
> + break;
> +
> + virTypedParamListAddDouble(params,
> resdata[i]->stats[j]->dvals[k],
> +
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_PREFIX "%zu"
> VIR_DOMAIN_STATS_CPU_ENERGY_MONITOR_SUFFIX_PKG_PREFIX "%zu" ".%s", i, j,
> + features[k]);
> + }
> + }
> + }
> +
> + for (i = 0; i < nresdata; i++)
> + qemuDomainFreeResctrlMonData(resdata[i]);
> +}
> +
> +
> static void
> qemuDomainGetStatsCpuCache(virQEMUDriver *driver,
> virDomainObj *dom,
> @@ -17415,6 +17471,8 @@ qemuDomainGetStatsCpu(virQEMUDriver *driver,
>
> qemuDomainGetStatsCpuCache(driver, dom, params);
>
> + qemuDomainGetStatsEnergy(driver, dom, params);
> +
> qemuDomainGetStatsCpuHaltPollTime(dom, params, privflags);
> }
>
Michal