diff options
| author | Mark Brown <broonie@kernel.org> | 2026-10-10 01:31:05 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-10-10 01:31:05 +0100 |
| commit | fa85755aa8188ae855161fa5ba5e39916ef69ddf (patch) | |
| tree | 3b613287a96f578e9aa99eab6c73798cb74967aa | |
| parent | d5d00ad3d23c56a178b5ea5fe4217cb2c4d8f872 (diff) | |
| parent | f31adc690d6834db65d8683b6b835497606f5e6c (diff) | |
| download | linux-next-fa85755aa8188ae855161fa5ba5e39916ef69ddf.tar.gz linux-next-fa85755aa8188ae855161fa5ba5e39916ef69ddf.zip | |
Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git
| -rw-r--r-- | MAINTAINERS | 9 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.8 | 6 | ||||
| -rw-r--r-- | tools/power/x86/turbostat/turbostat.c | 753 | ||||
| -rw-r--r-- | tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c | 192 |
4 files changed, 542 insertions, 418 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 12f2b780f8fc..aeb967828d84 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -30109,6 +30109,15 @@ M: Borislav Petkov <bp@alien8.de> S: Maintained F: arch/x86/kernel/cpu/microcode/* +X86_ENERGY_PERF_POLICY UTILITY +M: "Len Brown" <lenb@kernel.org> +L: linux-pm@vger.kernel.org +S: Supported +Q: https://patchwork.kernel.org/project/linux-pm/list/ +B: https://bugzilla.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git x86_energy_perf_policy +F: tools/power/x86/x86_energy_perf_policy/ + X86 MM M: Dave Hansen <dave.hansen@linux.intel.com> M: Andy Lutomirski <luto@kernel.org> diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 344ede2f8546..c905198d0501 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -92,7 +92,7 @@ name as necessary to disambiguate it from others is necessary. Note that option '%x' hex identifier of the PMT MMIO region. .fi .PP -\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44 +\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44 Multiple invocations of --cpu are OR'd together. .PP \fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. .PP @@ -269,7 +269,7 @@ Periodic output goes to stdout, by default, unless --out is used to specify an o The 5-second interval can be changed with the "-i sec" option. .nf sudo turbostat --quiet --show CPU,frequency - Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMhz + Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMHz - - 524 12.48 4198 3096 74.53 3800 0 0 4 0.09 4081 3096 98.88 3800 0 4 1 0.02 4063 3096 @@ -279,7 +279,7 @@ sudo turbostat --quiet --show CPU,frequency 2 6 3 0.08 4159 3096 3 3 1 0.04 4046 3096 99.66 3 7 0 0.01 3989 3096 - Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMhz + Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMHz - - 525 12.52 4198 3096 74.54 3800 0 0 4 0.10 4051 3096 99.49 3800 0 4 2 0.04 3993 3096 diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 920694c3c1ec..ac06aef531d1 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -98,6 +98,8 @@ #define ROUND_UP_TO_PAGE_SIZE(n) (((n) + 0x1000UL-1UL) & ~(0x1000UL-1UL)) +FILE *outf; + enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M }; enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT, FORMAT_AVERAGE }; @@ -138,8 +140,6 @@ struct msr_counter { enum counter_format format; struct msr_counter *next; unsigned int flags; -#define FLAGS_HIDE (1 << 0) -#define FLAGS_SHOW (1 << 1) #define SYSFS_PERCPU (1 << 1) }; static int use_android_msr_path; @@ -292,33 +292,53 @@ enum bic_names { MAX_BIC }; -void print_bic_set(char *s, cpu_set_t *set) +typedef cpu_set_t bic_set_t; /* implement bic_set_t using cpu_set_t */ + +/* + * debug helper + */ +static void print_bic_set(const char *s, const bic_set_t *set) { int i; assert(MAX_BIC < CPU_SETSIZE); - printf("%s:", s); + fprintf(outf, "%s:", s); for (i = 0; i < MAX_BIC; ++i) { if (CPU_ISSET(i, set)) - printf(" %s", bic[i].name); + fprintf(outf, " %s", bic[i].name); } - putchar('\n'); + fputc('\n', outf); } -static cpu_set_t bic_group_topology; -static cpu_set_t bic_group_thermal_pwr; -static cpu_set_t bic_group_frequency; -static cpu_set_t bic_group_hw_idle; -static cpu_set_t bic_group_sw_idle; -static cpu_set_t bic_group_idle; -static cpu_set_t bic_group_cache; -static cpu_set_t bic_group_other; -static cpu_set_t bic_group_disabled_by_default; -static cpu_set_t bic_enabled; -static cpu_set_t bic_present; +static bic_set_t bic_group_topology; +static bic_set_t bic_group_thermal_pwr; +static bic_set_t bic_group_frequency; +static bic_set_t bic_group_hw_idle; +static bic_set_t bic_group_sw_idle; +static bic_set_t bic_group_idle; +static bic_set_t bic_group_cache; +static bic_set_t bic_group_other; +static bic_set_t bic_group_disabled_by_default; +static bic_set_t bic_enabled; +static bic_set_t bic_present; + +static void dump_bic_sets(void) +{ + print_bic_set("bic_enabled", &bic_enabled); + print_bic_set("bic_present", &bic_present); + print_bic_set("bic_group_topology", &bic_group_topology); + print_bic_set("bic_group_thermal_pwr", &bic_group_thermal_pwr); + print_bic_set("bic_group_frequency", &bic_group_frequency); + print_bic_set("bic_group_hw_idle", &bic_group_hw_idle); + print_bic_set("bic_group_sw_idle", &bic_group_sw_idle); + print_bic_set("bic_group_idle", &bic_group_idle); + print_bic_set("bic_group_cache", &bic_group_cache); + print_bic_set("bic_group_other", &bic_group_other); + print_bic_set("bic_group_disabled_by_default", &bic_group_disabled_by_default); +} /* modify */ #define BIC_INIT(set) CPU_ZERO(set) @@ -334,7 +354,7 @@ static cpu_set_t bic_present; #define DO_BIC_READ(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_present) #define DO_BIC(COUNTER_NUMBER) (CPU_ISSET(COUNTER_NUMBER, &bic_enabled) && CPU_ISSET(COUNTER_NUMBER, &bic_present)) -static void bic_set_all(cpu_set_t *set) +static void bic_set_all(bic_set_t *set) { int i; @@ -348,7 +368,7 @@ static void bic_set_all(cpu_set_t *set) * bic_clear_bits() * clear all the bits from "clr" in "dst" */ -static void bic_clear_bits(cpu_set_t *dst, cpu_set_t *clr) +static void bic_clear_bits(bic_set_t *dst, bic_set_t *clr) { int i; @@ -485,7 +505,6 @@ static void bic_groups_init(void) #define PCLUNL 15 /* Unlimited */ char *proc_stat = "/proc/stat"; -FILE *outf; int *fd_percpu; int *fd_instr_count_percpu; int *fd_llc_percpu; @@ -504,7 +523,7 @@ unsigned int valid_rapl_msrs; unsigned int summary_only; unsigned int list_header_only; unsigned int dump_only; -unsigned int force_load; +bool force_load; unsigned int cpuid_has_aperf_mperf; unsigned int cpuid_has_hv; unsigned int has_aperf_access; @@ -570,9 +589,9 @@ struct gfx_sysfs_info { static struct gfx_sysfs_info gfx_info[GFX_MAX]; -int get_msr(int cpu, off_t offset, unsigned long long *msr); -int add_counter(unsigned int msr_num, char *path, char *name, - unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int package_num); +void get_msr(int cpu, off_t offset, unsigned long long *msr); +int add_counter(unsigned int msr_num, const char *path, const char *name, + unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int id); /* Model specific support Start */ @@ -629,8 +648,7 @@ double slm_bclk(void) unsigned int i; double freq; - if (get_msr(master_cpu, MSR_FSB_FREQ, &msr)) - fprintf(outf, "SLM BCLK: unknown\n"); + get_msr(master_cpu, MSR_FSB_FREQ, &msr); i = msr & 0xf; if (i >= SLM_BCLK_FREQS) { @@ -640,7 +658,7 @@ double slm_bclk(void) freq = slm_freq_table[i]; if (!quiet) - fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); + fprintf(outf, "SLM BCLK: %.1f MHz\n", freq); return freq; } @@ -1229,6 +1247,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_ARROWLAKE, &adl_features }, { INTEL_LUNARLAKE_M, &lnl_features }, { INTEL_PANTHERLAKE_L, &lnl_features }, + { INTEL_PANTHERLAKE_R, &lnl_features }, { INTEL_NOVALAKE, &lnl_features }, { INTEL_NOVALAKE_L, &lnl_features }, { INTEL_WILDCATLAKE_L, &lnl_features }, @@ -1313,7 +1332,6 @@ static struct perf_model_support turbostat_perf_model_support[] = { { INTEL_ATOM_DARKMONT_X, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {}, {} }, /* CWF */ { INTEL_ALDERLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} }, - { INTEL_ALDERLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} }, { INTEL_ALDERLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} }, { INTEL_RAPTORLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} }, { INTEL_RAPTORLAKE_P, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} }, @@ -1327,6 +1345,7 @@ static struct perf_model_support turbostat_perf_model_support[] = { { INTEL_ARROWLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x00, 0x07), PCE(0x00, 0x02)}, {} }, { INTEL_PANTHERLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} }, + { INTEL_PANTHERLAKE_R, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} }, { INTEL_WILDCATLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} }, { INTEL_NOVALAKE, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} }, @@ -1343,7 +1362,7 @@ void probe_platform_features(unsigned int family, unsigned int model) if (authentic_amd || hygon_genuine) { /* fallback to default features on unsupported models */ - force_load++; + force_load = true; if (max_extended_level >= 0x80000007) { unsigned int eax, ebx, ecx, edx; @@ -1366,7 +1385,7 @@ void probe_platform_features(unsigned int family, unsigned int model) } end: - if (force_load && !platform) { + if ((force_load == true) && !platform) { fprintf(outf, "Forced to run on unsupported platform!\n"); platform = &default_features; } @@ -1407,10 +1426,9 @@ void init_perf_model_support(unsigned int family, unsigned int model) int backwards_count; char *progname; -#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, *cpuset_cmdline; cpu_set_t *perf_pcore_set, *perf_ecore_set, *perf_lcore_set; -size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size; +size_t cpu_setsize; #define MAX_ADDED_THREAD_COUNTERS 24 #define MAX_ADDED_CORE_COUNTERS 8 #define MAX_ADDED_PACKAGE_COUNTERS 16 @@ -1995,15 +2013,17 @@ int pmt_telemdir_filter(const struct dirent *e) { unsigned int dummy; - return sscanf(e->d_name, "telem%u", &dummy); + return (sscanf(e->d_name, "telem%u", &dummy) == 1); } int pmt_telemdir_sort(const struct dirent **a, const struct dirent **b) { unsigned int aidx = 0, bidx = 0; - sscanf((*a)->d_name, "telem%u", &aidx); - sscanf((*b)->d_name, "telem%u", &bidx); + if (sscanf((*a)->d_name, "telem%u", &aidx) != 1) + aidx = 0; + if (sscanf((*b)->d_name, "telem%u", &bidx) != 1) + bidx = 0; return (aidx > bidx) ? 1 : (aidx < bidx) ? -1 : 0; } @@ -2034,8 +2054,11 @@ const struct dirent *pmt_diriter_begin(struct pmt_diriter_t *iter, const char *p return NULL; num_names = scandir(pmt_root_path, &iter->namelist, pmt_telemdir_filter, pmt_telemdir_sort); - if (num_names == -1) + if (num_names == -1) { + closedir(iter->dir); + iter->dir = NULL; return NULL; + } } iter->current_name_idx = 0; @@ -2063,8 +2086,10 @@ void pmt_diriter_remove(struct pmt_diriter_t *iter) iter->num_names = 0; iter->current_name_idx = 0; - closedir(iter->dir); - iter->dir = NULL; + if (iter->dir) { + closedir(iter->dir); + iter->dir = NULL; + } } unsigned int pmt_counter_get_width(const struct pmt_counter *p) @@ -2436,7 +2461,7 @@ int cpu_is_not_present(int cpu) if (cpu < 0) return 1; - return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set); + return !CPU_ISSET_S(cpu, cpu_setsize, cpu_present_set); } int cpu_is_not_allowed(int cpu) @@ -2444,7 +2469,7 @@ int cpu_is_not_allowed(int cpu) if (cpu < 0) return 1; - return !CPU_ISSET_S(cpu, cpu_allowed_setsize, cpu_allowed_set); + return !CPU_ISSET_S(cpu, cpu_setsize, cpu_allowed_set); } #define GLOBAL_CORE_ID(core_id, pkg_id) (core_id + pkg_id * (topo.max_core_id + 1)) @@ -2537,9 +2562,9 @@ int is_cpu_first_thread_in_package(struct thread_data *t, struct core_data *c, s int cpu_migrate(int cpu) { - CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); - CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set); - if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) + CPU_ZERO_S(cpu_setsize, cpu_affinity_set); + CPU_SET_S(cpu, cpu_setsize, cpu_affinity_set); + if (sched_setaffinity(0, cpu_setsize, cpu_affinity_set) == -1) return -1; else return 0; @@ -2625,18 +2650,12 @@ int get_instr_count_fd(int cpu) return fd_instr_count_percpu[cpu]; } -int get_msr(int cpu, off_t offset, unsigned long long *msr) +void get_msr(int cpu, off_t offset, unsigned long long *msr) { - ssize_t retval; - assert(!no_msr); - retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); - - if (retval != sizeof *msr) + if (pread(get_msr_fd(cpu), msr, sizeof(*msr), offset) != sizeof(*msr)) err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset); - - return 0; } int add_msr_counter(int cpu, off_t offset) @@ -2780,7 +2799,7 @@ void help(void) * for all the strings in comma separate name_list, * set the approprate bit in return value. */ -void bic_lookup(cpu_set_t *ret_set, char *name_list, enum show_hide_mode mode) +void bic_lookup(bic_set_t *ret_set, char *name_list, enum show_hide_mode mode) { unsigned int i; @@ -3280,8 +3299,6 @@ int dump_counters(PER_THREAD_PARAMS) double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desired_unit, double interval) { - assert(desired_unit != RAPL_UNIT_INVALID); - /* * For now we don't expect anything other than joules, * so just simplify the logic. @@ -3367,7 +3384,7 @@ int format_counters(PER_THREAD_PARAMS) return 0; /*if not summary line and --cpu is used */ - if ((t != average.threads) && (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset))) + if ((t != average.threads) && (cpuset_cmdline && !CPU_ISSET_S(t->cpu_id, cpu_setsize, cpuset_cmdline))) return 0; if (DO_BIC(BIC_USEC)) { @@ -3636,7 +3653,7 @@ int format_counters(PER_THREAD_PARAMS) if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */ outp += sprintf(outp, "%s**.**", (printed++ ? delim : "")); } else { - outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->gfx_rc6_ms / 10.0 / interval_float); + outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->gfx_rc6_ms / 10.0, interval_float)); } } @@ -3653,7 +3670,7 @@ int format_counters(PER_THREAD_PARAMS) if (p->sam_mc6_ms == -1) { /* detect GFX counter reset */ outp += sprintf(outp, "%s**.**", (printed++ ? delim : "")); } else { - outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->sam_mc6_ms / 10.0 / interval_float); + outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->sam_mc6_ms / 10.0, interval_float)); } } @@ -4532,8 +4549,7 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp, char * { if (mp->msr_num != 0) { assert(!no_msr); - if (get_msr(cpu, mp->msr_num, counterp)) - return -1; + get_msr(cpu, mp->msr_num, counterp); } else { char path[128 + PATH_BYTES]; @@ -4897,13 +4913,10 @@ int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct fprintf(stderr, "Reading rapl counter via msr at %u\n", i); assert(!no_msr); - if (rci->flags[i] & RAPL_COUNTER_FLAG_USE_MSR_SUM) { - if (get_msr_sum(cpu, rci->msr[i], &rci->data[i])) - return -13 - i; - } else { - if (get_msr(cpu, rci->msr[i], &rci->data[i])) - return -13 - i; - } + if (rci->flags[i] & RAPL_COUNTER_FLAG_USE_MSR_SUM) + get_msr_sum(cpu, rci->msr[i], &rci->data[i]); + else + get_msr(cpu, rci->msr[i], &rci->data[i]); rci->data[i] &= rci->msr_mask[i]; if (rci->msr_shift[i] >= 0) @@ -5032,8 +5045,7 @@ int get_cstate_counters(unsigned int cpu, PER_THREAD_PARAMS) case COUNTER_SOURCE_MSR: assert(!no_msr); - if (get_msr(cpu, cci->msr[i], &cci->data[i])) - return -13 - i; + get_msr(cpu, cci->msr[i], &cci->data[i]); if (debug >= 2) fprintf(stderr, "cstate via %s0x%llx %u: %llu\n", "msr", cci->msr[i], i, cci->data[i]); @@ -5131,8 +5143,7 @@ int get_smi_aperf_mperf(unsigned int cpu, struct thread_data *t) case COUNTER_SOURCE_MSR: assert(!no_msr); - if (get_msr(cpu, mci->msr[i], &mci->data[i])) - return -2 - i; + get_msr(cpu, mci->msr[i], &mci->data[i]); mci->data[i] &= mci->msr_mask[i]; @@ -5297,12 +5308,10 @@ int get_counters(PER_THREAD_PARAMS) } if (DO_BIC(BIC_Mod_c6)) - if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us)) - return -8; + get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us); if (DO_BIC(BIC_CoreTmp)) { - if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) - return -9; + get_msr(cpu, MSR_IA32_THERM_STATUS, &msr); c->core_temp_c = tj_max - ((msr >> 16) & 0x7F); } @@ -5324,22 +5333,14 @@ int get_counters(PER_THREAD_PARAMS) if (!is_cpu_first_core_in_package(t, p)) goto done; - if (DO_BIC(BIC_Totl_c0)) { - if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0)) - return -10; - } - if (DO_BIC(BIC_Any_c0)) { - if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0)) - return -11; - } - if (DO_BIC(BIC_GFX_c0)) { - if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0)) - return -12; - } - if (DO_BIC(BIC_CPUGFX)) { - if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0)) - return -13; - } + if (DO_BIC(BIC_Totl_c0)) + get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0); + if (DO_BIC(BIC_Any_c0)) + get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0); + if (DO_BIC(BIC_GFX_c0)) + get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0); + if (DO_BIC(BIC_CPUGFX)) + get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0); if (DO_BIC(BIC_CPU_LPI)) p->cpu_lpi = cpuidle_cur_cpu_lpi_us; @@ -5353,8 +5354,7 @@ int get_counters(PER_THREAD_PARAMS) } if (DO_BIC(BIC_PkgTmp)) { - if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) - return -17; + get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr); p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F); } @@ -5833,7 +5833,7 @@ void free_fd_percpu(void) if (!fd_percpu) return; - for (i = 0; i < topo.max_cpu_num + 1; ++i) { + for (i = 0; i <= topo.max_cpu_num; ++i) { if (fd_percpu[i] != 0) close(fd_percpu[i]); } @@ -5847,7 +5847,7 @@ void free_fd_instr_count_percpu(void) if (!fd_instr_count_percpu) return; - for (int i = 0; i < topo.max_cpu_num + 1; ++i) { + for (int i = 0; i <= topo.max_cpu_num; ++i) { if (fd_instr_count_percpu[i] != 0) close(fd_instr_count_percpu[i]); } @@ -5861,7 +5861,7 @@ void free_fd_llc_percpu(void) if (!fd_llc_percpu) return; - for (int i = 0; i < topo.max_cpu_num + 1; ++i) { + for (int i = 0; i <= topo.max_cpu_num; ++i) { if (fd_llc_percpu[i] != 0) close(fd_llc_percpu[i]); } @@ -5878,7 +5878,7 @@ void free_fd_l2_percpu(void) if (!fd_l2_percpu) return; - for (int i = 0; i < topo.max_cpu_num + 1; ++i) { + for (int i = 0; i <= topo.max_cpu_num; ++i) { if (fd_l2_percpu[i] != 0) close(fd_l2_percpu[i]); } @@ -5915,7 +5915,7 @@ void free_fd_msr(void) if (!msr_counter_info) return; - for (int cpu = 0; cpu < topo.max_cpu_num; ++cpu) { + for (int cpu = 0; cpu <= topo.max_cpu_num; ++cpu) { if (msr_counter_info[cpu].fd_perf != -1) close(msr_counter_info[cpu].fd_perf); } @@ -5978,19 +5978,15 @@ void free_all_buffers(void) CPU_FREE(cpu_present_set); cpu_present_set = NULL; - cpu_present_setsize = 0; CPU_FREE(cpu_effective_set); cpu_effective_set = NULL; - cpu_effective_setsize = 0; CPU_FREE(cpu_allowed_set); cpu_allowed_set = NULL; - cpu_allowed_setsize = 0; CPU_FREE(cpu_affinity_set); cpu_affinity_set = NULL; - cpu_affinity_setsize = 0; if (perf_pcore_set) { CPU_FREE(perf_pcore_set); @@ -6165,7 +6161,7 @@ int get_physical_node_id(struct cpu_topology *thiscpu) static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size) { - unsigned int start, end; + int start, end; char *next = cpu_str; while (next && *next) { @@ -6178,7 +6174,7 @@ static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size) start = strtoul(next, &next, 10); - if (start >= CPU_SUBSET_MAXCPUS) + if (start > topo.max_cpu_num) return 1; CPU_SET_S(start, cpu_set_size, cpu_set); @@ -6205,7 +6201,7 @@ static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size) return 1; while (++start <= end) { - if (start >= CPU_SUBSET_MAXCPUS) + if (start > topo.max_cpu_num) return 1; CPU_SET_S(start, cpu_set_size, cpu_set); } @@ -6311,33 +6307,35 @@ int for_all_proc_cpus(int (func) (int)) #define PATH_EFFECTIVE_CPUS "/sys/fs/cgroup/cpuset.cpus.effective" -static char cpu_effective_str[1024]; +static char *cpu_effective_str; static int update_effective_str(bool startup) { FILE *fp; - char *pos; - char buf[1024]; + char *buf = NULL; + size_t size = 0; int ret; - if (cpu_effective_str[0] == '\0' && !startup) + if (!cpu_effective_str && !startup) return 0; fp = fopen(PATH_EFFECTIVE_CPUS, "r"); if (!fp) return 0; - pos = fgets(buf, 1024, fp); - if (!pos) + if (getline(&buf, &size, fp) < 0) err(1, "%s: file read failed", PATH_EFFECTIVE_CPUS); fclose(fp); - ret = strncmp(cpu_effective_str, buf, 1024); - if (!ret) + ret = cpu_effective_str ? strcmp(cpu_effective_str, buf) : 1; + if (!ret) { + free(buf); return 0; + } - strncpy(cpu_effective_str, buf, 1024); + free(cpu_effective_str); + cpu_effective_str = buf; return 1; } @@ -6345,7 +6343,7 @@ static void update_effective_set(bool startup) { update_effective_str(startup); - if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_effective_setsize)) + if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_setsize)) err(1, "%s: cpu str malformat %s", PATH_EFFECTIVE_CPUS, cpu_effective_str); } @@ -6373,26 +6371,6 @@ void re_initialize(void) fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); } -void set_max_cpu_num(void) -{ - FILE *filep; - int current_cpu; - unsigned long dummy; - char pathname[64]; - - current_cpu = sched_getcpu(); - if (current_cpu < 0) - err(1, "cannot find calling cpu ID"); - sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", current_cpu); - - filep = fopen_or_die(pathname, "r"); - topo.max_cpu_num = 0; - while (fscanf(filep, "%lx,", &dummy) == 1) - topo.max_cpu_num += BITMASK_SIZE; - fclose(filep); - topo.max_cpu_num--; /* 0 based */ -} - /* * count_cpus() * remember the last one seen, it will be the max @@ -6407,7 +6385,7 @@ int count_cpus(int cpu) int mark_cpu_present(int cpu) { - CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set); + CPU_SET_S(cpu, cpu_setsize, cpu_present_set); return 0; } @@ -6710,7 +6688,7 @@ void do_sleep(void) int get_msr_sum(int cpu, off_t offset, unsigned long long *msr) { - int ret, idx; + int idx; unsigned long long msr_cur, msr_last; assert(!no_msr); @@ -6722,9 +6700,7 @@ int get_msr_sum(int cpu, off_t offset, unsigned long long *msr) if (idx < 0) return idx; /* get_msr_sum() = sum + (get_msr() - last) */ - ret = get_msr(cpu, offset, &msr_cur); - if (ret) - return ret; + get_msr(cpu, offset, &msr_cur); msr_last = per_cpu_msr_sum[cpu].entries[idx].last; DELTA_WRAP32(msr_cur, msr_last); *msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum; @@ -6737,7 +6713,7 @@ timer_t timerid; /* Timer callback, update the sum of MSRs periodically. */ static int update_msr_sum(PER_THREAD_PARAMS) { - int i, ret; + int i; int cpu = t->cpu_id; UNUSED(c); @@ -6754,11 +6730,7 @@ static int update_msr_sum(PER_THREAD_PARAMS) offset = idx_to_offset(i); if (offset < 0) continue; - ret = get_msr(cpu, offset, &msr_cur); - if (ret) { - fprintf(outf, "Can not update msr(0x%llx)\n", (unsigned long long)offset); - continue; - } + get_msr(cpu, offset, &msr_cur); msr_last = per_cpu_msr_sum[cpu].entries[i].last; per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff; @@ -7568,27 +7540,21 @@ int print_hwp(PER_THREAD_PARAMS) return -1; } - if (get_msr(cpu, MSR_PM_ENABLE, &msr)) - return 0; - + get_msr(cpu, MSR_PM_ENABLE, &msr); fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", cpu, msr, (msr & (1 << 0)) ? "" : "No-"); /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */ if ((msr & (1 << 0)) == 0) return 0; - if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr)) - return 0; - + get_msr(cpu, MSR_HWP_CAPABILITIES, &msr); fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx " "(high %d guar %d eff %d low %d)\n", cpu, msr, (unsigned int)HWP_HIGHEST_PERF(msr), (unsigned int)HWP_GUARANTEED_PERF(msr), (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), (unsigned int)HWP_LOWEST_PERF(msr)); - if (get_msr(cpu, MSR_HWP_REQUEST, &msr)) - return 0; - + get_msr(cpu, MSR_HWP_REQUEST, &msr); fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx " "(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n", cpu, msr, @@ -7598,9 +7564,7 @@ int print_hwp(PER_THREAD_PARAMS) (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3), (unsigned int)(((msr) >> 42) & 0x1)); if (has_hwp_pkg) { - if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr)) - return 0; - + get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr); fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx " "(min %d max %d des %d epp 0x%x window 0x%x)\n", cpu, msr, @@ -7609,15 +7573,11 @@ int print_hwp(PER_THREAD_PARAMS) (unsigned int)(((msr) >> 16) & 0xff), (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3)); } if (has_hwp_notify) { - if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr)) - return 0; - + get_msr(cpu, MSR_HWP_INTERRUPT, &msr); fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx " "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n", cpu, msr, ((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x2) ? "EN" : "Dis"); } - if (get_msr(cpu, MSR_HWP_STATUS, &msr)) - return 0; - + get_msr(cpu, MSR_HWP_STATUS, &msr); fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx " "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-"); @@ -7730,9 +7690,10 @@ double get_tdp_intel(void) { unsigned long long msr; - if (valid_rapl_msrs & RAPL_PKG_POWER_INFO) - if (!get_msr(master_cpu, MSR_PKG_POWER_INFO, &msr)) - return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; + if (valid_rapl_msrs & RAPL_PKG_POWER_INFO) { + get_msr(master_cpu, MSR_PKG_POWER_INFO, &msr); + return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; + } return get_quirk_tdp(); } @@ -7770,8 +7731,7 @@ void rapl_probe_intel(void) CLR_BIC(BIC_RAM__, &bic_enabled); /* units on package 0, verify later other packages match */ - if (get_msr(master_cpu, MSR_RAPL_POWER_UNIT, &msr)) - return; + get_msr(master_cpu, MSR_RAPL_POWER_UNIT, &msr); rapl_power_units = 1.0 / (1 << (msr & 0xF)); if (platform->has_rapl_divisor) @@ -7818,9 +7778,7 @@ void rapl_probe_amd(void) if (!valid_rapl_msrs || no_msr) return; - if (get_msr(master_cpu, MSR_RAPL_PWR_UNIT, &msr)) - return; - + get_msr(master_cpu, MSR_RAPL_PWR_UNIT, &msr); rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf)); rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f)); rapl_power_units = ldexp(1.0, -(msr & 0xf)); @@ -7976,7 +7934,7 @@ static int print_rapl_sysfs(void) snprintf(path, PATH_MAX, "%s/%s", PATH_RAPL_SYSFS, entry->d_name); if ((cdir = opendir(path)) == NULL) { - perror("opendir() error"); + warn("%s", path); return 1; } @@ -8019,21 +7977,17 @@ int print_rapl(PER_THREAD_PARAMS) if (valid_rapl_msrs & RAPL_AMD_F17H) { msr_name = "MSR_RAPL_PWR_UNIT"; - if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr)) - return -1; + get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr); } else { msr_name = "MSR_RAPL_POWER_UNIT"; - if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) - return -1; + get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr); } fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr, rapl_power_units, rapl_energy_units, rapl_time_units); if (valid_rapl_msrs & RAPL_PKG_POWER_INFO) { - if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) - return -5; - + get_msr(cpu, MSR_PKG_POWER_INFO, &msr); fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", cpu, msr, ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, @@ -8043,9 +7997,7 @@ int print_rapl(PER_THREAD_PARAMS) } if (valid_rapl_msrs & RAPL_PKG) { - if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) - return -9; - + get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr); fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 63) & 1 ? "" : "UN"); print_power_limit_msr(cpu, msr, "PKG Limit #1"); @@ -8055,17 +8007,13 @@ int print_rapl(PER_THREAD_PARAMS) ((msr >> 32) & 0x7FFF) * rapl_power_units, (1.0 + (((msr >> 54) & 0x3) / 4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units, ((msr >> 48) & 1) ? "EN" : "DIS"); - if (get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr)) - return -9; - + get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr); fprintf(outf, "cpu%d: MSR_VR_CURRENT_CONFIG: 0x%08llx\n", cpu, msr); fprintf(outf, "cpu%d: PKG Limit #4: %f Watts (%slocked)\n", cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN"); } if (valid_rapl_msrs & RAPL_DRAM_POWER_INFO) { - if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) - return -6; - + get_msr(cpu, MSR_DRAM_POWER_INFO, &msr); fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", cpu, msr, ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, @@ -8073,32 +8021,25 @@ int print_rapl(PER_THREAD_PARAMS) ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); } if (valid_rapl_msrs & RAPL_DRAM) { - if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) - return -9; + get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr); fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); print_power_limit_msr(cpu, msr, "DRAM Limit"); } if (valid_rapl_msrs & RAPL_CORE_POLICY) { - if (get_msr(cpu, MSR_PP0_POLICY, &msr)) - return -7; - + get_msr(cpu, MSR_PP0_POLICY, &msr); fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); } if (valid_rapl_msrs & RAPL_CORE_POWER_LIMIT) { - if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) - return -9; + get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr); fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); print_power_limit_msr(cpu, msr, "Cores Limit"); } if (valid_rapl_msrs & RAPL_GFX) { - if (get_msr(cpu, MSR_PP1_POLICY, &msr)) - return -8; - + get_msr(cpu, MSR_PP1_POLICY, &msr); fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF); - if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr)) - return -9; + get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr); fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); print_power_limit_msr(cpu, msr, "GFX Limit"); } @@ -8113,7 +8054,6 @@ int print_rapl(PER_THREAD_PARAMS) */ void probe_rapl_msrs(void) { - int ret; off_t offset; unsigned long long msr_value; @@ -8127,12 +8067,7 @@ void probe_rapl_msrs(void) if (offset < 0) return; - ret = get_msr(master_cpu, offset, &msr_value); - if (ret) { - if (debug) - fprintf(outf, "Can not read RAPL_PKG_ENERGY MSR(0x%llx)\n", (unsigned long long)offset); - return; - } + get_msr(master_cpu, offset, &msr_value); if (msr_value == 0) { if (debug) fprintf(outf, "RAPL_PKG_ENERGY MSR(0x%llx) == ZERO: disabling all RAPL MSRs\n", (unsigned long long)offset); @@ -8212,17 +8147,17 @@ int set_temperature_target(PER_THREAD_PARAMS) if (!platform->has_nhm_msrs || no_msr) goto guess; - if (get_msr(master_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr)) - goto guess; - + get_msr(master_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr); tcc_default = (msr >> 16) & 0xFF; if (!quiet) { int bits = platform->tcc_offset_bits; unsigned long long enabled = 0; - if (bits && !get_msr(master_cpu, MSR_PLATFORM_INFO, &enabled)) + if (bits) { + get_msr(master_cpu, MSR_PLATFORM_INFO, &enabled); enabled = (enabled >> 30) & 1; + } if (bits && enabled) { tcc_offset = (msr >> 24) & GENMASK(bits - 1, 0); @@ -8274,15 +8209,11 @@ int print_thermal(PER_THREAD_PARAMS) } if (do_ptm && is_cpu_first_core_in_package(t, p)) { - if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) - return 0; - + get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr); dts = (msr >> 16) & 0x7F; fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts); - if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr)) - return 0; - + get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr); dts = (msr >> 16) & 0x7F; dts2 = (msr >> 8) & 0x7F; fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", cpu, msr, tj_max - dts, tj_max - dts2); @@ -8291,16 +8222,12 @@ int print_thermal(PER_THREAD_PARAMS) if (do_dts && debug) { unsigned int resolution; - if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) - return 0; - + get_msr(cpu, MSR_IA32_THERM_STATUS, &msr); dts = (msr >> 16) & 0x7F; resolution = (msr >> 27) & 0xF; fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", cpu, msr, tj_max - dts, resolution); - if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr)) - return 0; - + get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr); dts = (msr >> 16) & 0x7F; dts2 = (msr >> 8) & 0x7F; fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", cpu, msr, tj_max - dts, tj_max - dts2); @@ -8356,12 +8283,9 @@ void decode_feature_control_msr(void) if (no_msr) return; - if (quiet) - return; - - if (!get_msr(master_cpu, MSR_IA32_FEAT_CTL, &msr)) - fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n", - master_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : ""); + get_msr(master_cpu, MSR_IA32_FEAT_CTL, &msr); + fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n", + master_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : ""); } void decode_misc_enable_msr(void) @@ -8374,13 +8298,13 @@ void decode_misc_enable_msr(void) if (!genuine_intel) return; - if (!get_msr(master_cpu, MSR_IA32_MISC_ENABLE, &msr)) - fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n", - master_cpu, msr, - msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-", - msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-", - msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-", - msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "", msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : ""); + get_msr(master_cpu, MSR_IA32_MISC_ENABLE, &msr); + fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n", + master_cpu, msr, + msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-", + msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-", + msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-", + msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "", msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : ""); } void decode_misc_feature_control(void) @@ -8393,10 +8317,10 @@ void decode_misc_feature_control(void) if (!platform->has_msr_misc_feature_control) return; - if (!get_msr(master_cpu, MSR_MISC_FEATURE_CONTROL, &msr)) - fprintf(outf, - "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n", - master_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "", msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : ""); + get_msr(master_cpu, MSR_MISC_FEATURE_CONTROL, &msr); + fprintf(outf, + "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n", + master_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "", msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : ""); } /* @@ -8416,9 +8340,9 @@ void decode_misc_pwr_mgmt_msr(void) if (!platform->has_msr_misc_pwr_mgmt) return; - if (!get_msr(master_cpu, MSR_MISC_PWR_MGMT, &msr)) - fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n", - master_cpu, msr, msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS"); + get_msr(master_cpu, MSR_MISC_PWR_MGMT, &msr); + fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n", + master_cpu, msr, msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS"); } /* @@ -8437,11 +8361,11 @@ void decode_c6_demotion_policy_msr(void) if (!platform->has_msr_c6_demotion_policy_config) return; - if (!get_msr(master_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr)) - fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n", master_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); + get_msr(master_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr); + fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n", master_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); - if (!get_msr(master_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr)) - fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n", master_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); + get_msr(master_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr); + fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n", master_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); } void print_dev_latency(void) @@ -8529,13 +8453,16 @@ end: return ret; } -char cpuset_buf[1024]; -int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, char *sysfs_path, char *sysfs_file) +int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, const char *sysfs_path, + const char *sysfs_file) { FILE *fp; + char *cpuset_buf = NULL; + size_t size = 0; char path[128]; + int ret = -1; - if (snprintf(path, 128, "%s/%s", sysfs_path, sysfs_file) > 128) + if (snprintf(path, sizeof(path), "%s/%s", sysfs_path, sysfs_file) >= (int)sizeof(path)) err(-1, "%s %s", sysfs_path, sysfs_file); fp = fopen(path, "r"); @@ -8543,19 +8470,20 @@ int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, char *sysfs_path, char *sy warn("open %s", path); return -1; } - if (fread(cpuset_buf, sizeof(char), 1024, fp) == 0) { + if (getline(&cpuset_buf, &size, fp) < 0) { warn("read %s", sysfs_path); - goto err; + goto out; } - if (parse_cpu_str(cpuset_buf, cpu_set, cpu_possible_setsize)) { - warnx("%s: cpu str malformat %s\n", sysfs_path, cpu_effective_str); - goto err; + if (parse_cpu_str(cpuset_buf, cpu_set, cpu_setsize)) { + warnx("%s: cpu str malformat %s\n", sysfs_path, cpuset_buf); + goto out; } - return 0; + ret = 0; -err: +out: fclose(fp); - return -1; + free(cpuset_buf); + return ret; } void print_cpu_set(char *s, cpu_set_t *set) @@ -8583,7 +8511,7 @@ void linux_perf_init_hybrid_cpus(void) perf_pcore_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (perf_pcore_set == NULL) err(3, "CPU_ALLOC"); - CPU_ZERO_S(cpu_possible_setsize, perf_pcore_set); + CPU_ZERO_S(cpu_setsize, perf_pcore_set); initialize_cpu_set_from_sysfs(perf_pcore_set, perf_cpu_pcore_path, "cpus"); if (debug) print_cpu_set("perf pcores", perf_pcore_set); @@ -8595,7 +8523,7 @@ void linux_perf_init_hybrid_cpus(void) perf_ecore_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (perf_ecore_set == NULL) err(3, "CPU_ALLOC"); - CPU_ZERO_S(cpu_possible_setsize, perf_ecore_set); + CPU_ZERO_S(cpu_setsize, perf_ecore_set); initialize_cpu_set_from_sysfs(perf_ecore_set, perf_cpu_ecore_path, "cpus"); if (debug) print_cpu_set("perf ecores", perf_ecore_set); @@ -8607,7 +8535,7 @@ void linux_perf_init_hybrid_cpus(void) perf_lcore_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (perf_lcore_set == NULL) err(3, "CPU_ALLOC"); - CPU_ZERO_S(cpu_possible_setsize, perf_lcore_set); + CPU_ZERO_S(cpu_setsize, perf_lcore_set); initialize_cpu_set_from_sysfs(perf_lcore_set, perf_cpu_lcore_path, "cpus"); if (debug) print_cpu_set("perf lcores", perf_lcore_set); @@ -8655,6 +8583,8 @@ void rapl_perf_init(void) { const unsigned int num_domains = get_rapl_num_domains(); bool *domain_visited = calloc(num_domains, sizeof(bool)); + if (!domain_visited) + err(-1, "calloc domain_visited"); rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain)); if (rapl_counter_info_perdomain == NULL) @@ -8691,7 +8621,7 @@ void rapl_perf_init(void) 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; ++cpu) { if (cpu_is_not_allowed(cpu)) continue; @@ -9102,6 +9032,86 @@ void dump_cpuid_hypervisor(void) fprintf(outf, "\n"); } +void dump_rdt_m_leaf(int leaf) +{ + unsigned int eax, ebx, ecx, edx; + int cpu = sched_getcpu(); + + __cpuid_count(leaf, 0, eax, ebx, ecx, edx); + + fprintf(outf, "cpu%d: CPUID(0x%x).0: MAX_RMID:%d %sL3_MON\n", cpu, leaf, ebx, edx & 0x1 ? "" : "No-"); +} + +#define RDT_CAT_L3_INDEX 1 +#define RDT_CAT_L2_INDEX 2 +#define RDT_MBA_INDEX 3 +#define RDT_CBA_INDEX 5 +#define RDT_RP_INDEX 6 + +#ifndef MSR_IA32_RESOURCE_PRIORITY +#define MSR_IA32_RESOURCE_PRIORITY 0xc88 +#endif + +#ifndef MSR_IA32_RESOURCE_PRIORITY_PKG +#define MSR_IA32_RESOURCE_PRIORITY_PKG 0xc89 +#endif + +void dump_rdt_a_leaf(int leaf) +{ + unsigned int eax, ebx, ecx, edx; + int cpu = sched_getcpu(); + unsigned int has_cat_l3, has_cat_l2, has_mba, has_cba, has_rp; + + __cpuid_count(leaf, 0, eax, ebx, ecx, edx); + + has_cat_l3 = ebx & (1 << RDT_CAT_L3_INDEX); + has_cat_l2 = ebx & (1 << RDT_CAT_L2_INDEX); + has_mba = ebx & (1 << RDT_MBA_INDEX); + has_cba = ebx & (1 << RDT_CBA_INDEX); + has_rp = ebx & (1 << RDT_RP_INDEX); + + fprintf(outf, "cpu%d: CPUID(0x%x).0: %sCATL3, %sCATL2, %sMBA, %sCBA, %sRP\n", cpu, leaf, + has_cat_l3 ? "" : "No-", has_cat_l2 ? "" : "No-", has_mba ? "" : "No-", has_cba ? "" : "No-", has_rp ? "" : "No-"); + if (has_rp) { + unsigned int has_rp_thread, has_rp_package; + + __cpuid_count(leaf, RDT_RP_INDEX, eax, ebx, ecx, edx); + + has_rp_thread = eax & (1 << 0); + has_rp_package = eax & (1 << 1); + + fprintf(outf, "cpu%d: CPUID(0x%x).%d: %sRP_THREAD, %sRP_PKG", + cpu, leaf, RDT_RP_INDEX, has_rp_thread ? "" : "No-", has_rp_package ? "" : "No-"); + if (has_rp_thread) { + unsigned long long msr; + + get_msr(cpu, MSR_IA32_RESOURCE_PRIORITY, &msr); + fprintf(outf, " MSR_RP_THREAD_EN:%llu", msr); + } + if (has_rp_package) { + unsigned long long msr; + + get_msr(cpu, MSR_IA32_RESOURCE_PRIORITY_PKG, &msr); + fprintf(outf, " MSR_RP_PKG_EN:%llu", msr); + } + fprintf(outf, "\n"); + } +} + +int dump_ardt_m(int cpu) +{ + cpu_migrate(cpu); + dump_rdt_m_leaf(0x27); + return 0; +} + +int dump_ardt_a(int cpu) +{ + cpu_migrate(cpu); + dump_rdt_a_leaf(0x28); + return 0; +} + void process_cpuid() { unsigned int eax, ebx, ecx, edx; @@ -9136,13 +9146,10 @@ void process_cpuid() cpuid_has_hv = ecx_flags & (1 << 31); if (!no_msr) { - if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) { - warnx("get_msr(UCODE)"); - } else { - ucode_patch_valid = true; - if (!authentic_amd && !hygon_genuine) - ucode_patch >>= 32; - } + get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch); + ucode_patch_valid = true; + if (!authentic_amd && !hygon_genuine) + ucode_patch >>= 32; } /* @@ -9226,21 +9233,40 @@ void process_cpuid() decode_misc_enable_msr(); if (max_level >= 0x7) { - int has_sgx; + eax = ebx = ecx = edx = 0; + __cpuid_count(0x7, 0, eax, ebx, ecx, edx); - ecx = 0; + is_hybrid = !!(edx & (1 << 15)); - __cpuid_count(0x7, 0, eax, ebx, ecx, edx); + if (!quiet) { + int has_sgx, has_rdt_m, has_rdt_a, has_ardt_m, has_ardt_a; - has_sgx = ebx & (1 << 2); + has_sgx = ebx & (1 << 2); + has_rdt_m = ebx & (1 << 12); + has_rdt_a = ebx & (1 << 15); - is_hybrid = !!(edx & (1 << 15)); + eax = ebx = ecx = edx = 0; + __cpuid_count(0x7, 1, eax, ebx, ecx, edx); - if (!quiet) - fprintf(outf, "CPUID(7): %sSGX %sHybrid\n", has_sgx ? "" : "No-", is_hybrid ? "" : "No-"); + has_ardt_m = ecx & (1 << 0); + has_ardt_a = ecx & (1 << 1); + + fprintf(outf, "CPUID(7): %sSGX %sRDT_M %sRDT_A %sARDT_M %sARDT_A %sHybrid\n", + has_sgx ? "" : "No-", has_rdt_m ? "" : "No-", has_rdt_a ? "" : "No-", has_ardt_m ? "" : "No-", has_ardt_a ? "" : "No-", + is_hybrid ? "" : "No-"); + + if (has_sgx) + decode_feature_control_msr(); - if (has_sgx) - decode_feature_control_msr(); + if (has_rdt_m && max_level >= 0xF) + dump_rdt_m_leaf(0xF); + if (has_rdt_a && max_level >= 0x10) + dump_rdt_a_leaf(0x10); + if (has_ardt_m && max_level >= 0x27) + for_all_proc_cpus(dump_ardt_m); + if (has_ardt_a && max_level >= 0x28) + for_all_proc_cpus(dump_ardt_a); + } } if (max_level >= 0x15) { @@ -9432,7 +9458,7 @@ void perf_l2_init(void) } continue; } - if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_pcore_set)) { + if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_setsize, perf_pcore_set)) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs); @@ -9445,7 +9471,7 @@ void perf_l2_init(void) free_fd_l2_percpu(); return; } - } else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_ecore_set)) { + } else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_setsize, perf_ecore_set)) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.refs); @@ -9458,7 +9484,7 @@ void perf_l2_init(void) free_fd_l2_percpu(); return; } - } else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_lcore_set)) { + } else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_setsize, perf_lcore_set)) { fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.refs, -1, PERF_FORMAT_GROUP); if (fd_l2_percpu[cpu] == -1) { warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.refs); @@ -9471,8 +9497,10 @@ void perf_l2_init(void) free_fd_l2_percpu(); return; } - } else - err(-1, "%s: cpu%d: type %d", __func__, cpu, cpus[cpu].type); + } else { + warn("%s: cpu%d: type %d: Update kernel perf support or use \"--hide L2MRPS,L2%%hit\" or \"--hide cache\" or \"--no-perf\"", __func__, cpu, cpus[cpu].type); + return; + } } BIC_PRESENT(BIC_L2_MRPS); BIC_PRESENT(BIC_L2_HIT); @@ -9521,6 +9549,35 @@ int set_thread_siblings(struct cpu_topology *thiscpu) return (ht_id - 1); } +/* + * get_max_cpu_num(path) + * return the last number of the cpu list in this file + */ +static int get_max_cpu_num(char *path) +{ + FILE *filep; + int retval, num; + char c; + + filep = fopen(path, "r"); + if (filep == NULL) { + warn("%s", path); + return 255; + } + + while ((retval = fscanf(filep, "%d%c", &num, &c)) == 2) { + if (c == '\n') + break; + if (c != ',' && c != '-') + errx(1, "Bad Format '%s'", path); + } + if (retval != 2) + errx(1, "Bad format '%s'", path); + + fclose(filep); + return num; +} + void topology_probe(bool startup) { int i; @@ -9528,8 +9585,7 @@ void topology_probe(bool startup) int max_package_id = 0; int max_siblings = 0; - /* Initialize num_cpus, max_cpu_num */ - set_max_cpu_num(); + /* Initialize num_cpus */ topo.num_cpus = 0; for_all_proc_cpus(count_cpus); if (!summary_only) @@ -9548,8 +9604,7 @@ void topology_probe(bool startup) cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (cpu_present_set == NULL) err(3, "CPU_ALLOC"); - cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); - CPU_ZERO_S(cpu_present_setsize, cpu_present_set); + CPU_ZERO_S(cpu_setsize, cpu_present_set); for_all_proc_cpus(mark_cpu_present); if (debug) print_cpu_set("present set", cpu_present_set); @@ -9560,8 +9615,7 @@ void topology_probe(bool startup) cpu_possible_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (cpu_possible_set == NULL) err(3, "CPU_ALLOC"); - cpu_possible_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); - CPU_ZERO_S(cpu_possible_setsize, cpu_possible_set); + CPU_ZERO_S(cpu_setsize, cpu_possible_set); initialize_cpu_set_from_sysfs(cpu_possible_set, "/sys/devices/system/cpu", "possible"); if (debug) print_cpu_set("possible set", cpu_possible_set); @@ -9572,8 +9626,7 @@ void topology_probe(bool startup) cpu_effective_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (cpu_effective_set == NULL) err(3, "CPU_ALLOC"); - cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); - CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set); + CPU_ZERO_S(cpu_setsize, cpu_effective_set); update_effective_set(startup); if (debug) print_cpu_set("effective set", cpu_effective_set); @@ -9584,48 +9637,47 @@ void topology_probe(bool startup) cpu_allowed_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (cpu_allowed_set == NULL) err(3, "CPU_ALLOC"); - cpu_allowed_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); - CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set); + CPU_ZERO_S(cpu_setsize, cpu_allowed_set); /* * Validate and update cpu_allowed_set. * - * Make sure all cpus in cpu_subset are also in cpu_present_set during startup. - * Give a warning when cpus in cpu_subset become unavailable at runtime. + * Make sure all cpus in cpuset_cmdline are also in cpu_present_set during startup. + * Give a warning when cpus in cpuset_cmdline become unavailable at runtime. * Give a warning when cpus are not effective because of cgroup setting. * - * cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpu_subset. + * cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpuset_cmdline. */ - for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) { - if (cpu_subset && !CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) + for (i = 0; i <= topo.max_cpu_num; ++i) { + if (cpuset_cmdline && !CPU_ISSET_S(i, cpu_setsize, cpuset_cmdline)) continue; - if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) { - if (cpu_subset) { - /* cpus in cpu_subset must be in cpu_present_set during startup */ + if (!CPU_ISSET_S(i, cpu_setsize, cpu_present_set)) { + if (cpuset_cmdline) { + /* cpus in cpuset_cmdline must be in cpu_present_set during startup */ if (startup) - err(1, "cpu%d not present", i); + errx(1, "cpu%d not present", i); else fprintf(stderr, "cpu%d not present\n", i); } continue; } - if (CPU_COUNT_S(cpu_effective_setsize, cpu_effective_set)) { - if (!CPU_ISSET_S(i, cpu_effective_setsize, cpu_effective_set)) { + if (CPU_COUNT_S(cpu_setsize, cpu_effective_set)) { + if (!CPU_ISSET_S(i, cpu_setsize, cpu_effective_set)) { fprintf(stderr, "cpu%d not effective\n", i); continue; } } - CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); + CPU_SET_S(i, cpu_setsize, cpu_allowed_set); } if (debug) print_cpu_set("allowed set", cpu_allowed_set); - if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set)) - err(-ENODEV, "No valid cpus found"); - sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set); + if (!CPU_COUNT_S(cpu_setsize, cpu_allowed_set)) + errx(-ENODEV, "No valid cpus found"); + sched_setaffinity(0, cpu_setsize, cpu_allowed_set); /* * Allocate and initialize cpu_affinity_set @@ -9633,8 +9685,7 @@ void topology_probe(bool startup) cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1)); if (cpu_affinity_set == NULL) err(3, "CPU_ALLOC"); - cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); - CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); + CPU_ZERO_S(cpu_setsize, cpu_affinity_set); for_all_proc_cpus(clear_ht_id); @@ -9782,7 +9833,7 @@ void allocate_counters(struct counters *counters) if (counters->threads == NULL) goto error; - for (i = 0; i < topo.max_cpu_num + 1; i++) + for (i = 0; i <= topo.max_cpu_num; i++) (counters->threads)[i].cpu_id = -1; counters->cores = calloc(num_cores, sizeof(struct core_data)); @@ -9911,7 +9962,7 @@ void set_master_cpu(void) { int i; - for (i = 0; i < topo.max_cpu_num + 1; ++i) { + for (i = 0; i <= topo.max_cpu_num; ++i) { if (cpu_is_not_allowed(i)) continue; master_cpu = i; @@ -9999,6 +10050,8 @@ int added_perf_counters_init_(struct perf_counter_info *pinfo) const size_t max_num_domains = MAX(topo.max_cpu_num + 1, MAX(topo.max_core_id + 1, topo.max_package_id + 1)); domain_visited = calloc(max_num_domains, sizeof(*domain_visited)); + if (!domain_visited) + errx(1, "%s: alloc %s", __func__, "domain_visited"); while (pinfo) { switch (pinfo->scope) { @@ -10028,7 +10081,7 @@ int added_perf_counters_init_(struct perf_counter_info *pinfo) memset(domain_visited, 0, max_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; ++cpu) { next_domain = cpu_to_domain(pinfo, cpu); @@ -10390,6 +10443,8 @@ int pmt_add_counter(unsigned int guid, unsigned int seq, const char *name, enum pcounter = pmt_find_counter(*pmt_root, name); if (!pcounter) { pcounter = calloc(1, sizeof(*pcounter)); + if (!pcounter) + return 1; new_counter = true; } @@ -10439,7 +10494,7 @@ void pmt_init(void) mod_num = 0; /* Relative module number for current PMT file. */ /* Open the counter for each CPU. */ - for (cpu_num = 0; cpu_num < topo.max_cpu_num;) { + for (cpu_num = 0; cpu_num <= topo.max_cpu_num;) { if (cpu_is_not_allowed(cpu_num)) goto next_loop_iter; @@ -10448,7 +10503,7 @@ void pmt_init(void) * Set the scope to CPU, even though CWF report the counter per module. * CPUs inside the same module will read from the same location, instead of reporting zeros. * - * CWF with newer firmware might require a PMT_TYPE_XTAL_TIME intead of PMT_TYPE_TCORE_CLOCK. + * CWF with newer firmware might require a PMT_TYPE_XTAL_TIME instead of PMT_TYPE_TCORE_CLOCK. */ pmt_add_counter(PMT_CWF_MC1E_GUID, seq, "CPU%c1e", PMT_TYPE_TCORE_CLOCK, PMT_COUNTER_CWF_MC1E_LSB, PMT_COUNTER_CWF_MC1E_MSB, offset, SCOPE_CPU, FORMAT_DELTA, cpu_num, PMT_OPEN_TRY); @@ -10525,11 +10580,11 @@ void turbostat_init() void affinitize_child(void) { /* Prefer cpu_possible_set, if available */ - if (sched_setaffinity(0, cpu_possible_setsize, cpu_possible_set)) { + if (sched_setaffinity(0, cpu_setsize, cpu_possible_set)) { warn("sched_setaffinity cpu_possible_set"); /* Otherwise, allow child to run on same cpu set as turbostat */ - if (sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set)) + if (sched_setaffinity(0, cpu_setsize, cpu_allowed_set)) warn("sched_setaffinity cpu_allowed_set"); } } @@ -10608,7 +10663,7 @@ int get_and_dump_counters(void) void print_version() { - fprintf(outf, "turbostat version 2026.04.21 - Len Brown <lenb@kernel.org>\n"); + fprintf(outf, "turbostat version 2026.09.28 - Len Brown <lenb@kernel.org>\n"); } #define COMMAND_LINE_SIZE 2048 @@ -10634,7 +10689,7 @@ void print_bootcmd(void) fclose(fp); } -struct msr_counter *find_msrp_by_name(struct msr_counter *head, char *name) +struct msr_counter *find_msrp_by_name(struct msr_counter *head, const char *name) { struct msr_counter *mp; @@ -10647,7 +10702,7 @@ struct msr_counter *find_msrp_by_name(struct msr_counter *head, char *name) return NULL; } -int add_counter(unsigned int msr_num, char *path, char *name, +int add_counter(unsigned int msr_num, const char *path, const char *name, unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int id) { struct msr_counter *msrp; @@ -10668,10 +10723,11 @@ int add_counter(unsigned int msr_num, char *path, char *name, fprintf(stderr, "%s: %s FOUND\n", __func__, name); break; } - if (sys.added_thread_counters++ >= MAX_ADDED_THREAD_COUNTERS) { + if (sys.added_thread_counters >= MAX_ADDED_THREAD_COUNTERS) { warnx("ignoring thread counter %s", name); return -1; } + sys.added_thread_counters++; break; case SCOPE_CORE: msrp = find_msrp_by_name(sys.cp, name); @@ -10680,10 +10736,11 @@ int add_counter(unsigned int msr_num, char *path, char *name, fprintf(stderr, "%s: %s FOUND\n", __func__, name); break; } - if (sys.added_core_counters++ >= MAX_ADDED_CORE_COUNTERS) { + if (sys.added_core_counters >= MAX_ADDED_CORE_COUNTERS) { warnx("ignoring core counter %s", name); return -1; } + sys.added_core_counters++; break; case SCOPE_PACKAGE: msrp = find_msrp_by_name(sys.pp, name); @@ -10692,10 +10749,11 @@ int add_counter(unsigned int msr_num, char *path, char *name, fprintf(stderr, "%s: %s FOUND\n", __func__, name); break; } - if (sys.added_package_counters++ >= MAX_ADDED_PACKAGE_COUNTERS) { + if (sys.added_package_counters >= MAX_ADDED_PACKAGE_COUNTERS) { warnx("ignoring package counter %s", name); return -1; } + sys.added_package_counters++; break; default: warnx("ignoring counter %s with unknown scope", name); @@ -10734,10 +10792,8 @@ int add_counter(unsigned int msr_num, char *path, char *name, struct sysfs_path *sp; sp = calloc(1, sizeof(struct sysfs_path)); - if (sp == NULL) { - perror("calloc"); - exit(1); - } + if (sp == NULL) + err(-1, "%s", path); strncpy(sp->path, path, PATH_BYTES - 1); sp->id = id; sp->next = msrp->sp; @@ -11437,18 +11493,18 @@ void probe_cpuidle_counts(void) /* * parse cpuset with following syntax - * 1,2,4..6,8-10 and set bits in cpu_subset + * 1,2,4..6,8-10 and set bits in cpuset_cmdline */ void parse_cpu_command(char *optarg) { if (!strcmp(optarg, "core")) { - if (cpu_subset) + if (cpuset_cmdline) goto error; show_core_only++; return; } if (!strcmp(optarg, "package")) { - if (cpu_subset) + if (cpuset_cmdline) goto error; show_pkg_only++; return; @@ -11456,15 +11512,23 @@ void parse_cpu_command(char *optarg) if (show_core_only || show_pkg_only) goto error; - cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS); - if (cpu_subset == NULL) - err(3, "CPU_ALLOC"); - cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS); + /* + * cpuset_cmdline is allocated on the first invocation of --cpu + * It is re-used for subsequent invocations. + * It is never freed. + */ + if (!cpuset_cmdline) { + cpuset_cmdline = CPU_ALLOC(topo.max_cpu_num + 1); + if (cpuset_cmdline == NULL) + err(3, "CPU_ALLOC"); - CPU_ZERO_S(cpu_subset_size, cpu_subset); + CPU_ZERO_S(cpu_setsize, cpuset_cmdline); + } - if (parse_cpu_str(optarg, cpu_subset, cpu_subset_size)) + if (parse_cpu_str(optarg, cpuset_cmdline, cpu_setsize)) goto error; + if (debug) + print_cpu_set("--cpu", cpuset_cmdline); return; @@ -11546,7 +11610,7 @@ void cmdline(int argc, char **argv) bic_lookup(&bic_enabled, optarg, SHOW_LIST); break; case 'f': - force_load++; + force_load = true; break; case 'd': debug++; @@ -11558,7 +11622,7 @@ void cmdline(int argc, char **argv) * multiple invocations simply clear more bits in enabled mask */ { - cpu_set_t bic_group_hide; + bic_set_t bic_group_hide; BIC_INIT(&bic_group_hide); @@ -11671,11 +11735,16 @@ int main(int argc, char **argv) ret = write(fd, "0\n", 2); if (ret == -1) - perror("Can't update cgroup\n"); + warn("/sys/fs/cgroup/cgroup.procs"); close(fd); skip_cgroup_setting: + + /* probe max_cpu_num and set cpu_setsize early for use by cmdline() */ + topo.max_cpu_num = get_max_cpu_num("/sys/devices/system/cpu/possible"); + cpu_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); + outf = stderr; cmdline(argc, argv); @@ -11698,8 +11767,10 @@ skip_cgroup_setting: msr_sum_record(); /* dump counters and exit */ - if (dump_only) + if (dump_only) { + dump_bic_sets(); return get_and_dump_counters(); + } /* list header and exit */ if (list_header_only) { diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c index 0dc959e30076..f7ab4904befb 100644 --- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c +++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c @@ -9,17 +9,22 @@ */ #define _GNU_SOURCE -#include MSRHEADER +/* + * MSRHEADER macro should be defined by the build system to include the + * appropriate MSR definitions header file. Typical usage: + * gcc -DMSRHEADER=\"msr-index.h\" or similar platform-specific MSR header + */ +#include MSRHEADER /* e.g., msr-index.h with MSR_* constant definitions */ #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sched.h> #include <sys/stat.h> +#include <sys/wait.h> #include <sys/resource.h> #include <getopt.h> #include <err.h> #include <fcntl.h> -#include <signal.h> #include <sys/time.h> #include <limits.h> #include <stdlib.h> @@ -33,6 +38,12 @@ #define OPTARG_BALANCE_PERFORMANCE (INT_MAX - 4) #define OPTARG_PERFORMANCE (INT_MAX - 5) +/* Maximum HWP activity window duration in microseconds */ +#define HWP_WINDOW_MAX_USEC 1270000000U + +/* Nominal bus clock frequency in MHz - assumed for all HWP systems */ +#define BCLK_MHZ 100 + struct msr_hwp_cap { unsigned char highest; unsigned char guaranteed; @@ -98,6 +109,7 @@ unsigned char update_platform_profile; int soc_slider_balance; int soc_slider_offset; char platform_profile[64]; +char msr_path[64]; #define PATH_TO_CPU "/sys/devices/system/cpu/" #define SYSFS_PATH_MAX 255 @@ -139,11 +151,13 @@ void usage(void) int ratio_2_msr_perf(int ratio) { int msr_perf; + unsigned long long temp; if (!bdx_highest_ratio) return ratio; - msr_perf = ratio * 255 / bdx_highest_ratio; + temp = (unsigned long long)ratio * 255; + msr_perf = (int)(temp / bdx_highest_ratio); if (debug) fprintf(stderr, "%d = ratio_to_msr_perf(%d)\n", msr_perf, ratio); @@ -189,7 +203,7 @@ int parse_cmdline_epb(int i) return ENERGY_PERF_BIAS_PERFORMANCE; } if (i < 0 || i > ENERGY_PERF_BIAS_POWERSAVE) - errx(1, "--epb must be from 0 to 15"); + errx(1, "--epb must be 0 through 15"); return i; } @@ -269,8 +283,8 @@ int parse_cmdline_hwp_window(int i) case OPTARG_PERFORMANCE: return 0; } - if (i < 0 || i > 1270000000) { - fprintf(stderr, "--hwp-window: 0 for auto; 1 - 1270000000 usec for window duration\n"); + if (i < 0 || i > HWP_WINDOW_MAX_USEC) { + fprintf(stderr, "--hwp-window: 0 for auto; 1 - %u usec for window duration\n", HWP_WINDOW_MAX_USEC); usage(); } for (exponent = 0;; ++exponent) { @@ -303,8 +317,8 @@ int parse_cmdline_hwp_epp(int i) case OPTARG_PERFORMANCE: return HWP_EPP_PERFORMANCE; } - if (i < 0 || i > 0xff) { - fprintf(stderr, "--hwp-epp must be from 0 to 0xff\n"); + if (i < 0 || i > 255) { + fprintf(stderr, "--hwp-epp must be 0 through 255\n"); usage(); } return i; @@ -330,42 +344,36 @@ int parse_cmdline_turbo(int i) return i; } -int parse_optarg_string(char *s) +int parse_optarg_string(const char *s) { int i; char *endptr; - if (!strncmp(s, "default", 7)) + if (strcmp(s, "default") == 0) return OPTARG_NORMAL; - if (!strncmp(s, "normal", 6)) + if (strcmp(s, "normal") == 0) return OPTARG_NORMAL; - if (!strncmp(s, "power", 9)) + if (strcmp(s, "power") == 0) return OPTARG_POWER; - if (!strncmp(s, "balance-power", 17)) + if (strcmp(s, "balance-power") == 0) return OPTARG_BALANCE_POWER; - if (!strncmp(s, "balance-performance", 19)) + if (strcmp(s, "balance-performance") == 0) return OPTARG_BALANCE_PERFORMANCE; - if (!strncmp(s, "performance", 11)) + if (strcmp(s, "performance") == 0) return OPTARG_PERFORMANCE; + errno = 0; i = strtol(s, &endptr, 0); - if (s == endptr) { - fprintf(stderr, "no digits in \"%s\"\n", s); + if (endptr == s || errno == ERANGE || i < 0 || i > 256) { + warnx("bad value \"%s\"\n", s); usage(); } - if (i == LONG_MIN || i == LONG_MAX) - errx(-1, "%s", s); - - if (i > 0xFF) - errx(-1, "%d (0x%x) must be < 256", i, i); - if (i < 0) - errx(-1, "%d (0x%x) must be >= 0", i, i); return i; } @@ -423,7 +431,7 @@ void parse_cmdline_cpu(char *s) startp++; end_cpu = strtol(startp, &endp, 10); - if (startp == endp) + if (endp == startp) continue; while (cpu <= end_cpu) { @@ -467,11 +475,11 @@ void parse_cmdline_cpu(char *s) break; } + errno = 0; cpu = strtol(startp, &endp, 10); - if (startp == endp) + if (endp == startp || errno == ERANGE || cpu < 0 || cpu > max_cpu_num) errx(1, "--cpu cpu-set: confused by '%s'", startp); - if (cpu > max_cpu_num) - errx(1, "Requested cpu%d exceeds max cpu%d", cpu, max_cpu_num); + CPU_SET_S(cpu, cpu_setsize, cpu_selected_set); startp = endp; } @@ -503,7 +511,7 @@ void parse_cmdline_pkg(char *s) startp++; end_pkg = strtol(startp, &endp, 10); - if (startp == endp) + if (endp == startp) continue; while (pkg <= end_pkg) { @@ -524,6 +532,7 @@ void parse_cmdline_pkg(char *s) pkg = strtol(startp, &endp, 10); if (pkg > max_pkg_num) errx(1, "Requested pkg%d Exceeds max pkg%d", pkg, max_pkg_num); + pkg_selected_set |= 1 << pkg; startp = endp; } @@ -534,6 +543,8 @@ void for_packages(unsigned long long pkg_set, int (func) (int)) int pkg_num; for (pkg_num = 0; pkg_num <= max_pkg_num; ++pkg_num) { + if (pkg_num >= MAX_PACKAGES) + break; if (pkg_set & (1UL << pkg_num)) func(pkg_num); } @@ -544,6 +555,7 @@ static int parse_cmdline_int(const char *s, int *out) char *endp; long val; + errno = 0; val = strtol(s, &endp, 0); if (endp == s || errno == ERANGE) return -1; @@ -572,7 +584,7 @@ static int platform_profile_access(int mode) return 1; } -static int platform_profile_name_is(char *name) +static int platform_profile_name_is(const char *name) { char buf[64]; @@ -677,7 +689,7 @@ void cmdline(int argc, char **argv) errx(1, "--platform-profile: value too long"); if (!platform_profile_access(W_OK)) errx(1, "Can not update platform-profile in '%s'", PATH_PLATFORM_PROFILE); - strcpy(platform_profile, optarg); + strncpy(platform_profile, optarg, sizeof(platform_profile) - 1); update_platform_profile = 1; break; case 'm': @@ -714,7 +726,15 @@ void cmdline(int argc, char **argv) break; case 'u': update_hwp_use_pkg++; - if (atoi(optarg) == 0) + char *endp; + long val; + + errno = 0; + val = strtol(optarg, &endp, 10); + if (endp == optarg || errno == ERANGE || val < 0 || val > 1) + errx(1, "--hwp-use-pkg: must be 0 or 1"); + + if (val == 0) req_update.hwp_use_pkg = 0; else req_update.hwp_use_pkg = 1; @@ -764,10 +784,10 @@ void err_on_hypervisor(void) /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */ cpuinfo = fopen_or_die("/proc/cpuinfo", "r"); - buffer = malloc(4096); + buffer = calloc(4096, 1); if (!buffer) { fclose(cpuinfo); - err(-ENOMEM, "buffer malloc fail"); + err(-ENOMEM, "buffer calloc fail"); } if (!fread(buffer, 1024, 1, cpuinfo)) { @@ -775,6 +795,7 @@ void err_on_hypervisor(void) free(buffer); err(1, "Reading /proc/cpuinfo failed"); } + buffer[1024 - 1] = '\0'; flags = strstr(buffer, "flags"); if (!flags) { @@ -783,7 +804,11 @@ void err_on_hypervisor(void) err(1, "Failed to find 'flags' in /proc/cpuinfo"); } rewind(cpuinfo); - fseek(cpuinfo, flags - buffer, SEEK_SET); + if (fseek(cpuinfo, flags - buffer, SEEK_SET) != 0) { + fclose(cpuinfo); + free(buffer); + err(1, "Failed to seek in /proc/cpuinfo"); + } if (!fgets(buffer, 4096, cpuinfo)) { fclose(cpuinfo); free(buffer); @@ -792,28 +817,37 @@ void err_on_hypervisor(void) fclose(cpuinfo); hypervisor = strstr(buffer, "hypervisor"); + if (hypervisor) + err(-1, "not supported on this virtual machine"); free(buffer); +} - if (hypervisor) - err(-1, "not supported on this virtual machine"); +/* + * The Linux MSR driver uses offsets into /dev/cpu/{cpu#}/msr + * Some Android versions uses an incompatible path: /dev/msr{cpu#} + * Probe and prefer the Linux path, use Android if Linux does not work. + */ +static void set_msr_path(int cpu) +{ + if (snprintf(msr_path, sizeof(msr_path), use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu) >= (int)sizeof(msr_path)) + err(-1, "MSR path buffer overflow for cpu%d", cpu); } int get_msr(int cpu, int offset, unsigned long long *msr) { int retval; - char pathname[32]; int fd; - sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu); - fd = open(pathname, O_RDONLY); + set_msr_path(cpu); + fd = open(msr_path, O_RDONLY); if (fd < 0) - err(-1, "%s open failed, try chown or chmod +r %s, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); + err(-1, "%s open failed, try chown or chmod +r, or run as root", msr_path); retval = pread(fd, msr, sizeof(*msr), offset); if (retval != sizeof(*msr)) { err_on_hypervisor(); - err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset); + err(-1, "%s offset 0x%llx read failed", msr_path, (unsigned long long)offset); } if (debug > 1) @@ -825,14 +859,13 @@ int get_msr(int cpu, int offset, unsigned long long *msr) int put_msr(int cpu, int offset, unsigned long long new_msr) { - char pathname[32]; int retval; int fd; - sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu); - fd = open(pathname, O_RDWR); + set_msr_path(cpu); + fd = open(msr_path, O_RDWR); if (fd < 0) - err(-1, "%s open failed, try chown or chmod +r %s, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr"); + err(-1, "%s open failed, try chown or chmod +r, or run as root", msr_path); retval = pwrite(fd, &new_msr, sizeof(new_msr), offset); if (retval != sizeof(new_msr)) @@ -867,7 +900,7 @@ static unsigned int read_sysfs(const char *path, char *buf, size_t buflen) return (unsigned int)numread; } -static unsigned int write_sysfs(const char *path, char *buf, size_t buflen) +static ssize_t write_sysfs(const char *path, char *buf, size_t buflen) { ssize_t numwritten; int fd; @@ -886,7 +919,7 @@ static unsigned int write_sysfs(const char *path, char *buf, size_t buflen) close(fd); - return (unsigned int)numwritten; + return numwritten; } static int sysfs_read_string(const char *path, char *buf, size_t buflen) @@ -911,7 +944,7 @@ static int sysfs_write_string(const char *path, const char *buf) len = snprintf(tmp, sizeof(tmp), "%s\n", buf); if (len < 0 || len >= (int)sizeof(tmp)) return -1; - return write_sysfs(path, tmp, (size_t)len + 1) ? 0 : -1; + return write_sysfs(path, tmp, (size_t)len + 1) > 0 ? 0 : -1; } void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str) @@ -934,7 +967,7 @@ void read_hwp_cap(int cpu, struct msr_hwp_cap *cap, unsigned int msr_offset) cap->lowest = msr_perf_2_ratio(HWP_LOWEST_PERF(msr)); } -void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str) +void print_hwp_request(int cpu, struct msr_hwp_request *h, const char *str) { if (cpu != -1) printf("cpu%d: ", cpu); @@ -946,7 +979,7 @@ void print_hwp_request(int cpu, struct msr_hwp_request *h, char *str) h->hwp_min, h->hwp_max, h->hwp_desired, h->hwp_epp, h->hwp_window, h->hwp_window & 0x7F, (h->hwp_window >> 7) & 0x7, h->hwp_use_pkg); } -void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, char *str) +void print_hwp_request_pkg(int pkg, struct msr_hwp_request *h, const char *str) { printf("pkg%d: ", pkg); @@ -1004,8 +1037,9 @@ static int get_epb_sysfs(int cpu) if (!read_sysfs(path, linebuf, 3)) return -1; + errno = 0; val = strtol(linebuf, &endp, 0); - if (endp == linebuf || errno == ERANGE) + if (endp == linebuf || errno == ERANGE || val < 0 || val > 15) return -1; return (int)val; @@ -1016,7 +1050,7 @@ static int set_epb_sysfs(int cpu, int val) char path[SYSFS_PATH_MAX]; char linebuf[3]; char *endp; - int ret; + ssize_t ret; if (!has_epb) return -1; @@ -1028,8 +1062,9 @@ static int set_epb_sysfs(int cpu, int val) if (ret <= 0) return -1; + errno = 0; val = strtol(linebuf, &endp, 0); - if (endp == linebuf || errno == ERANGE) + if (endp == linebuf || errno == ERANGE || val < 0 || val > 15) return -1; return (int)val; @@ -1139,7 +1174,7 @@ int print_pkg_msrs(int pkg) */ int ratio_2_sysfs_khz(int ratio) { - int bclk_khz = 100 * 1000; /* 100,000 KHz = 100 MHz */ + int bclk_khz = BCLK_MHZ * 1000; /* Convert MHz to KHz */ return ratio * bclk_khz; } @@ -1155,12 +1190,12 @@ int ratio_2_sysfs_khz(int ratio) */ void update_cpufreq_scaling_freq(int is_max, int cpu, unsigned int ratio) { - char pathname[64]; + char pathname[96]; FILE *fp; int retval; int khz; - sprintf(pathname, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", cpu, is_max ? "max" : "min"); + snprintf(pathname, sizeof(pathname), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_%s_freq", cpu, is_max ? "max" : "min"); fp = fopen(pathname, "w"); if (!fp) { @@ -1601,32 +1636,41 @@ void set_base_cpu(void) err(-ENODEV, "No valid cpus found"); } -static void probe_android_msr_path(void) +/* return 0 if path exists */ +static int check_msr_path(void) { struct stat sb; - char test_path[32]; - sprintf(test_path, "/dev/msr%d", base_cpu); - if (stat(test_path, &sb) == 0) - use_android_msr_path = 1; + return stat(msr_path, &sb); } +/* + * Check Linux MSR path + * If it fails, try modprobe and check it again + * If still no joy, enable Android path and try again + */ void probe_dev_msr(void) { - struct stat sb; - char pathname[32]; + int retval; - probe_android_msr_path(); + use_android_msr_path = 0; + set_msr_path(base_cpu); + if (check_msr_path() == 0) + return; - sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", base_cpu); - if (stat(pathname, &sb)) { - if (system("/sbin/modprobe msr > /dev/null 2>&1")) { - if (use_android_msr_path) - err(-5, "no /dev/msr0, Try \"# modprobe msr\" "); - else - err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); - } - } + retval = system("/sbin/modprobe msr > /dev/null 2>&1"); + + if (check_msr_path() == 0) + return; + + use_android_msr_path = 1; + set_msr_path(base_cpu); + if (check_msr_path() == 0) + return; + + if (WIFEXITED(retval)) + retval = WEXITSTATUS(retval); + err(-1, "\"msr\" driver support required, modprobe msr returned %d", retval); } static void get_cpuid_or_exit(unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) |
