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

Configure Feed

Select the types of activity you want to include in your feed.

perf tsc: Add cpuinfo fall back for arch_get_tsc_freq()

The CPUID method of arch_get_tsc_freq fails for older Intel processors,
such as Skylake. Compute using /proc/cpuinfo.

Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Caleb Biggers <caleb.biggers@intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.garry@huawei.com>
Cc: Kshipra Bopardikar <kshipra.bopardikar@intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Perry Taylor <perry.taylor@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Link: https://lore.kernel.org/r/20220718164312.3994191-3-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
1276ade6 bc2373a5

+48 -4
+48 -4
tools/perf/arch/x86/util/tsc.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <linux/types.h> 3 + #include <math.h> 3 4 #include <string.h> 4 5 6 + #include "../../../util/debug.h" 5 7 #include "../../../util/tsc.h" 6 8 #include "cpuid.h" 7 9 ··· 14 12 asm volatile("rdtsc" : "=a" (low), "=d" (high)); 15 13 16 14 return low | ((u64)high) << 32; 15 + } 16 + 17 + /* 18 + * Derive the TSC frequency in Hz from the /proc/cpuinfo, for example: 19 + * ... 20 + * model name : Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz 21 + * ... 22 + * will return 3000000000. 23 + */ 24 + static double cpuinfo_tsc_freq(void) 25 + { 26 + double result = 0; 27 + FILE *cpuinfo; 28 + char *line = NULL; 29 + size_t len = 0; 30 + 31 + cpuinfo = fopen("/proc/cpuinfo", "r"); 32 + if (!cpuinfo) { 33 + pr_err("Failed to read /proc/cpuinfo for TSC frequency"); 34 + return NAN; 35 + } 36 + while (getline(&line, &len, cpuinfo) > 0) { 37 + if (!strncmp(line, "model name", 10)) { 38 + char *pos = strstr(line + 11, " @ "); 39 + 40 + if (pos && sscanf(pos, " @ %lfGHz", &result) == 1) { 41 + result *= 1000000000; 42 + goto out; 43 + } 44 + } 45 + } 46 + out: 47 + if (fpclassify(result) == FP_ZERO) 48 + pr_err("Failed to find TSC frequency in /proc/cpuinfo"); 49 + 50 + free(line); 51 + fclose(cpuinfo); 52 + return result; 17 53 } 18 54 19 55 double arch_get_tsc_freq(void) ··· 73 33 * Don't support Time Stamp Counter and 74 34 * Nominal Core Crystal Clock Information Leaf. 75 35 */ 76 - if (lvl < 0x15) 77 - return 0; 36 + if (lvl < 0x15) { 37 + tsc = cpuinfo_tsc_freq(); 38 + return tsc; 39 + } 78 40 79 41 cpuid(0x15, 0, &a, &b, &c, &d); 80 42 /* TSC frequency is not enumerated */ 81 - if (!a || !b || !c) 82 - return 0; 43 + if (!a || !b || !c) { 44 + tsc = cpuinfo_tsc_freq(); 45 + return tsc; 46 + } 83 47 84 48 tsc = (double)c * (double)b / (double)a; 85 49 return tsc;