mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
turbostat v2025.06.08
Add initial DMR support, which required smarter RAPL probe Fix AMD MSR RAPL energy reporting Add RAPL power limit configuration output Minor fixes -----BEGIN PGP SIGNATURE----- iQJIBAABCgAyFiEE67dNfPFP+XUaA73mB9BFOha3NhcFAmhF0rgUHGxlbi5icm93 bkBpbnRlbC5jb20ACgkQB9BFOha3NhcwRA/+IHnZoisw+uxY2TVY99Oi6mUx7i2r UH8Q6USFj4FVY1UXLeL4OfEY1pGukM+plDD+GjfzCgOsI6prARwEfQuR9to/lWaF in+EpSPJLpaLvRlug0fC+MENbPI/lR2NMq9SUd9WGyUZRfrVqyMgqOnogUzpMVxZ nvjtxO7scG5Vlqz7jTzyYquF9wZJjHMY0uUTOSydEAYMBH1X2TtG0N0TfoorGedf nZ/eEOCmoMIn0MD25tL8NZ1FaSR8p21r/aTP3zLj6y2bMmYEUGEzDfaHTSXjOzNK xQNIvxWdeo4PtF6ydxm5jmbW5aw8/iigGWnRJEltIJiAC5LcU4EFPVpqiYxp+ks4 Ci+TbgypCg2W5XwnHEEG4aKwIPAJXfkvZgoyPac0jP4q6CZqVfy8zxNijZvuSkdq fzbjYfUtdgCIeiFex2txJPgHfv5VyOtN1vlPuVjQiZGYnyDXOhVZv67Rb8xTZxk1 OUbxdewAB6Z2oLhUYYYH576yjF1U2ec2mRNVIWDZ549RFoyVjMJGYta8iabMJrRV hM6N61LzJb8/xQsFtZh5hmc6Z/+lfQKUn3idb1eN65vFf2QUfzcc+oBP5IwL0oIf sOJc4NLph4VwctKv+xekHPFmy1OMa2OmgC96VYMrFGvd3YKvmMB4JwxzVk0N49pq qLZd7ZHha5llG/w= =ZmFu -----END PGP SIGNATURE----- Merge tag 'turbostat-2025.06.08' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux Pull turbostat updates from Len Brown: - Add initial DMR support, which required smarter RAPL probe - Fix AMD MSR RAPL energy reporting - Add RAPL power limit configuration output - Minor fixes * tag 'turbostat-2025.06.08' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: tools/power turbostat: version 2025.06.08 tools/power turbostat: Add initial support for BartlettLake tools/power turbostat: Add initial support for DMR tools/power turbostat: Dump RAPL sysfs info tools/power turbostat: Avoid probing the same perf counters tools/power turbostat: Allow probing RAPL with platform_features->rapl_msrs cleared tools/power turbostat: Clean up add perf/msr counter logic tools/power turbostat: Introduce add_msr_counter() tools/power turbostat: Remove add_msr_perf_counter_() tools/power turbostat: Remove add_cstate_perf_counter_() tools/power turbostat: Remove add_rapl_perf_counter_() tools/power turbostat: Quit early for unsupported RAPL counters tools/power turbostat: Always check rapl_joules flag tools/power turbostat: Fix AMD package-energy reporting tools/power turbostat: Fix RAPL_GFX_ALL typo tools/power turbostat: Add Android support for MSR device handling tools/power turbostat.8: pm_domain wording fix tools/power turbostat.8: fix typo: idle_pct should be pct_idle
This commit is contained in:
commit
939f15e640
|
@ -100,7 +100,7 @@ The column name "all" can be used to enable all disabled-by-default built-in cou
|
||||||
.PP
|
.PP
|
||||||
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names.
|
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names.
|
||||||
.PP
|
.PP
|
||||||
\fB--show CATEGORY --hide CATEGORY\fP Show and hide also accept a single CATEGORY of columns: "all", "topology", "idle", "frequency", "power", "cpuidle", "hwidle", "swidle", "other". "idle" (enabled by default), includes "hwidle" and "idle_pct". "cpuidle" (default disabled) includes cpuidle software invocation counters. "swidle" includes "cpuidle" plus "idle_pct". "hwidle" includes only hardware based idle residency counters. Older versions of turbostat used the term "sysfs" for what is now "swidle".
|
\fB--show CATEGORY --hide CATEGORY\fP Show and hide also accept a single CATEGORY of columns: "all", "topology", "idle", "frequency", "power", "cpuidle", "hwidle", "swidle", "other". "idle" (enabled by default), includes "hwidle" and "pct_idle". "cpuidle" (default disabled) includes cpuidle software invocation counters. "swidle" includes "cpuidle" plus "pct_idle". "hwidle" includes only hardware based idle residency counters. Older versions of turbostat used the term "sysfs" for what is now "swidle".
|
||||||
.PP
|
.PP
|
||||||
\fB--Dump\fP displays the raw counter values.
|
\fB--Dump\fP displays the raw counter values.
|
||||||
.PP
|
.PP
|
||||||
|
@ -204,8 +204,8 @@ The system configuration dump (if --quiet is not used) is followed by statistics
|
||||||
.PP
|
.PP
|
||||||
\fBUncMHz\fP per-package uncore MHz, instantaneous sample.
|
\fBUncMHz\fP per-package uncore MHz, instantaneous sample.
|
||||||
.PP
|
.PP
|
||||||
\fBUMHz1.0\fP per-package uncore MHz for domain=1 and fabric_cluster=0, instantaneous sample. System summary is the average of all packages.
|
\fBUMHz1.0\fP per-package uncore MHz for pm_domain=1 and fabric_cluster=0, instantaneous sample. System summary is the average of all packages.
|
||||||
Intel Granite Rapids systems use domains 0-2 for CPUs, and 3-4 for IO, with cluster always 0.
|
Intel Granite Rapids systems use pm_domains 0-2 for CPUs, and 3-4 for IO, with cluster always 0.
|
||||||
For the "--show" and "--hide" options, use "UncMHz" to operate on all UMHz*.* as a group.
|
For the "--show" and "--hide" options, use "UncMHz" to operate on all UMHz*.* as a group.
|
||||||
.SH TOO MUCH INFORMATION EXAMPLE
|
.SH TOO MUCH INFORMATION EXAMPLE
|
||||||
By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters.
|
By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters.
|
||||||
|
|
|
@ -280,7 +280,7 @@ struct msr_counter bic[] = {
|
||||||
#define BIC_GROUP_FREQUENCY (BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_SAMMHz | BIC_SAMACTMHz | BIC_UNCORE_MHZ)
|
#define BIC_GROUP_FREQUENCY (BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_SAMMHz | BIC_SAMACTMHz | BIC_UNCORE_MHZ)
|
||||||
#define BIC_GROUP_HW_IDLE (BIC_Busy | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6)
|
#define BIC_GROUP_HW_IDLE (BIC_Busy | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6)
|
||||||
#define BIC_GROUP_SW_IDLE (BIC_Busy | BIC_cpuidle | BIC_pct_idle )
|
#define BIC_GROUP_SW_IDLE (BIC_Busy | BIC_cpuidle | BIC_pct_idle )
|
||||||
#define BIC_GROUP_IDLE (BIC_GROUP_HW_IDLE | BIC_pct_idle)
|
#define BIC_GROUP_IDLE (BIC_GROUP_HW_IDLE | BIC_pct_idle)
|
||||||
#define BIC_OTHER (BIC_IRQ | BIC_NMI | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC)
|
#define BIC_OTHER (BIC_IRQ | BIC_NMI | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC)
|
||||||
|
|
||||||
#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC | BIC_cpuidle)
|
#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC | BIC_cpuidle)
|
||||||
|
@ -539,7 +539,7 @@ enum rapl_msrs {
|
||||||
#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)
|
#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)
|
||||||
#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)
|
#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)
|
||||||
#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY)
|
#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY)
|
||||||
#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLIGY)
|
#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLICY)
|
||||||
|
|
||||||
#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT)
|
#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT)
|
||||||
|
|
||||||
|
@ -839,6 +839,23 @@ static const struct platform_features spr_features = {
|
||||||
.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
|
.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct platform_features dmr_features = {
|
||||||
|
.has_msr_misc_feature_control = spr_features.has_msr_misc_feature_control,
|
||||||
|
.has_msr_misc_pwr_mgmt = spr_features.has_msr_misc_pwr_mgmt,
|
||||||
|
.has_nhm_msrs = spr_features.has_nhm_msrs,
|
||||||
|
.has_config_tdp = spr_features.has_config_tdp,
|
||||||
|
.bclk_freq = spr_features.bclk_freq,
|
||||||
|
.supported_cstates = spr_features.supported_cstates,
|
||||||
|
.cst_limit = spr_features.cst_limit,
|
||||||
|
.has_msr_core_c1_res = spr_features.has_msr_core_c1_res,
|
||||||
|
.has_msr_module_c6_res_ms = 1, /* DMR has Dual Core Module and MC6 MSR */
|
||||||
|
.has_irtl_msrs = spr_features.has_irtl_msrs,
|
||||||
|
.has_cst_prewake_bit = spr_features.has_cst_prewake_bit,
|
||||||
|
.has_fixed_rapl_psys_unit = spr_features.has_fixed_rapl_psys_unit,
|
||||||
|
.trl_msrs = spr_features.trl_msrs,
|
||||||
|
.rapl_msrs = 0, /* DMR does not have RAPL MSRs */
|
||||||
|
};
|
||||||
|
|
||||||
static const struct platform_features srf_features = {
|
static const struct platform_features srf_features = {
|
||||||
.has_msr_misc_feature_control = 1,
|
.has_msr_misc_feature_control = 1,
|
||||||
.has_msr_misc_pwr_mgmt = 1,
|
.has_msr_misc_pwr_mgmt = 1,
|
||||||
|
@ -1028,12 +1045,14 @@ static const struct platform_data turbostat_pdata[] = {
|
||||||
{ INTEL_EMERALDRAPIDS_X, &spr_features },
|
{ INTEL_EMERALDRAPIDS_X, &spr_features },
|
||||||
{ INTEL_GRANITERAPIDS_X, &spr_features },
|
{ INTEL_GRANITERAPIDS_X, &spr_features },
|
||||||
{ INTEL_GRANITERAPIDS_D, &spr_features },
|
{ INTEL_GRANITERAPIDS_D, &spr_features },
|
||||||
|
{ INTEL_PANTHERCOVE_X, &dmr_features },
|
||||||
{ INTEL_LAKEFIELD, &cnl_features },
|
{ INTEL_LAKEFIELD, &cnl_features },
|
||||||
{ INTEL_ALDERLAKE, &adl_features },
|
{ INTEL_ALDERLAKE, &adl_features },
|
||||||
{ INTEL_ALDERLAKE_L, &adl_features },
|
{ INTEL_ALDERLAKE_L, &adl_features },
|
||||||
{ INTEL_RAPTORLAKE, &adl_features },
|
{ INTEL_RAPTORLAKE, &adl_features },
|
||||||
{ INTEL_RAPTORLAKE_P, &adl_features },
|
{ INTEL_RAPTORLAKE_P, &adl_features },
|
||||||
{ INTEL_RAPTORLAKE_S, &adl_features },
|
{ INTEL_RAPTORLAKE_S, &adl_features },
|
||||||
|
{ INTEL_BARTLETTLAKE, &adl_features },
|
||||||
{ INTEL_METEORLAKE, &adl_features },
|
{ INTEL_METEORLAKE, &adl_features },
|
||||||
{ INTEL_METEORLAKE_L, &adl_features },
|
{ INTEL_METEORLAKE_L, &adl_features },
|
||||||
{ INTEL_ARROWLAKE_H, &adl_features },
|
{ INTEL_ARROWLAKE_H, &adl_features },
|
||||||
|
@ -1072,7 +1091,6 @@ void probe_platform_features(unsigned int family, unsigned int model)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
if (authentic_amd || hygon_genuine) {
|
if (authentic_amd || hygon_genuine) {
|
||||||
/* fallback to default features on unsupported models */
|
/* fallback to default features on unsupported models */
|
||||||
force_load++;
|
force_load++;
|
||||||
|
@ -1106,8 +1124,7 @@ end:
|
||||||
if (platform)
|
if (platform)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(stderr, "Unsupported platform detected.\n"
|
fprintf(stderr, "Unsupported platform detected.\n\tSee RUN THE LATEST VERSION on turbostat(8)\n");
|
||||||
"\tSee RUN THE LATEST VERSION on turbostat(8)\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,7 +1144,8 @@ char *progname;
|
||||||
|
|
||||||
#define CPU_SUBSET_MAXCPUS 8192 /* need to use before probe... */
|
#define CPU_SUBSET_MAXCPUS 8192 /* need to use before probe... */
|
||||||
cpu_set_t *cpu_present_set, *cpu_possible_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;
|
cpu_set_t *cpu_present_set, *cpu_possible_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;
|
||||||
size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size;
|
size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize,
|
||||||
|
cpu_subset_size;
|
||||||
#define MAX_ADDED_THREAD_COUNTERS 24
|
#define MAX_ADDED_THREAD_COUNTERS 24
|
||||||
#define MAX_ADDED_CORE_COUNTERS 8
|
#define MAX_ADDED_CORE_COUNTERS 8
|
||||||
#define MAX_ADDED_PACKAGE_COUNTERS 16
|
#define MAX_ADDED_PACKAGE_COUNTERS 16
|
||||||
|
@ -2140,13 +2158,20 @@ int get_msr_fd(int cpu)
|
||||||
|
|
||||||
if (fd)
|
if (fd)
|
||||||
return fd;
|
return fd;
|
||||||
|
#if defined(ANDROID)
|
||||||
|
sprintf(pathname, "/dev/msr%d", cpu);
|
||||||
|
#else
|
||||||
sprintf(pathname, "/dev/cpu/%d/msr", cpu);
|
sprintf(pathname, "/dev/cpu/%d/msr", cpu);
|
||||||
|
#endif
|
||||||
fd = open(pathname, O_RDONLY);
|
fd = open(pathname, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
#if defined(ANDROID)
|
||||||
|
err(-1, "%s open failed, try chown or chmod +r /dev/msr*, "
|
||||||
|
"or run with --no-msr, or run as root", pathname);
|
||||||
|
#else
|
||||||
err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, "
|
err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, "
|
||||||
"or run with --no-msr, or run as root", pathname);
|
"or run with --no-msr, or run as root", pathname);
|
||||||
|
#endif
|
||||||
fd_percpu[cpu] = fd;
|
fd_percpu[cpu] = fd;
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -2215,32 +2240,52 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int probe_rapl_msr(int cpu, off_t offset, int index)
|
int add_msr_counter(int cpu, off_t offset)
|
||||||
{
|
{
|
||||||
ssize_t retval;
|
ssize_t retval;
|
||||||
unsigned long long value;
|
unsigned long long value;
|
||||||
|
|
||||||
assert(!no_msr);
|
if (no_msr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!offset)
|
||||||
|
return -1;
|
||||||
|
|
||||||
retval = pread(get_msr_fd(cpu), &value, sizeof(value), offset);
|
retval = pread(get_msr_fd(cpu), &value, sizeof(value), offset);
|
||||||
|
|
||||||
/* if the read failed, the probe fails */
|
/* if the read failed, the probe fails */
|
||||||
if (retval != sizeof(value))
|
if (retval != sizeof(value))
|
||||||
return 1;
|
return -1;
|
||||||
|
|
||||||
/* If an Energy Status Counter MSR returns 0, the probe fails */
|
if (value == 0)
|
||||||
switch (index) {
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_rapl_msr_counter(int cpu, const struct rapl_counter_arch_info *cai)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!(platform->rapl_msrs & cai->feature_mask))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = add_msr_counter(cpu, cai->msr);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (cai->rci_index) {
|
||||||
case RAPL_RCI_INDEX_ENERGY_PKG:
|
case RAPL_RCI_INDEX_ENERGY_PKG:
|
||||||
case RAPL_RCI_INDEX_ENERGY_CORES:
|
case RAPL_RCI_INDEX_ENERGY_CORES:
|
||||||
case RAPL_RCI_INDEX_DRAM:
|
case RAPL_RCI_INDEX_DRAM:
|
||||||
case RAPL_RCI_INDEX_GFX:
|
case RAPL_RCI_INDEX_GFX:
|
||||||
case RAPL_RCI_INDEX_ENERGY_PLATFORM:
|
case RAPL_RCI_INDEX_ENERGY_PLATFORM:
|
||||||
if (value == 0)
|
if (ret == 0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PKG,DRAM_PERF_STATUS MSRs, can return any value */
|
/* PKG,DRAM_PERF_STATUS MSRs, can return any value */
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert CPU ID to domain ID for given added perf counter. */
|
/* Convert CPU ID to domain ID for given added perf counter. */
|
||||||
|
@ -2327,8 +2372,7 @@ void help(void)
|
||||||
" degrees Celsius\n"
|
" degrees Celsius\n"
|
||||||
" -h, --help\n"
|
" -h, --help\n"
|
||||||
" print this help message\n"
|
" print this help message\n"
|
||||||
" -v, --version\n"
|
" -v, --version\n\t\tprint version information\n\nFor more help, run \"man turbostat\"\n");
|
||||||
" print version information\n\nFor more help, run \"man turbostat\"\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2644,7 +2688,7 @@ void print_header(char *delim)
|
||||||
if (DO_BIC(BIC_SYS_LPI))
|
if (DO_BIC(BIC_SYS_LPI))
|
||||||
outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));
|
||||||
|
|
||||||
if (platform->rapl_msrs && !rapl_joules) {
|
if (!rapl_joules) {
|
||||||
if (DO_BIC(BIC_PkgWatt))
|
if (DO_BIC(BIC_PkgWatt))
|
||||||
outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)
|
if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)
|
||||||
|
@ -2657,7 +2701,7 @@ void print_header(char *delim)
|
||||||
outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_RAM__))
|
if (DO_BIC(BIC_RAM__))
|
||||||
outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
|
||||||
} else if (platform->rapl_msrs && rapl_joules) {
|
} else {
|
||||||
if (DO_BIC(BIC_Pkg_J))
|
if (DO_BIC(BIC_Pkg_J))
|
||||||
outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)
|
if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)
|
||||||
|
@ -3943,7 +3987,6 @@ void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data
|
||||||
if (average.threads.nmi_count > 9999999)
|
if (average.threads.nmi_count > 9999999)
|
||||||
sums_need_wide_columns = 1;
|
sums_need_wide_columns = 1;
|
||||||
|
|
||||||
|
|
||||||
average.cores.c3 /= topo.allowed_cores;
|
average.cores.c3 /= topo.allowed_cores;
|
||||||
average.cores.c6 /= topo.allowed_cores;
|
average.cores.c6 /= topo.allowed_cores;
|
||||||
average.cores.c7 /= topo.allowed_cores;
|
average.cores.c7 /= topo.allowed_cores;
|
||||||
|
@ -4766,6 +4809,37 @@ unsigned long pmt_read_counter(struct pmt_counter *ppmt, unsigned int domain_id)
|
||||||
return (value & value_mask) >> value_shift;
|
return (value & value_mask) >> value_shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rapl domain enumeration helpers */
|
||||||
|
static inline int get_rapl_num_domains(void)
|
||||||
|
{
|
||||||
|
int num_packages = topo.max_package_id + 1;
|
||||||
|
int num_cores_per_package;
|
||||||
|
int num_cores;
|
||||||
|
|
||||||
|
if (!platform->has_per_core_rapl)
|
||||||
|
return num_packages;
|
||||||
|
|
||||||
|
num_cores_per_package = topo.max_core_id + 1;
|
||||||
|
num_cores = num_cores_per_package * num_packages;
|
||||||
|
|
||||||
|
return num_cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_rapl_domain_id(int cpu)
|
||||||
|
{
|
||||||
|
int nr_cores_per_package = topo.max_core_id + 1;
|
||||||
|
int rapl_core_id;
|
||||||
|
|
||||||
|
if (!platform->has_per_core_rapl)
|
||||||
|
return cpus[cpu].physical_package_id;
|
||||||
|
|
||||||
|
/* Compute the system-wide unique core-id for @cpu */
|
||||||
|
rapl_core_id = cpus[cpu].physical_core_id;
|
||||||
|
rapl_core_id += cpus[cpu].physical_package_id * nr_cores_per_package;
|
||||||
|
|
||||||
|
return rapl_core_id;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_counters(...)
|
* get_counters(...)
|
||||||
* migrate to cpu
|
* migrate to cpu
|
||||||
|
@ -4821,7 +4895,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (platform->has_per_core_rapl) {
|
if (platform->has_per_core_rapl) {
|
||||||
status = get_rapl_counters(cpu, c->core_id, c, p);
|
status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -4887,7 +4961,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
||||||
p->sys_lpi = cpuidle_cur_sys_lpi_us;
|
p->sys_lpi = cpuidle_cur_sys_lpi_us;
|
||||||
|
|
||||||
if (!platform->has_per_core_rapl) {
|
if (!platform->has_per_core_rapl) {
|
||||||
status = get_rapl_counters(cpu, p->package_id, c, p);
|
status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -6476,8 +6550,11 @@ void check_dev_msr()
|
||||||
|
|
||||||
if (no_msr)
|
if (no_msr)
|
||||||
return;
|
return;
|
||||||
|
#if defined(ANDROID)
|
||||||
|
sprintf(pathname, "/dev/msr%d", base_cpu);
|
||||||
|
#else
|
||||||
sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
|
sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
|
||||||
|
#endif
|
||||||
if (stat(pathname, &sb))
|
if (stat(pathname, &sb))
|
||||||
if (system("/sbin/modprobe msr > /dev/null 2>&1"))
|
if (system("/sbin/modprobe msr > /dev/null 2>&1"))
|
||||||
no_msr = 1;
|
no_msr = 1;
|
||||||
|
@ -6527,7 +6604,11 @@ void check_msr_permission(void)
|
||||||
failed += check_for_cap_sys_rawio();
|
failed += check_for_cap_sys_rawio();
|
||||||
|
|
||||||
/* test file permissions */
|
/* test file permissions */
|
||||||
|
#if defined(ANDROID)
|
||||||
|
sprintf(pathname, "/dev/msr%d", base_cpu);
|
||||||
|
#else
|
||||||
sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
|
sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
|
||||||
|
#endif
|
||||||
if (euidaccess(pathname, R_OK)) {
|
if (euidaccess(pathname, R_OK)) {
|
||||||
failed++;
|
failed++;
|
||||||
}
|
}
|
||||||
|
@ -6737,8 +6818,10 @@ static void probe_intel_uncore_frequency_cluster(void)
|
||||||
* This allows "--show/--hide UncMHz" to be effective for
|
* This allows "--show/--hide UncMHz" to be effective for
|
||||||
* the clustered MHz counters, as a group.
|
* the clustered MHz counters, as a group.
|
||||||
*/
|
*/
|
||||||
if BIC_IS_ENABLED(BIC_UNCORE_MHZ)
|
if BIC_IS_ENABLED
|
||||||
add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id);
|
(BIC_UNCORE_MHZ)
|
||||||
|
add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0,
|
||||||
|
package_id);
|
||||||
|
|
||||||
if (quiet)
|
if (quiet)
|
||||||
continue;
|
continue;
|
||||||
|
@ -6810,17 +6893,21 @@ static void probe_graphics(void)
|
||||||
else
|
else
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", gt0_is_gt ? GFX_rc6 : SAM_mc6);
|
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms",
|
||||||
|
gt0_is_gt ? GFX_rc6 : SAM_mc6);
|
||||||
|
|
||||||
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", gt0_is_gt ? GFX_MHz : SAM_MHz);
|
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", gt0_is_gt ? GFX_MHz : SAM_MHz);
|
||||||
|
|
||||||
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz);
|
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq",
|
||||||
|
gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz);
|
||||||
|
|
||||||
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", gt0_is_gt ? SAM_mc6 : GFX_rc6);
|
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms",
|
||||||
|
gt0_is_gt ? SAM_mc6 : GFX_rc6);
|
||||||
|
|
||||||
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", gt0_is_gt ? SAM_MHz : GFX_MHz);
|
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", gt0_is_gt ? SAM_MHz : GFX_MHz);
|
||||||
|
|
||||||
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz);
|
set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq",
|
||||||
|
gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz);
|
||||||
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -7256,6 +7343,9 @@ void rapl_probe_intel(void)
|
||||||
else
|
else
|
||||||
bic_enabled &= ~bic_joules_bits;
|
bic_enabled &= ~bic_joules_bits;
|
||||||
|
|
||||||
|
if (!platform->rapl_msrs || no_msr)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!(platform->rapl_msrs & RAPL_PKG_PERF_STATUS))
|
if (!(platform->rapl_msrs & RAPL_PKG_PERF_STATUS))
|
||||||
bic_enabled &= ~BIC_PKG__;
|
bic_enabled &= ~BIC_PKG__;
|
||||||
if (!(platform->rapl_msrs & RAPL_DRAM_PERF_STATUS))
|
if (!(platform->rapl_msrs & RAPL_DRAM_PERF_STATUS))
|
||||||
|
@ -7306,6 +7396,9 @@ void rapl_probe_amd(void)
|
||||||
else
|
else
|
||||||
bic_enabled &= ~bic_joules_bits;
|
bic_enabled &= ~bic_joules_bits;
|
||||||
|
|
||||||
|
if (!platform->rapl_msrs || no_msr)
|
||||||
|
return;
|
||||||
|
|
||||||
if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
|
if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -7332,6 +7425,158 @@ void print_power_limit_msr(int cpu, unsigned long long msr, char *label)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fread_int(char *path, int *val)
|
||||||
|
{
|
||||||
|
FILE *filep;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
filep = fopen(path, "r");
|
||||||
|
if (!filep)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = fscanf(filep, "%d", val);
|
||||||
|
fclose(filep);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fread_ull(char *path, unsigned long long *val)
|
||||||
|
{
|
||||||
|
FILE *filep;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
filep = fopen(path, "r");
|
||||||
|
if (!filep)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = fscanf(filep, "%llu", val);
|
||||||
|
fclose(filep);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fread_str(char *path, char *buf, int size)
|
||||||
|
{
|
||||||
|
FILE *filep;
|
||||||
|
int ret;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
filep = fopen(path, "r");
|
||||||
|
if (!filep)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = fread(buf, 1, size, filep);
|
||||||
|
fclose(filep);
|
||||||
|
|
||||||
|
/* replace '\n' with '\0' */
|
||||||
|
cp = strchr(buf, '\n');
|
||||||
|
if (cp != NULL)
|
||||||
|
*cp = '\0';
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PATH_RAPL_SYSFS "/sys/class/powercap"
|
||||||
|
|
||||||
|
static int dump_one_domain(char *domain_path)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char str[PATH_MAX];
|
||||||
|
unsigned long long val;
|
||||||
|
int constraint;
|
||||||
|
int enable;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/name", domain_path);
|
||||||
|
ret = fread_str(path, str, PATH_MAX);
|
||||||
|
if (ret <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fprintf(outf, "%s: %s", domain_path + strlen(PATH_RAPL_SYSFS) + 1, str);
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/enabled", domain_path);
|
||||||
|
ret = fread_int(path, &enable);
|
||||||
|
if (ret <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!enable) {
|
||||||
|
fputs(" disabled\n", outf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (constraint = 0;; constraint++) {
|
||||||
|
snprintf(path, PATH_MAX, "%s/constraint_%d_time_window_us", domain_path, constraint);
|
||||||
|
ret = fread_ull(path, &val);
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (val > 1000000)
|
||||||
|
fprintf(outf, " %0.1fs", (double)val / 1000000);
|
||||||
|
else if (val > 1000)
|
||||||
|
fprintf(outf, " %0.1fms", (double)val / 1000);
|
||||||
|
else
|
||||||
|
fprintf(outf, " %0.1fus", (double)val);
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/constraint_%d_power_limit_uw", domain_path, constraint);
|
||||||
|
ret = fread_ull(path, &val);
|
||||||
|
if (ret > 0 && val)
|
||||||
|
fprintf(outf, ":%lluW", val / 1000000);
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/constraint_%d_max_power_uw", domain_path, constraint);
|
||||||
|
ret = fread_ull(path, &val);
|
||||||
|
if (ret > 0 && val)
|
||||||
|
fprintf(outf, ",max:%lluW", val / 1000000);
|
||||||
|
}
|
||||||
|
fputc('\n', outf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int print_rapl_sysfs(void)
|
||||||
|
{
|
||||||
|
DIR *dir, *cdir;
|
||||||
|
struct dirent *entry, *centry;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char str[PATH_MAX];
|
||||||
|
|
||||||
|
if ((dir = opendir(PATH_RAPL_SYSFS)) == NULL) {
|
||||||
|
warn("open %s failed", PATH_RAPL_SYSFS);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (strlen(entry->d_name) > 100)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strncmp(entry->d_name, "intel-rapl", strlen("intel-rapl")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/%s/name", PATH_RAPL_SYSFS, entry->d_name);
|
||||||
|
|
||||||
|
/* Parse top level domains first, including package and psys */
|
||||||
|
fread_str(path, str, PATH_MAX);
|
||||||
|
if (strncmp(str, "package", strlen("package")) && strncmp(str, "psys", strlen("psys")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/%s", PATH_RAPL_SYSFS, entry->d_name);
|
||||||
|
if ((cdir = opendir(path)) == NULL) {
|
||||||
|
perror("opendir() error");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_one_domain(path);
|
||||||
|
|
||||||
|
while ((centry = readdir(cdir)) != NULL) {
|
||||||
|
if (strncmp(centry->d_name, "intel-rapl", strlen("intel-rapl")))
|
||||||
|
continue;
|
||||||
|
snprintf(path, PATH_MAX, "%s/%s/%s", PATH_RAPL_SYSFS, entry->d_name, centry->d_name);
|
||||||
|
dump_one_domain(path);
|
||||||
|
}
|
||||||
|
closedir(cdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
||||||
{
|
{
|
||||||
unsigned long long msr;
|
unsigned long long msr;
|
||||||
|
@ -7458,9 +7703,6 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
||||||
*/
|
*/
|
||||||
void probe_rapl(void)
|
void probe_rapl(void)
|
||||||
{
|
{
|
||||||
if (!platform->rapl_msrs || no_msr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (genuine_intel)
|
if (genuine_intel)
|
||||||
rapl_probe_intel();
|
rapl_probe_intel();
|
||||||
if (authentic_amd || hygon_genuine)
|
if (authentic_amd || hygon_genuine)
|
||||||
|
@ -7469,6 +7711,11 @@ void probe_rapl(void)
|
||||||
if (quiet)
|
if (quiet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
print_rapl_sysfs();
|
||||||
|
|
||||||
|
if (!platform->rapl_msrs || no_msr)
|
||||||
|
return;
|
||||||
|
|
||||||
for_all_cpus(print_rapl, ODD_COUNTERS);
|
for_all_cpus(print_rapl, ODD_COUNTERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7801,44 +8048,42 @@ static int has_instr_count_access(void)
|
||||||
return has_access;
|
return has_access;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_rapl_perf_counter_(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai,
|
int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai,
|
||||||
double *scale_, enum rapl_unit *unit_)
|
double *scale_, enum rapl_unit *unit_)
|
||||||
{
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (no_perf)
|
if (no_perf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!cai->perf_name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
const double scale = read_perf_scale(cai->perf_subsys, cai->perf_name);
|
const double scale = read_perf_scale(cai->perf_subsys, cai->perf_name);
|
||||||
|
|
||||||
if (scale == 0.0)
|
if (scale == 0.0)
|
||||||
return -1;
|
goto end;
|
||||||
|
|
||||||
const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name);
|
const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name);
|
||||||
|
|
||||||
if (unit == RAPL_UNIT_INVALID)
|
if (unit == RAPL_UNIT_INVALID)
|
||||||
return -1;
|
goto end;
|
||||||
|
|
||||||
const unsigned int rapl_type = read_perf_type(cai->perf_subsys);
|
const unsigned int rapl_type = read_perf_type(cai->perf_subsys);
|
||||||
const unsigned int rapl_energy_pkg_config = read_perf_config(cai->perf_subsys, cai->perf_name);
|
const unsigned int rapl_energy_pkg_config = read_perf_config(cai->perf_subsys, cai->perf_name);
|
||||||
|
|
||||||
const int fd_counter =
|
ret = open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP);
|
||||||
open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP);
|
if (ret == -1)
|
||||||
if (fd_counter == -1)
|
goto end;
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* If it's the first counter opened, make it a group descriptor */
|
/* If it's the first counter opened, make it a group descriptor */
|
||||||
if (rci->fd_perf == -1)
|
if (rci->fd_perf == -1)
|
||||||
rci->fd_perf = fd_counter;
|
rci->fd_perf = ret;
|
||||||
|
|
||||||
*scale_ = scale;
|
*scale_ = scale;
|
||||||
*unit_ = unit;
|
*unit_ = unit;
|
||||||
return fd_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai,
|
|
||||||
double *scale, enum rapl_unit *unit)
|
|
||||||
{
|
|
||||||
int ret = add_rapl_perf_counter_(cpu, rci, cai, scale, unit);
|
|
||||||
|
|
||||||
|
end:
|
||||||
if (debug >= 2)
|
if (debug >= 2)
|
||||||
fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);
|
fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);
|
||||||
|
|
||||||
|
@ -7863,7 +8108,7 @@ void linux_perf_init(void)
|
||||||
|
|
||||||
void rapl_perf_init(void)
|
void rapl_perf_init(void)
|
||||||
{
|
{
|
||||||
const unsigned int num_domains = (platform->has_per_core_rapl ? topo.max_core_id : topo.max_package_id) + 1;
|
const unsigned int num_domains = get_rapl_num_domains();
|
||||||
bool *domain_visited = calloc(num_domains, sizeof(bool));
|
bool *domain_visited = calloc(num_domains, sizeof(bool));
|
||||||
|
|
||||||
rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain));
|
rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain));
|
||||||
|
@ -7896,6 +8141,9 @@ void rapl_perf_init(void)
|
||||||
enum rapl_unit unit;
|
enum rapl_unit unit;
|
||||||
unsigned int next_domain;
|
unsigned int next_domain;
|
||||||
|
|
||||||
|
if (!BIC_IS_ENABLED(cai->bic))
|
||||||
|
continue;
|
||||||
|
|
||||||
memset(domain_visited, 0, num_domains * sizeof(*domain_visited));
|
memset(domain_visited, 0, num_domains * sizeof(*domain_visited));
|
||||||
|
|
||||||
for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) {
|
for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) {
|
||||||
|
@ -7904,8 +8152,7 @@ void rapl_perf_init(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Skip already seen and handled RAPL domains */
|
/* Skip already seen and handled RAPL domains */
|
||||||
next_domain =
|
next_domain = get_rapl_domain_id(cpu);
|
||||||
platform->has_per_core_rapl ? cpus[cpu].physical_core_id : cpus[cpu].physical_package_id;
|
|
||||||
|
|
||||||
assert(next_domain < num_domains);
|
assert(next_domain < num_domains);
|
||||||
|
|
||||||
|
@ -7919,27 +8166,37 @@ void rapl_perf_init(void)
|
||||||
|
|
||||||
struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain];
|
struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain];
|
||||||
|
|
||||||
/* Check if the counter is enabled and accessible */
|
/*
|
||||||
if (BIC_IS_ENABLED(cai->bic) && (platform->rapl_msrs & cai->feature_mask)) {
|
* rapl_counter_arch_infos[] can have multiple entries describing the same
|
||||||
|
* counter, due to the difference from different platforms/Vendors.
|
||||||
|
* E.g. rapl_counter_arch_infos[0] and rapl_counter_arch_infos[1] share the
|
||||||
|
* same perf_subsys and perf_name, but with different MSR address.
|
||||||
|
* rapl_counter_arch_infos[0] is for Intel and rapl_counter_arch_infos[1]
|
||||||
|
* is for AMD.
|
||||||
|
* In this case, it is possible that multiple rapl_counter_arch_infos[]
|
||||||
|
* entries are probed just because their perf/msr is duplicate and valid.
|
||||||
|
*
|
||||||
|
* Thus need a check to avoid re-probe the same counters.
|
||||||
|
*/
|
||||||
|
if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE)
|
||||||
|
break;
|
||||||
|
|
||||||
/* Use perf API for this counter */
|
/* Use perf API for this counter */
|
||||||
if (!no_perf && cai->perf_name
|
if (add_rapl_perf_counter(cpu, rci, cai, &scale, &unit) != -1) {
|
||||||
&& add_rapl_perf_counter(cpu, rci, cai, &scale, &unit) != -1) {
|
rci->source[cai->rci_index] = COUNTER_SOURCE_PERF;
|
||||||
rci->source[cai->rci_index] = COUNTER_SOURCE_PERF;
|
rci->scale[cai->rci_index] = scale * cai->compat_scale;
|
||||||
rci->scale[cai->rci_index] = scale * cai->compat_scale;
|
rci->unit[cai->rci_index] = unit;
|
||||||
rci->unit[cai->rci_index] = unit;
|
rci->flags[cai->rci_index] = cai->flags;
|
||||||
rci->flags[cai->rci_index] = cai->flags;
|
|
||||||
|
|
||||||
/* Use MSR for this counter */
|
/* Use MSR for this counter */
|
||||||
} else if (!no_msr && cai->msr && probe_rapl_msr(cpu, cai->msr, cai->rci_index) == 0) {
|
} else if (add_rapl_msr_counter(cpu, cai) >= 0) {
|
||||||
rci->source[cai->rci_index] = COUNTER_SOURCE_MSR;
|
rci->source[cai->rci_index] = COUNTER_SOURCE_MSR;
|
||||||
rci->msr[cai->rci_index] = cai->msr;
|
rci->msr[cai->rci_index] = cai->msr;
|
||||||
rci->msr_mask[cai->rci_index] = cai->msr_mask;
|
rci->msr_mask[cai->rci_index] = cai->msr_mask;
|
||||||
rci->msr_shift[cai->rci_index] = cai->msr_shift;
|
rci->msr_shift[cai->rci_index] = cai->msr_shift;
|
||||||
rci->unit[cai->rci_index] = RAPL_UNIT_JOULES;
|
rci->unit[cai->rci_index] = RAPL_UNIT_JOULES;
|
||||||
rci->scale[cai->rci_index] = *cai->platform_rapl_msr_scale * cai->compat_scale;
|
rci->scale[cai->rci_index] = *cai->platform_rapl_msr_scale * cai->compat_scale;
|
||||||
rci->flags[cai->rci_index] = cai->flags;
|
rci->flags[cai->rci_index] = cai->flags;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE)
|
if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE)
|
||||||
|
@ -7972,65 +8229,63 @@ int *get_cstate_perf_group_fd(struct cstate_counter_info_t *cci, const char *gro
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_cstate_perf_counter_(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai)
|
int add_cstate_perf_counter(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai)
|
||||||
{
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (no_perf)
|
if (no_perf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!cai->perf_name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int *pfd_group = get_cstate_perf_group_fd(cci, cai->perf_subsys);
|
int *pfd_group = get_cstate_perf_group_fd(cci, cai->perf_subsys);
|
||||||
|
|
||||||
if (pfd_group == NULL)
|
if (pfd_group == NULL)
|
||||||
return -1;
|
goto end;
|
||||||
|
|
||||||
const unsigned int type = read_perf_type(cai->perf_subsys);
|
const unsigned int type = read_perf_type(cai->perf_subsys);
|
||||||
const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);
|
const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);
|
||||||
|
|
||||||
const int fd_counter = open_perf_counter(cpu, type, config, *pfd_group, PERF_FORMAT_GROUP);
|
ret = open_perf_counter(cpu, type, config, *pfd_group, PERF_FORMAT_GROUP);
|
||||||
|
|
||||||
if (fd_counter == -1)
|
if (ret == -1)
|
||||||
return -1;
|
goto end;
|
||||||
|
|
||||||
/* If it's the first counter opened, make it a group descriptor */
|
/* If it's the first counter opened, make it a group descriptor */
|
||||||
if (*pfd_group == -1)
|
if (*pfd_group == -1)
|
||||||
*pfd_group = fd_counter;
|
*pfd_group = ret;
|
||||||
|
|
||||||
return fd_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
int add_cstate_perf_counter(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai)
|
|
||||||
{
|
|
||||||
int ret = add_cstate_perf_counter_(cpu, cci, cai);
|
|
||||||
|
|
||||||
|
end:
|
||||||
if (debug >= 2)
|
if (debug >= 2)
|
||||||
fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);
|
fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_msr_perf_counter_(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai)
|
int add_msr_perf_counter(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai)
|
||||||
{
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (no_perf)
|
if (no_perf)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!cai->perf_name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
const unsigned int type = read_perf_type(cai->perf_subsys);
|
const unsigned int type = read_perf_type(cai->perf_subsys);
|
||||||
const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);
|
const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);
|
||||||
|
|
||||||
const int fd_counter = open_perf_counter(cpu, type, config, cci->fd_perf, PERF_FORMAT_GROUP);
|
ret = open_perf_counter(cpu, type, config, cci->fd_perf, PERF_FORMAT_GROUP);
|
||||||
|
|
||||||
if (fd_counter == -1)
|
if (ret == -1)
|
||||||
return -1;
|
goto end;
|
||||||
|
|
||||||
/* If it's the first counter opened, make it a group descriptor */
|
/* If it's the first counter opened, make it a group descriptor */
|
||||||
if (cci->fd_perf == -1)
|
if (cci->fd_perf == -1)
|
||||||
cci->fd_perf = fd_counter;
|
cci->fd_perf = ret;
|
||||||
|
|
||||||
return fd_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
int add_msr_perf_counter(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai)
|
|
||||||
{
|
|
||||||
int ret = add_msr_perf_counter_(cpu, cci, cai);
|
|
||||||
|
|
||||||
|
end:
|
||||||
if (debug)
|
if (debug)
|
||||||
fprintf(stderr, "%s: %s/%s: %d (cpu: %d)\n", __func__, cai->perf_subsys, cai->perf_name, ret, cpu);
|
fprintf(stderr, "%s: %s/%s: %d (cpu: %d)\n", __func__, cai->perf_subsys, cai->perf_name, ret, cpu);
|
||||||
|
|
||||||
|
@ -8064,12 +8319,12 @@ void msr_perf_init_(void)
|
||||||
|
|
||||||
if (cai->needed) {
|
if (cai->needed) {
|
||||||
/* Use perf API for this counter */
|
/* Use perf API for this counter */
|
||||||
if (!no_perf && cai->perf_name && add_msr_perf_counter(cpu, cci, cai) != -1) {
|
if (add_msr_perf_counter(cpu, cci, cai) != -1) {
|
||||||
cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;
|
cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;
|
||||||
cai->present = true;
|
cai->present = true;
|
||||||
|
|
||||||
/* User MSR for this counter */
|
/* User MSR for this counter */
|
||||||
} else if (!no_msr && cai->msr && probe_rapl_msr(cpu, cai->msr, cai->rci_index) == 0) {
|
} else if (add_msr_counter(cpu, cai->msr) >= 0) {
|
||||||
cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;
|
cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;
|
||||||
cci->msr[cai->rci_index] = cai->msr;
|
cci->msr[cai->rci_index] = cai->msr;
|
||||||
cci->msr_mask[cai->rci_index] = cai->msr_mask;
|
cci->msr_mask[cai->rci_index] = cai->msr_mask;
|
||||||
|
@ -8177,13 +8432,13 @@ void cstate_perf_init_(bool soft_c1)
|
||||||
|
|
||||||
if (counter_needed && counter_supported) {
|
if (counter_needed && counter_supported) {
|
||||||
/* Use perf API for this counter */
|
/* Use perf API for this counter */
|
||||||
if (!no_perf && cai->perf_name && add_cstate_perf_counter(cpu, cci, cai) != -1) {
|
if (add_cstate_perf_counter(cpu, cci, cai) != -1) {
|
||||||
|
|
||||||
cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;
|
cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;
|
||||||
|
|
||||||
/* User MSR for this counter */
|
/* User MSR for this counter */
|
||||||
} else if (!no_msr && cai->msr && pkg_cstate_limit >= cai->pkg_cstate_limit
|
} else if (pkg_cstate_limit >= cai->pkg_cstate_limit
|
||||||
&& probe_rapl_msr(cpu, cai->msr, cai->rci_index) == 0) {
|
&& add_msr_counter(cpu, cai->msr) >= 0) {
|
||||||
cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;
|
cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;
|
||||||
cci->msr[cai->rci_index] = cai->msr;
|
cci->msr[cai->rci_index] = cai->msr;
|
||||||
}
|
}
|
||||||
|
@ -9044,15 +9299,14 @@ int added_perf_counters_init_(struct perf_counter_info *pinfo)
|
||||||
perf_device = "cpu_atom";
|
perf_device = "cpu_atom";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* Don't change, we will probably fail and report a problem soon. */
|
default: /* Don't change, we will probably fail and report a problem soon. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
perf_type = read_perf_type(perf_device);
|
perf_type = read_perf_type(perf_device);
|
||||||
if (perf_type == (unsigned int)-1) {
|
if (perf_type == (unsigned int)-1) {
|
||||||
warnx("%s: perf/%s/%s: failed to read %s",
|
warnx("%s: perf/%s/%s: failed to read %s", __func__, perf_device, pinfo->event, "type");
|
||||||
__func__, perf_device, pinfo->event, "type");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9154,7 +9408,7 @@ struct pmt_mmio *pmt_mmio_open(unsigned int target_guid)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( ; entry != NULL; entry = pmt_diriter_next(&pmt_iter)) {
|
for (; entry != NULL; entry = pmt_diriter_next(&pmt_iter)) {
|
||||||
if (fstatat(dirfd(pmt_iter.dir), entry->d_name, &st, 0) == -1)
|
if (fstatat(dirfd(pmt_iter.dir), entry->d_name, &st, 0) == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -9594,7 +9848,7 @@ int get_and_dump_counters(void)
|
||||||
|
|
||||||
void print_version()
|
void print_version()
|
||||||
{
|
{
|
||||||
fprintf(outf, "turbostat version 2025.04.06 - Len Brown <lenb@kernel.org>\n");
|
fprintf(outf, "turbostat version 2025.06.08 - Len Brown <lenb@kernel.org>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMMAND_LINE_SIZE 2048
|
#define COMMAND_LINE_SIZE 2048
|
||||||
|
@ -10050,7 +10304,7 @@ void parse_add_command_pmt(char *add_command)
|
||||||
unsigned int lsb;
|
unsigned int lsb;
|
||||||
unsigned int msb;
|
unsigned int msb;
|
||||||
unsigned int guid;
|
unsigned int guid;
|
||||||
unsigned int seq = 0; /* By default, pick first file in a sequence with a given GUID. */
|
unsigned int seq = 0; /* By default, pick first file in a sequence with a given GUID. */
|
||||||
unsigned int domain_id;
|
unsigned int domain_id;
|
||||||
enum counter_scope scope = 0;
|
enum counter_scope scope = 0;
|
||||||
enum pmt_datatype type = PMT_TYPE_RAW;
|
enum pmt_datatype type = PMT_TYPE_RAW;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user