Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'turbostat-fixes-for-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux

Pull turbostat fixes from Len Brown:

- Fix a memory allocation issue that could corrupt output values or
SEGV

- Fix a perf initilization issue that could exit on some HW + kernels

- Minor fixes

* tag 'turbostat-fixes-for-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux:
tools/power turbostat: Allow execution to continue after perf_l2_init() failure
tools/power turbostat: Fix delimiter bug in print functions
tools/power turbostat: Fix --show/--hide for individual cpuidle counters
tools/power turbostat: Fix incorrect format variable
tools/power turbostat: Consistently use print_float_value()
tools/power/turbostat: Fix microcode patch level output for AMD/Hygon
tools/power turbostat: Eliminate unnecessary data structure allocation
tools/power turbostat: Fix swidle header vs data display
tools/power turbostat: Fix illegal memory access when SMT is present and disabled

+54 -46
+54 -46
tools/power/x86/turbostat/turbostat.c
··· 2409 2409 int max_l3_id; 2410 2410 int max_node_num; 2411 2411 int nodes_per_pkg; 2412 - int cores_per_node; 2412 + int cores_per_pkg; 2413 2413 int threads_per_core; 2414 2414 } topo; 2415 2415 ··· 2837 2837 UNUSED(type); 2838 2838 2839 2839 if (format == FORMAT_RAW && width >= 64) 2840 - return (sprintf(outp, "%s%-8s", (*printed++ ? delim : ""), name)); 2840 + return (sprintf(outp, "%s%-8s", ((*printed)++ ? delim : ""), name)); 2841 2841 else 2842 - return (sprintf(outp, "%s%s", (*printed++ ? delim : ""), name)); 2842 + return (sprintf(outp, "%s%s", ((*printed)++ ? delim : ""), name)); 2843 2843 } 2844 2844 2845 2845 static inline int print_hex_value(int width, int *printed, char *delim, unsigned long long value) 2846 2846 { 2847 2847 if (width <= 32) 2848 - return (sprintf(outp, "%s%08x", (*printed++ ? delim : ""), (unsigned int)value)); 2848 + return (sprintf(outp, "%s%08x", ((*printed)++ ? delim : ""), (unsigned int)value)); 2849 2849 else 2850 - return (sprintf(outp, "%s%016llx", (*printed++ ? delim : ""), value)); 2850 + return (sprintf(outp, "%s%016llx", ((*printed)++ ? delim : ""), value)); 2851 2851 } 2852 2852 2853 2853 static inline int print_decimal_value(int width, int *printed, char *delim, unsigned long long value) 2854 2854 { 2855 - if (width <= 32) 2856 - return (sprintf(outp, "%s%d", (*printed++ ? delim : ""), (unsigned int)value)); 2857 - else 2858 - return (sprintf(outp, "%s%-8lld", (*printed++ ? delim : ""), value)); 2855 + UNUSED(width); 2856 + 2857 + return (sprintf(outp, "%s%lld", ((*printed)++ ? delim : ""), value)); 2859 2858 } 2860 2859 2861 2860 static inline int print_float_value(int *printed, char *delim, double value) 2862 2861 { 2863 - return (sprintf(outp, "%s%0.2f", (*printed++ ? delim : ""), value)); 2862 + return (sprintf(outp, "%s%0.2f", ((*printed)++ ? delim : ""), value)); 2864 2863 } 2865 2864 2866 2865 void print_header(char *delim) ··· 3468 3469 for (i = 0, pp = sys.perf_tp; pp; ++i, pp = pp->next) { 3469 3470 if (pp->format == FORMAT_RAW) 3470 3471 outp += print_hex_value(pp->width, &printed, delim, t->perf_counter[i]); 3471 - else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) 3472 + else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) 3472 3473 outp += print_decimal_value(pp->width, &printed, delim, t->perf_counter[i]); 3473 3474 else if (pp->format == FORMAT_PERCENT) { 3474 3475 if (pp->type == COUNTER_USEC) ··· 3489 3490 3490 3491 case PMT_TYPE_XTAL_TIME: 3491 3492 value_converted = pct(value_raw / crystal_hz, interval_float); 3492 - outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 3493 + outp += print_float_value(&printed, delim, value_converted); 3493 3494 break; 3494 3495 3495 3496 case PMT_TYPE_TCORE_CLOCK: 3496 3497 value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float); 3497 - outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 3498 + outp += print_float_value(&printed, delim, value_converted); 3498 3499 } 3499 3500 } 3500 3501 ··· 3538 3539 for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) { 3539 3540 if (pp->format == FORMAT_RAW) 3540 3541 outp += print_hex_value(pp->width, &printed, delim, c->perf_counter[i]); 3541 - else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) 3542 + else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) 3542 3543 outp += print_decimal_value(pp->width, &printed, delim, c->perf_counter[i]); 3543 3544 else if (pp->format == FORMAT_PERCENT) 3544 3545 outp += print_float_value(&printed, delim, pct(c->perf_counter[i], tsc)); ··· 3694 3695 outp += print_hex_value(pp->width, &printed, delim, p->perf_counter[i]); 3695 3696 else if (pp->type == COUNTER_K2M) 3696 3697 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->perf_counter[i] / 1000); 3697 - else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE) 3698 + else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE) 3698 3699 outp += print_decimal_value(pp->width, &printed, delim, p->perf_counter[i]); 3699 3700 else if (pp->format == FORMAT_PERCENT) 3700 3701 outp += print_float_value(&printed, delim, pct(p->perf_counter[i], tsc)); ··· 9121 9122 cpuid_has_hv = ecx_flags & (1 << 31); 9122 9123 9123 9124 if (!no_msr) { 9124 - if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) 9125 + if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) { 9125 9126 warnx("get_msr(UCODE)"); 9126 - else 9127 + } else { 9127 9128 ucode_patch_valid = true; 9129 + if (!authentic_amd && !hygon_genuine) 9130 + ucode_patch >>= 32; 9131 + } 9128 9132 } 9129 9133 9130 9134 /* ··· 9141 9139 if (!quiet) { 9142 9140 fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", family, model, stepping, family, model, stepping); 9143 9141 if (ucode_patch_valid) 9144 - fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF)); 9142 + fprintf(outf, " microcode 0x%x", (unsigned int)ucode_patch); 9145 9143 fputc('\n', outf); 9146 9144 9147 9145 fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level); ··· 9405 9403 if (!is_hybrid) { 9406 9404 fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP); 9407 9405 if (fd_l2_percpu[cpu] == -1) { 9408 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs); 9406 + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs); 9409 9407 free_fd_l2_percpu(); 9410 9408 return; 9411 9409 } 9412 9410 retval = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); 9413 9411 if (retval == -1) { 9414 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits); 9412 + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits); 9415 9413 free_fd_l2_percpu(); 9416 9414 return; 9417 9415 } ··· 9420 9418 if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_pcore_set)) { 9421 9419 fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP); 9422 9420 if (fd_l2_percpu[cpu] == -1) { 9423 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs); 9421 + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs); 9424 9422 free_fd_l2_percpu(); 9425 9423 return; 9426 9424 } 9427 9425 retval = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); 9428 9426 if (retval == -1) { 9429 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits); 9427 + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits); 9430 9428 free_fd_l2_percpu(); 9431 9429 return; 9432 9430 } 9433 9431 } else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_ecore_set)) { 9434 9432 fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.refs, -1, PERF_FORMAT_GROUP); 9435 9433 if (fd_l2_percpu[cpu] == -1) { 9436 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.refs); 9434 + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.refs); 9437 9435 free_fd_l2_percpu(); 9438 9436 return; 9439 9437 } 9440 9438 retval = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); 9441 9439 if (retval == -1) { 9442 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.hits); 9440 + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.hits); 9443 9441 free_fd_l2_percpu(); 9444 9442 return; 9445 9443 } 9446 9444 } else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_lcore_set)) { 9447 9445 fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.refs, -1, PERF_FORMAT_GROUP); 9448 9446 if (fd_l2_percpu[cpu] == -1) { 9449 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.refs); 9447 + warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.refs); 9450 9448 free_fd_l2_percpu(); 9451 9449 return; 9452 9450 } 9453 9451 retval = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP); 9454 9452 if (retval == -1) { 9455 - err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.hits); 9453 + warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.hits); 9456 9454 free_fd_l2_percpu(); 9457 9455 return; 9458 9456 } ··· 9636 9634 topo.max_core_id = max_core_id; /* within a package */ 9637 9635 topo.max_package_id = max_package_id; 9638 9636 9639 - topo.cores_per_node = max_core_id + 1; 9637 + topo.cores_per_pkg = max_core_id + 1; 9640 9638 if (debug > 1) 9641 - fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node); 9639 + fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_pkg); 9642 9640 if (!summary_only) 9643 9641 BIC_PRESENT(BIC_Core); 9644 9642 ··· 9703 9701 void allocate_counters(struct counters *counters) 9704 9702 { 9705 9703 int i; 9706 - int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages; 9707 - int num_threads = topo.threads_per_core * num_cores; 9704 + int num_cores = topo.cores_per_pkg * topo.num_packages; 9708 9705 9709 - counters->threads = calloc(num_threads, sizeof(struct thread_data)); 9706 + counters->threads = calloc(topo.max_cpu_num + 1, sizeof(struct thread_data)); 9710 9707 if (counters->threads == NULL) 9711 9708 goto error; 9712 9709 9713 - for (i = 0; i < num_threads; i++) 9710 + for (i = 0; i < topo.max_cpu_num + 1; i++) 9714 9711 (counters->threads)[i].cpu_id = -1; 9715 9712 9716 9713 counters->cores = calloc(num_cores, sizeof(struct core_data)); ··· 11285 11284 } 11286 11285 } 11287 11286 11287 + static bool cpuidle_counter_wanted(char *name) 11288 + { 11289 + if (is_deferred_skip(name)) 11290 + return false; 11291 + 11292 + return DO_BIC(BIC_cpuidle) || is_deferred_add(name); 11293 + } 11294 + 11288 11295 void probe_cpuidle_counts(void) 11289 11296 { 11290 11297 char path[64]; ··· 11302 11293 int min_state = 1024, max_state = 0; 11303 11294 char *sp; 11304 11295 11305 - if (!DO_BIC(BIC_cpuidle)) 11296 + if (!DO_BIC(BIC_cpuidle) && !deferred_add_index) 11306 11297 return; 11307 11298 11308 11299 for (state = 10; state >= 0; --state) { ··· 11316 11307 fclose(input); 11317 11308 11318 11309 remove_underbar(name_buf); 11319 - 11320 - if (!DO_BIC(BIC_cpuidle) && !is_deferred_add(name_buf)) 11321 - continue; 11322 - 11323 - if (is_deferred_skip(name_buf)) 11324 - continue; 11325 11310 11326 11311 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ 11327 11312 sp = strchr(name_buf, '-'); ··· 11331 11328 * Add 'C1+' for C1, and so on. The 'below' sysfs file always contains 0 for 11332 11329 * the last state, so do not add it. 11333 11330 */ 11334 - 11335 11331 *sp = '+'; 11336 11332 *(sp + 1) = '\0'; 11337 - sprintf(path, "cpuidle/state%d/below", state); 11338 - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 11333 + if (cpuidle_counter_wanted(name_buf)) { 11334 + sprintf(path, "cpuidle/state%d/below", state); 11335 + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 11336 + } 11339 11337 } 11340 11338 11341 11339 *sp = '\0'; 11342 - sprintf(path, "cpuidle/state%d/usage", state); 11343 - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 11340 + if (cpuidle_counter_wanted(name_buf)) { 11341 + sprintf(path, "cpuidle/state%d/usage", state); 11342 + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 11343 + } 11344 11344 11345 11345 /* 11346 11346 * The 'above' sysfs file always contains 0 for the shallowest state (smallest ··· 11352 11346 if (state != min_state) { 11353 11347 *sp = '-'; 11354 11348 *(sp + 1) = '\0'; 11355 - sprintf(path, "cpuidle/state%d/above", state); 11356 - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 11349 + if (cpuidle_counter_wanted(name_buf)) { 11350 + sprintf(path, "cpuidle/state%d/above", state); 11351 + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); 11352 + } 11357 11353 } 11358 11354 } 11359 11355 }