1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/types.h>
7 #include "../../../util/debug.h"
8 #include "../../../util/tsc.h"
13 unsigned int low, high;
15 asm volatile("rdtsc" : "=a" (low), "=d" (high));
17 return low | ((u64)high) << 32;
21 * Derive the TSC frequency in Hz from the /proc/cpuinfo, for example:
23 * model name : Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz
25 * will return 3000000000.
27 static double cpuinfo_tsc_freq(void)
34 cpuinfo = fopen("/proc/cpuinfo", "r");
36 pr_err("Failed to read /proc/cpuinfo for TSC frequency");
39 while (getline(&line, &len, cpuinfo) > 0) {
40 if (!strncmp(line, "model name", 10)) {
41 char *pos = strstr(line + 11, " @ ");
43 if (pos && sscanf(pos, " @ %lfGHz", &result) == 1) {
50 if (fpclassify(result) == FP_ZERO)
51 pr_err("Failed to find TSC frequency in /proc/cpuinfo");
58 double arch_get_tsc_freq(void)
60 unsigned int a, b, c, d, lvl;
69 get_cpuid_0(vendor, &lvl);
70 if (!strstr(vendor, "Intel"))
74 * Don't support Time Stamp Counter and
75 * Nominal Core Crystal Clock Information Leaf.
78 tsc = cpuinfo_tsc_freq();
82 cpuid(0x15, 0, &a, &b, &c, &d);
83 /* TSC frequency is not enumerated */
85 tsc = cpuinfo_tsc_freq();
89 tsc = (double)c * (double)b / (double)a;