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

Reply via email to