File Index
Files and directories
Sign in
FILE

tsc.c

File preview with syntax highlighting.

linux-6.19.14/tools/perf/arch/x86/util/tsc.c C
 1// SPDX-License-Identifier: GPL-2.0
 2#include <linux/types.h>
 3#include <math.h>
 4#include <string.h>
 5#include <stdlib.h>
 6
 7#include "../../../util/debug.h"
 8#include "../../../util/tsc.h"
 9#include "cpuid.h"
10
11u64 rdtsc(void)
12{
13	unsigned int low, high;
14
15	asm volatile("rdtsc" : "=a" (low), "=d" (high));
16
17	return low | ((u64)high) << 32;
18}
19
20/*
21 * Derive the TSC frequency in Hz from the /proc/cpuinfo, for example:
22 * ...
23 * model name      : Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz
24 * ...
25 * will return 3000000000.
26 */
27static u64 cpuinfo_tsc_freq(void)
28{
29	u64 result = 0;
30	FILE *cpuinfo;
31	char *line = NULL;
32	size_t len = 0;
33
34	cpuinfo = fopen("/proc/cpuinfo", "r");
35	if (!cpuinfo) {
36		pr_err("Failed to read /proc/cpuinfo for TSC frequency\n");
37		return 0;
38	}
39	while (getline(&line, &len, cpuinfo) > 0) {
40		if (!strncmp(line, "model name", 10)) {
41			char *pos = strstr(line + 11, " @ ");
42			double float_result;
43
44			if (pos && sscanf(pos, " @ %lfGHz", &float_result) == 1) {
45				float_result *= 1000000000;
46				result = (u64)float_result;
47				goto out;
48			}
49		}
50	}
51out:
52	if (result == 0)
53		pr_err("Failed to find TSC frequency in /proc/cpuinfo\n");
54
55	free(line);
56	fclose(cpuinfo);
57	return result;
58}
59
60u64 arch_get_tsc_freq(void)
61{
62	unsigned int a, b, c, d, lvl;
63	static bool cached;
64	static double tsc;
65	char vendor[16];
66
67	if (cached)
68		return tsc;
69
70	cached = true;
71	get_cpuid_0(vendor, &lvl);
72	if (!strstr(vendor, "Intel"))
73		return 0;
74
75	/*
76	 * Don't support Time Stamp Counter and
77	 * Nominal Core Crystal Clock Information Leaf.
78	 */
79	if (lvl < 0x15) {
80		tsc = cpuinfo_tsc_freq();
81		return tsc;
82	}
83
84	cpuid(0x15, 0, &a, &b, &c, &d);
85	/* TSC frequency is not enumerated */
86	if (!a || !b || !c) {
87		tsc = cpuinfo_tsc_freq();
88		return tsc;
89	}
90
91	tsc = (u64)c * (u64)b / (u64)a;
92	return tsc;
93}
~/ Read-only file preview.