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.." 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..eda1f42054 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,63 @@ 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; + + 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++) { + size_t j = 0; + + 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; + size_t k = 0; + + 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 +17472,8 @@ qemuDomainGetStatsCpu(virQEMUDriver *driver, qemuDomainGetStatsCpuCache(driver, dom, params); + qemuDomainGetStatsEnergy(driver, dom, params); + qemuDomainGetStatsCpuHaltPollTime(dom, params, privflags); }