tools/power/turbostat: Remove PC7/PC9 support on ADL/RPL
[linux-block.git] / tools / power / x86 / turbostat / turbostat.c
CommitLineData
a61127c2 1// SPDX-License-Identifier: GPL-2.0-only
103a8fea
LB
2/*
3 * turbostat -- show CPU frequency and C-state residency
34041551 4 * on modern Intel and AMD processors.
103a8fea 5 *
de7839ee 6 * Copyright (c) 2023 Intel Corporation.
103a8fea 7 * Len Brown <len.brown@intel.com>
103a8fea
LB
8 */
9
88c3281f 10#define _GNU_SOURCE
b731f311 11#include MSRHEADER
869ce69e 12#include INTEL_FAMILY_HEADER
95aebc44 13#include <stdarg.h>
103a8fea 14#include <stdio.h>
b2c95d90 15#include <err.h>
103a8fea
LB
16#include <unistd.h>
17#include <sys/types.h>
18#include <sys/wait.h>
19#include <sys/stat.h>
b9ad8ee0 20#include <sys/select.h>
103a8fea
LB
21#include <sys/resource.h>
22#include <fcntl.h>
23#include <signal.h>
24#include <sys/time.h>
25#include <stdlib.h>
d8af6f5f 26#include <getopt.h>
103a8fea
LB
27#include <dirent.h>
28#include <string.h>
29#include <ctype.h>
88c3281f 30#include <sched.h>
2a0609c0 31#include <time.h>
2b92865e 32#include <cpuid.h>
fcaa681c 33#include <sys/capability.h>
98481e79 34#include <errno.h>
9392bd98 35#include <math.h>
2af4f9b8
LB
36#include <linux/perf_event.h>
37#include <asm/unistd.h>
7ab5ff49 38#include <stdbool.h>
103a8fea 39
9878bf7a
LB
40#define UNUSED(x) (void)(x)
41
164d7a96
LB
42/*
43 * This list matches the column headers, except
44 * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
45 * 2. Core and CPU are moved to the end, we can't have strings that contain them
46 * matching on them for --show and --hide.
47 */
48
49/*
50 * buffer size used by sscanf() for added column names
51 * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
52 */
53#define NAME_BYTES 20
54#define PATH_BYTES 128
55
56enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };
57enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC };
58enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT };
59
60struct msr_counter {
61 unsigned int msr_num;
62 char name[NAME_BYTES];
63 char path[PATH_BYTES];
64 unsigned int width;
65 enum counter_type type;
66 enum counter_format format;
67 struct msr_counter *next;
68 unsigned int flags;
69#define FLAGS_HIDE (1 << 0)
70#define FLAGS_SHOW (1 << 1)
71#define SYSFS_PERCPU (1 << 1)
72};
73
74struct msr_counter bic[] = {
9878bf7a
LB
75 { 0x0, "usec", "", 0, 0, 0, NULL, 0 },
76 { 0x0, "Time_Of_Day_Seconds", "", 0, 0, 0, NULL, 0 },
77 { 0x0, "Package", "", 0, 0, 0, NULL, 0 },
78 { 0x0, "Node", "", 0, 0, 0, NULL, 0 },
79 { 0x0, "Avg_MHz", "", 0, 0, 0, NULL, 0 },
80 { 0x0, "Busy%", "", 0, 0, 0, NULL, 0 },
81 { 0x0, "Bzy_MHz", "", 0, 0, 0, NULL, 0 },
82 { 0x0, "TSC_MHz", "", 0, 0, 0, NULL, 0 },
83 { 0x0, "IRQ", "", 0, 0, 0, NULL, 0 },
84 { 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL, 0 },
85 { 0x0, "sysfs", "", 0, 0, 0, NULL, 0 },
86 { 0x0, "CPU%c1", "", 0, 0, 0, NULL, 0 },
87 { 0x0, "CPU%c3", "", 0, 0, 0, NULL, 0 },
88 { 0x0, "CPU%c6", "", 0, 0, 0, NULL, 0 },
89 { 0x0, "CPU%c7", "", 0, 0, 0, NULL, 0 },
90 { 0x0, "ThreadC", "", 0, 0, 0, NULL, 0 },
91 { 0x0, "CoreTmp", "", 0, 0, 0, NULL, 0 },
92 { 0x0, "CoreCnt", "", 0, 0, 0, NULL, 0 },
93 { 0x0, "PkgTmp", "", 0, 0, 0, NULL, 0 },
94 { 0x0, "GFX%rc6", "", 0, 0, 0, NULL, 0 },
95 { 0x0, "GFXMHz", "", 0, 0, 0, NULL, 0 },
96 { 0x0, "Pkg%pc2", "", 0, 0, 0, NULL, 0 },
97 { 0x0, "Pkg%pc3", "", 0, 0, 0, NULL, 0 },
98 { 0x0, "Pkg%pc6", "", 0, 0, 0, NULL, 0 },
99 { 0x0, "Pkg%pc7", "", 0, 0, 0, NULL, 0 },
100 { 0x0, "Pkg%pc8", "", 0, 0, 0, NULL, 0 },
101 { 0x0, "Pkg%pc9", "", 0, 0, 0, NULL, 0 },
102 { 0x0, "Pk%pc10", "", 0, 0, 0, NULL, 0 },
103 { 0x0, "CPU%LPI", "", 0, 0, 0, NULL, 0 },
104 { 0x0, "SYS%LPI", "", 0, 0, 0, NULL, 0 },
105 { 0x0, "PkgWatt", "", 0, 0, 0, NULL, 0 },
106 { 0x0, "CorWatt", "", 0, 0, 0, NULL, 0 },
107 { 0x0, "GFXWatt", "", 0, 0, 0, NULL, 0 },
108 { 0x0, "PkgCnt", "", 0, 0, 0, NULL, 0 },
109 { 0x0, "RAMWatt", "", 0, 0, 0, NULL, 0 },
110 { 0x0, "PKG_%", "", 0, 0, 0, NULL, 0 },
111 { 0x0, "RAM_%", "", 0, 0, 0, NULL, 0 },
112 { 0x0, "Pkg_J", "", 0, 0, 0, NULL, 0 },
113 { 0x0, "Cor_J", "", 0, 0, 0, NULL, 0 },
114 { 0x0, "GFX_J", "", 0, 0, 0, NULL, 0 },
115 { 0x0, "RAM_J", "", 0, 0, 0, NULL, 0 },
116 { 0x0, "Mod%c6", "", 0, 0, 0, NULL, 0 },
117 { 0x0, "Totl%C0", "", 0, 0, 0, NULL, 0 },
118 { 0x0, "Any%C0", "", 0, 0, 0, NULL, 0 },
119 { 0x0, "GFX%C0", "", 0, 0, 0, NULL, 0 },
120 { 0x0, "CPUGFX%", "", 0, 0, 0, NULL, 0 },
121 { 0x0, "Core", "", 0, 0, 0, NULL, 0 },
122 { 0x0, "CPU", "", 0, 0, 0, NULL, 0 },
123 { 0x0, "APIC", "", 0, 0, 0, NULL, 0 },
124 { 0x0, "X2APIC", "", 0, 0, 0, NULL, 0 },
125 { 0x0, "Die", "", 0, 0, 0, NULL, 0 },
126 { 0x0, "GFXAMHz", "", 0, 0, 0, NULL, 0 },
127 { 0x0, "IPC", "", 0, 0, 0, NULL, 0 },
128 { 0x0, "CoreThr", "", 0, 0, 0, NULL, 0 },
a5c6d65d 129 { 0x0, "UncMHz", "", 0, 0, 0, NULL, 0 },
164d7a96
LB
130};
131
132#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
133#define BIC_USEC (1ULL << 0)
134#define BIC_TOD (1ULL << 1)
135#define BIC_Package (1ULL << 2)
136#define BIC_Node (1ULL << 3)
137#define BIC_Avg_MHz (1ULL << 4)
138#define BIC_Busy (1ULL << 5)
139#define BIC_Bzy_MHz (1ULL << 6)
140#define BIC_TSC_MHz (1ULL << 7)
141#define BIC_IRQ (1ULL << 8)
142#define BIC_SMI (1ULL << 9)
143#define BIC_sysfs (1ULL << 10)
144#define BIC_CPU_c1 (1ULL << 11)
145#define BIC_CPU_c3 (1ULL << 12)
146#define BIC_CPU_c6 (1ULL << 13)
147#define BIC_CPU_c7 (1ULL << 14)
148#define BIC_ThreadC (1ULL << 15)
149#define BIC_CoreTmp (1ULL << 16)
150#define BIC_CoreCnt (1ULL << 17)
151#define BIC_PkgTmp (1ULL << 18)
152#define BIC_GFX_rc6 (1ULL << 19)
153#define BIC_GFXMHz (1ULL << 20)
154#define BIC_Pkgpc2 (1ULL << 21)
155#define BIC_Pkgpc3 (1ULL << 22)
156#define BIC_Pkgpc6 (1ULL << 23)
157#define BIC_Pkgpc7 (1ULL << 24)
158#define BIC_Pkgpc8 (1ULL << 25)
159#define BIC_Pkgpc9 (1ULL << 26)
160#define BIC_Pkgpc10 (1ULL << 27)
161#define BIC_CPU_LPI (1ULL << 28)
162#define BIC_SYS_LPI (1ULL << 29)
163#define BIC_PkgWatt (1ULL << 30)
164#define BIC_CorWatt (1ULL << 31)
165#define BIC_GFXWatt (1ULL << 32)
166#define BIC_PkgCnt (1ULL << 33)
167#define BIC_RAMWatt (1ULL << 34)
168#define BIC_PKG__ (1ULL << 35)
169#define BIC_RAM__ (1ULL << 36)
170#define BIC_Pkg_J (1ULL << 37)
171#define BIC_Cor_J (1ULL << 38)
172#define BIC_GFX_J (1ULL << 39)
173#define BIC_RAM_J (1ULL << 40)
174#define BIC_Mod_c6 (1ULL << 41)
175#define BIC_Totl_c0 (1ULL << 42)
176#define BIC_Any_c0 (1ULL << 43)
177#define BIC_GFX_c0 (1ULL << 44)
178#define BIC_CPUGFX (1ULL << 45)
179#define BIC_Core (1ULL << 46)
180#define BIC_CPU (1ULL << 47)
181#define BIC_APIC (1ULL << 48)
182#define BIC_X2APIC (1ULL << 49)
183#define BIC_Die (1ULL << 50)
184#define BIC_GFXACTMHz (1ULL << 51)
185#define BIC_IPC (1ULL << 52)
186#define BIC_CORE_THROT_CNT (1ULL << 53)
a5c6d65d 187#define BIC_UNCORE_MHZ (1ULL << 54)
164d7a96
LB
188
189#define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die )
190#define BIC_THERMAL_PWR ( BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__)
a5c6d65d 191#define BIC_FREQUENCY ( BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_UNCORE_MHZ)
164d7a96
LB
192#define BIC_IDLE ( BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX)
193#define BIC_OTHER ( BIC_IRQ | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC)
194
195#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
196
197unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
198unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
199
200#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
201#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
202#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
203#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
204#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
205#define BIC_IS_ENABLED(COUNTER_BIT) (bic_enabled & COUNTER_BIT)
206
103a8fea 207char *proc_stat = "/proc/stat";
b7d8c148 208FILE *outf;
36229897 209int *fd_percpu;
2af4f9b8 210int *fd_instr_count_percpu;
1b439f01
LB
211struct timeval interval_tv = { 5, 0 };
212struct timespec interval_ts = { 5, 0 };
e9d3092f 213
023fe0ac 214unsigned int num_iterations;
c7e399f8 215unsigned int header_iterations;
d8af6f5f 216unsigned int debug;
96e47158 217unsigned int quiet;
3f44a5c6 218unsigned int shown;
0de6c0df 219unsigned int sums_need_wide_columns;
d8af6f5f
LB
220unsigned int rapl_joules;
221unsigned int summary_only;
c8ade361 222unsigned int list_header_only;
d8af6f5f 223unsigned int dump_only;
103a8fea 224unsigned int has_aperf;
889facbe 225unsigned int has_epb;
3ea8e52e 226unsigned int has_turbo;
774627c5 227unsigned int is_hybrid;
fc04cc67 228unsigned int units = 1000000; /* MHz etc */
103a8fea 229unsigned int genuine_intel;
34041551 230unsigned int authentic_amd;
c1c10cc7 231unsigned int hygon_genuine;
34041551 232unsigned int max_level, max_extended_level;
103a8fea 233unsigned int has_invariant_tsc;
b2b34dfe 234unsigned int aperf_mperf_multiplier = 1;
103a8fea 235double bclk;
a2b7b749 236double base_hz;
21ed5574 237unsigned int has_base_hz;
a2b7b749 238double tsc_tweak = 1.0;
c98d5d94
LB
239unsigned int show_pkg_only;
240unsigned int show_core_only;
241char *output_buffer, *outp;
889facbe
LB
242unsigned int do_dts;
243unsigned int do_ptm;
2af4f9b8 244unsigned int do_ipc;
1b439f01 245unsigned long long gfx_cur_rc6_ms;
be0e54c4
LB
246unsigned long long cpuidle_cur_cpu_lpi_us;
247unsigned long long cpuidle_cur_sys_lpi_us;
27d47356 248unsigned int gfx_cur_mhz;
b4b91569 249unsigned int gfx_act_mhz;
55279aef
ZR
250unsigned int tj_max;
251unsigned int tj_max_override;
40ee8e3b
AS
252double rapl_power_units, rapl_time_units;
253double rapl_dram_energy_units, rapl_energy_units;
889facbe 254double rapl_joule_counter_range;
8a5bdf41
LB
255unsigned int crystal_hz;
256unsigned long long tsc_hz;
7ce7d5de 257int base_cpu;
1b439f01 258unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
7f5c258e 259 /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
1b439f01 260unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
7f5c258e 261unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
1b439f01
LB
262unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
263unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
4c2122d4 264unsigned int first_counter_read = 1;
c026c236 265int ignore_stdin;
889facbe 266
71e84129
ZR
267int get_msr(int cpu, off_t offset, unsigned long long *msr);
268
45232ab1
ZR
269/* Model specific support Start */
270
271/* List of features that may diverge among different platforms */
272struct platform_features {
778fc34a 273 bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */
3dd0e754 274 bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */
045acf60 275 bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, MSR_IA32_POWER_CTL, TRL MSRs */
a61c9cb4 276 bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */
71e84129 277 int bclk_freq; /* CPU base clock */
a5d1ab93 278 int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */
3c6a17b8 279 int supported_cstates; /* Core cstates and Package cstates supported */
3989fc89 280 int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */
d90120bf 281 bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */
148df4fd 282 bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */
76d83d2a 283 bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */
9cc1c103 284 bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */
6c36882e 285 bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */
c8202a6c 286 bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */
80d132cb 287 bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */
58ddb691 288 bool has_ext_cst_msrs; /* MSR_PKG_WEIGHTED_CORE_C0_RES/MSR_PKG_ANY_CORE_C0_RES/MSR_PKG_ANY_GFXE_C0_RES/MSR_PKG_BOTH_CORE_GFXE_C0_RES */
7d0ebe6f 289 bool has_cst_prewake_bit; /* Cstate prewake bit in MSR_IA32_POWER_CTL */
10d85d85 290 int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */
0c057cf7 291 int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */
86ba263d 292 int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */
e338831b 293 bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */
6d35b8c4 294 bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */
9e6f3515 295 bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */
7c604093 296 int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */
d8e1623b 297 int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */
485a017c 298 bool enable_tsc_tweak; /* Use CPU Base freq instead of TSC freq for aperf/mperf counter */
ed43247b 299 bool need_perf_multiplier; /* mperf/aperf multiplier */
45232ab1
ZR
300};
301
302struct platform_data {
303 unsigned int model;
304 const struct platform_features *features;
305};
306
71e84129
ZR
307/* For BCLK */
308enum bclk_freq {
309 BCLK_100MHZ = 1,
310 BCLK_133MHZ,
311 BCLK_SLV,
312};
313
314#define SLM_BCLK_FREQS 5
315double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 };
316
317double slm_bclk(void)
318{
319 unsigned long long msr = 3;
320 unsigned int i;
321 double freq;
322
323 if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))
324 fprintf(outf, "SLM BCLK: unknown\n");
325
326 i = msr & 0xf;
327 if (i >= SLM_BCLK_FREQS) {
328 fprintf(outf, "SLM BCLK[%d] invalid\n", i);
329 i = 3;
330 }
331 freq = slm_freq_table[i];
332
333 if (!quiet)
334 fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
335
336 return freq;
337}
338
3989fc89
ZR
339/* For Package cstate limit */
340enum package_cstate_limit {
341 CST_LIMIT_NHM = 1,
342 CST_LIMIT_SNB,
343 CST_LIMIT_HSW,
344 CST_LIMIT_SKX,
345 CST_LIMIT_ICX,
346 CST_LIMIT_SLV,
347 CST_LIMIT_AMT,
348 CST_LIMIT_KNL,
349 CST_LIMIT_GMT,
350};
351
10d85d85
ZR
352/* For Turbo Ratio Limit MSRs */
353enum turbo_ratio_limit_msrs {
354 TRL_BASE = BIT(0),
355 TRL_LIMIT1 = BIT(1),
356 TRL_LIMIT2 = BIT(2),
357 TRL_ATOM = BIT(3),
358 TRL_KNL = BIT(4),
359 TRL_CORECOUNT = BIT(5),
360};
361
0c057cf7
ZR
362/* For Perf Limit Reason MSRs */
363enum perf_limit_reason_msrs {
364 PLR_CORE = BIT(0),
365 PLR_GFX = BIT(1),
366 PLR_RING = BIT(2),
367};
368
b9cd6683
ZR
369/* For RAPL MSRs */
370enum rapl_msrs {
371 RAPL_PKG_POWER_LIMIT = BIT(0), /* 0x610 MSR_PKG_POWER_LIMIT */
372 RAPL_PKG_ENERGY_STATUS = BIT(1), /* 0x611 MSR_PKG_ENERGY_STATUS */
373 RAPL_PKG_PERF_STATUS = BIT(2), /* 0x613 MSR_PKG_PERF_STATUS */
374 RAPL_PKG_POWER_INFO = BIT(3), /* 0x614 MSR_PKG_POWER_INFO */
375 RAPL_DRAM_POWER_LIMIT = BIT(4), /* 0x618 MSR_DRAM_POWER_LIMIT */
376 RAPL_DRAM_ENERGY_STATUS = BIT(5), /* 0x619 MSR_DRAM_ENERGY_STATUS */
377 RAPL_DRAM_PERF_STATUS = BIT(6), /* 0x61b MSR_DRAM_PERF_STATUS */
378 RAPL_DRAM_POWER_INFO = BIT(7), /* 0x61c MSR_DRAM_POWER_INFO */
379 RAPL_CORE_POWER_LIMIT = BIT(8), /* 0x638 MSR_PP0_POWER_LIMIT */
380 RAPL_CORE_ENERGY_STATUS = BIT(9), /* 0x639 MSR_PP0_ENERGY_STATUS */
381 RAPL_CORE_POLICY = BIT(10), /* 0x63a MSR_PP0_POLICY */
382 RAPL_GFX_POWER_LIMIT = BIT(11), /* 0x640 MSR_PP1_POWER_LIMIT */
383 RAPL_GFX_ENERGY_STATUS = BIT(12), /* 0x641 MSR_PP1_ENERGY_STATUS */
384 RAPL_GFX_POLICY = BIT(13), /* 0x642 MSR_PP1_POLICY */
385 RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */
386 RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */
387 RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */
b9cd6683
ZR
388};
389
390#define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT)
391#define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT)
392#define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT)
393#define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS)
394
395#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)
396#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)
397#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY)
398#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLIGY)
399
400#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT)
401
3c6a17b8
ZR
402/* For Cstates */
403enum cstates {
404 CC1 = BIT(0),
405 CC3 = BIT(1),
406 CC6 = BIT(2),
407 CC7 = BIT(3),
408 PC2 = BIT(4),
409 PC3 = BIT(5),
410 PC6 = BIT(6),
411 PC7 = BIT(7),
412 PC8 = BIT(8),
413 PC9 = BIT(9),
414 PC10 = BIT(10),
415};
416
45232ab1 417static const struct platform_features nhm_features = {
3dd0e754 418 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 419 .has_nhm_msrs = 1,
71e84129 420 .bclk_freq = BCLK_133MHZ,
6f1935c0 421 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,
3989fc89 422 .cst_limit = CST_LIMIT_NHM,
10d85d85 423 .trl_msrs = TRL_BASE,
45232ab1
ZR
424};
425
426static const struct platform_features nhx_features = {
3dd0e754 427 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 428 .has_nhm_msrs = 1,
71e84129 429 .bclk_freq = BCLK_133MHZ,
6f1935c0 430 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,
3989fc89 431 .cst_limit = CST_LIMIT_NHM,
45232ab1
ZR
432};
433
434static const struct platform_features snb_features = {
778fc34a 435 .has_msr_misc_feature_control = 1,
3dd0e754 436 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 437 .has_nhm_msrs = 1,
71e84129 438 .bclk_freq = BCLK_100MHZ,
192cbf04 439 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 440 .cst_limit = CST_LIMIT_SNB,
148df4fd 441 .has_irtl_msrs = 1,
10d85d85 442 .trl_msrs = TRL_BASE,
86ba263d 443 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
444};
445
446static const struct platform_features snx_features = {
778fc34a 447 .has_msr_misc_feature_control = 1,
3dd0e754 448 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 449 .has_nhm_msrs = 1,
71e84129 450 .bclk_freq = BCLK_100MHZ,
192cbf04 451 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 452 .cst_limit = CST_LIMIT_SNB,
148df4fd 453 .has_irtl_msrs = 1,
10d85d85 454 .trl_msrs = TRL_BASE,
86ba263d 455 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,
45232ab1
ZR
456};
457
458static const struct platform_features ivb_features = {
778fc34a 459 .has_msr_misc_feature_control = 1,
3dd0e754 460 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 461 .has_nhm_msrs = 1,
a61c9cb4 462 .has_config_tdp = 1,
71e84129 463 .bclk_freq = BCLK_100MHZ,
192cbf04 464 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 465 .cst_limit = CST_LIMIT_SNB,
148df4fd 466 .has_irtl_msrs = 1,
10d85d85 467 .trl_msrs = TRL_BASE,
86ba263d 468 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
469};
470
471static const struct platform_features ivx_features = {
778fc34a 472 .has_msr_misc_feature_control = 1,
3dd0e754 473 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 474 .has_nhm_msrs = 1,
71e84129 475 .bclk_freq = BCLK_100MHZ,
192cbf04 476 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 477 .cst_limit = CST_LIMIT_SNB,
148df4fd 478 .has_irtl_msrs = 1,
10d85d85 479 .trl_msrs = TRL_BASE | TRL_LIMIT1,
86ba263d 480 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,
45232ab1
ZR
481};
482
483static const struct platform_features hsw_features = {
778fc34a 484 .has_msr_misc_feature_control = 1,
3dd0e754 485 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 486 .has_nhm_msrs = 1,
a61c9cb4 487 .has_config_tdp = 1,
71e84129 488 .bclk_freq = BCLK_100MHZ,
192cbf04 489 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 490 .cst_limit = CST_LIMIT_HSW,
148df4fd 491 .has_irtl_msrs = 1,
10d85d85 492 .trl_msrs = TRL_BASE,
0c057cf7 493 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,
86ba263d 494 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
495};
496
497static const struct platform_features hsx_features = {
778fc34a 498 .has_msr_misc_feature_control = 1,
3dd0e754 499 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 500 .has_nhm_msrs = 1,
a61c9cb4 501 .has_config_tdp = 1,
71e84129 502 .bclk_freq = BCLK_100MHZ,
192cbf04 503 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 504 .cst_limit = CST_LIMIT_HSW,
148df4fd 505 .has_irtl_msrs = 1,
10d85d85 506 .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2,
0c057cf7 507 .plr_msrs = PLR_CORE | PLR_RING,
86ba263d 508 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
9e6f3515 509 .has_fixed_rapl_unit = 1,
45232ab1
ZR
510};
511
512static const struct platform_features hswl_features = {
778fc34a 513 .has_msr_misc_feature_control = 1,
3dd0e754 514 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 515 .has_nhm_msrs = 1,
a61c9cb4 516 .has_config_tdp = 1,
71e84129 517 .bclk_freq = BCLK_100MHZ,
4d2c95d4 518 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 519 .cst_limit = CST_LIMIT_HSW,
148df4fd 520 .has_irtl_msrs = 1,
10d85d85 521 .trl_msrs = TRL_BASE,
0c057cf7 522 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,
86ba263d 523 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
524};
525
526static const struct platform_features hswg_features = {
778fc34a 527 .has_msr_misc_feature_control = 1,
3dd0e754 528 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 529 .has_nhm_msrs = 1,
a61c9cb4 530 .has_config_tdp = 1,
71e84129 531 .bclk_freq = BCLK_100MHZ,
192cbf04 532 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 533 .cst_limit = CST_LIMIT_HSW,
148df4fd 534 .has_irtl_msrs = 1,
10d85d85 535 .trl_msrs = TRL_BASE,
0c057cf7 536 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,
86ba263d 537 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
538};
539
540static const struct platform_features bdw_features = {
778fc34a 541 .has_msr_misc_feature_control = 1,
3dd0e754 542 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 543 .has_nhm_msrs = 1,
a61c9cb4 544 .has_config_tdp = 1,
71e84129 545 .bclk_freq = BCLK_100MHZ,
4d2c95d4 546 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 547 .cst_limit = CST_LIMIT_HSW,
148df4fd 548 .has_irtl_msrs = 1,
10d85d85 549 .trl_msrs = TRL_BASE,
86ba263d 550 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
551};
552
553static const struct platform_features bdwg_features = {
778fc34a 554 .has_msr_misc_feature_control = 1,
3dd0e754 555 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 556 .has_nhm_msrs = 1,
a61c9cb4 557 .has_config_tdp = 1,
71e84129 558 .bclk_freq = BCLK_100MHZ,
192cbf04 559 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
3989fc89 560 .cst_limit = CST_LIMIT_HSW,
148df4fd 561 .has_irtl_msrs = 1,
10d85d85 562 .trl_msrs = TRL_BASE,
86ba263d 563 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
45232ab1
ZR
564};
565
566static const struct platform_features bdx_features = {
778fc34a 567 .has_msr_misc_feature_control = 1,
3dd0e754 568 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 569 .has_nhm_msrs = 1,
a61c9cb4 570 .has_config_tdp = 1,
71e84129 571 .bclk_freq = BCLK_100MHZ,
11096948 572 .supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6,
3989fc89 573 .cst_limit = CST_LIMIT_HSW,
148df4fd 574 .has_irtl_msrs = 1,
d90120bf 575 .has_cst_auto_convension = 1,
10d85d85 576 .trl_msrs = TRL_BASE,
86ba263d 577 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
9e6f3515 578 .has_fixed_rapl_unit = 1,
45232ab1
ZR
579};
580
581static const struct platform_features skl_features = {
778fc34a 582 .has_msr_misc_feature_control = 1,
3dd0e754 583 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 584 .has_nhm_msrs = 1,
a61c9cb4 585 .has_config_tdp = 1,
71e84129 586 .bclk_freq = BCLK_100MHZ,
a5d1ab93 587 .crystal_freq = 24000000,
4d2c95d4 588 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 589 .cst_limit = CST_LIMIT_HSW,
148df4fd 590 .has_irtl_msrs = 1,
58ddb691 591 .has_ext_cst_msrs = 1,
10d85d85 592 .trl_msrs = TRL_BASE,
d8e1623b 593 .tcc_offset_bits = 6,
86ba263d 594 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
485a017c 595 .enable_tsc_tweak = 1,
45232ab1
ZR
596};
597
598static const struct platform_features cnl_features = {
778fc34a 599 .has_msr_misc_feature_control = 1,
3dd0e754 600 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 601 .has_nhm_msrs = 1,
a61c9cb4 602 .has_config_tdp = 1,
71e84129 603 .bclk_freq = BCLK_100MHZ,
cd7a2b6a 604 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 605 .cst_limit = CST_LIMIT_HSW,
148df4fd 606 .has_irtl_msrs = 1,
05ad96ff 607 .has_msr_core_c1_res = 1,
58ddb691 608 .has_ext_cst_msrs = 1,
10d85d85 609 .trl_msrs = TRL_BASE,
d8e1623b 610 .tcc_offset_bits = 6,
86ba263d 611 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
485a017c 612 .enable_tsc_tweak = 1,
45232ab1
ZR
613};
614
6b74a30b
ZR
615static const struct platform_features adl_features = {
616 .has_msr_misc_feature_control = 1,
617 .has_msr_misc_pwr_mgmt = 1,
618 .has_nhm_msrs = 1,
619 .has_config_tdp = 1,
620 .bclk_freq = BCLK_100MHZ,
621 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10,
622 .cst_limit = CST_LIMIT_HSW,
623 .has_irtl_msrs = 1,
624 .has_msr_core_c1_res = 1,
625 .has_ext_cst_msrs = 1,
626 .trl_msrs = TRL_BASE,
627 .tcc_offset_bits = 6,
628 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
629 .enable_tsc_tweak = 1,
630};
631
45232ab1 632static const struct platform_features skx_features = {
778fc34a 633 .has_msr_misc_feature_control = 1,
3dd0e754 634 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 635 .has_nhm_msrs = 1,
a61c9cb4 636 .has_config_tdp = 1,
71e84129 637 .bclk_freq = BCLK_100MHZ,
24d16bec 638 .supported_cstates = CC1 | CC6 | PC2 | PC6,
3989fc89 639 .cst_limit = CST_LIMIT_SKX,
148df4fd 640 .has_irtl_msrs = 1,
d90120bf 641 .has_cst_auto_convension = 1,
10d85d85 642 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
86ba263d 643 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
9e6f3515 644 .has_fixed_rapl_unit = 1,
45232ab1
ZR
645};
646
647static const struct platform_features icx_features = {
778fc34a 648 .has_msr_misc_feature_control = 1,
3dd0e754 649 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 650 .has_nhm_msrs = 1,
a61c9cb4 651 .has_config_tdp = 1,
71e84129 652 .bclk_freq = BCLK_100MHZ,
24d16bec 653 .supported_cstates = CC1 | CC6 | PC2 | PC6,
3989fc89 654 .cst_limit = CST_LIMIT_ICX,
148df4fd 655 .has_irtl_msrs = 1,
7d0ebe6f 656 .has_cst_prewake_bit = 1,
10d85d85 657 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
86ba263d 658 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
9e6f3515 659 .has_fixed_rapl_unit = 1,
45232ab1
ZR
660};
661
662static const struct platform_features spr_features = {
778fc34a 663 .has_msr_misc_feature_control = 1,
3dd0e754 664 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 665 .has_nhm_msrs = 1,
a61c9cb4 666 .has_config_tdp = 1,
71e84129 667 .bclk_freq = BCLK_100MHZ,
24d16bec 668 .supported_cstates = CC1 | CC6 | PC2 | PC6,
3989fc89 669 .cst_limit = CST_LIMIT_SKX,
148df4fd 670 .has_irtl_msrs = 1,
7d0ebe6f 671 .has_cst_prewake_bit = 1,
10d85d85 672 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
86ba263d 673 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
45232ab1
ZR
674};
675
676static const struct platform_features slv_features = {
fcfa1ce0 677 .has_nhm_msrs = 1,
71e84129 678 .bclk_freq = BCLK_SLV,
cd7a2b6a 679 .supported_cstates = CC1 | CC6 | PC6,
3989fc89 680 .cst_limit = CST_LIMIT_SLV,
76d83d2a 681 .has_msr_core_c1_res = 1,
9cc1c103 682 .has_msr_module_c6_res_ms = 1,
6c36882e 683 .has_msr_c6_demotion_policy_config = 1,
c8202a6c 684 .has_msr_atom_pkg_c6_residency = 1,
10d85d85 685 .trl_msrs = TRL_ATOM,
86ba263d 686 .rapl_msrs = RAPL_PKG | RAPL_CORE,
6d35b8c4 687 .has_rapl_divisor = 1,
7c604093 688 .rapl_quirk_tdp = 30,
45232ab1
ZR
689};
690
691static const struct platform_features slvd_features = {
3dd0e754 692 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 693 .has_nhm_msrs = 1,
71e84129 694 .bclk_freq = BCLK_SLV,
cd7a2b6a 695 .supported_cstates = CC1 | CC6 | PC3 | PC6,
3989fc89 696 .cst_limit = CST_LIMIT_SLV,
c8202a6c 697 .has_msr_atom_pkg_c6_residency = 1,
10d85d85 698 .trl_msrs = TRL_BASE,
86ba263d 699 .rapl_msrs = RAPL_PKG | RAPL_CORE,
7c604093 700 .rapl_quirk_tdp = 30,
45232ab1
ZR
701};
702
703static const struct platform_features amt_features = {
fcfa1ce0 704 .has_nhm_msrs = 1,
71e84129 705 .bclk_freq = BCLK_133MHZ,
6f1935c0 706 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,
3989fc89 707 .cst_limit = CST_LIMIT_AMT,
10d85d85 708 .trl_msrs = TRL_BASE,
45232ab1
ZR
709};
710
711static const struct platform_features gmt_features = {
3dd0e754 712 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 713 .has_nhm_msrs = 1,
71e84129 714 .bclk_freq = BCLK_100MHZ,
a5d1ab93 715 .crystal_freq = 19200000,
4d2c95d4 716 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 717 .cst_limit = CST_LIMIT_GMT,
148df4fd 718 .has_irtl_msrs = 1,
10d85d85 719 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
86ba263d 720 .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,
45232ab1
ZR
721};
722
723static const struct platform_features gmtd_features = {
3dd0e754 724 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 725 .has_nhm_msrs = 1,
71e84129 726 .bclk_freq = BCLK_100MHZ,
a5d1ab93 727 .crystal_freq = 25000000,
8e20ced0 728 .supported_cstates = CC1 | CC6 | PC2 | PC6,
3989fc89 729 .cst_limit = CST_LIMIT_GMT,
148df4fd 730 .has_irtl_msrs = 1,
76d83d2a 731 .has_msr_core_c1_res = 1,
10d85d85 732 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
86ba263d 733 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS,
45232ab1
ZR
734};
735
736static const struct platform_features gmtp_features = {
3dd0e754 737 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 738 .has_nhm_msrs = 1,
71e84129 739 .bclk_freq = BCLK_100MHZ,
a5d1ab93 740 .crystal_freq = 19200000,
4d2c95d4 741 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 742 .cst_limit = CST_LIMIT_GMT,
148df4fd 743 .has_irtl_msrs = 1,
10d85d85 744 .trl_msrs = TRL_BASE,
86ba263d 745 .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,
45232ab1
ZR
746};
747
748static const struct platform_features tmt_features = {
3dd0e754 749 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 750 .has_nhm_msrs = 1,
71e84129 751 .bclk_freq = BCLK_100MHZ,
cd7a2b6a 752 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
3989fc89 753 .cst_limit = CST_LIMIT_GMT,
148df4fd 754 .has_irtl_msrs = 1,
10d85d85 755 .trl_msrs = TRL_BASE,
86ba263d 756 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
485a017c 757 .enable_tsc_tweak = 1,
45232ab1
ZR
758};
759
760static const struct platform_features tmtd_features = {
3dd0e754 761 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 762 .has_nhm_msrs = 1,
71e84129 763 .bclk_freq = BCLK_100MHZ,
3d982ac0 764 .supported_cstates = CC1 | CC6,
3989fc89 765 .cst_limit = CST_LIMIT_GMT,
148df4fd 766 .has_irtl_msrs = 1,
10d85d85 767 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
86ba263d 768 .rapl_msrs = RAPL_PKG_ALL,
45232ab1
ZR
769};
770
771static const struct platform_features knl_features = {
3dd0e754 772 .has_msr_misc_pwr_mgmt = 1,
fcfa1ce0 773 .has_nhm_msrs = 1,
a61c9cb4 774 .has_config_tdp = 1,
71e84129 775 .bclk_freq = BCLK_100MHZ,
cd7a2b6a 776 .supported_cstates = CC1 | CC6 | PC3 | PC6,
3989fc89 777 .cst_limit = CST_LIMIT_KNL,
80d132cb 778 .has_msr_knl_core_c6_residency = 1,
10d85d85 779 .trl_msrs = TRL_KNL,
86ba263d 780 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
9e6f3515 781 .has_fixed_rapl_unit = 1,
ed43247b 782 .need_perf_multiplier = 1,
45232ab1
ZR
783};
784
785static const struct platform_features default_features = {
786};
787
86ba263d
ZR
788static const struct platform_features amd_features_with_rapl = {
789 .rapl_msrs = RAPL_AMD_F17H,
e338831b 790 .has_per_core_rapl = 1,
7c604093 791 .rapl_quirk_tdp = 280, /* This is the max stock TDP of HEDT/Server Fam17h+ chips */
86ba263d
ZR
792};
793
45232ab1
ZR
794static const struct platform_data turbostat_pdata[] = {
795 { INTEL_FAM6_NEHALEM, &nhm_features },
796 { INTEL_FAM6_NEHALEM_G, &nhm_features },
797 { INTEL_FAM6_NEHALEM_EP, &nhm_features },
798 { INTEL_FAM6_NEHALEM_EX, &nhx_features },
799 { INTEL_FAM6_WESTMERE, &nhm_features },
800 { INTEL_FAM6_WESTMERE_EP, &nhm_features },
801 { INTEL_FAM6_WESTMERE_EX, &nhx_features },
802 { INTEL_FAM6_SANDYBRIDGE, &snb_features },
803 { INTEL_FAM6_SANDYBRIDGE_X, &snx_features },
804 { INTEL_FAM6_IVYBRIDGE, &ivb_features },
805 { INTEL_FAM6_IVYBRIDGE_X, &ivx_features },
806 { INTEL_FAM6_HASWELL, &hsw_features },
807 { INTEL_FAM6_HASWELL_X, &hsx_features },
808 { INTEL_FAM6_HASWELL_L, &hswl_features },
809 { INTEL_FAM6_HASWELL_G, &hswg_features },
810 { INTEL_FAM6_BROADWELL, &bdw_features },
811 { INTEL_FAM6_BROADWELL_G, &bdwg_features },
812 { INTEL_FAM6_BROADWELL_X, &bdx_features },
813 { INTEL_FAM6_BROADWELL_D, &bdx_features },
814 { INTEL_FAM6_SKYLAKE_L, &skl_features },
815 { INTEL_FAM6_SKYLAKE, &skl_features },
816 { INTEL_FAM6_SKYLAKE_X, &skx_features },
817 { INTEL_FAM6_KABYLAKE_L, &skl_features },
818 { INTEL_FAM6_KABYLAKE, &skl_features },
819 { INTEL_FAM6_COMETLAKE, &skl_features },
820 { INTEL_FAM6_COMETLAKE_L, &skl_features },
821 { INTEL_FAM6_CANNONLAKE_L, &cnl_features },
822 { INTEL_FAM6_ICELAKE_X, &icx_features },
823 { INTEL_FAM6_ICELAKE_D, &icx_features },
824 { INTEL_FAM6_ICELAKE_L, &cnl_features },
825 { INTEL_FAM6_ICELAKE_NNPI, &cnl_features },
826 { INTEL_FAM6_ROCKETLAKE, &cnl_features },
827 { INTEL_FAM6_TIGERLAKE_L, &cnl_features },
828 { INTEL_FAM6_TIGERLAKE, &cnl_features },
829 { INTEL_FAM6_SAPPHIRERAPIDS_X, &spr_features },
830 { INTEL_FAM6_EMERALDRAPIDS_X, &spr_features },
831 { INTEL_FAM6_LAKEFIELD, &cnl_features },
6b74a30b
ZR
832 { INTEL_FAM6_ALDERLAKE, &adl_features },
833 { INTEL_FAM6_ALDERLAKE_L, &adl_features },
834 { INTEL_FAM6_RAPTORLAKE, &adl_features },
835 { INTEL_FAM6_RAPTORLAKE_P, &adl_features },
836 { INTEL_FAM6_RAPTORLAKE_S, &adl_features },
45232ab1
ZR
837 { INTEL_FAM6_METEORLAKE, &cnl_features },
838 { INTEL_FAM6_METEORLAKE_L, &cnl_features },
839 { INTEL_FAM6_ATOM_SILVERMONT, &slv_features },
840 { INTEL_FAM6_ATOM_SILVERMONT_D, &slvd_features },
841 { INTEL_FAM6_ATOM_AIRMONT, &amt_features },
842 { INTEL_FAM6_ATOM_GOLDMONT, &gmt_features },
843 { INTEL_FAM6_ATOM_GOLDMONT_D, &gmtd_features },
844 { INTEL_FAM6_ATOM_GOLDMONT_PLUS, &gmtp_features },
845 { INTEL_FAM6_ATOM_TREMONT_D, &tmtd_features },
846 { INTEL_FAM6_ATOM_TREMONT, &tmt_features },
847 { INTEL_FAM6_ATOM_TREMONT_L, &tmt_features },
6b74a30b 848 { INTEL_FAM6_ATOM_GRACEMONT, &adl_features },
45232ab1
ZR
849 { INTEL_FAM6_XEON_PHI_KNL, &knl_features },
850 { INTEL_FAM6_XEON_PHI_KNM, &knl_features },
851 /*
852 * Missing support for
853 * INTEL_FAM6_ICELAKE
854 * INTEL_FAM6_ATOM_SILVERMONT_MID
855 * INTEL_FAM6_ATOM_AIRMONT_MID
856 * INTEL_FAM6_ATOM_AIRMONT_NP
857 */
858 { 0, NULL },
859};
860
861static const struct platform_features *platform;
862
863void probe_platform_features(unsigned int family, unsigned int model)
864{
865 int i;
866
32e8c616 867 platform = &default_features;
86ba263d 868
32e8c616 869 if (authentic_amd || hygon_genuine) {
86ba263d
ZR
870 if (max_extended_level >= 0x80000007) {
871 unsigned int eax, ebx, ecx, edx;
872
873 __cpuid(0x80000007, eax, ebx, ecx, edx);
874 /* RAPL (Fam 17h+) */
e338831b 875 if ((edx & (1 << 14)) && family >= 0x17)
86ba263d 876 platform = &amd_features_with_rapl;
86ba263d 877 }
45232ab1
ZR
878 return;
879 }
880
45232ab1
ZR
881 if (!genuine_intel || family != 6)
882 return;
883
884 for (i = 0; turbostat_pdata[i].features; i++) {
885 if (turbostat_pdata[i].model == model) {
886 platform = turbostat_pdata[i].features;
887 return;
888 }
889 }
890}
891
892/* Model specific support End */
893
889facbe
LB
894#define TJMAX_DEFAULT 100
895
9392bd98
CW
896/* MSRs that are not yet in the kernel-provided header. */
897#define MSR_RAPL_PWR_UNIT 0xc0010299
898#define MSR_CORE_ENERGY_STAT 0xc001029a
899#define MSR_PKG_ENERGY_STAT 0xc001029b
900
889facbe 901#define MAX(a, b) ((a) > (b) ? (a) : (b))
103a8fea 902
103a8fea
LB
903int backwards_count;
904char *progname;
103a8fea 905
1ef7d21a
LB
906#define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */
907cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset;
908size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
0748eaf0
LB
909#define MAX_ADDED_COUNTERS 8
910#define MAX_ADDED_THREAD_COUNTERS 24
0e2d8f05 911#define BITMASK_SIZE 32
c98d5d94
LB
912
913struct thread_data {
f4fdf2b4
LB
914 struct timeval tv_begin;
915 struct timeval tv_end;
d4794f25 916 struct timeval tv_delta;
c98d5d94
LB
917 unsigned long long tsc;
918 unsigned long long aperf;
919 unsigned long long mperf;
144b44b1 920 unsigned long long c1;
2af4f9b8 921 unsigned long long instr_count;
1b439f01 922 unsigned long long irq_count;
1ed51011 923 unsigned int smi_count;
c98d5d94 924 unsigned int cpu_id;
4c2122d4
LB
925 unsigned int apic_id;
926 unsigned int x2apic_id;
c98d5d94 927 unsigned int flags;
7ab5ff49 928 bool is_atom;
c98d5d94
LB
929#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
930#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
0748eaf0 931 unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];
c98d5d94
LB
932} *thread_even, *thread_odd;
933
934struct core_data {
935 unsigned long long c3;
936 unsigned long long c6;
937 unsigned long long c7;
0539ba11 938 unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */
889facbe 939 unsigned int core_temp_c;
9392bd98 940 unsigned int core_energy; /* MSR_CORE_ENERGY_STAT */
c98d5d94 941 unsigned int core_id;
eae97e05 942 unsigned long long core_throt_cnt;
678a3bd1 943 unsigned long long counter[MAX_ADDED_COUNTERS];
c98d5d94
LB
944} *core_even, *core_odd;
945
946struct pkg_data {
947 unsigned long long pc2;
948 unsigned long long pc3;
949 unsigned long long pc6;
950 unsigned long long pc7;
ca58710f
KCA
951 unsigned long long pc8;
952 unsigned long long pc9;
953 unsigned long long pc10;
be0e54c4
LB
954 unsigned long long cpu_lpi;
955 unsigned long long sys_lpi;
0b2bb692
LB
956 unsigned long long pkg_wtd_core_c0;
957 unsigned long long pkg_any_core_c0;
958 unsigned long long pkg_any_gfxe_c0;
959 unsigned long long pkg_both_core_gfxe_c0;
9185e988 960 long long gfx_rc6_ms;
27d47356 961 unsigned int gfx_mhz;
b4b91569 962 unsigned int gfx_act_mhz;
c98d5d94 963 unsigned int package_id;
7c2ccc50
CY
964 unsigned long long energy_pkg; /* MSR_PKG_ENERGY_STATUS */
965 unsigned long long energy_dram; /* MSR_DRAM_ENERGY_STATUS */
966 unsigned long long energy_cores; /* MSR_PP0_ENERGY_STATUS */
967 unsigned long long energy_gfx; /* MSR_PP1_ENERGY_STATUS */
968 unsigned long long rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
969 unsigned long long rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
889facbe 970 unsigned int pkg_temp_c;
a5c6d65d 971 unsigned int uncore_mhz;
678a3bd1 972 unsigned long long counter[MAX_ADDED_COUNTERS];
c98d5d94
LB
973} *package_even, *package_odd;
974
975#define ODD_COUNTERS thread_odd, core_odd, package_odd
976#define EVEN_COUNTERS thread_even, core_even, package_even
977
40f5cfe7
PB
978#define GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no) \
979 ((thread_base) + \
980 ((pkg_no) * \
981 topo.nodes_per_pkg * topo.cores_per_node * topo.threads_per_core) + \
982 ((node_no) * topo.cores_per_node * topo.threads_per_core) + \
983 ((core_no) * topo.threads_per_core) + \
984 (thread_no))
985
986#define GET_CORE(core_base, core_no, node_no, pkg_no) \
987 ((core_base) + \
988 ((pkg_no) * topo.nodes_per_pkg * topo.cores_per_node) + \
989 ((node_no) * topo.cores_per_node) + \
990 (core_no))
991
c98d5d94
LB
992#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
993
87e15da9
CY
994/*
995 * The accumulated sum of MSR is defined as a monotonic
996 * increasing MSR, it will be accumulated periodically,
997 * despite its register's bit width.
998 */
999enum {
1000 IDX_PKG_ENERGY,
1001 IDX_DRAM_ENERGY,
1002 IDX_PP0_ENERGY,
1003 IDX_PP1_ENERGY,
1004 IDX_PKG_PERF,
1005 IDX_DRAM_PERF,
1006 IDX_COUNT,
1007};
1008
1009int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);
1010
1011struct msr_sum_array {
1012 /* get_msr_sum() = sum + (get_msr() - last) */
1013 struct {
1b439f01 1014 /*The accumulated MSR value is updated by the timer */
87e15da9 1015 unsigned long long sum;
1b439f01 1016 /*The MSR footprint recorded in last timer */
87e15da9
CY
1017 unsigned long long last;
1018 } entries[IDX_COUNT];
1019};
1020
1021/* The percpu MSR sum array.*/
1022struct msr_sum_array *per_cpu_msr_sum;
1023
13a779de 1024off_t idx_to_offset(int idx)
87e15da9 1025{
13a779de 1026 off_t offset;
87e15da9
CY
1027
1028 switch (idx) {
1029 case IDX_PKG_ENERGY:
86ba263d 1030 if (platform->rapl_msrs & RAPL_AMD_F17H)
301b1d3a
BN
1031 offset = MSR_PKG_ENERGY_STAT;
1032 else
1033 offset = MSR_PKG_ENERGY_STATUS;
87e15da9
CY
1034 break;
1035 case IDX_DRAM_ENERGY:
1036 offset = MSR_DRAM_ENERGY_STATUS;
1037 break;
1038 case IDX_PP0_ENERGY:
1039 offset = MSR_PP0_ENERGY_STATUS;
1040 break;
1041 case IDX_PP1_ENERGY:
1042 offset = MSR_PP1_ENERGY_STATUS;
1043 break;
1044 case IDX_PKG_PERF:
1045 offset = MSR_PKG_PERF_STATUS;
1046 break;
1047 case IDX_DRAM_PERF:
1048 offset = MSR_DRAM_PERF_STATUS;
1049 break;
1050 default:
1051 offset = -1;
1052 }
1053 return offset;
1054}
1055
13a779de 1056int offset_to_idx(off_t offset)
87e15da9
CY
1057{
1058 int idx;
1059
1060 switch (offset) {
1061 case MSR_PKG_ENERGY_STATUS:
301b1d3a 1062 case MSR_PKG_ENERGY_STAT:
87e15da9
CY
1063 idx = IDX_PKG_ENERGY;
1064 break;
1065 case MSR_DRAM_ENERGY_STATUS:
1066 idx = IDX_DRAM_ENERGY;
1067 break;
1068 case MSR_PP0_ENERGY_STATUS:
1069 idx = IDX_PP0_ENERGY;
1070 break;
1071 case MSR_PP1_ENERGY_STATUS:
1072 idx = IDX_PP1_ENERGY;
1073 break;
1074 case MSR_PKG_PERF_STATUS:
1075 idx = IDX_PKG_PERF;
1076 break;
1077 case MSR_DRAM_PERF_STATUS:
1078 idx = IDX_DRAM_PERF;
1079 break;
1080 default:
1081 idx = -1;
1082 }
1083 return idx;
1084}
1085
1086int idx_valid(int idx)
1087{
1088 switch (idx) {
1089 case IDX_PKG_ENERGY:
86ba263d 1090 return platform->rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H);
87e15da9 1091 case IDX_DRAM_ENERGY:
86ba263d 1092 return platform->rapl_msrs & RAPL_DRAM;
87e15da9 1093 case IDX_PP0_ENERGY:
86ba263d 1094 return platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS;
87e15da9 1095 case IDX_PP1_ENERGY:
86ba263d 1096 return platform->rapl_msrs & RAPL_GFX;
87e15da9 1097 case IDX_PKG_PERF:
86ba263d 1098 return platform->rapl_msrs & RAPL_PKG_PERF_STATUS;
87e15da9 1099 case IDX_DRAM_PERF:
86ba263d 1100 return platform->rapl_msrs & RAPL_DRAM_PERF_STATUS;
87e15da9
CY
1101 default:
1102 return 0;
1103 }
1104}
1b439f01 1105
388e9c81 1106struct sys_counters {
678a3bd1
LB
1107 unsigned int added_thread_counters;
1108 unsigned int added_core_counters;
1109 unsigned int added_package_counters;
388e9c81
LB
1110 struct msr_counter *tp;
1111 struct msr_counter *cp;
1112 struct msr_counter *pp;
1113} sys;
1114
c98d5d94
LB
1115struct system_summary {
1116 struct thread_data threads;
1117 struct core_data cores;
1118 struct pkg_data packages;
388e9c81 1119} average;
c98d5d94 1120
0e2d8f05
LB
1121struct cpu_topology {
1122 int physical_package_id;
6de68fe1 1123 int die_id;
0e2d8f05 1124 int logical_cpu_id;
ef605741
PB
1125 int physical_node_id;
1126 int logical_node_id; /* 0-based count within the package */
0e2d8f05 1127 int physical_core_id;
8cb48b32 1128 int thread_id;
1b439f01 1129 cpu_set_t *put_ids; /* Processing Unit/Thread IDs */
0e2d8f05 1130} *cpus;
c98d5d94
LB
1131
1132struct topo_params {
1133 int num_packages;
6de68fe1 1134 int num_die;
c98d5d94
LB
1135 int num_cpus;
1136 int num_cores;
1137 int max_cpu_num;
ef605741 1138 int max_node_num;
70a9c6e8
PB
1139 int nodes_per_pkg;
1140 int cores_per_node;
1141 int threads_per_core;
c98d5d94
LB
1142} topo;
1143
1144struct timeval tv_even, tv_odd, tv_delta;
1145
1b439f01 1146int *irq_column_2_cpu; /* /proc/interrupts column numbers */
562a2d37
LB
1147int *irqs_per_cpu; /* indexed by cpu_num */
1148
c98d5d94
LB
1149void setup_all_buffers(void);
1150
1f81c5ef
LB
1151char *sys_lpi_file;
1152char *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us";
1153char *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec";
1154
c98d5d94 1155int cpu_is_not_present(int cpu)
d15cf7c1 1156{
c98d5d94 1157 return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);
d15cf7c1 1158}
1b439f01 1159
88c3281f 1160/*
c98d5d94
LB
1161 * run func(thread, core, package) in topology order
1162 * skip non-present cpus
88c3281f 1163 */
c98d5d94 1164
1b439f01
LB
1165int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *),
1166 struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
88c3281f 1167{
40f5cfe7 1168 int retval, pkg_no, core_no, thread_no, node_no;
d15cf7c1 1169
c98d5d94 1170 for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
df2f677d
LB
1171 for (node_no = 0; node_no < topo.nodes_per_pkg; node_no++) {
1172 for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {
1b439f01 1173 for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) {
40f5cfe7
PB
1174 struct thread_data *t;
1175 struct core_data *c;
1176 struct pkg_data *p;
1177
1b439f01 1178 t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no);
40f5cfe7
PB
1179
1180 if (cpu_is_not_present(t->cpu_id))
1181 continue;
1182
1b439f01 1183 c = GET_CORE(core_base, core_no, node_no, pkg_no);
40f5cfe7
PB
1184 p = GET_PKG(pkg_base, pkg_no);
1185
1186 retval = func(t, c, p);
1187 if (retval)
1188 return retval;
1189 }
c98d5d94
LB
1190 }
1191 }
1192 }
1193 return 0;
88c3281f
LB
1194}
1195
1196int cpu_migrate(int cpu)
1197{
c98d5d94
LB
1198 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
1199 CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
1200 if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)
88c3281f
LB
1201 return -1;
1202 else
1203 return 0;
1204}
1b439f01 1205
36229897 1206int get_msr_fd(int cpu)
103a8fea 1207{
103a8fea
LB
1208 char pathname[32];
1209 int fd;
1210
36229897
LB
1211 fd = fd_percpu[cpu];
1212
1213 if (fd)
1214 return fd;
1215
103a8fea
LB
1216 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
1217 fd = open(pathname, O_RDONLY);
15aaa346 1218 if (fd < 0)
98481e79 1219 err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
103a8fea 1220
36229897
LB
1221 fd_percpu[cpu] = fd;
1222
1223 return fd;
1224}
1225
2af4f9b8
LB
1226static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)
1227{
1228 return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
1229}
1230
1231static int perf_instr_count_open(int cpu_num)
1232{
1233 struct perf_event_attr pea;
1234 int fd;
1235
1236 memset(&pea, 0, sizeof(struct perf_event_attr));
1237 pea.type = PERF_TYPE_HARDWARE;
1238 pea.size = sizeof(struct perf_event_attr);
1239 pea.config = PERF_COUNT_HW_INSTRUCTIONS;
1240
1241 /* counter for cpu_num, including user + kernel and all processes */
1242 fd = perf_event_open(&pea, -1, cpu_num, -1, 0);
164d7a96 1243 if (fd == -1) {
de7839ee 1244 warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"", progname);
164d7a96
LB
1245 BIC_NOT_PRESENT(BIC_IPC);
1246 }
2af4f9b8
LB
1247
1248 return fd;
1249}
1250
1251int get_instr_count_fd(int cpu)
1252{
1253 if (fd_instr_count_percpu[cpu])
1254 return fd_instr_count_percpu[cpu];
1255
1256 fd_instr_count_percpu[cpu] = perf_instr_count_open(cpu);
1257
1258 return fd_instr_count_percpu[cpu];
1259}
1260
36229897
LB
1261int get_msr(int cpu, off_t offset, unsigned long long *msr)
1262{
1263 ssize_t retval;
1264
1265 retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
15aaa346 1266
98481e79 1267 if (retval != sizeof *msr)
cf4cbe53 1268 err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
15aaa346
LB
1269
1270 return 0;
103a8fea
LB
1271}
1272
dd778a5e 1273#define MAX_DEFERRED 16
0fc521bc 1274char *deferred_add_names[MAX_DEFERRED];
dd778a5e 1275char *deferred_skip_names[MAX_DEFERRED];
0fc521bc 1276int deferred_add_index;
dd778a5e
LB
1277int deferred_skip_index;
1278
1279/*
1280 * HIDE_LIST - hide this list of counters, show the rest [default]
1281 * SHOW_LIST - show this list of counters, hide the rest
1282 */
1283enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
1284
1285void help(void)
1286{
1287 fprintf(outf,
1b439f01
LB
1288 "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
1289 "\n"
1290 "Turbostat forks the specified COMMAND and prints statistics\n"
1291 "when COMMAND completes.\n"
1292 "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
1293 "to print statistics, until interrupted.\n"
1294 " -a, --add add a counter\n"
1295 " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
1296 " -c, --cpu cpu-set limit output to summary plus cpu-set:\n"
1297 " {core | package | j,k,l..m,n-p }\n"
1298 " -d, --debug displays usec, Time_Of_Day_Seconds and more debugging\n"
1299 " -D, --Dump displays the raw counter values\n"
1300 " -e, --enable [all | column]\n"
1301 " shows all or the specified disabled column\n"
1302 " -H, --hide [column|column,column,...]\n"
1303 " hide the specified column(s)\n"
1304 " -i, --interval sec.subsec\n"
1305 " Override default 5-second measurement interval\n"
1306 " -J, --Joules displays energy in Joules instead of Watts\n"
1307 " -l, --list list column headers only\n"
1308 " -n, --num_iterations num\n"
1309 " number of the measurement iterations\n"
c7e399f8
ZLCH
1310 " -N, --header_iterations num\n"
1311 " print header every num iterations\n"
1b439f01
LB
1312 " -o, --out file\n"
1313 " create or truncate \"file\" for all output\n"
1314 " -q, --quiet skip decoding system configuration header\n"
1315 " -s, --show [column|column,column,...]\n"
1316 " show only the specified column(s)\n"
1317 " -S, --Summary\n"
1318 " limits output to 1-line system summary per interval\n"
1319 " -T, --TCC temperature\n"
1320 " sets the Thermal Control Circuit temperature in\n"
1321 " degrees Celsius\n"
1322 " -h, --help print this help message\n"
1323 " -v, --version print version information\n" "\n" "For more help, run \"man turbostat\"\n");
dd778a5e
LB
1324}
1325
812db3f7
LB
1326/*
1327 * bic_lookup
1328 * for all the strings in comma separate name_list,
1329 * set the approprate bit in return value.
1330 */
dd778a5e 1331unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
812db3f7 1332{
9878bf7a 1333 unsigned int i;
812db3f7
LB
1334 unsigned long long retval = 0;
1335
1336 while (name_list) {
1337 char *comma;
1338
1339 comma = strchr(name_list, ',');
1340
1341 if (comma)
1342 *comma = '\0';
1343
1344 for (i = 0; i < MAX_BIC; ++i) {
1345 if (!strcmp(name_list, bic[i].name)) {
1346 retval |= (1ULL << i);
1347 break;
1348 }
5dc241f2
LB
1349 if (!strcmp(name_list, "all")) {
1350 retval |= ~0;
1351 break;
1352 } else if (!strcmp(name_list, "topology")) {
1353 retval |= BIC_TOPOLOGY;
1354 break;
1355 } else if (!strcmp(name_list, "power")) {
1356 retval |= BIC_THERMAL_PWR;
1357 break;
1358 } else if (!strcmp(name_list, "idle")) {
1359 retval |= BIC_IDLE;
1360 break;
1361 } else if (!strcmp(name_list, "frequency")) {
1362 retval |= BIC_FREQUENCY;
1363 break;
1364 } else if (!strcmp(name_list, "other")) {
1365 retval |= BIC_OTHER;
1366 break;
1367 }
1368
812db3f7
LB
1369 }
1370 if (i == MAX_BIC) {
dd778a5e 1371 if (mode == SHOW_LIST) {
0fc521bc
ZLCH
1372 deferred_add_names[deferred_add_index++] = name_list;
1373 if (deferred_add_index >= MAX_DEFERRED) {
1374 fprintf(stderr, "More than max %d un-recognized --add options '%s'\n",
164d7a96 1375 MAX_DEFERRED, name_list);
0fc521bc
ZLCH
1376 help();
1377 exit(1);
1378 }
1379 } else {
1380 deferred_skip_names[deferred_skip_index++] = name_list;
1381 if (debug)
1382 fprintf(stderr, "deferred \"%s\"\n", name_list);
1383 if (deferred_skip_index >= MAX_DEFERRED) {
1384 fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
164d7a96 1385 MAX_DEFERRED, name_list);
0fc521bc
ZLCH
1386 help();
1387 exit(1);
1388 }
dd778a5e 1389 }
812db3f7
LB
1390 }
1391
1392 name_list = comma;
1393 if (name_list)
1394 name_list++;
1395
1396 }
1397 return retval;
1398}
fc04cc67 1399
c8ade361 1400void print_header(char *delim)
103a8fea 1401{
388e9c81 1402 struct msr_counter *mp;
6168c2e0 1403 int printed = 0;
388e9c81 1404
3f44a5c6
LB
1405 if (DO_BIC(BIC_USEC))
1406 outp += sprintf(outp, "%susec", (printed++ ? delim : ""));
1407 if (DO_BIC(BIC_TOD))
1408 outp += sprintf(outp, "%sTime_Of_Day_Seconds", (printed++ ? delim : ""));
812db3f7 1409 if (DO_BIC(BIC_Package))
6168c2e0 1410 outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));
6de68fe1
LB
1411 if (DO_BIC(BIC_Die))
1412 outp += sprintf(outp, "%sDie", (printed++ ? delim : ""));
01235041
PB
1413 if (DO_BIC(BIC_Node))
1414 outp += sprintf(outp, "%sNode", (printed++ ? delim : ""));
812db3f7 1415 if (DO_BIC(BIC_Core))
6168c2e0 1416 outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
812db3f7 1417 if (DO_BIC(BIC_CPU))
6168c2e0 1418 outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
4c2122d4
LB
1419 if (DO_BIC(BIC_APIC))
1420 outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));
1421 if (DO_BIC(BIC_X2APIC))
1422 outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));
812db3f7 1423 if (DO_BIC(BIC_Avg_MHz))
6168c2e0 1424 outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
812db3f7 1425 if (DO_BIC(BIC_Busy))
6168c2e0 1426 outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));
812db3f7 1427 if (DO_BIC(BIC_Bzy_MHz))
6168c2e0 1428 outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));
812db3f7 1429 if (DO_BIC(BIC_TSC_MHz))
6168c2e0 1430 outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));
1cc21f7b 1431
2af4f9b8
LB
1432 if (DO_BIC(BIC_IPC))
1433 outp += sprintf(outp, "%sIPC", (printed++ ? delim : ""));
1434
0de6c0df
LB
1435 if (DO_BIC(BIC_IRQ)) {
1436 if (sums_need_wide_columns)
6168c2e0 1437 outp += sprintf(outp, "%s IRQ", (printed++ ? delim : ""));
0de6c0df 1438 else
6168c2e0 1439 outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));
0de6c0df
LB
1440 }
1441
812db3f7 1442 if (DO_BIC(BIC_SMI))
6168c2e0 1443 outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));
1cc21f7b 1444
388e9c81 1445 for (mp = sys.tp; mp; mp = mp->next) {
dd778a5e 1446
388e9c81
LB
1447 if (mp->format == FORMAT_RAW) {
1448 if (mp->width == 64)
dd778a5e 1449 outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), mp->name);
388e9c81 1450 else
dd778a5e 1451 outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), mp->name);
388e9c81 1452 } else {
0de6c0df 1453 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
dd778a5e 1454 outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), mp->name);
0de6c0df 1455 else
dd778a5e 1456 outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), mp->name);
388e9c81
LB
1457 }
1458 }
1459
41618e63 1460 if (DO_BIC(BIC_CPU_c1))
6168c2e0 1461 outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));
562855ee 1462 if (DO_BIC(BIC_CPU_c3))
6168c2e0 1463 outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));
812db3f7 1464 if (DO_BIC(BIC_CPU_c6))
6168c2e0 1465 outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));
812db3f7 1466 if (DO_BIC(BIC_CPU_c7))
6168c2e0 1467 outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));
678a3bd1 1468
0539ba11 1469 if (DO_BIC(BIC_Mod_c6))
6168c2e0 1470 outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));
678a3bd1 1471
812db3f7 1472 if (DO_BIC(BIC_CoreTmp))
6168c2e0 1473 outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));
388e9c81 1474
eae97e05
CY
1475 if (DO_BIC(BIC_CORE_THROT_CNT))
1476 outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : ""));
1477
86ba263d 1478 if (platform->rapl_msrs && !rapl_joules) {
e338831b 1479 if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl)
9392bd98 1480 outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
86ba263d 1481 } else if (platform->rapl_msrs && rapl_joules) {
e338831b 1482 if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl)
9392bd98
CW
1483 outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
1484 }
1485
388e9c81
LB
1486 for (mp = sys.cp; mp; mp = mp->next) {
1487 if (mp->format == FORMAT_RAW) {
1488 if (mp->width == 64)
c8ade361 1489 outp += sprintf(outp, "%s%18.18s", delim, mp->name);
388e9c81 1490 else
c8ade361 1491 outp += sprintf(outp, "%s%10.10s", delim, mp->name);
388e9c81 1492 } else {
0de6c0df
LB
1493 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
1494 outp += sprintf(outp, "%s%8s", delim, mp->name);
1495 else
1496 outp += sprintf(outp, "%s%s", delim, mp->name);
388e9c81
LB
1497 }
1498 }
1499
812db3f7 1500 if (DO_BIC(BIC_PkgTmp))
6168c2e0 1501 outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));
889facbe 1502
812db3f7 1503 if (DO_BIC(BIC_GFX_rc6))
6168c2e0 1504 outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));
fdf676e5 1505
812db3f7 1506 if (DO_BIC(BIC_GFXMHz))
6168c2e0 1507 outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
27d47356 1508
b4b91569
RA
1509 if (DO_BIC(BIC_GFXACTMHz))
1510 outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));
1511
a99d8730 1512 if (DO_BIC(BIC_Totl_c0))
6168c2e0 1513 outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
a99d8730 1514 if (DO_BIC(BIC_Any_c0))
6168c2e0 1515 outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));
a99d8730 1516 if (DO_BIC(BIC_GFX_c0))
6168c2e0 1517 outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));
a99d8730 1518 if (DO_BIC(BIC_CPUGFX))
6168c2e0 1519 outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));
0b2bb692 1520
0f47c08d 1521 if (DO_BIC(BIC_Pkgpc2))
6168c2e0 1522 outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));
0f47c08d 1523 if (DO_BIC(BIC_Pkgpc3))
6168c2e0 1524 outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));
0f47c08d 1525 if (DO_BIC(BIC_Pkgpc6))
6168c2e0 1526 outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));
0f47c08d 1527 if (DO_BIC(BIC_Pkgpc7))
6168c2e0 1528 outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));
0f47c08d 1529 if (DO_BIC(BIC_Pkgpc8))
6168c2e0 1530 outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));
0f47c08d 1531 if (DO_BIC(BIC_Pkgpc9))
6168c2e0 1532 outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));
0f47c08d 1533 if (DO_BIC(BIC_Pkgpc10))
6168c2e0 1534 outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));
be0e54c4
LB
1535 if (DO_BIC(BIC_CPU_LPI))
1536 outp += sprintf(outp, "%sCPU%%LPI", (printed++ ? delim : ""));
1537 if (DO_BIC(BIC_SYS_LPI))
1538 outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));
103a8fea 1539
86ba263d 1540 if (platform->rapl_msrs && !rapl_joules) {
812db3f7 1541 if (DO_BIC(BIC_PkgWatt))
6168c2e0 1542 outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
e338831b 1543 if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)
6168c2e0 1544 outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
812db3f7 1545 if (DO_BIC(BIC_GFXWatt))
6168c2e0 1546 outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));
812db3f7 1547 if (DO_BIC(BIC_RAMWatt))
6168c2e0 1548 outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));
812db3f7 1549 if (DO_BIC(BIC_PKG__))
6168c2e0 1550 outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
812db3f7 1551 if (DO_BIC(BIC_RAM__))
6168c2e0 1552 outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
86ba263d 1553 } else if (platform->rapl_msrs && rapl_joules) {
812db3f7 1554 if (DO_BIC(BIC_Pkg_J))
6168c2e0 1555 outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
e338831b 1556 if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)
6168c2e0 1557 outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
812db3f7 1558 if (DO_BIC(BIC_GFX_J))
6168c2e0 1559 outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));
812db3f7 1560 if (DO_BIC(BIC_RAM_J))
6168c2e0 1561 outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));
812db3f7 1562 if (DO_BIC(BIC_PKG__))
6168c2e0 1563 outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
812db3f7 1564 if (DO_BIC(BIC_RAM__))
6168c2e0 1565 outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
5c56be9a 1566 }
a5c6d65d
LB
1567 if (DO_BIC(BIC_UNCORE_MHZ))
1568 outp += sprintf(outp, "%sUncMHz", (printed++ ? delim : ""));
1569
388e9c81
LB
1570 for (mp = sys.pp; mp; mp = mp->next) {
1571 if (mp->format == FORMAT_RAW) {
1572 if (mp->width == 64)
c8ade361 1573 outp += sprintf(outp, "%s%18.18s", delim, mp->name);
388e9c81 1574 else
c8ade361 1575 outp += sprintf(outp, "%s%10.10s", delim, mp->name);
388e9c81 1576 } else {
0de6c0df
LB
1577 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
1578 outp += sprintf(outp, "%s%8s", delim, mp->name);
1579 else
1580 outp += sprintf(outp, "%s%s", delim, mp->name);
388e9c81
LB
1581 }
1582 }
1583
c98d5d94 1584 outp += sprintf(outp, "\n");
103a8fea
LB
1585}
1586
1b439f01 1587int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
103a8fea 1588{
388e9c81
LB
1589 int i;
1590 struct msr_counter *mp;
1591
3b4d5c7f 1592 outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);
c98d5d94
LB
1593
1594 if (t) {
1b439f01 1595 outp += sprintf(outp, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags);
3b4d5c7f
AS
1596 outp += sprintf(outp, "TSC: %016llX\n", t->tsc);
1597 outp += sprintf(outp, "aperf: %016llX\n", t->aperf);
1598 outp += sprintf(outp, "mperf: %016llX\n", t->mperf);
1599 outp += sprintf(outp, "c1: %016llX\n", t->c1);
6886fee4 1600
2af4f9b8
LB
1601 if (DO_BIC(BIC_IPC))
1602 outp += sprintf(outp, "IPC: %lld\n", t->instr_count);
1603
812db3f7 1604 if (DO_BIC(BIC_IRQ))
0de6c0df 1605 outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);
812db3f7 1606 if (DO_BIC(BIC_SMI))
218f0e8d 1607 outp += sprintf(outp, "SMI: %d\n", t->smi_count);
388e9c81
LB
1608
1609 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1b439f01 1610 outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, t->counter[i]);
388e9c81 1611 }
c98d5d94 1612 }
103a8fea 1613
c98d5d94 1614 if (c) {
3b4d5c7f
AS
1615 outp += sprintf(outp, "core: %d\n", c->core_id);
1616 outp += sprintf(outp, "c3: %016llX\n", c->c3);
1617 outp += sprintf(outp, "c6: %016llX\n", c->c6);
1618 outp += sprintf(outp, "c7: %016llX\n", c->c7);
1619 outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c);
eae97e05 1620 outp += sprintf(outp, "cpu_throt_count: %016llX\n", c->core_throt_cnt);
9392bd98 1621 outp += sprintf(outp, "Joules: %0X\n", c->core_energy);
388e9c81
LB
1622
1623 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1b439f01 1624 outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, c->counter[i]);
388e9c81 1625 }
0539ba11 1626 outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);
c98d5d94 1627 }
103a8fea 1628
c98d5d94 1629 if (p) {
3b4d5c7f 1630 outp += sprintf(outp, "package: %d\n", p->package_id);
0b2bb692
LB
1631
1632 outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0);
1633 outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0);
1634 outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0);
1635 outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);
1636
3b4d5c7f 1637 outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
0f47c08d 1638 if (DO_BIC(BIC_Pkgpc3))
ee7e38e3 1639 outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
0f47c08d 1640 if (DO_BIC(BIC_Pkgpc6))
ee7e38e3 1641 outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
0f47c08d 1642 if (DO_BIC(BIC_Pkgpc7))
ee7e38e3 1643 outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
3b4d5c7f
AS
1644 outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
1645 outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
1646 outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
be0e54c4
LB
1647 outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
1648 outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
7c2ccc50
CY
1649 outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg);
1650 outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores);
1651 outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx);
1652 outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram);
1b439f01
LB
1653 outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status);
1654 outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status);
3b4d5c7f 1655 outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
388e9c81
LB
1656
1657 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1b439f01 1658 outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, p->counter[i]);
388e9c81 1659 }
c98d5d94 1660 }
3b4d5c7f
AS
1661
1662 outp += sprintf(outp, "\n");
1663
c98d5d94 1664 return 0;
103a8fea
LB
1665}
1666
e23da037
LB
1667/*
1668 * column formatting convention & formats
e23da037 1669 */
1b439f01 1670int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
103a8fea 1671{
008d396e 1672 double interval_float, tsc;
fc04cc67 1673 char *fmt8;
388e9c81
LB
1674 int i;
1675 struct msr_counter *mp;
6168c2e0
LB
1676 char *delim = "\t";
1677 int printed = 0;
103a8fea 1678
1b439f01 1679 /* if showing only 1st thread in core and this isn't one, bail out */
c98d5d94
LB
1680 if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1681 return 0;
1682
1b439f01 1683 /* if showing only 1st thread in pkg and this isn't one, bail out */
c98d5d94
LB
1684 if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1685 return 0;
1686
1ef7d21a 1687 /*if not summary line and --cpu is used */
1b439f01 1688 if ((t != &average.threads) && (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
1ef7d21a
LB
1689 return 0;
1690
3f44a5c6 1691 if (DO_BIC(BIC_USEC)) {
f4fdf2b4
LB
1692 /* on each row, print how many usec each timestamp took to gather */
1693 struct timeval tv;
1694
1695 timersub(&t->tv_end, &t->tv_begin, &tv);
1696 outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec);
1697 }
1698
3f44a5c6
LB
1699 /* Time_Of_Day_Seconds: on each row, print sec.usec last timestamp taken */
1700 if (DO_BIC(BIC_TOD))
1701 outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
1702
1b439f01 1703 interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec / 1000000.0;
103a8fea 1704
008d396e
LB
1705 tsc = t->tsc * tsc_tweak;
1706
c98d5d94
LB
1707 /* topo columns, print blanks on 1st (average) line */
1708 if (t == &average.threads) {
812db3f7 1709 if (DO_BIC(BIC_Package))
6168c2e0 1710 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
6de68fe1
LB
1711 if (DO_BIC(BIC_Die))
1712 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
01235041
PB
1713 if (DO_BIC(BIC_Node))
1714 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
812db3f7 1715 if (DO_BIC(BIC_Core))
6168c2e0 1716 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
812db3f7 1717 if (DO_BIC(BIC_CPU))
6168c2e0 1718 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
4c2122d4
LB
1719 if (DO_BIC(BIC_APIC))
1720 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1721 if (DO_BIC(BIC_X2APIC))
1722 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
103a8fea 1723 } else {
812db3f7 1724 if (DO_BIC(BIC_Package)) {
c98d5d94 1725 if (p)
6168c2e0 1726 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id);
c98d5d94 1727 else
6168c2e0 1728 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
c98d5d94 1729 }
6de68fe1
LB
1730 if (DO_BIC(BIC_Die)) {
1731 if (c)
1732 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].die_id);
1733 else
1734 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1735 }
01235041
PB
1736 if (DO_BIC(BIC_Node)) {
1737 if (t)
1738 outp += sprintf(outp, "%s%d",
1b439f01 1739 (printed++ ? delim : ""), cpus[t->cpu_id].physical_node_id);
01235041 1740 else
1b439f01 1741 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
01235041 1742 }
812db3f7 1743 if (DO_BIC(BIC_Core)) {
c98d5d94 1744 if (c)
6168c2e0 1745 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id);
c98d5d94 1746 else
6168c2e0 1747 outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
c98d5d94 1748 }
812db3f7 1749 if (DO_BIC(BIC_CPU))
6168c2e0 1750 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
4c2122d4
LB
1751 if (DO_BIC(BIC_APIC))
1752 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);
1753 if (DO_BIC(BIC_X2APIC))
1754 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);
103a8fea 1755 }
fc04cc67 1756
812db3f7 1757 if (DO_BIC(BIC_Avg_MHz))
1b439f01 1758 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 / units * t->aperf / interval_float);
fc04cc67 1759
812db3f7 1760 if (DO_BIC(BIC_Busy))
1b439f01 1761 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf / tsc);
103a8fea 1762
812db3f7 1763 if (DO_BIC(BIC_Bzy_MHz)) {
21ed5574 1764 if (has_base_hz)
1b439f01
LB
1765 outp +=
1766 sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
21ed5574 1767 else
6168c2e0 1768 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
1b439f01 1769 tsc / units * t->aperf / t->mperf / interval_float);
21ed5574 1770 }
103a8fea 1771
812db3f7 1772 if (DO_BIC(BIC_TSC_MHz))
1b439f01 1773 outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc / units / interval_float);
103a8fea 1774
2af4f9b8
LB
1775 if (DO_BIC(BIC_IPC))
1776 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 1.0 * t->instr_count / t->aperf);
1777
562a2d37 1778 /* IRQ */
0de6c0df
LB
1779 if (DO_BIC(BIC_IRQ)) {
1780 if (sums_need_wide_columns)
6168c2e0 1781 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);
0de6c0df 1782 else
6168c2e0 1783 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);
0de6c0df 1784 }
562a2d37 1785
1cc21f7b 1786 /* SMI */
812db3f7 1787 if (DO_BIC(BIC_SMI))
6168c2e0 1788 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);
1cc21f7b 1789
678a3bd1 1790 /* Added counters */
388e9c81
LB
1791 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1792 if (mp->format == FORMAT_RAW) {
1793 if (mp->width == 32)
1b439f01
LB
1794 outp +=
1795 sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)t->counter[i]);
388e9c81 1796 else
6168c2e0 1797 outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
388e9c81 1798 } else if (mp->format == FORMAT_DELTA) {
0de6c0df 1799 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
6168c2e0 1800 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->counter[i]);
0de6c0df 1801 else
6168c2e0 1802 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);
388e9c81 1803 } else if (mp->format == FORMAT_PERCENT) {
41618e63 1804 if (mp->type == COUNTER_USEC)
1b439f01
LB
1805 outp +=
1806 sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
1807 t->counter[i] / interval_float / 10000);
41618e63 1808 else
1b439f01 1809 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i] / tsc);
388e9c81
LB
1810 }
1811 }
1812
41618e63
LB
1813 /* C1 */
1814 if (DO_BIC(BIC_CPU_c1))
1b439f01 1815 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1 / tsc);
41618e63 1816
678a3bd1
LB
1817 /* print per-core data only for 1st thread in core */
1818 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1819 goto done;
1820
562855ee 1821 if (DO_BIC(BIC_CPU_c3))
1b439f01 1822 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3 / tsc);
812db3f7 1823 if (DO_BIC(BIC_CPU_c6))
1b439f01 1824 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6 / tsc);
812db3f7 1825 if (DO_BIC(BIC_CPU_c7))
1b439f01 1826 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7 / tsc);
678a3bd1 1827
0539ba11
LB
1828 /* Mod%c6 */
1829 if (DO_BIC(BIC_Mod_c6))
6168c2e0 1830 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->mc6_us / tsc);
0539ba11 1831
812db3f7 1832 if (DO_BIC(BIC_CoreTmp))
6168c2e0 1833 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
889facbe 1834
eae97e05
CY
1835 /* Core throttle count */
1836 if (DO_BIC(BIC_CORE_THROT_CNT))
1837 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->core_throt_cnt);
1838
388e9c81
LB
1839 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1840 if (mp->format == FORMAT_RAW) {
1841 if (mp->width == 32)
1b439f01
LB
1842 outp +=
1843 sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)c->counter[i]);
388e9c81 1844 else
6168c2e0 1845 outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
388e9c81 1846 } else if (mp->format == FORMAT_DELTA) {
0de6c0df 1847 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
6168c2e0 1848 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->counter[i]);
0de6c0df 1849 else
6168c2e0 1850 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);
388e9c81 1851 } else if (mp->format == FORMAT_PERCENT) {
1b439f01 1852 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i] / tsc);
388e9c81
LB
1853 }
1854 }
1855
9972d5d8 1856 fmt8 = "%s%.2f";
9392bd98 1857
e338831b 1858 if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl)
1b439f01
LB
1859 outp +=
1860 sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
e338831b 1861 if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl)
9392bd98
CW
1862 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units);
1863
c98d5d94
LB
1864 /* print per-package data only for 1st core in package */
1865 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1866 goto done;
1867
0b2bb692 1868 /* PkgTmp */
812db3f7 1869 if (DO_BIC(BIC_PkgTmp))
6168c2e0 1870 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);
889facbe 1871
fdf676e5 1872 /* GFXrc6 */
812db3f7 1873 if (DO_BIC(BIC_GFX_rc6)) {
ba3dec99 1874 if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */
6168c2e0 1875 outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
9185e988 1876 } else {
6168c2e0 1877 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
1b439f01 1878 p->gfx_rc6_ms / 10.0 / interval_float);
9185e988
LB
1879 }
1880 }
fdf676e5 1881
27d47356 1882 /* GFXMHz */
812db3f7 1883 if (DO_BIC(BIC_GFXMHz))
6168c2e0 1884 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
27d47356 1885
b4b91569
RA
1886 /* GFXACTMHz */
1887 if (DO_BIC(BIC_GFXACTMHz))
1888 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);
1889
0b2bb692 1890 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
a99d8730 1891 if (DO_BIC(BIC_Totl_c0))
1b439f01 1892 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0 / tsc);
a99d8730 1893 if (DO_BIC(BIC_Any_c0))
1b439f01 1894 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0 / tsc);
a99d8730 1895 if (DO_BIC(BIC_GFX_c0))
1b439f01 1896 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0 / tsc);
a99d8730 1897 if (DO_BIC(BIC_CPUGFX))
1b439f01 1898 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0 / tsc);
0b2bb692 1899
0f47c08d 1900 if (DO_BIC(BIC_Pkgpc2))
1b439f01 1901 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2 / tsc);
0f47c08d 1902 if (DO_BIC(BIC_Pkgpc3))
1b439f01 1903 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3 / tsc);
0f47c08d 1904 if (DO_BIC(BIC_Pkgpc6))
1b439f01 1905 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6 / tsc);
0f47c08d 1906 if (DO_BIC(BIC_Pkgpc7))
1b439f01 1907 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7 / tsc);
0f47c08d 1908 if (DO_BIC(BIC_Pkgpc8))
1b439f01 1909 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8 / tsc);
0f47c08d 1910 if (DO_BIC(BIC_Pkgpc9))
1b439f01 1911 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9 / tsc);
0f47c08d 1912 if (DO_BIC(BIC_Pkgpc10))
1b439f01 1913 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10 / tsc);
889facbe 1914
be0e54c4 1915 if (DO_BIC(BIC_CPU_LPI))
1b439f01
LB
1916 outp +=
1917 sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
be0e54c4 1918 if (DO_BIC(BIC_SYS_LPI))
1b439f01
LB
1919 outp +=
1920 sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float);
be0e54c4 1921
812db3f7 1922 if (DO_BIC(BIC_PkgWatt))
1b439f01
LB
1923 outp +=
1924 sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
eae97e05 1925
e338831b 1926 if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)
1b439f01
LB
1927 outp +=
1928 sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
812db3f7 1929 if (DO_BIC(BIC_GFXWatt))
1b439f01
LB
1930 outp +=
1931 sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
812db3f7 1932 if (DO_BIC(BIC_RAMWatt))
1b439f01
LB
1933 outp +=
1934 sprintf(outp, fmt8, (printed++ ? delim : ""),
1935 p->energy_dram * rapl_dram_energy_units / interval_float);
812db3f7 1936 if (DO_BIC(BIC_Pkg_J))
6168c2e0 1937 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units);
e338831b 1938 if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)
6168c2e0 1939 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units);
812db3f7 1940 if (DO_BIC(BIC_GFX_J))
6168c2e0 1941 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units);
812db3f7 1942 if (DO_BIC(BIC_RAM_J))
6168c2e0 1943 outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units);
812db3f7 1944 if (DO_BIC(BIC_PKG__))
1b439f01
LB
1945 outp +=
1946 sprintf(outp, fmt8, (printed++ ? delim : ""),
1947 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
812db3f7 1948 if (DO_BIC(BIC_RAM__))
1b439f01
LB
1949 outp +=
1950 sprintf(outp, fmt8, (printed++ ? delim : ""),
1951 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
a5c6d65d
LB
1952 /* UncMHz */
1953 if (DO_BIC(BIC_UNCORE_MHZ))
1954 outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->uncore_mhz);
812db3f7 1955
388e9c81
LB
1956 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1957 if (mp->format == FORMAT_RAW) {
1958 if (mp->width == 32)
1b439f01
LB
1959 outp +=
1960 sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)p->counter[i]);
388e9c81 1961 else
6168c2e0 1962 outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
388e9c81 1963 } else if (mp->format == FORMAT_DELTA) {
0de6c0df 1964 if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
6168c2e0 1965 outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->counter[i]);
0de6c0df 1966 else
6168c2e0 1967 outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);
388e9c81 1968 } else if (mp->format == FORMAT_PERCENT) {
1b439f01 1969 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i] / tsc);
388e9c81
LB
1970 }
1971 }
1972
c98d5d94 1973done:
94d6ab4b
LB
1974 if (*(outp - 1) != '\n')
1975 outp += sprintf(outp, "\n");
c98d5d94
LB
1976
1977 return 0;
103a8fea
LB
1978}
1979
b7d8c148 1980void flush_output_stdout(void)
c98d5d94 1981{
b7d8c148
LB
1982 FILE *filep;
1983
1984 if (outf == stderr)
1985 filep = stdout;
1986 else
1987 filep = outf;
1988
1989 fputs(output_buffer, filep);
1990 fflush(filep);
1991
c98d5d94
LB
1992 outp = output_buffer;
1993}
1b439f01 1994
b7d8c148 1995void flush_output_stderr(void)
c98d5d94 1996{
b7d8c148
LB
1997 fputs(output_buffer, outf);
1998 fflush(outf);
c98d5d94
LB
1999 outp = output_buffer;
2000}
1b439f01 2001
c98d5d94 2002void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
103a8fea 2003{
c7e399f8 2004 static int count;
103a8fea 2005
c7e399f8 2006 if ((!count || (header_iterations && !(count % header_iterations))) || !summary_only)
c8ade361 2007 print_header("\t");
103a8fea 2008
9d83601a 2009 format_counters(&average.threads, &average.cores, &average.packages);
103a8fea 2010
c7e399f8 2011 count++;
e23da037
LB
2012
2013 if (summary_only)
2014 return;
2015
c98d5d94 2016 for_all_cpus(format_counters, t, c, p);
103a8fea
LB
2017}
2018
889facbe 2019#define DELTA_WRAP32(new, old) \
7c2ccc50 2020 old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);
889facbe 2021
1b439f01 2022int delta_package(struct pkg_data *new, struct pkg_data *old)
c98d5d94 2023{
388e9c81
LB
2024 int i;
2025 struct msr_counter *mp;
0b2bb692 2026
a99d8730 2027 if (DO_BIC(BIC_Totl_c0))
0b2bb692 2028 old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;
a99d8730 2029 if (DO_BIC(BIC_Any_c0))
0b2bb692 2030 old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;
a99d8730 2031 if (DO_BIC(BIC_GFX_c0))
0b2bb692 2032 old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;
a99d8730 2033 if (DO_BIC(BIC_CPUGFX))
0b2bb692 2034 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
a99d8730 2035
c98d5d94 2036 old->pc2 = new->pc2 - old->pc2;
0f47c08d 2037 if (DO_BIC(BIC_Pkgpc3))
ee7e38e3 2038 old->pc3 = new->pc3 - old->pc3;
0f47c08d 2039 if (DO_BIC(BIC_Pkgpc6))
ee7e38e3 2040 old->pc6 = new->pc6 - old->pc6;
0f47c08d 2041 if (DO_BIC(BIC_Pkgpc7))
ee7e38e3 2042 old->pc7 = new->pc7 - old->pc7;
ca58710f
KCA
2043 old->pc8 = new->pc8 - old->pc8;
2044 old->pc9 = new->pc9 - old->pc9;
2045 old->pc10 = new->pc10 - old->pc10;
be0e54c4
LB
2046 old->cpu_lpi = new->cpu_lpi - old->cpu_lpi;
2047 old->sys_lpi = new->sys_lpi - old->sys_lpi;
889facbe
LB
2048 old->pkg_temp_c = new->pkg_temp_c;
2049
9185e988 2050 /* flag an error when rc6 counter resets/wraps */
1b439f01 2051 if (old->gfx_rc6_ms > new->gfx_rc6_ms)
9185e988
LB
2052 old->gfx_rc6_ms = -1;
2053 else
2054 old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
2055
a5c6d65d 2056 old->uncore_mhz = new->uncore_mhz;
27d47356 2057 old->gfx_mhz = new->gfx_mhz;
b4b91569 2058 old->gfx_act_mhz = new->gfx_act_mhz;
27d47356 2059
87e15da9
CY
2060 old->energy_pkg = new->energy_pkg - old->energy_pkg;
2061 old->energy_cores = new->energy_cores - old->energy_cores;
2062 old->energy_gfx = new->energy_gfx - old->energy_gfx;
2063 old->energy_dram = new->energy_dram - old->energy_dram;
2064 old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status;
2065 old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status;
ba3dec99 2066
388e9c81
LB
2067 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
2068 if (mp->format == FORMAT_RAW)
2069 old->counter[i] = new->counter[i];
2070 else
2071 old->counter[i] = new->counter[i] - old->counter[i];
2072 }
2073
ba3dec99 2074 return 0;
c98d5d94 2075}
103a8fea 2076
1b439f01 2077void delta_core(struct core_data *new, struct core_data *old)
103a8fea 2078{
388e9c81
LB
2079 int i;
2080 struct msr_counter *mp;
2081
c98d5d94
LB
2082 old->c3 = new->c3 - old->c3;
2083 old->c6 = new->c6 - old->c6;
2084 old->c7 = new->c7 - old->c7;
889facbe 2085 old->core_temp_c = new->core_temp_c;
eae97e05 2086 old->core_throt_cnt = new->core_throt_cnt;
0539ba11 2087 old->mc6_us = new->mc6_us - old->mc6_us;
388e9c81 2088
9392bd98
CW
2089 DELTA_WRAP32(new->core_energy, old->core_energy);
2090
388e9c81
LB
2091 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
2092 if (mp->format == FORMAT_RAW)
2093 old->counter[i] = new->counter[i];
2094 else
2095 old->counter[i] = new->counter[i] - old->counter[i];
2096 }
c98d5d94 2097}
103a8fea 2098
1e9042b9
SP
2099int soft_c1_residency_display(int bic)
2100{
76d83d2a 2101 if (!DO_BIC(BIC_CPU_c1) || platform->has_msr_core_c1_res)
1e9042b9
SP
2102 return 0;
2103
2104 return DO_BIC_READ(bic);
2105}
2106
c3ae331d
LB
2107/*
2108 * old = new - old
2109 */
1b439f01 2110int delta_thread(struct thread_data *new, struct thread_data *old, struct core_data *core_delta)
c98d5d94 2111{
388e9c81
LB
2112 int i;
2113 struct msr_counter *mp;
2114
4c2122d4
LB
2115 /* we run cpuid just the 1st time, copy the results */
2116 if (DO_BIC(BIC_APIC))
2117 new->apic_id = old->apic_id;
2118 if (DO_BIC(BIC_X2APIC))
2119 new->x2apic_id = old->x2apic_id;
2120
3f44a5c6
LB
2121 /*
2122 * the timestamps from start of measurement interval are in "old"
2123 * the timestamp from end of measurement interval are in "new"
2124 * over-write old w/ new so we can print end of interval values
2125 */
2126
d4794f25 2127 timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
3f44a5c6
LB
2128 old->tv_begin = new->tv_begin;
2129 old->tv_end = new->tv_end;
2130
c98d5d94
LB
2131 old->tsc = new->tsc - old->tsc;
2132
2133 /* check for TSC < 1 Mcycles over interval */
b2c95d90
JT
2134 if (old->tsc < (1000 * 1000))
2135 errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n"
2136 "You can disable all c-states by booting with \"idle=poll\"\n"
2137 "or just the deep ones with \"processor.max_cstate=1\"");
103a8fea 2138
c98d5d94 2139 old->c1 = new->c1 - old->c1;
103a8fea 2140
1b439f01 2141 if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || soft_c1_residency_display(BIC_Avg_MHz)) {
a729617c
LB
2142 if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
2143 old->aperf = new->aperf - old->aperf;
2144 old->mperf = new->mperf - old->mperf;
2145 } else {
ba3dec99 2146 return -1;
103a8fea 2147 }
c98d5d94 2148 }
103a8fea 2149
76d83d2a 2150 if (platform->has_msr_core_c1_res) {
144b44b1
LB
2151 /*
2152 * Some models have a dedicated C1 residency MSR,
2153 * which should be more accurate than the derivation below.
2154 */
2155 } else {
2156 /*
2157 * As counter collection is not atomic,
2158 * it is possible for mperf's non-halted cycles + idle states
2159 * to exceed TSC's all cycles: show c1 = 0% in that case.
2160 */
95149369 2161 if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > (old->tsc * tsc_tweak))
144b44b1
LB
2162 old->c1 = 0;
2163 else {
2164 /* normal case, derive c1 */
008d396e 2165 old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3
1b439f01 2166 - core_delta->c6 - core_delta->c7;
144b44b1 2167 }
c98d5d94 2168 }
c3ae331d 2169
c98d5d94 2170 if (old->mperf == 0) {
b7d8c148
LB
2171 if (debug > 1)
2172 fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);
c98d5d94 2173 old->mperf = 1; /* divide by 0 protection */
103a8fea 2174 }
c98d5d94 2175
2af4f9b8
LB
2176 if (DO_BIC(BIC_IPC))
2177 old->instr_count = new->instr_count - old->instr_count;
2178
812db3f7 2179 if (DO_BIC(BIC_IRQ))
562a2d37
LB
2180 old->irq_count = new->irq_count - old->irq_count;
2181
812db3f7 2182 if (DO_BIC(BIC_SMI))
1ed51011 2183 old->smi_count = new->smi_count - old->smi_count;
ba3dec99 2184
388e9c81
LB
2185 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
2186 if (mp->format == FORMAT_RAW)
2187 old->counter[i] = new->counter[i];
2188 else
2189 old->counter[i] = new->counter[i] - old->counter[i];
2190 }
ba3dec99 2191 return 0;
c98d5d94
LB
2192}
2193
2194int delta_cpu(struct thread_data *t, struct core_data *c,
1b439f01 2195 struct pkg_data *p, struct thread_data *t2, struct core_data *c2, struct pkg_data *p2)
c98d5d94 2196{
ba3dec99
LB
2197 int retval = 0;
2198
c98d5d94
LB
2199 /* calculate core delta only for 1st thread in core */
2200 if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE)
2201 delta_core(c, c2);
2202
2203 /* always calculate thread delta */
ba3dec99
LB
2204 retval = delta_thread(t, t2, c2); /* c2 is core delta */
2205 if (retval)
2206 return retval;
c98d5d94
LB
2207
2208 /* calculate package delta only for 1st core in package */
2209 if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)
ba3dec99 2210 retval = delta_package(p, p2);
c98d5d94 2211
ba3dec99 2212 return retval;
103a8fea
LB
2213}
2214
c98d5d94
LB
2215void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
2216{
388e9c81 2217 int i;
1b439f01 2218 struct msr_counter *mp;
388e9c81 2219
3f44a5c6
LB
2220 t->tv_begin.tv_sec = 0;
2221 t->tv_begin.tv_usec = 0;
2222 t->tv_end.tv_sec = 0;
2223 t->tv_end.tv_usec = 0;
d4794f25
YG
2224 t->tv_delta.tv_sec = 0;
2225 t->tv_delta.tv_usec = 0;
3f44a5c6 2226
c98d5d94
LB
2227 t->tsc = 0;
2228 t->aperf = 0;
2229 t->mperf = 0;
2230 t->c1 = 0;
2231
2af4f9b8
LB
2232 t->instr_count = 0;
2233
562a2d37
LB
2234 t->irq_count = 0;
2235 t->smi_count = 0;
2236
c98d5d94
LB
2237 /* tells format_counters to dump all fields from this set */
2238 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
2239
2240 c->c3 = 0;
2241 c->c6 = 0;
2242 c->c7 = 0;
0539ba11 2243 c->mc6_us = 0;
889facbe 2244 c->core_temp_c = 0;
9392bd98 2245 c->core_energy = 0;
eae97e05 2246 c->core_throt_cnt = 0;
c98d5d94 2247
0b2bb692
LB
2248 p->pkg_wtd_core_c0 = 0;
2249 p->pkg_any_core_c0 = 0;
2250 p->pkg_any_gfxe_c0 = 0;
2251 p->pkg_both_core_gfxe_c0 = 0;
2252
c98d5d94 2253 p->pc2 = 0;
0f47c08d 2254 if (DO_BIC(BIC_Pkgpc3))
ee7e38e3 2255 p->pc3 = 0;
0f47c08d 2256 if (DO_BIC(BIC_Pkgpc6))
ee7e38e3 2257 p->pc6 = 0;
0f47c08d 2258 if (DO_BIC(BIC_Pkgpc7))
ee7e38e3 2259 p->pc7 = 0;
ca58710f
KCA
2260 p->pc8 = 0;
2261 p->pc9 = 0;
2262 p->pc10 = 0;
be0e54c4
LB
2263 p->cpu_lpi = 0;
2264 p->sys_lpi = 0;
889facbe
LB
2265
2266 p->energy_pkg = 0;
2267 p->energy_dram = 0;
2268 p->energy_cores = 0;
2269 p->energy_gfx = 0;
2270 p->rapl_pkg_perf_status = 0;
2271 p->rapl_dram_perf_status = 0;
2272 p->pkg_temp_c = 0;
27d47356 2273
fdf676e5 2274 p->gfx_rc6_ms = 0;
a5c6d65d 2275 p->uncore_mhz = 0;
27d47356 2276 p->gfx_mhz = 0;
b4b91569 2277 p->gfx_act_mhz = 0;
388e9c81
LB
2278 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
2279 t->counter[i] = 0;
2280
2281 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next)
2282 c->counter[i] = 0;
2283
2284 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next)
2285 p->counter[i] = 0;
c98d5d94 2286}
1b439f01
LB
2287
2288int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
103a8fea 2289{
388e9c81
LB
2290 int i;
2291 struct msr_counter *mp;
2292
4c2122d4
LB
2293 /* copy un-changing apic_id's */
2294 if (DO_BIC(BIC_APIC))
2295 average.threads.apic_id = t->apic_id;
2296 if (DO_BIC(BIC_X2APIC))
2297 average.threads.x2apic_id = t->x2apic_id;
2298
3f44a5c6
LB
2299 /* remember first tv_begin */
2300 if (average.threads.tv_begin.tv_sec == 0)
2301 average.threads.tv_begin = t->tv_begin;
2302
2303 /* remember last tv_end */
2304 average.threads.tv_end = t->tv_end;
2305
c98d5d94
LB
2306 average.threads.tsc += t->tsc;
2307 average.threads.aperf += t->aperf;
2308 average.threads.mperf += t->mperf;
2309 average.threads.c1 += t->c1;
103a8fea 2310
2af4f9b8
LB
2311 average.threads.instr_count += t->instr_count;
2312
562a2d37
LB
2313 average.threads.irq_count += t->irq_count;
2314 average.threads.smi_count += t->smi_count;
2315
388e9c81
LB
2316 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
2317 if (mp->format == FORMAT_RAW)
2318 continue;
2319 average.threads.counter[i] += t->counter[i];
2320 }
2321
c98d5d94
LB
2322 /* sum per-core values only for 1st thread in core */
2323 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
2324 return 0;
103a8fea 2325
c98d5d94
LB
2326 average.cores.c3 += c->c3;
2327 average.cores.c6 += c->c6;
2328 average.cores.c7 += c->c7;
0539ba11 2329 average.cores.mc6_us += c->mc6_us;
c98d5d94 2330
889facbe 2331 average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);
eae97e05 2332 average.cores.core_throt_cnt = MAX(average.cores.core_throt_cnt, c->core_throt_cnt);
889facbe 2333
9392bd98
CW
2334 average.cores.core_energy += c->core_energy;
2335
388e9c81
LB
2336 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
2337 if (mp->format == FORMAT_RAW)
2338 continue;
2339 average.cores.counter[i] += c->counter[i];
2340 }
2341
c98d5d94
LB
2342 /* sum per-pkg values only for 1st core in pkg */
2343 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
2344 return 0;
2345
a99d8730 2346 if (DO_BIC(BIC_Totl_c0))
0b2bb692 2347 average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0;
a99d8730 2348 if (DO_BIC(BIC_Any_c0))
0b2bb692 2349 average.packages.pkg_any_core_c0 += p->pkg_any_core_c0;
a99d8730 2350 if (DO_BIC(BIC_GFX_c0))
0b2bb692 2351 average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;
a99d8730 2352 if (DO_BIC(BIC_CPUGFX))
0b2bb692 2353 average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;
0b2bb692 2354
c98d5d94 2355 average.packages.pc2 += p->pc2;
0f47c08d 2356 if (DO_BIC(BIC_Pkgpc3))
ee7e38e3 2357 average.packages.pc3 += p->pc3;
0f47c08d 2358 if (DO_BIC(BIC_Pkgpc6))
ee7e38e3 2359 average.packages.pc6 += p->pc6;
0f47c08d 2360 if (DO_BIC(BIC_Pkgpc7))
ee7e38e3 2361 average.packages.pc7 += p->pc7;
ca58710f
KCA
2362 average.packages.pc8 += p->pc8;
2363 average.packages.pc9 += p->pc9;
2364 average.packages.pc10 += p->pc10;
c98d5d94 2365
be0e54c4
LB
2366 average.packages.cpu_lpi = p->cpu_lpi;
2367 average.packages.sys_lpi = p->sys_lpi;
2368
889facbe
LB
2369 average.packages.energy_pkg += p->energy_pkg;
2370 average.packages.energy_dram += p->energy_dram;
2371 average.packages.energy_cores += p->energy_cores;
2372 average.packages.energy_gfx += p->energy_gfx;
2373
fdf676e5 2374 average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
a5c6d65d 2375 average.packages.uncore_mhz = p->uncore_mhz;
27d47356 2376 average.packages.gfx_mhz = p->gfx_mhz;
b4b91569 2377 average.packages.gfx_act_mhz = p->gfx_act_mhz;
27d47356 2378
889facbe
LB
2379 average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
2380
2381 average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status;
2382 average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status;
388e9c81
LB
2383
2384 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
2385 if (mp->format == FORMAT_RAW)
2386 continue;
2387 average.packages.counter[i] += p->counter[i];
2388 }
c98d5d94
LB
2389 return 0;
2390}
1b439f01 2391
c98d5d94
LB
2392/*
2393 * sum the counters for all cpus in the system
2394 * compute the weighted average
2395 */
1b439f01 2396void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data *p)
c98d5d94 2397{
388e9c81
LB
2398 int i;
2399 struct msr_counter *mp;
2400
c98d5d94
LB
2401 clear_counters(&average.threads, &average.cores, &average.packages);
2402
2403 for_all_cpus(sum_counters, t, c, p);
2404
d4794f25
YG
2405 /* Use the global time delta for the average. */
2406 average.threads.tv_delta = tv_delta;
2407
c98d5d94
LB
2408 average.threads.tsc /= topo.num_cpus;
2409 average.threads.aperf /= topo.num_cpus;
2410 average.threads.mperf /= topo.num_cpus;
2af4f9b8 2411 average.threads.instr_count /= topo.num_cpus;
c98d5d94
LB
2412 average.threads.c1 /= topo.num_cpus;
2413
0de6c0df
LB
2414 if (average.threads.irq_count > 9999999)
2415 sums_need_wide_columns = 1;
2416
c98d5d94
LB
2417 average.cores.c3 /= topo.num_cores;
2418 average.cores.c6 /= topo.num_cores;
2419 average.cores.c7 /= topo.num_cores;
0539ba11 2420 average.cores.mc6_us /= topo.num_cores;
c98d5d94 2421
a99d8730 2422 if (DO_BIC(BIC_Totl_c0))
0b2bb692 2423 average.packages.pkg_wtd_core_c0 /= topo.num_packages;
a99d8730 2424 if (DO_BIC(BIC_Any_c0))
0b2bb692 2425 average.packages.pkg_any_core_c0 /= topo.num_packages;
a99d8730 2426 if (DO_BIC(BIC_GFX_c0))
0b2bb692 2427 average.packages.pkg_any_gfxe_c0 /= topo.num_packages;
a99d8730 2428 if (DO_BIC(BIC_CPUGFX))
0b2bb692 2429 average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages;
0b2bb692 2430
c98d5d94 2431 average.packages.pc2 /= topo.num_packages;
0f47c08d 2432 if (DO_BIC(BIC_Pkgpc3))
ee7e38e3 2433 average.packages.pc3 /= topo.num_packages;
0f47c08d 2434 if (DO_BIC(BIC_Pkgpc6))
ee7e38e3 2435 average.packages.pc6 /= topo.num_packages;
0f47c08d 2436 if (DO_BIC(BIC_Pkgpc7))
ee7e38e3 2437 average.packages.pc7 /= topo.num_packages;
ca58710f
KCA
2438
2439 average.packages.pc8 /= topo.num_packages;
2440 average.packages.pc9 /= topo.num_packages;
2441 average.packages.pc10 /= topo.num_packages;
388e9c81
LB
2442
2443 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
2444 if (mp->format == FORMAT_RAW)
2445 continue;
0de6c0df
LB
2446 if (mp->type == COUNTER_ITEMS) {
2447 if (average.threads.counter[i] > 9999999)
2448 sums_need_wide_columns = 1;
41618e63 2449 continue;
0de6c0df 2450 }
388e9c81
LB
2451 average.threads.counter[i] /= topo.num_cpus;
2452 }
2453 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
2454 if (mp->format == FORMAT_RAW)
2455 continue;
0de6c0df
LB
2456 if (mp->type == COUNTER_ITEMS) {
2457 if (average.cores.counter[i] > 9999999)
2458 sums_need_wide_columns = 1;
2459 }
388e9c81
LB
2460 average.cores.counter[i] /= topo.num_cores;
2461 }
2462 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
2463 if (mp->format == FORMAT_RAW)
2464 continue;
0de6c0df
LB
2465 if (mp->type == COUNTER_ITEMS) {
2466 if (average.packages.counter[i] > 9999999)
2467 sums_need_wide_columns = 1;
2468 }
388e9c81
LB
2469 average.packages.counter[i] /= topo.num_packages;
2470 }
103a8fea
LB
2471}
2472
c98d5d94 2473static unsigned long long rdtsc(void)
103a8fea 2474{
c98d5d94 2475 unsigned int low, high;
15aaa346 2476
1b439f01 2477 asm volatile ("rdtsc":"=a" (low), "=d"(high));
15aaa346 2478
c98d5d94
LB
2479 return low | ((unsigned long long)high) << 32;
2480}
15aaa346 2481
495c7654
LB
2482/*
2483 * Open a file, and exit on failure
2484 */
2485FILE *fopen_or_die(const char *path, const char *mode)
2486{
2487 FILE *filep = fopen(path, mode);
2488
2489 if (!filep)
2490 err(1, "%s: open failed", path);
2491 return filep;
2492}
1b439f01 2493
495c7654
LB
2494/*
2495 * snapshot_sysfs_counter()
2496 *
2497 * return snapshot of given counter
2498 */
2499unsigned long long snapshot_sysfs_counter(char *path)
2500{
2501 FILE *fp;
2502 int retval;
2503 unsigned long long counter;
2504
2505 fp = fopen_or_die(path, "r");
2506
2507 retval = fscanf(fp, "%lld", &counter);
2508 if (retval != 1)
2509 err(1, "snapshot_sysfs_counter(%s)", path);
2510
2511 fclose(fp);
2512
2513 return counter;
2514}
2515
2516int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
2517{
2518 if (mp->msr_num != 0) {
2519 if (get_msr(cpu, mp->msr_num, counterp))
2520 return -1;
2521 } else {
46c27978 2522 char path[128 + PATH_BYTES];
41618e63
LB
2523
2524 if (mp->flags & SYSFS_PERCPU) {
1b439f01 2525 sprintf(path, "/sys/devices/system/cpu/cpu%d/%s", cpu, mp->path);
41618e63
LB
2526
2527 *counterp = snapshot_sysfs_counter(path);
2528 } else {
2529 *counterp = snapshot_sysfs_counter(mp->path);
2530 }
495c7654
LB
2531 }
2532
2533 return 0;
2534}
2535
a5c6d65d
LB
2536unsigned long long get_uncore_mhz(int package, int die)
2537{
2538 char path[128];
2539
2540 sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/current_freq_khz", package,
2541 die);
2542
2543 return (snapshot_sysfs_counter(path) / 1000);
2544}
2545
6d6501d9
BP
2546int get_epb(int cpu)
2547{
2548 char path[128 + PATH_BYTES];
7f1b11ba 2549 unsigned long long msr;
6d6501d9
BP
2550 int ret, epb = -1;
2551 FILE *fp;
2552
2553 sprintf(path, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", cpu);
2554
7f1b11ba
BP
2555 fp = fopen(path, "r");
2556 if (!fp)
2557 goto msr_fallback;
6d6501d9
BP
2558
2559 ret = fscanf(fp, "%d", &epb);
2560 if (ret != 1)
2561 err(1, "%s(%s)", __func__, path);
2562
2563 fclose(fp);
2564
2565 return epb;
7f1b11ba
BP
2566
2567msr_fallback:
2568 get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
2569
2570 return msr & 0xf;
6d6501d9
BP
2571}
2572
4c2122d4
LB
2573void get_apic_id(struct thread_data *t)
2574{
34041551 2575 unsigned int eax, ebx, ecx, edx;
4c2122d4 2576
34041551
LB
2577 if (DO_BIC(BIC_APIC)) {
2578 eax = ebx = ecx = edx = 0;
2579 __cpuid(1, eax, ebx, ecx, edx);
4c2122d4 2580
34041551
LB
2581 t->apic_id = (ebx >> 24) & 0xff;
2582 }
2583
2584 if (!DO_BIC(BIC_X2APIC))
4c2122d4
LB
2585 return;
2586
c1c10cc7 2587 if (authentic_amd || hygon_genuine) {
34041551 2588 unsigned int topology_extensions;
4c2122d4 2589
34041551
LB
2590 if (max_extended_level < 0x8000001e)
2591 return;
4c2122d4 2592
34041551
LB
2593 eax = ebx = ecx = edx = 0;
2594 __cpuid(0x80000001, eax, ebx, ecx, edx);
1b439f01 2595 topology_extensions = ecx & (1 << 22);
34041551
LB
2596
2597 if (topology_extensions == 0)
2598 return;
2599
2600 eax = ebx = ecx = edx = 0;
2601 __cpuid(0x8000001e, eax, ebx, ecx, edx);
2602
2603 t->x2apic_id = eax;
4c2122d4 2604 return;
34041551 2605 }
4c2122d4 2606
34041551
LB
2607 if (!genuine_intel)
2608 return;
2609
2610 if (max_level < 0xb)
4c2122d4
LB
2611 return;
2612
2613 ecx = 0;
2614 __cpuid(0xb, eax, ebx, ecx, edx);
2615 t->x2apic_id = edx;
2616
34041551 2617 if (debug && (t->apic_id != (t->x2apic_id & 0xff)))
1b439f01 2618 fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id);
4c2122d4
LB
2619}
2620
eae97e05
CY
2621int get_core_throt_cnt(int cpu, unsigned long long *cnt)
2622{
2623 char path[128 + PATH_BYTES];
2624 unsigned long long tmp;
2625 FILE *fp;
2626 int ret;
2627
2628 sprintf(path, "/sys/devices/system/cpu/cpu%d/thermal_throttle/core_throttle_count", cpu);
2629 fp = fopen(path, "r");
2630 if (!fp)
2631 return -1;
2632 ret = fscanf(fp, "%lld", &tmp);
5e5fd36c 2633 fclose(fp);
eae97e05
CY
2634 if (ret != 1)
2635 return -1;
eae97e05
CY
2636 *cnt = tmp;
2637
2638 return 0;
2639}
2640
c98d5d94
LB
2641/*
2642 * get_counters(...)
2643 * migrate to cpu
2644 * acquire and record local counters for that cpu
2645 */
2646int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
2647{
2648 int cpu = t->cpu_id;
889facbe 2649 unsigned long long msr;
0102b067 2650 int aperf_mperf_retry_count = 0;
388e9c81
LB
2651 struct msr_counter *mp;
2652 int i;
88c3281f 2653
e52966c0 2654 if (cpu_migrate(cpu)) {
3d7772ea 2655 fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu);
c98d5d94 2656 return -1;
e52966c0 2657 }
15aaa346 2658
d4794f25
YG
2659 gettimeofday(&t->tv_begin, (struct timezone *)NULL);
2660
4c2122d4
LB
2661 if (first_counter_read)
2662 get_apic_id(t);
0102b067 2663retry:
c98d5d94
LB
2664 t->tsc = rdtsc(); /* we are running on local CPU of interest */
2665
1b439f01 2666 if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || soft_c1_residency_display(BIC_Avg_MHz)) {
0102b067
LB
2667 unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
2668
2669 /*
2670 * The TSC, APERF and MPERF must be read together for
2671 * APERF/MPERF and MPERF/TSC to give accurate results.
2672 *
2673 * Unfortunately, APERF and MPERF are read by
2674 * individual system call, so delays may occur
2675 * between them. If the time to read them
2676 * varies by a large amount, we re-read them.
2677 */
2678
2679 /*
2680 * This initial dummy APERF read has been seen to
2681 * reduce jitter in the subsequent reads.
2682 */
2683
2684 if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
2685 return -3;
2686
2687 t->tsc = rdtsc(); /* re-read close to APERF */
2688
2689 tsc_before = t->tsc;
2690
9c63a650 2691 if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
c98d5d94 2692 return -3;
0102b067
LB
2693
2694 tsc_between = rdtsc();
2695
9c63a650 2696 if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf))
c98d5d94 2697 return -4;
0102b067
LB
2698
2699 tsc_after = rdtsc();
2700
2701 aperf_time = tsc_between - tsc_before;
2702 mperf_time = tsc_after - tsc_between;
2703
2704 /*
2705 * If the system call latency to read APERF and MPERF
2706 * differ by more than 2x, then try again.
2707 */
2708 if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) {
2709 aperf_mperf_retry_count++;
2710 if (aperf_mperf_retry_count < 5)
2711 goto retry;
2712 else
1b439f01 2713 warnx("cpu%d jitter %lld %lld", cpu, aperf_time, mperf_time);
0102b067
LB
2714 }
2715 aperf_mperf_retry_count = 0;
2716
b2b34dfe
HC
2717 t->aperf = t->aperf * aperf_mperf_multiplier;
2718 t->mperf = t->mperf * aperf_mperf_multiplier;
c98d5d94
LB
2719 }
2720
2af4f9b8
LB
2721 if (DO_BIC(BIC_IPC))
2722 if (read(get_instr_count_fd(cpu), &t->instr_count, sizeof(long long)) != sizeof(long long))
2723 return -4;
2724
812db3f7 2725 if (DO_BIC(BIC_IRQ))
562a2d37 2726 t->irq_count = irqs_per_cpu[cpu];
812db3f7 2727 if (DO_BIC(BIC_SMI)) {
1ed51011
LB
2728 if (get_msr(cpu, MSR_SMI_COUNT, &msr))
2729 return -5;
2730 t->smi_count = msr & 0xFFFFFFFF;
2731 }
76d83d2a 2732 if (DO_BIC(BIC_CPU_c1) && platform->has_msr_core_c1_res) {
144b44b1
LB
2733 if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
2734 return -6;
2735 }
2736
388e9c81 2737 for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
495c7654 2738 if (get_mp(cpu, mp, &t->counter[i]))
388e9c81
LB
2739 return -10;
2740 }
2741
c98d5d94
LB
2742 /* collect core counters only for 1st thread in core */
2743 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
f4fdf2b4 2744 goto done;
c98d5d94 2745
1e9042b9 2746 if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) {
c98d5d94
LB
2747 if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
2748 return -6;
144b44b1
LB
2749 }
2750
80d132cb 2751 if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !platform->has_msr_knl_core_c6_residency) {
c98d5d94
LB
2752 if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
2753 return -7;
80d132cb 2754 } else if (platform->has_msr_knl_core_c6_residency && soft_c1_residency_display(BIC_CPU_c6)) {
fb5d4327
DC
2755 if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
2756 return -7;
c98d5d94
LB
2757 }
2758
7ab5ff49 2759 if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7)) {
c98d5d94
LB
2760 if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
2761 return -8;
7ab5ff49
ZR
2762 else if (t->is_atom) {
2763 /*
2764 * For Atom CPUs that has core cstate deeper than c6,
2765 * MSR_CORE_C6_RESIDENCY returns residency of cc6 and deeper.
2766 * Minus CC7 (and deeper cstates) residency to get
2767 * accturate cc6 residency.
2768 */
2769 c->c6 -= c->c7;
2770 }
2771 }
c98d5d94 2772
0539ba11
LB
2773 if (DO_BIC(BIC_Mod_c6))
2774 if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))
2775 return -8;
2776
812db3f7 2777 if (DO_BIC(BIC_CoreTmp)) {
889facbe
LB
2778 if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
2779 return -9;
55279aef 2780 c->core_temp_c = tj_max - ((msr >> 16) & 0x7F);
889facbe
LB
2781 }
2782
eae97e05
CY
2783 if (DO_BIC(BIC_CORE_THROT_CNT))
2784 get_core_throt_cnt(cpu, &c->core_throt_cnt);
2785
86ba263d 2786 if (platform->rapl_msrs & RAPL_AMD_F17H) {
9392bd98
CW
2787 if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr))
2788 return -14;
2789 c->core_energy = msr & 0xFFFFFFFF;
2790 }
2791
388e9c81 2792 for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
495c7654 2793 if (get_mp(cpu, mp, &c->counter[i]))
388e9c81
LB
2794 return -10;
2795 }
889facbe 2796
c98d5d94
LB
2797 /* collect package counters only for 1st core in package */
2798 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
f4fdf2b4 2799 goto done;
c98d5d94 2800
a99d8730 2801 if (DO_BIC(BIC_Totl_c0)) {
0b2bb692
LB
2802 if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))
2803 return -10;
a99d8730
LB
2804 }
2805 if (DO_BIC(BIC_Any_c0)) {
0b2bb692
LB
2806 if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))
2807 return -11;
a99d8730
LB
2808 }
2809 if (DO_BIC(BIC_GFX_c0)) {
0b2bb692
LB
2810 if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))
2811 return -12;
a99d8730
LB
2812 }
2813 if (DO_BIC(BIC_CPUGFX)) {
0b2bb692
LB
2814 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
2815 return -13;
2816 }
0f47c08d 2817 if (DO_BIC(BIC_Pkgpc3))
c98d5d94
LB
2818 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
2819 return -9;
0f47c08d 2820 if (DO_BIC(BIC_Pkgpc6)) {
c8202a6c 2821 if (platform->has_msr_atom_pkg_c6_residency) {
0539ba11
LB
2822 if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6))
2823 return -10;
2824 } else {
2825 if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
2826 return -10;
2827 }
2828 }
2829
0f47c08d 2830 if (DO_BIC(BIC_Pkgpc2))
c98d5d94
LB
2831 if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
2832 return -11;
0f47c08d 2833 if (DO_BIC(BIC_Pkgpc7))
c98d5d94
LB
2834 if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
2835 return -12;
0f47c08d 2836 if (DO_BIC(BIC_Pkgpc8))
ca58710f
KCA
2837 if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
2838 return -13;
0f47c08d 2839 if (DO_BIC(BIC_Pkgpc9))
ca58710f
KCA
2840 if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9))
2841 return -13;
0f47c08d 2842 if (DO_BIC(BIC_Pkgpc10))
ca58710f
KCA
2843 if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10))
2844 return -13;
0f47c08d 2845
be0e54c4
LB
2846 if (DO_BIC(BIC_CPU_LPI))
2847 p->cpu_lpi = cpuidle_cur_cpu_lpi_us;
2848 if (DO_BIC(BIC_SYS_LPI))
2849 p->sys_lpi = cpuidle_cur_sys_lpi_us;
2850
86ba263d 2851 if (platform->rapl_msrs & RAPL_PKG) {
9972d5d8 2852 if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr))
889facbe 2853 return -13;
9972d5d8 2854 p->energy_pkg = msr;
889facbe 2855 }
86ba263d 2856 if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) {
9972d5d8 2857 if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr))
889facbe 2858 return -14;
9972d5d8 2859 p->energy_cores = msr;
889facbe 2860 }
86ba263d 2861 if (platform->rapl_msrs & RAPL_DRAM) {
9972d5d8 2862 if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
889facbe 2863 return -15;
9972d5d8 2864 p->energy_dram = msr;
889facbe 2865 }
86ba263d 2866 if (platform->rapl_msrs & RAPL_GFX) {
9972d5d8 2867 if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr))
889facbe 2868 return -16;
9972d5d8 2869 p->energy_gfx = msr;
889facbe 2870 }
86ba263d 2871 if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) {
9972d5d8 2872 if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr))
889facbe 2873 return -16;
9972d5d8 2874 p->rapl_pkg_perf_status = msr;
889facbe 2875 }
86ba263d 2876 if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) {
9972d5d8 2877 if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr))
889facbe 2878 return -16;
9972d5d8 2879 p->rapl_dram_perf_status = msr;
889facbe 2880 }
86ba263d 2881 if (platform->rapl_msrs & RAPL_AMD_F17H) {
9972d5d8 2882 if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr))
3316f99a 2883 return -13;
9972d5d8 2884 p->energy_pkg = msr;
3316f99a 2885 }
812db3f7 2886 if (DO_BIC(BIC_PkgTmp)) {
889facbe
LB
2887 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
2888 return -17;
55279aef 2889 p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F);
889facbe 2890 }
fdf676e5 2891
812db3f7 2892 if (DO_BIC(BIC_GFX_rc6))
fdf676e5
LB
2893 p->gfx_rc6_ms = gfx_cur_rc6_ms;
2894
a5c6d65d
LB
2895 /* n.b. assume die0 uncore frequency applies to whole package */
2896 if (DO_BIC(BIC_UNCORE_MHZ))
2897 p->uncore_mhz = get_uncore_mhz(p->package_id, 0);
2898
812db3f7 2899 if (DO_BIC(BIC_GFXMHz))
27d47356
LB
2900 p->gfx_mhz = gfx_cur_mhz;
2901
b4b91569
RA
2902 if (DO_BIC(BIC_GFXACTMHz))
2903 p->gfx_act_mhz = gfx_act_mhz;
2904
388e9c81 2905 for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
495c7654 2906 if (get_mp(cpu, mp, &p->counter[i]))
388e9c81
LB
2907 return -10;
2908 }
f4fdf2b4
LB
2909done:
2910 gettimeofday(&t->tv_end, (struct timezone *)NULL);
388e9c81 2911
15aaa346 2912 return 0;
103a8fea
LB
2913}
2914
ee7e38e3
LB
2915/*
2916 * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:
2917 * If you change the values, note they are used both in comparisons
2918 * (>= PCL__7) and to index pkg_cstate_limit_strings[].
2919 */
2920
1b439f01
LB
2921#define PCLUKN 0 /* Unknown */
2922#define PCLRSV 1 /* Reserved */
2923#define PCL__0 2 /* PC0 */
2924#define PCL__1 3 /* PC1 */
2925#define PCL__2 4 /* PC2 */
2926#define PCL__3 5 /* PC3 */
2927#define PCL__4 6 /* PC4 */
2928#define PCL__6 7 /* PC6 */
2929#define PCL_6N 8 /* PC6 No Retention */
2930#define PCL_6R 9 /* PC6 Retention */
2931#define PCL__7 10 /* PC7 */
2932#define PCL_7S 11 /* PC7 Shrink */
2933#define PCL__8 12 /* PC8 */
2934#define PCL__9 13 /* PC9 */
2935#define PCL_10 14 /* PC10 */
2936#define PCLUNL 15 /* Unlimited */
ee7e38e3
LB
2937
2938int pkg_cstate_limit = PCLUKN;
2939char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
1b439f01
LB
2940 "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"
2941};
a2b7b749 2942
1b439f01
LB
2943int nhm_pkg_cstate_limits[16] =
2944 { PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2945 PCLRSV, PCLRSV
2946};
2947
1b439f01
LB
2948int snb_pkg_cstate_limits[16] =
2949 { PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2950 PCLRSV, PCLRSV
2951};
2952
1b439f01
LB
2953int hsw_pkg_cstate_limits[16] =
2954 { PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2955 PCLRSV, PCLRSV
2956};
2957
1b439f01
LB
2958int slv_pkg_cstate_limits[16] =
2959 { PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2960 PCL__6, PCL__7
2961};
2962
1b439f01
LB
2963int amt_pkg_cstate_limits[16] =
2964 { PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2965 PCLRSV, PCLRSV
2966};
2967
1b439f01
LB
2968int phi_pkg_cstate_limits[16] =
2969 { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2970 PCLRSV, PCLRSV
2971};
2972
1b439f01
LB
2973int glm_pkg_cstate_limits[16] =
2974 { PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2975 PCLRSV, PCLRSV
2976};
2977
1b439f01
LB
2978int skx_pkg_cstate_limits[16] =
2979 { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2980 PCLRSV, PCLRSV
2981};
2982
1b439f01 2983int icx_pkg_cstate_limits[16] =
a1b6f487 2984 { PCL__0, PCL__2, PCL__6, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
38c6663a
LB
2985 PCLRSV, PCLRSV
2986};
1b439f01 2987
3989fc89
ZR
2988void probe_cst_limit(void)
2989{
2990 unsigned long long msr;
2991 int *pkg_cstate_limits;
2992
fcfa1ce0 2993 if (!platform->has_nhm_msrs)
3989fc89
ZR
2994 return;
2995
2996 switch (platform->cst_limit) {
2997 case CST_LIMIT_NHM:
2998 pkg_cstate_limits = nhm_pkg_cstate_limits;
2999 break;
3000 case CST_LIMIT_SNB:
3001 pkg_cstate_limits = snb_pkg_cstate_limits;
3002 break;
3003 case CST_LIMIT_HSW:
3004 pkg_cstate_limits = hsw_pkg_cstate_limits;
3005 break;
3006 case CST_LIMIT_SKX:
3007 pkg_cstate_limits = skx_pkg_cstate_limits;
3008 break;
3009 case CST_LIMIT_ICX:
3010 pkg_cstate_limits = icx_pkg_cstate_limits;
3011 break;
3012 case CST_LIMIT_SLV:
3013 pkg_cstate_limits = slv_pkg_cstate_limits;
3014 break;
3015 case CST_LIMIT_AMT:
3016 pkg_cstate_limits = amt_pkg_cstate_limits;
3017 break;
3018 case CST_LIMIT_KNL:
3019 pkg_cstate_limits = phi_pkg_cstate_limits;
3020 break;
3021 case CST_LIMIT_GMT:
3022 pkg_cstate_limits = glm_pkg_cstate_limits;
3023 break;
3024 default:
3025 return;
3026 }
3027
3028 get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
3029 pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
3030}
3031
8b7199c0 3032static void dump_platform_info(void)
103a8fea
LB
3033{
3034 unsigned long long msr;
3035 unsigned int ratio;
3036
11cd9a09
ZR
3037 if (!platform->has_nhm_msrs)
3038 return;
3039
ec0adc53 3040 get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
103a8fea 3041
b7d8c148 3042 fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
6574a5d5 3043
103a8fea 3044 ratio = (msr >> 40) & 0xFF;
1b439f01 3045 fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n", ratio, bclk, ratio * bclk);
103a8fea
LB
3046
3047 ratio = (msr >> 8) & 0xFF;
1b439f01 3048 fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);
045acf60
ZR
3049}
3050
3051static void dump_power_ctl(void)
3052{
3053 unsigned long long msr;
3054
3055 if (!platform->has_nhm_msrs)
3056 return;
103a8fea 3057
7ce7d5de 3058 get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
b7d8c148 3059 fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
bfae2052 3060 base_cpu, msr, msr & 0x2 ? "EN" : "DIS");
67920418 3061
aeb01e6d 3062 /* C-state Pre-wake Disable (CSTATE_PREWAKE_DISABLE) */
7d0ebe6f 3063 if (platform->has_cst_prewake_bit)
1b439f01 3064 fprintf(outf, "C-state Pre-wake: %sabled\n", msr & 0x40000000 ? "DIS" : "EN");
aeb01e6d 3065
fcd17211
LB
3066 return;
3067}
3068
a3943dea 3069static void dump_turbo_ratio_limit2(void)
fcd17211
LB
3070{
3071 unsigned long long msr;
3072 unsigned int ratio;
3073
7ce7d5de 3074 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);
fcd17211 3075
b7d8c148 3076 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);
fcd17211
LB
3077
3078 ratio = (msr >> 8) & 0xFF;
3079 if (ratio)
1b439f01 3080 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n", ratio, bclk, ratio * bclk);
fcd17211
LB
3081
3082 ratio = (msr >> 0) & 0xFF;
3083 if (ratio)
1b439f01 3084 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n", ratio, bclk, ratio * bclk);
fcd17211
LB
3085 return;
3086}
3087
a3943dea 3088static void dump_turbo_ratio_limit1(void)
fcd17211
LB
3089{
3090 unsigned long long msr;
3091 unsigned int ratio;
6574a5d5 3092
7ce7d5de 3093 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);
6574a5d5 3094
b7d8c148 3095 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);
6574a5d5
LB
3096
3097 ratio = (msr >> 56) & 0xFF;
3098 if (ratio)
1b439f01 3099 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3100
3101 ratio = (msr >> 48) & 0xFF;
3102 if (ratio)
1b439f01 3103 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3104
3105 ratio = (msr >> 40) & 0xFF;
3106 if (ratio)
1b439f01 3107 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3108
3109 ratio = (msr >> 32) & 0xFF;
3110 if (ratio)
1b439f01 3111 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3112
3113 ratio = (msr >> 24) & 0xFF;
3114 if (ratio)
1b439f01 3115 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3116
3117 ratio = (msr >> 16) & 0xFF;
3118 if (ratio)
1b439f01 3119 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3120
3121 ratio = (msr >> 8) & 0xFF;
3122 if (ratio)
1b439f01 3123 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n", ratio, bclk, ratio * bclk);
6574a5d5
LB
3124
3125 ratio = (msr >> 0) & 0xFF;
3126 if (ratio)
1b439f01 3127 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n", ratio, bclk, ratio * bclk);
fcd17211
LB
3128 return;
3129}
1b439f01 3130
10d85d85 3131static void dump_turbo_ratio_limits(int trl_msr_offset)
fcd17211 3132{
31e07522 3133 unsigned long long msr, core_counts;
5d622845 3134 int shift;
103a8fea 3135
4af184ee
LB
3136 get_msr(base_cpu, trl_msr_offset, &msr);
3137 fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n",
884a1f95 3138 base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr);
6574a5d5 3139
10d85d85 3140 if (platform->trl_msrs & TRL_CORECOUNT) {
31e07522
LB
3141 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
3142 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts);
3143 } else {
3144 core_counts = 0x0807060504030201;
3145 }
3146
5d622845
LB
3147 for (shift = 56; shift >= 0; shift -= 8) {
3148 unsigned int ratio, group_size;
6574a5d5 3149
5d622845
LB
3150 ratio = (msr >> shift) & 0xFF;
3151 group_size = (core_counts >> shift) & 0xFF;
3152 if (ratio)
3153 fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
3154 ratio, bclk, ratio * bclk, group_size);
3155 }
103a8fea 3156
fcd17211
LB
3157 return;
3158}
3a9a941d 3159
1b439f01 3160static void dump_atom_turbo_ratio_limits(void)
0f7887c4
LB
3161{
3162 unsigned long long msr;
3163 unsigned int ratio;
3164
3165 get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);
3166 fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
3167
3168 ratio = (msr >> 0) & 0x3F;
3169 if (ratio)
1b439f01 3170 fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3171
3172 ratio = (msr >> 8) & 0x3F;
3173 if (ratio)
1b439f01 3174 fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3175
3176 ratio = (msr >> 16) & 0x3F;
3177 if (ratio)
1b439f01 3178 fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3179
3180 get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
3181 fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
3182
3183 ratio = (msr >> 24) & 0x3F;
3184 if (ratio)
1b439f01 3185 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3186
3187 ratio = (msr >> 16) & 0x3F;
3188 if (ratio)
1b439f01 3189 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3190
3191 ratio = (msr >> 8) & 0x3F;
3192 if (ratio)
1b439f01 3193 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3194
3195 ratio = (msr >> 0) & 0x3F;
3196 if (ratio)
1b439f01 3197 fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n", ratio, bclk, ratio * bclk);
0f7887c4
LB
3198}
3199
1b439f01 3200static void dump_knl_turbo_ratio_limits(void)
fb5d4327 3201{
cbf97aba
HC
3202 const unsigned int buckets_no = 7;
3203
fb5d4327 3204 unsigned long long msr;
cbf97aba
HC
3205 int delta_cores, delta_ratio;
3206 int i, b_nr;
3207 unsigned int cores[buckets_no];
3208 unsigned int ratio[buckets_no];
fb5d4327 3209
ebf5926a 3210 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
fb5d4327 3211
1b439f01 3212 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
fb5d4327 3213
1e3ec5cd 3214 /*
fb5d4327 3215 * Turbo encoding in KNL is as follows:
cbf97aba
HC
3216 * [0] -- Reserved
3217 * [7:1] -- Base value of number of active cores of bucket 1.
fb5d4327
DC
3218 * [15:8] -- Base value of freq ratio of bucket 1.
3219 * [20:16] -- +ve delta of number of active cores of bucket 2.
3220 * i.e. active cores of bucket 2 =
3221 * active cores of bucket 1 + delta
3222 * [23:21] -- Negative delta of freq ratio of bucket 2.
3223 * i.e. freq ratio of bucket 2 =
3224 * freq ratio of bucket 1 - delta
3225 * [28:24]-- +ve delta of number of active cores of bucket 3.
3226 * [31:29]-- -ve delta of freq ratio of bucket 3.
3227 * [36:32]-- +ve delta of number of active cores of bucket 4.
3228 * [39:37]-- -ve delta of freq ratio of bucket 4.
3229 * [44:40]-- +ve delta of number of active cores of bucket 5.
3230 * [47:45]-- -ve delta of freq ratio of bucket 5.
3231 * [52:48]-- +ve delta of number of active cores of bucket 6.
3232 * [55:53]-- -ve delta of freq ratio of bucket 6.
3233 * [60:56]-- +ve delta of number of active cores of bucket 7.
3234 * [63:61]-- -ve delta of freq ratio of bucket 7.
3235 */
cbf97aba
HC
3236
3237 b_nr = 0;
3238 cores[b_nr] = (msr & 0xFF) >> 1;
3239 ratio[b_nr] = (msr >> 8) & 0xFF;
3240
3241 for (i = 16; i < 64; i += 8) {
fb5d4327 3242 delta_cores = (msr >> i) & 0x1F;
cbf97aba
HC
3243 delta_ratio = (msr >> (i + 5)) & 0x7;
3244
3245 cores[b_nr + 1] = cores[b_nr] + delta_cores;
3246 ratio[b_nr + 1] = ratio[b_nr] - delta_ratio;
3247 b_nr++;
fb5d4327 3248 }
cbf97aba
HC
3249
3250 for (i = buckets_no - 1; i >= 0; i--)
3251 if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
b7d8c148 3252 fprintf(outf,
710f273b 3253 "%d * %.1f = %.1f MHz max turbo %d active cores\n",
cbf97aba 3254 ratio[i], bclk, ratio[i] * bclk, cores[i]);
fb5d4327
DC
3255}
3256
8b7199c0 3257static void dump_cst_cfg(void)
fcd17211
LB
3258{
3259 unsigned long long msr;
3260
045acf60
ZR
3261 if (!platform->has_nhm_msrs)
3262 return;
3263
1df2e55a 3264 get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
fcd17211 3265
1df2e55a 3266 fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr);
fcd17211 3267
3e8b62bf 3268 fprintf(outf, " (%s%s%s%s%slocked, pkg-cstate-limit=%d (%s)",
fcd17211
LB
3269 (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
3270 (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
3271 (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
3272 (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
1b439f01 3273 (msr & (1 << 15)) ? "" : "UN", (unsigned int)msr & 0xF, pkg_cstate_limit_strings[pkg_cstate_limit]);
ac980e13
AB
3274
3275#define AUTOMATIC_CSTATE_CONVERSION (1UL << 16)
d90120bf 3276 if (platform->has_cst_auto_convension) {
1b439f01 3277 fprintf(outf, ", automatic c-state conversion=%s", (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");
ac980e13
AB
3278 }
3279
3280 fprintf(outf, ")\n");
3281
fcd17211 3282 return;
103a8fea
LB
3283}
3284
1b439f01 3285static void dump_config_tdp(void)
6fb3143b
LB
3286{
3287 unsigned long long msr;
3288
3289 get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);
b7d8c148 3290 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
685b535b 3291 fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);
6fb3143b
LB
3292
3293 get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);
b7d8c148 3294 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
6fb3143b 3295 if (msr) {
685b535b
CY
3296 fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
3297 fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
3298 fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
3299 fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);
6fb3143b 3300 }
b7d8c148 3301 fprintf(outf, ")\n");
6fb3143b
LB
3302
3303 get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);
b7d8c148 3304 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
6fb3143b 3305 if (msr) {
685b535b
CY
3306 fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
3307 fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
3308 fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
3309 fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);
6fb3143b 3310 }
b7d8c148 3311 fprintf(outf, ")\n");
6fb3143b
LB
3312
3313 get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr);
b7d8c148 3314 fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);
6fb3143b 3315 if ((msr) & 0x3)
b7d8c148
LB
3316 fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);
3317 fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
3318 fprintf(outf, ")\n");
36229897 3319
6fb3143b 3320 get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
b7d8c148 3321 fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
685b535b 3322 fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);
b7d8c148
LB
3323 fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
3324 fprintf(outf, ")\n");
6fb3143b 3325}
5a63426e 3326
1b439f01 3327unsigned int irtl_time_units[] = { 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
5a63426e
LB
3328
3329void print_irtl(void)
3330{
3331 unsigned long long msr;
3332
148df4fd
ZR
3333 if (!platform->has_irtl_msrs)
3334 return;
3335
8c382f9e
ZR
3336 if (platform->supported_cstates & PC3) {
3337 get_msr(base_cpu, MSR_PKGC3_IRTL, &msr);
3338 fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr);
3339 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
3340 (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
3341 }
5a63426e 3342
8c382f9e
ZR
3343 if (platform->supported_cstates & PC6) {
3344 get_msr(base_cpu, MSR_PKGC6_IRTL, &msr);
3345 fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr);
3346 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
3347 (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
3348 }
5a63426e 3349
8c382f9e
ZR
3350 if (platform->supported_cstates & PC7) {
3351 get_msr(base_cpu, MSR_PKGC7_IRTL, &msr);
3352 fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr);
3353 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
3354 (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
3355 }
5a63426e 3356
8c382f9e
ZR
3357 if (platform->supported_cstates & PC8) {
3358 get_msr(base_cpu, MSR_PKGC8_IRTL, &msr);
3359 fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr);
3360 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
3361 (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
3362 }
5a63426e 3363
8c382f9e
ZR
3364 if (platform->supported_cstates & PC9) {
3365 get_msr(base_cpu, MSR_PKGC9_IRTL, &msr);
3366 fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr);
3367 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
3368 (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
3369 }
5a63426e 3370
8c382f9e
ZR
3371 if (platform->supported_cstates & PC10) {
3372 get_msr(base_cpu, MSR_PKGC10_IRTL, &msr);
3373 fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr);
3374 fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
3375 (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
3376 }
5a63426e 3377}
1b439f01 3378
36229897
LB
3379void free_fd_percpu(void)
3380{
3381 int i;
3382
01a67adf 3383 for (i = 0; i < topo.max_cpu_num + 1; ++i) {
36229897
LB
3384 if (fd_percpu[i] != 0)
3385 close(fd_percpu[i]);
3386 }
3387
3388 free(fd_percpu);
6fb3143b
LB
3389}
3390
c98d5d94 3391void free_all_buffers(void)
103a8fea 3392{
0e2d8f05
LB
3393 int i;
3394
c98d5d94
LB
3395 CPU_FREE(cpu_present_set);
3396 cpu_present_set = NULL;
36229897 3397 cpu_present_setsize = 0;
103a8fea 3398
c98d5d94
LB
3399 CPU_FREE(cpu_affinity_set);
3400 cpu_affinity_set = NULL;
3401 cpu_affinity_setsize = 0;
103a8fea 3402
c98d5d94
LB
3403 free(thread_even);
3404 free(core_even);
3405 free(package_even);
103a8fea 3406
c98d5d94
LB
3407 thread_even = NULL;
3408 core_even = NULL;
3409 package_even = NULL;
103a8fea 3410
c98d5d94
LB
3411 free(thread_odd);
3412 free(core_odd);
3413 free(package_odd);
103a8fea 3414
c98d5d94
LB
3415 thread_odd = NULL;
3416 core_odd = NULL;
3417 package_odd = NULL;
103a8fea 3418
c98d5d94
LB
3419 free(output_buffer);
3420 output_buffer = NULL;
3421 outp = NULL;
36229897
LB
3422
3423 free_fd_percpu();
562a2d37
LB
3424
3425 free(irq_column_2_cpu);
3426 free(irqs_per_cpu);
0e2d8f05
LB
3427
3428 for (i = 0; i <= topo.max_cpu_num; ++i) {
3429 if (cpus[i].put_ids)
3430 CPU_FREE(cpus[i].put_ids);
3431 }
3432 free(cpus);
103a8fea
LB
3433}
3434
c98d5d94 3435/*
95aebc44 3436 * Parse a file containing a single int.
6de68fe1
LB
3437 * Return 0 if file can not be opened
3438 * Exit if file can be opened, but can not be parsed
c98d5d94 3439 */
95aebc44 3440int parse_int_file(const char *fmt, ...)
103a8fea 3441{
95aebc44
JT
3442 va_list args;
3443 char path[PATH_MAX];
c98d5d94 3444 FILE *filep;
95aebc44 3445 int value;
103a8fea 3446
95aebc44
JT
3447 va_start(args, fmt);
3448 vsnprintf(path, sizeof(path), fmt, args);
3449 va_end(args);
6de68fe1
LB
3450 filep = fopen(path, "r");
3451 if (!filep)
3452 return 0;
b2c95d90
JT
3453 if (fscanf(filep, "%d", &value) != 1)
3454 err(1, "%s: failed to parse number from file", path);
c98d5d94 3455 fclose(filep);
95aebc44
JT
3456 return value;
3457}
3458
c98d5d94
LB
3459/*
3460 * cpu_is_first_core_in_package(cpu)
3461 * return 1 if given CPU is 1st core in package
3462 */
3463int cpu_is_first_core_in_package(int cpu)
103a8fea 3464{
95aebc44 3465 return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu);
103a8fea
LB
3466}
3467
3468int get_physical_package_id(int cpu)
3469{
95aebc44 3470 return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
103a8fea
LB
3471}
3472
6de68fe1
LB
3473int get_die_id(int cpu)
3474{
3475 return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/die_id", cpu);
3476}
3477
103a8fea
LB
3478int get_core_id(int cpu)
3479{
95aebc44 3480 return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
103a8fea
LB
3481}
3482
ef605741
PB
3483void set_node_data(void)
3484{
2ffbb224
PB
3485 int pkg, node, lnode, cpu, cpux;
3486 int cpu_count;
3487
3488 /* initialize logical_node_id */
3489 for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu)
3490 cpus[cpu].logical_node_id = -1;
3491
3492 cpu_count = 0;
3493 for (pkg = 0; pkg < topo.num_packages; pkg++) {
3494 lnode = 0;
3495 for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {
3496 if (cpus[cpu].physical_package_id != pkg)
3497 continue;
3498 /* find a cpu with an unset logical_node_id */
3499 if (cpus[cpu].logical_node_id != -1)
3500 continue;
3501 cpus[cpu].logical_node_id = lnode;
3502 node = cpus[cpu].physical_node_id;
3503 cpu_count++;
3504 /*
3505 * find all matching cpus on this pkg and set
3506 * the logical_node_id
3507 */
3508 for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) {
1b439f01 3509 if ((cpus[cpux].physical_package_id == pkg) && (cpus[cpux].physical_node_id == node)) {
2ffbb224
PB
3510 cpus[cpux].logical_node_id = lnode;
3511 cpu_count++;
3512 }
3513 }
3514 lnode++;
3515 if (lnode > topo.nodes_per_pkg)
3516 topo.nodes_per_pkg = lnode;
3517 }
3518 if (cpu_count >= topo.max_cpu_num)
3519 break;
ef605741 3520 }
ef605741
PB
3521}
3522
3523int get_physical_node_id(struct cpu_topology *thiscpu)
c98d5d94
LB
3524{
3525 char path[80];
3526 FILE *filep;
0e2d8f05
LB
3527 int i;
3528 int cpu = thiscpu->logical_cpu_id;
e275b388 3529
0e2d8f05 3530 for (i = 0; i <= topo.max_cpu_num; i++) {
1b439f01 3531 sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist", cpu, i);
0e2d8f05
LB
3532 filep = fopen(path, "r");
3533 if (!filep)
3534 continue;
3535 fclose(filep);
3536 return i;
e275b388 3537 }
0e2d8f05
LB
3538 return -1;
3539}
c98d5d94 3540
0e2d8f05
LB
3541int get_thread_siblings(struct cpu_topology *thiscpu)
3542{
3543 char path[80], character;
3544 FILE *filep;
3545 unsigned long map;
8cb48b32 3546 int so, shift, sib_core;
0e2d8f05
LB
3547 int cpu = thiscpu->logical_cpu_id;
3548 int offset = topo.max_cpu_num + 1;
3549 size_t size;
8cb48b32 3550 int thread_id = 0;
0e2d8f05
LB
3551
3552 thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1));
8cb48b32
PB
3553 if (thiscpu->thread_id < 0)
3554 thiscpu->thread_id = thread_id++;
0e2d8f05
LB
3555 if (!thiscpu->put_ids)
3556 return -1;
3557
3558 size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
3559 CPU_ZERO_S(size, thiscpu->put_ids);
3560
1b439f01 3561 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
3d7772ea
LB
3562 filep = fopen(path, "r");
3563
3564 if (!filep) {
3565 warnx("%s: open failed", path);
3566 return -1;
3567 }
0e2d8f05
LB
3568 do {
3569 offset -= BITMASK_SIZE;
8173c336
BH
3570 if (fscanf(filep, "%lx%c", &map, &character) != 2)
3571 err(1, "%s: failed to parse file", path);
0e2d8f05
LB
3572 for (shift = 0; shift < BITMASK_SIZE; shift++) {
3573 if ((map >> shift) & 0x1) {
8cb48b32
PB
3574 so = shift + offset;
3575 sib_core = get_core_id(so);
3576 if (sib_core == thiscpu->physical_core_id) {
3577 CPU_SET_S(so, size, thiscpu->put_ids);
1b439f01
LB
3578 if ((so != cpu) && (cpus[so].thread_id < 0))
3579 cpus[so].thread_id = thread_id++;
8cb48b32 3580 }
0e2d8f05
LB
3581 }
3582 }
e13da9a1 3583 } while (character == ',');
c98d5d94 3584 fclose(filep);
0e2d8f05
LB
3585
3586 return CPU_COUNT_S(size, thiscpu->put_ids);
c98d5d94
LB
3587}
3588
103a8fea 3589/*
c98d5d94
LB
3590 * run func(thread, core, package) in topology order
3591 * skip non-present cpus
103a8fea
LB
3592 */
3593
1b439f01
LB
3594int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *,
3595 struct pkg_data *, struct thread_data *, struct core_data *,
3596 struct pkg_data *), struct thread_data *thread_base,
3597 struct core_data *core_base, struct pkg_data *pkg_base,
3598 struct thread_data *thread_base2, struct core_data *core_base2, struct pkg_data *pkg_base2)
c98d5d94 3599{
40f5cfe7 3600 int retval, pkg_no, node_no, core_no, thread_no;
c98d5d94
LB
3601
3602 for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
40f5cfe7 3603 for (node_no = 0; node_no < topo.nodes_per_pkg; ++node_no) {
1b439f01
LB
3604 for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {
3605 for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) {
40f5cfe7
PB
3606 struct thread_data *t, *t2;
3607 struct core_data *c, *c2;
3608 struct pkg_data *p, *p2;
3609
1b439f01 3610 t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no);
40f5cfe7
PB
3611
3612 if (cpu_is_not_present(t->cpu_id))
3613 continue;
3614
1b439f01 3615 t2 = GET_THREAD(thread_base2, thread_no, core_no, node_no, pkg_no);
40f5cfe7 3616
1b439f01
LB
3617 c = GET_CORE(core_base, core_no, node_no, pkg_no);
3618 c2 = GET_CORE(core_base2, core_no, node_no, pkg_no);
40f5cfe7
PB
3619
3620 p = GET_PKG(pkg_base, pkg_no);
3621 p2 = GET_PKG(pkg_base2, pkg_no);
3622
3623 retval = func(t, c, p, t2, c2, p2);
3624 if (retval)
3625 return retval;
3626 }
c98d5d94
LB
3627 }
3628 }
3629 }
3630 return 0;
3631}
3632
3633/*
3634 * run func(cpu) on every cpu in /proc/stat
3635 * return max_cpu number
3636 */
1b439f01 3637int for_all_proc_cpus(int (func) (int))
103a8fea
LB
3638{
3639 FILE *fp;
c98d5d94 3640 int cpu_num;
103a8fea
LB
3641 int retval;
3642
57a42a34 3643 fp = fopen_or_die(proc_stat, "r");
103a8fea
LB
3644
3645 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
b2c95d90
JT
3646 if (retval != 0)
3647 err(1, "%s: failed to parse format", proc_stat);
103a8fea 3648
c98d5d94
LB
3649 while (1) {
3650 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
103a8fea
LB
3651 if (retval != 1)
3652 break;
3653
c98d5d94
LB
3654 retval = func(cpu_num);
3655 if (retval) {
3656 fclose(fp);
1b439f01 3657 return (retval);
c98d5d94 3658 }
103a8fea
LB
3659 }
3660 fclose(fp);
c98d5d94 3661 return 0;
103a8fea
LB
3662}
3663
3664void re_initialize(void)
3665{
c98d5d94
LB
3666 free_all_buffers();
3667 setup_all_buffers();
3d7772ea 3668 fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
103a8fea
LB
3669}
3670
843c5791
PB
3671void set_max_cpu_num(void)
3672{
3673 FILE *filep;
8201a028 3674 int base_cpu;
843c5791 3675 unsigned long dummy;
8201a028 3676 char pathname[64];
843c5791 3677
8201a028
PB
3678 base_cpu = sched_getcpu();
3679 if (base_cpu < 0)
3680 err(1, "cannot find calling cpu ID");
1b439f01 3681 sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", base_cpu);
8201a028
PB
3682
3683 filep = fopen_or_die(pathname, "r");
843c5791 3684 topo.max_cpu_num = 0;
843c5791 3685 while (fscanf(filep, "%lx,", &dummy) == 1)
0e2d8f05 3686 topo.max_cpu_num += BITMASK_SIZE;
843c5791 3687 fclose(filep);
1b439f01 3688 topo.max_cpu_num--; /* 0 based */
843c5791 3689}
c98d5d94 3690
103a8fea 3691/*
c98d5d94
LB
3692 * count_cpus()
3693 * remember the last one seen, it will be the max
103a8fea 3694 */
c98d5d94 3695int count_cpus(int cpu)
103a8fea 3696{
9878bf7a
LB
3697 UNUSED(cpu);
3698
843c5791 3699 topo.num_cpus++;
c98d5d94
LB
3700 return 0;
3701}
1b439f01 3702
c98d5d94
LB
3703int mark_cpu_present(int cpu)
3704{
3705 CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
15aaa346 3706 return 0;
103a8fea
LB
3707}
3708
8cb48b32
PB
3709int init_thread_id(int cpu)
3710{
3711 cpus[cpu].thread_id = -1;
3712 return 0;
3713}
3714
562a2d37
LB
3715/*
3716 * snapshot_proc_interrupts()
3717 *
3718 * read and record summary of /proc/interrupts
3719 *
3720 * return 1 if config change requires a restart, else return 0
3721 */
3722int snapshot_proc_interrupts(void)
3723{
3724 static FILE *fp;
3725 int column, retval;
3726
3727 if (fp == NULL)
3728 fp = fopen_or_die("/proc/interrupts", "r");
3729 else
3730 rewind(fp);
3731
3732 /* read 1st line of /proc/interrupts to get cpu* name for each column */
3733 for (column = 0; column < topo.num_cpus; ++column) {
3734 int cpu_number;
3735
3736 retval = fscanf(fp, " CPU%d", &cpu_number);
3737 if (retval != 1)
3738 break;
3739
3740 if (cpu_number > topo.max_cpu_num) {
3741 warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);
3742 return 1;
3743 }
3744
3745 irq_column_2_cpu[column] = cpu_number;
3746 irqs_per_cpu[cpu_number] = 0;
3747 }
3748
3749 /* read /proc/interrupt count lines and sum up irqs per cpu */
3750 while (1) {
3751 int column;
3752 char buf[64];
3753
3754 retval = fscanf(fp, " %s:", buf); /* flush irq# "N:" */
3755 if (retval != 1)
3756 break;
3757
3758 /* read the count per cpu */
3759 for (column = 0; column < topo.num_cpus; ++column) {
3760
3761 int cpu_number, irq_count;
3762
3763 retval = fscanf(fp, " %d", &irq_count);
3764 if (retval != 1)
3765 break;
3766
3767 cpu_number = irq_column_2_cpu[column];
3768 irqs_per_cpu[cpu_number] += irq_count;
3769
3770 }
3771
1b439f01 3772 while (getc(fp) != '\n') ; /* flush interrupt description */
562a2d37
LB
3773
3774 }
3775 return 0;
3776}
1b439f01 3777
fdf676e5
LB
3778/*
3779 * snapshot_gfx_rc6_ms()
3780 *
3781 * record snapshot of
3782 * /sys/class/drm/card0/power/rc6_residency_ms
3783 *
3784 * return 1 if config change requires a restart, else return 0
3785 */
3786int snapshot_gfx_rc6_ms(void)
3787{
3788 FILE *fp;
3789 int retval;
3790
3791 fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r");
3792
3793 retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms);
3794 if (retval != 1)
3795 err(1, "GFX rc6");
3796
3797 fclose(fp);
3798
3799 return 0;
3800}
1b439f01 3801
27d47356
LB
3802/*
3803 * snapshot_gfx_mhz()
3804 *
2c019d65
ZR
3805 * fall back to /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz
3806 * when /sys/class/drm/card0/gt_cur_freq_mhz is not available.
27d47356
LB
3807 *
3808 * return 1 if config change requires a restart, else return 0
3809 */
3810int snapshot_gfx_mhz(void)
3811{
3812 static FILE *fp;
3813 int retval;
3814
2c019d65
ZR
3815 if (fp == NULL) {
3816 fp = fopen("/sys/class/drm/card0/gt_cur_freq_mhz", "r");
3817 if (!fp)
3818 fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r");
3819 } else {
27d47356 3820 rewind(fp);
22048c54
LB
3821 fflush(fp);
3822 }
27d47356
LB
3823
3824 retval = fscanf(fp, "%d", &gfx_cur_mhz);
3825 if (retval != 1)
3826 err(1, "GFX MHz");
3827
3828 return 0;
3829}
562a2d37 3830
b4b91569
RA
3831/*
3832 * snapshot_gfx_cur_mhz()
3833 *
2c019d65
ZR
3834 * fall back to /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz
3835 * when /sys/class/drm/card0/gt_act_freq_mhz is not available.
b4b91569
RA
3836 *
3837 * return 1 if config change requires a restart, else return 0
3838 */
3839int snapshot_gfx_act_mhz(void)
3840{
3841 static FILE *fp;
3842 int retval;
3843
2c019d65
ZR
3844 if (fp == NULL) {
3845 fp = fopen("/sys/class/drm/card0/gt_act_freq_mhz", "r");
3846 if (!fp)
3847 fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r");
3848 } else {
b4b91569
RA
3849 rewind(fp);
3850 fflush(fp);
3851 }
3852
3853 retval = fscanf(fp, "%d", &gfx_act_mhz);
3854 if (retval != 1)
3855 err(1, "GFX ACT MHz");
3856
3857 return 0;
3858}
3859
be0e54c4
LB
3860/*
3861 * snapshot_cpu_lpi()
3862 *
3863 * record snapshot of
3864 * /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us
be0e54c4
LB
3865 */
3866int snapshot_cpu_lpi_us(void)
3867{
3868 FILE *fp;
3869 int retval;
3870
3871 fp = fopen_or_die("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", "r");
3872
3873 retval = fscanf(fp, "%lld", &cpuidle_cur_cpu_lpi_us);
5ea7647b
PB
3874 if (retval != 1) {
3875 fprintf(stderr, "Disabling Low Power Idle CPU output\n");
3876 BIC_NOT_PRESENT(BIC_CPU_LPI);
605736c6 3877 fclose(fp);
5ea7647b
PB
3878 return -1;
3879 }
be0e54c4
LB
3880
3881 fclose(fp);
3882
3883 return 0;
3884}
1b439f01 3885
be0e54c4
LB
3886/*
3887 * snapshot_sys_lpi()
3888 *
1f81c5ef 3889 * record snapshot of sys_lpi_file
be0e54c4
LB
3890 */
3891int snapshot_sys_lpi_us(void)
3892{
3893 FILE *fp;
3894 int retval;
3895
1f81c5ef 3896 fp = fopen_or_die(sys_lpi_file, "r");
be0e54c4
LB
3897
3898 retval = fscanf(fp, "%lld", &cpuidle_cur_sys_lpi_us);
5ea7647b
PB
3899 if (retval != 1) {
3900 fprintf(stderr, "Disabling Low Power Idle System output\n");
3901 BIC_NOT_PRESENT(BIC_SYS_LPI);
15423b95 3902 fclose(fp);
5ea7647b
PB
3903 return -1;
3904 }
be0e54c4
LB
3905 fclose(fp);
3906
3907 return 0;
3908}
1b439f01 3909
562a2d37
LB
3910/*
3911 * snapshot /proc and /sys files
3912 *
3913 * return 1 if configuration restart needed, else return 0
3914 */
3915int snapshot_proc_sysfs_files(void)
3916{
218f0e8d
LB
3917 if (DO_BIC(BIC_IRQ))
3918 if (snapshot_proc_interrupts())
3919 return 1;
562a2d37 3920
812db3f7 3921 if (DO_BIC(BIC_GFX_rc6))
fdf676e5
LB
3922 snapshot_gfx_rc6_ms();
3923
812db3f7 3924 if (DO_BIC(BIC_GFXMHz))
27d47356
LB
3925 snapshot_gfx_mhz();
3926
b4b91569
RA
3927 if (DO_BIC(BIC_GFXACTMHz))
3928 snapshot_gfx_act_mhz();
3929
be0e54c4
LB
3930 if (DO_BIC(BIC_CPU_LPI))
3931 snapshot_cpu_lpi_us();
3932
3933 if (DO_BIC(BIC_SYS_LPI))
3934 snapshot_sys_lpi_us();
3935
562a2d37
LB
3936 return 0;
3937}
3938
8aa2ed0b
LB
3939int exit_requested;
3940
1b439f01 3941static void signal_handler(int signal)
8aa2ed0b
LB
3942{
3943 switch (signal) {
3944 case SIGINT:
3945 exit_requested = 1;
3946 if (debug)
3947 fprintf(stderr, " SIGINT\n");
3948 break;
07211960
LB
3949 case SIGUSR1:
3950 if (debug > 1)
3951 fprintf(stderr, "SIGUSR1\n");
3952 break;
8aa2ed0b
LB
3953 }
3954}
3955
3956void setup_signal_handler(void)
3957{
3958 struct sigaction sa;
3959
3960 memset(&sa, 0, sizeof(sa));
3961
3962 sa.sa_handler = &signal_handler;
3963
3964 if (sigaction(SIGINT, &sa, NULL) < 0)
3965 err(1, "sigaction SIGINT");
07211960
LB
3966 if (sigaction(SIGUSR1, &sa, NULL) < 0)
3967 err(1, "sigaction SIGUSR1");
8aa2ed0b 3968}
b9ad8ee0 3969
47936f94 3970void do_sleep(void)
b9ad8ee0 3971{
c026c236
AB
3972 struct timeval tout;
3973 struct timespec rest;
b9ad8ee0
LB
3974 fd_set readfds;
3975 int retval;
3976
3977 FD_ZERO(&readfds);
3978 FD_SET(0, &readfds);
3979
c026c236 3980 if (ignore_stdin) {
47936f94
AB
3981 nanosleep(&interval_ts, NULL);
3982 return;
3983 }
b9ad8ee0 3984
c026c236
AB
3985 tout = interval_tv;
3986 retval = select(1, &readfds, NULL, NULL, &tout);
b9ad8ee0
LB
3987
3988 if (retval == 1) {
b9ad8ee0
LB
3989 switch (getc(stdin)) {
3990 case 'q':
3991 exit_requested = 1;
3992 break;
c026c236
AB
3993 case EOF:
3994 /*
3995 * 'stdin' is a pipe closed on the other end. There
3996 * won't be any further input.
3997 */
3998 ignore_stdin = 1;
3999 /* Sleep the rest of the time */
4000 rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);
4001 rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;
4002 nanosleep(&rest, NULL);
b9ad8ee0 4003 }
b9ad8ee0 4004 }
b9ad8ee0 4005}
47936f94 4006
87e15da9
CY
4007int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)
4008{
4009 int ret, idx;
4010 unsigned long long msr_cur, msr_last;
4011
4012 if (!per_cpu_msr_sum)
4013 return 1;
4014
4015 idx = offset_to_idx(offset);
4016 if (idx < 0)
4017 return idx;
4018 /* get_msr_sum() = sum + (get_msr() - last) */
4019 ret = get_msr(cpu, offset, &msr_cur);
4020 if (ret)
4021 return ret;
4022 msr_last = per_cpu_msr_sum[cpu].entries[idx].last;
4023 DELTA_WRAP32(msr_cur, msr_last);
4024 *msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;
4025
4026 return 0;
4027}
4028
4029timer_t timerid;
4030
4031/* Timer callback, update the sum of MSRs periodically. */
4032static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4033{
4034 int i, ret;
4035 int cpu = t->cpu_id;
4036
9878bf7a
LB
4037 UNUSED(c);
4038 UNUSED(p);
4039
87e15da9
CY
4040 for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {
4041 unsigned long long msr_cur, msr_last;
13a779de 4042 off_t offset;
87e15da9
CY
4043
4044 if (!idx_valid(i))
4045 continue;
4046 offset = idx_to_offset(i);
4047 if (offset < 0)
4048 continue;
4049 ret = get_msr(cpu, offset, &msr_cur);
4050 if (ret) {
1b439f01 4051 fprintf(outf, "Can not update msr(0x%llx)\n", (unsigned long long)offset);
87e15da9
CY
4052 continue;
4053 }
4054
4055 msr_last = per_cpu_msr_sum[cpu].entries[i].last;
4056 per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;
4057
4058 DELTA_WRAP32(msr_cur, msr_last);
4059 per_cpu_msr_sum[cpu].entries[i].sum += msr_last;
4060 }
4061 return 0;
4062}
4063
1b439f01 4064static void msr_record_handler(union sigval v)
87e15da9 4065{
9878bf7a
LB
4066 UNUSED(v);
4067
87e15da9
CY
4068 for_all_cpus(update_msr_sum, EVEN_COUNTERS);
4069}
4070
4071void msr_sum_record(void)
4072{
4073 struct itimerspec its;
4074 struct sigevent sev;
4075
4076 per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));
4077 if (!per_cpu_msr_sum) {
4078 fprintf(outf, "Can not allocate memory for long time MSR.\n");
4079 return;
4080 }
4081 /*
4082 * Signal handler might be restricted, so use thread notifier instead.
4083 */
4084 memset(&sev, 0, sizeof(struct sigevent));
4085 sev.sigev_notify = SIGEV_THREAD;
4086 sev.sigev_notify_function = msr_record_handler;
4087
4088 sev.sigev_value.sival_ptr = &timerid;
4089 if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
4090 fprintf(outf, "Can not create timer.\n");
4091 goto release_msr;
4092 }
4093
4094 its.it_value.tv_sec = 0;
4095 its.it_value.tv_nsec = 1;
4096 /*
4097 * A wraparound time has been calculated early.
4098 * Some sources state that the peak power for a
4099 * microprocessor is usually 1.5 times the TDP rating,
4100 * use 2 * TDP for safety.
4101 */
4102 its.it_interval.tv_sec = rapl_joule_counter_range / 2;
4103 its.it_interval.tv_nsec = 0;
4104
4105 if (timer_settime(timerid, 0, &its, NULL) == -1) {
4106 fprintf(outf, "Can not set timer.\n");
4107 goto release_timer;
4108 }
4109 return;
4110
1b439f01 4111release_timer:
87e15da9 4112 timer_delete(timerid);
1b439f01 4113release_msr:
87e15da9
CY
4114 free(per_cpu_msr_sum);
4115}
4c2122d4 4116
38c6663a
LB
4117/*
4118 * set_my_sched_priority(pri)
4119 * return previous
4120 */
4121int set_my_sched_priority(int priority)
4122{
4123 int retval;
4124 int original_priority;
4125
4126 errno = 0;
4127 original_priority = getpriority(PRIO_PROCESS, 0);
4128 if (errno && (original_priority == -1))
4129 err(errno, "getpriority");
4130
4131 retval = setpriority(PRIO_PROCESS, 0, priority);
4132 if (retval)
de7839ee 4133 errx(retval, "capget(CAP_SYS_NICE) failed,try \"# setcap cap_sys_nice=ep %s\"", progname);
38c6663a
LB
4134
4135 errno = 0;
4136 retval = getpriority(PRIO_PROCESS, 0);
4137 if (retval != priority)
164d7a96 4138 err(retval, "getpriority(%d) != setpriority(%d)", retval, priority);
38c6663a
LB
4139
4140 return original_priority;
4141}
4142
103a8fea
LB
4143void turbostat_loop()
4144{
c98d5d94 4145 int retval;
e52966c0 4146 int restarted = 0;
9878bf7a 4147 unsigned int done_iters = 0;
c98d5d94 4148
8aa2ed0b
LB
4149 setup_signal_handler();
4150
38c6663a
LB
4151 /*
4152 * elevate own priority for interval mode
4153 */
4154 set_my_sched_priority(-20);
4155
103a8fea 4156restart:
e52966c0
LB
4157 restarted++;
4158
562a2d37 4159 snapshot_proc_sysfs_files();
c98d5d94 4160 retval = for_all_cpus(get_counters, EVEN_COUNTERS);
4c2122d4 4161 first_counter_read = 0;
d91bb17c
LB
4162 if (retval < -1) {
4163 exit(retval);
4164 } else if (retval == -1) {
3d7772ea 4165 if (restarted > 10) {
e52966c0
LB
4166 exit(retval);
4167 }
c98d5d94
LB
4168 re_initialize();
4169 goto restart;
4170 }
e52966c0 4171 restarted = 0;
023fe0ac 4172 done_iters = 0;
103a8fea
LB
4173 gettimeofday(&tv_even, (struct timezone *)NULL);
4174
4175 while (1) {
c98d5d94 4176 if (for_all_proc_cpus(cpu_is_not_present)) {
103a8fea
LB
4177 re_initialize();
4178 goto restart;
4179 }
b9ad8ee0 4180 do_sleep();
562a2d37
LB
4181 if (snapshot_proc_sysfs_files())
4182 goto restart;
c98d5d94 4183 retval = for_all_cpus(get_counters, ODD_COUNTERS);
d91bb17c
LB
4184 if (retval < -1) {
4185 exit(retval);
4186 } else if (retval == -1) {
15aaa346
LB
4187 re_initialize();
4188 goto restart;
4189 }
103a8fea 4190 gettimeofday(&tv_odd, (struct timezone *)NULL);
103a8fea 4191 timersub(&tv_odd, &tv_even, &tv_delta);
ba3dec99
LB
4192 if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) {
4193 re_initialize();
4194 goto restart;
4195 }
c98d5d94
LB
4196 compute_average(EVEN_COUNTERS);
4197 format_all_counters(EVEN_COUNTERS);
b7d8c148 4198 flush_output_stdout();
8aa2ed0b
LB
4199 if (exit_requested)
4200 break;
023fe0ac
CY
4201 if (num_iterations && ++done_iters >= num_iterations)
4202 break;
b9ad8ee0 4203 do_sleep();
562a2d37
LB
4204 if (snapshot_proc_sysfs_files())
4205 goto restart;
c98d5d94 4206 retval = for_all_cpus(get_counters, EVEN_COUNTERS);
d91bb17c
LB
4207 if (retval < -1) {
4208 exit(retval);
4209 } else if (retval == -1) {
103a8fea
LB
4210 re_initialize();
4211 goto restart;
4212 }
103a8fea 4213 gettimeofday(&tv_even, (struct timezone *)NULL);
103a8fea 4214 timersub(&tv_even, &tv_odd, &tv_delta);
ba3dec99
LB
4215 if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) {
4216 re_initialize();
4217 goto restart;
4218 }
c98d5d94
LB
4219 compute_average(ODD_COUNTERS);
4220 format_all_counters(ODD_COUNTERS);
b7d8c148 4221 flush_output_stdout();
8aa2ed0b
LB
4222 if (exit_requested)
4223 break;
023fe0ac
CY
4224 if (num_iterations && ++done_iters >= num_iterations)
4225 break;
103a8fea
LB
4226 }
4227}
4228
4229void check_dev_msr()
4230{
4231 struct stat sb;
7ce7d5de 4232 char pathname[32];
103a8fea 4233
7ce7d5de
PB
4234 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
4235 if (stat(pathname, &sb))
1b439f01 4236 if (system("/sbin/modprobe msr > /dev/null 2>&1"))
a21d38c8 4237 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
103a8fea
LB
4238}
4239
fcaa681c
LB
4240/*
4241 * check for CAP_SYS_RAWIO
4242 * return 0 on success
4243 * return 1 on fail
4244 */
4245int check_for_cap_sys_rawio(void)
103a8fea 4246{
fcaa681c
LB
4247 cap_t caps;
4248 cap_flag_value_t cap_flag_value;
98481e79 4249
fcaa681c
LB
4250 caps = cap_get_proc();
4251 if (caps == NULL)
4252 err(-6, "cap_get_proc\n");
98481e79 4253
fcaa681c
LB
4254 if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value))
4255 err(-6, "cap_get\n");
4256
4257 if (cap_flag_value != CAP_SET) {
1b439f01 4258 warnx("capget(CAP_SYS_RAWIO) failed," " try \"# setcap cap_sys_rawio=ep %s\"", progname);
fcaa681c 4259 return 1;
98481e79
LB
4260 }
4261
fcaa681c
LB
4262 if (cap_free(caps) == -1)
4263 err(-6, "cap_free\n");
4264
4265 return 0;
4266}
1b439f01 4267
fcaa681c
LB
4268void check_permissions(void)
4269{
4270 int do_exit = 0;
4271 char pathname[32];
4272
4273 /* check for CAP_SYS_RAWIO */
4274 do_exit += check_for_cap_sys_rawio();
4275
98481e79 4276 /* test file permissions */
7ce7d5de
PB
4277 sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
4278 if (euidaccess(pathname, R_OK)) {
98481e79
LB
4279 do_exit++;
4280 warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr");
4281 }
4282
4283 /* if all else fails, thell them to be root */
4284 if (do_exit)
4285 if (getuid() != 0)
d7899447 4286 warnx("... or simply run as root");
98481e79
LB
4287
4288 if (do_exit)
4289 exit(-6);
103a8fea
LB
4290}
4291
71e84129
ZR
4292void probe_bclk(void)
4293{
4294 unsigned long long msr;
4295 unsigned int base_ratio;
4296
fcfa1ce0 4297 if (!platform->has_nhm_msrs)
71e84129
ZR
4298 return;
4299
4300 if (platform->bclk_freq == BCLK_100MHZ)
4301 bclk = 100.00;
4302 else if (platform->bclk_freq == BCLK_133MHZ)
4303 bclk = 133.33;
4304 else if (platform->bclk_freq == BCLK_SLV)
4305 bclk = slm_bclk();
4306 else
4307 return;
4308
4309 get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
4310 base_ratio = (msr >> 8) & 0xFF;
4311
4312 base_hz = base_ratio * bclk * 1000000;
4313 has_base_hz = 1;
485a017c
ZR
4314
4315 if (platform->enable_tsc_tweak)
4316 tsc_tweak = base_hz / tsc_hz;
71e84129
ZR
4317}
4318
1b439f01 4319static void remove_underbar(char *s)
fecb3bc8
DA
4320{
4321 char *to = s;
4322
4323 while (*s) {
4324 if (*s != '_')
4325 *to++ = *s;
4326 s++;
4327 }
4328
4329 *to = 0;
4330}
4331
a61c9cb4 4332static void dump_turbo_ratio_info(void)
fcd17211 4333{
3ea8e52e 4334 if (!has_turbo)
fcd17211
LB
4335 return;
4336
11cd9a09
ZR
4337 if (!platform->has_nhm_msrs)
4338 return;
4339
10d85d85 4340 if (platform->trl_msrs & TRL_LIMIT2)
a3943dea 4341 dump_turbo_ratio_limit2();
fcd17211 4342
10d85d85 4343 if (platform->trl_msrs & TRL_LIMIT1)
a3943dea 4344 dump_turbo_ratio_limit1();
fcd17211 4345
10d85d85
ZR
4346 if (platform->trl_msrs & TRL_BASE) {
4347 dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT);
4af184ee
LB
4348
4349 if (is_hybrid)
10d85d85 4350 dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT);
4af184ee 4351 }
fcd17211 4352
10d85d85 4353 if (platform->trl_msrs & TRL_ATOM)
0f7887c4
LB
4354 dump_atom_turbo_ratio_limits();
4355
10d85d85 4356 if (platform->trl_msrs & TRL_KNL)
fb5d4327
DC
4357 dump_knl_turbo_ratio_limits();
4358
a61c9cb4 4359 if (platform->has_config_tdp)
6fb3143b 4360 dump_config_tdp();
3ea8e52e 4361}
6fb3143b 4362
a5c6d65d
LB
4363static int read_sysfs_int(char *path)
4364{
4365 FILE *input;
4366 int retval = -1;
4367
4368 input = fopen(path, "r");
4369 if (input == NULL) {
4370 if (debug)
4371 fprintf(outf, "NSFOD %s\n", path);
4372 return (-1);
4373 }
4374 if (fscanf(input, "%d", &retval) != 1)
4375 err(1, "%s: failed to read int from file", path);
4376 fclose(input);
4377
4378 return (retval);
4379}
4380
abdcbdb2
LB
4381static void dump_sysfs_file(char *path)
4382{
4383 FILE *input;
4384 char cpuidle_buf[64];
4385
4386 input = fopen(path, "r");
4387 if (input == NULL) {
4388 if (debug)
4389 fprintf(outf, "NSFOD %s\n", path);
4390 return;
4391 }
4392 if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input))
4393 err(1, "%s: failed to read file", path);
4394 fclose(input);
4395
4396 fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);
4397}
1b439f01 4398
622c8f23 4399static void probe_intel_uncore_frequency(void)
a5c6d65d
LB
4400{
4401 int i, j;
4402 char path[128];
4403
4404 if (!genuine_intel)
4405 return;
4406
4407 if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00", R_OK))
4408 return;
4409
4d182748
ZR
4410 /* Cluster level sysfs not supported yet. */
4411 if (!access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK))
4412 return;
4413
a5c6d65d
LB
4414 if (!access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK))
4415 BIC_PRESENT(BIC_UNCORE_MHZ);
4416
4417 if (quiet)
4418 return;
4419
4420 for (i = 0; i < topo.num_packages; ++i) {
4421 for (j = 0; j < topo.num_die; ++j) {
4422 int k, l;
4423
4424 sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/min_freq_khz",
4425 i, j);
4426 k = read_sysfs_int(path);
4427 sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/max_freq_khz",
4428 i, j);
4429 l = read_sysfs_int(path);
4430 fprintf(outf, "Uncore Frequency pkg%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000);
4431
4432 sprintf(path,
4433 "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_min_freq_khz",
4434 i, j);
4435 k = read_sysfs_int(path);
4436 sprintf(path,
4437 "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_max_freq_khz",
4438 i, j);
4439 l = read_sysfs_int(path);
4440 fprintf(outf, "(%d - %d MHz)\n", k / 1000, l / 1000);
4441 }
4442 }
4443}
4444
2538d167
ZR
4445static void probe_graphics(void)
4446{
4447 if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
4448 BIC_PRESENT(BIC_GFX_rc6);
4449
4450 if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK) ||
4451 !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
4452 BIC_PRESENT(BIC_GFXMHz);
4453
4454 if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK) ||
4455 !access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
4456 BIC_PRESENT(BIC_GFXACTMHz);
4457}
4458
1b439f01 4459static void dump_sysfs_cstate_config(void)
41618e63
LB
4460{
4461 char path[64];
4462 char name_buf[16];
4463 char desc[64];
4464 FILE *input;
4465 int state;
4466 char *sp;
4467
abdcbdb2
LB
4468 if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {
4469 fprintf(outf, "cpuidle not loaded\n");
4470 return;
4471 }
4472
4473 dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver");
4474 dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor");
4475 dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro");
4476
41618e63
LB
4477 for (state = 0; state < 10; ++state) {
4478
1b439f01 4479 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);
41618e63
LB
4480 input = fopen(path, "r");
4481 if (input == NULL)
4482 continue;
8173c336
BH
4483 if (!fgets(name_buf, sizeof(name_buf), input))
4484 err(1, "%s: failed to read file", path);
41618e63 4485
1b439f01 4486 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
41618e63
LB
4487 sp = strchr(name_buf, '-');
4488 if (!sp)
4489 sp = strchrnul(name_buf, '\n');
4490 *sp = '\0';
41618e63
LB
4491 fclose(input);
4492
fecb3bc8
DA
4493 remove_underbar(name_buf);
4494
1b439f01 4495 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc", base_cpu, state);
41618e63
LB
4496 input = fopen(path, "r");
4497 if (input == NULL)
4498 continue;
8173c336
BH
4499 if (!fgets(desc, sizeof(desc), input))
4500 err(1, "%s: failed to read file", path);
41618e63
LB
4501
4502 fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc);
4503 fclose(input);
4504 }
4505}
1b439f01
LB
4506
4507static void dump_sysfs_pstate_config(void)
7293fccd
LB
4508{
4509 char path[64];
4510 char driver_buf[64];
4511 char governor_buf[64];
4512 FILE *input;
4513 int turbo;
4514
1b439f01 4515 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", base_cpu);
7293fccd
LB
4516 input = fopen(path, "r");
4517 if (input == NULL) {
0a42d235 4518 fprintf(outf, "NSFOD %s\n", path);
7293fccd
LB
4519 return;
4520 }
8173c336
BH
4521 if (!fgets(driver_buf, sizeof(driver_buf), input))
4522 err(1, "%s: failed to read file", path);
7293fccd
LB
4523 fclose(input);
4524
1b439f01 4525 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", base_cpu);
7293fccd
LB
4526 input = fopen(path, "r");
4527 if (input == NULL) {
0a42d235 4528 fprintf(outf, "NSFOD %s\n", path);
7293fccd
LB
4529 return;
4530 }
8173c336
BH
4531 if (!fgets(governor_buf, sizeof(governor_buf), input))
4532 err(1, "%s: failed to read file", path);
7293fccd
LB
4533 fclose(input);
4534
4535 fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf);
4536 fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf);
4537
4538 sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");
4539 input = fopen(path, "r");
4540 if (input != NULL) {
8173c336
BH
4541 if (fscanf(input, "%d", &turbo) != 1)
4542 err(1, "%s: failed to parse number from file", path);
7293fccd
LB
4543 fprintf(outf, "cpufreq boost: %d\n", turbo);
4544 fclose(input);
4545 }
4546
4547 sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");
4548 input = fopen(path, "r");
4549 if (input != NULL) {
8173c336
BH
4550 if (fscanf(input, "%d", &turbo) != 1)
4551 err(1, "%s: failed to parse number from file", path);
7293fccd
LB
4552 fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);
4553 fclose(input);
4554 }
4555}
41618e63 4556
889facbe
LB
4557/*
4558 * print_epb()
4559 * Decode the ENERGY_PERF_BIAS MSR
4560 */
4561int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4562{
889facbe 4563 char *epb_string;
6d6501d9 4564 int cpu, epb;
889facbe 4565
9878bf7a
LB
4566 UNUSED(c);
4567 UNUSED(p);
4568
889facbe
LB
4569 if (!has_epb)
4570 return 0;
4571
4572 cpu = t->cpu_id;
4573
4574 /* EPB is per-package */
4575 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4576 return 0;
4577
4578 if (cpu_migrate(cpu)) {
3d7772ea 4579 fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);
889facbe
LB
4580 return -1;
4581 }
4582
6d6501d9
BP
4583 epb = get_epb(cpu);
4584 if (epb < 0)
889facbe
LB
4585 return 0;
4586
6d6501d9 4587 switch (epb) {
889facbe
LB
4588 case ENERGY_PERF_BIAS_PERFORMANCE:
4589 epb_string = "performance";
4590 break;
4591 case ENERGY_PERF_BIAS_NORMAL:
4592 epb_string = "balanced";
4593 break;
4594 case ENERGY_PERF_BIAS_POWERSAVE:
4595 epb_string = "powersave";
4596 break;
4597 default:
4598 epb_string = "custom";
4599 break;
4600 }
6d6501d9 4601 fprintf(outf, "cpu%d: EPB: %d (%s)\n", cpu, epb, epb_string);
889facbe
LB
4602
4603 return 0;
4604}
1b439f01 4605
7f5c258e
LB
4606/*
4607 * print_hwp()
4608 * Decode the MSR_HWP_CAPABILITIES
4609 */
4610int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4611{
4612 unsigned long long msr;
4613 int cpu;
4614
9878bf7a
LB
4615 UNUSED(c);
4616 UNUSED(p);
4617
7f5c258e
LB
4618 if (!has_hwp)
4619 return 0;
4620
4621 cpu = t->cpu_id;
4622
4623 /* MSR_HWP_CAPABILITIES is per-package */
4624 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4625 return 0;
4626
4627 if (cpu_migrate(cpu)) {
3d7772ea 4628 fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);
7f5c258e
LB
4629 return -1;
4630 }
4631
4632 if (get_msr(cpu, MSR_PM_ENABLE, &msr))
4633 return 0;
4634
1b439f01 4635 fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", cpu, msr, (msr & (1 << 0)) ? "" : "No-");
7f5c258e
LB
4636
4637 /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
4638 if ((msr & (1 << 0)) == 0)
4639 return 0;
4640
4641 if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))
4642 return 0;
4643
b7d8c148 4644 fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "
1b439f01
LB
4645 "(high %d guar %d eff %d low %d)\n",
4646 cpu, msr,
4647 (unsigned int)HWP_HIGHEST_PERF(msr),
4648 (unsigned int)HWP_GUARANTEED_PERF(msr),
4649 (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), (unsigned int)HWP_LOWEST_PERF(msr));
7f5c258e
LB
4650
4651 if (get_msr(cpu, MSR_HWP_REQUEST, &msr))
4652 return 0;
4653
b7d8c148 4654 fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "
1b439f01
LB
4655 "(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",
4656 cpu, msr,
4657 (unsigned int)(((msr) >> 0) & 0xff),
4658 (unsigned int)(((msr) >> 8) & 0xff),
4659 (unsigned int)(((msr) >> 16) & 0xff),
4660 (unsigned int)(((msr) >> 24) & 0xff),
4661 (unsigned int)(((msr) >> 32) & 0xff3), (unsigned int)(((msr) >> 42) & 0x1));
7f5c258e
LB
4662
4663 if (has_hwp_pkg) {
4664 if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))
4665 return 0;
4666
b7d8c148 4667 fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "
6dbd25a2 4668 "(min %d max %d des %d epp 0x%x window 0x%x)\n",
7f5c258e
LB
4669 cpu, msr,
4670 (unsigned int)(((msr) >> 0) & 0xff),
4671 (unsigned int)(((msr) >> 8) & 0xff),
4672 (unsigned int)(((msr) >> 16) & 0xff),
1b439f01 4673 (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3));
7f5c258e
LB
4674 }
4675 if (has_hwp_notify) {
4676 if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))
4677 return 0;
4678
b7d8c148 4679 fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "
7f5c258e 4680 "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",
1b439f01 4681 cpu, msr, ((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x2) ? "EN" : "Dis");
7f5c258e
LB
4682 }
4683 if (get_msr(cpu, MSR_HWP_STATUS, &msr))
4684 return 0;
4685
b7d8c148 4686 fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
1b439f01 4687 "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
92c25393 4688 cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-");
889facbe
LB
4689
4690 return 0;
4691}
4692
3a9a941d
LB
4693/*
4694 * print_perf_limit()
4695 */
4696int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4697{
4698 unsigned long long msr;
4699 int cpu;
4700
9878bf7a
LB
4701 UNUSED(c);
4702 UNUSED(p);
4703
3a9a941d
LB
4704 cpu = t->cpu_id;
4705
4706 /* per-package */
4707 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4708 return 0;
4709
4710 if (cpu_migrate(cpu)) {
3d7772ea 4711 fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);
3a9a941d
LB
4712 return -1;
4713 }
4714
0c057cf7 4715 if (platform->plr_msrs & PLR_CORE) {
3a9a941d 4716 get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
b7d8c148
LB
4717 fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
4718 fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
e33cbe85 4719 (msr & 1 << 15) ? "bit15, " : "",
3a9a941d 4720 (msr & 1 << 14) ? "bit14, " : "",
e33cbe85
LB
4721 (msr & 1 << 13) ? "Transitions, " : "",
4722 (msr & 1 << 12) ? "MultiCoreTurbo, " : "",
4723 (msr & 1 << 11) ? "PkgPwrL2, " : "",
4724 (msr & 1 << 10) ? "PkgPwrL1, " : "",
4725 (msr & 1 << 9) ? "CorePwr, " : "",
4726 (msr & 1 << 8) ? "Amps, " : "",
4727 (msr & 1 << 6) ? "VR-Therm, " : "",
4728 (msr & 1 << 5) ? "Auto-HWP, " : "",
4729 (msr & 1 << 4) ? "Graphics, " : "",
4730 (msr & 1 << 2) ? "bit2, " : "",
1b439f01 4731 (msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 0) ? "PROCHOT, " : "");
b7d8c148 4732 fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
e33cbe85 4733 (msr & 1 << 31) ? "bit31, " : "",
3a9a941d 4734 (msr & 1 << 30) ? "bit30, " : "",
e33cbe85
LB
4735 (msr & 1 << 29) ? "Transitions, " : "",
4736 (msr & 1 << 28) ? "MultiCoreTurbo, " : "",
4737 (msr & 1 << 27) ? "PkgPwrL2, " : "",
4738 (msr & 1 << 26) ? "PkgPwrL1, " : "",
4739 (msr & 1 << 25) ? "CorePwr, " : "",
4740 (msr & 1 << 24) ? "Amps, " : "",
4741 (msr & 1 << 22) ? "VR-Therm, " : "",
4742 (msr & 1 << 21) ? "Auto-HWP, " : "",
4743 (msr & 1 << 20) ? "Graphics, " : "",
4744 (msr & 1 << 18) ? "bit18, " : "",
1b439f01 4745 (msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 16) ? "PROCHOT, " : "");
3a9a941d
LB
4746
4747 }
0c057cf7 4748 if (platform->plr_msrs & PLR_GFX) {
3a9a941d 4749 get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);
b7d8c148
LB
4750 fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
4751 fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",
3a9a941d
LB
4752 (msr & 1 << 0) ? "PROCHOT, " : "",
4753 (msr & 1 << 1) ? "ThermStatus, " : "",
4754 (msr & 1 << 4) ? "Graphics, " : "",
4755 (msr & 1 << 6) ? "VR-Therm, " : "",
4756 (msr & 1 << 8) ? "Amps, " : "",
4757 (msr & 1 << 9) ? "GFXPwr, " : "",
1b439f01 4758 (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");
b7d8c148 4759 fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",
3a9a941d
LB
4760 (msr & 1 << 16) ? "PROCHOT, " : "",
4761 (msr & 1 << 17) ? "ThermStatus, " : "",
4762 (msr & 1 << 20) ? "Graphics, " : "",
4763 (msr & 1 << 22) ? "VR-Therm, " : "",
4764 (msr & 1 << 24) ? "Amps, " : "",
4765 (msr & 1 << 25) ? "GFXPwr, " : "",
1b439f01 4766 (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");
3a9a941d 4767 }
0c057cf7 4768 if (platform->plr_msrs & PLR_RING) {
3a9a941d 4769 get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
b7d8c148
LB
4770 fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
4771 fprintf(outf, " (Active: %s%s%s%s%s%s)",
3a9a941d
LB
4772 (msr & 1 << 0) ? "PROCHOT, " : "",
4773 (msr & 1 << 1) ? "ThermStatus, " : "",
4774 (msr & 1 << 6) ? "VR-Therm, " : "",
4775 (msr & 1 << 8) ? "Amps, " : "",
1b439f01 4776 (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");
b7d8c148 4777 fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",
3a9a941d
LB
4778 (msr & 1 << 16) ? "PROCHOT, " : "",
4779 (msr & 1 << 17) ? "ThermStatus, " : "",
4780 (msr & 1 << 22) ? "VR-Therm, " : "",
4781 (msr & 1 << 24) ? "Amps, " : "",
1b439f01 4782 (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");
3a9a941d
LB
4783 }
4784 return 0;
4785}
4786
889facbe 4787#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */
1b439f01 4788#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */
889facbe 4789
7c604093
ZR
4790double get_quirk_tdp(void)
4791{
4792 if (platform->rapl_quirk_tdp)
4793 return platform->rapl_quirk_tdp;
4794
4795 return 135.0;
4796}
4797
bf1ad57c 4798double get_tdp_intel(void)
144b44b1
LB
4799{
4800 unsigned long long msr;
4801
86ba263d 4802 if (platform->rapl_msrs & RAPL_PKG_POWER_INFO)
7ce7d5de 4803 if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr))
144b44b1 4804 return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;
7c604093 4805 return get_quirk_tdp();
144b44b1
LB
4806}
4807
bf1ad57c 4808double get_tdp_amd(void)
9392bd98 4809{
7c604093 4810 return get_quirk_tdp();
9392bd98
CW
4811}
4812
bf1ad57c 4813void rapl_probe_intel(void)
889facbe
LB
4814{
4815 unsigned long long msr;
144b44b1 4816 unsigned int time_unit;
889facbe
LB
4817 double tdp;
4818
a98f8860 4819 if (rapl_joules) {
86ba263d 4820 if (platform->rapl_msrs & RAPL_PKG_ENERGY_STATUS)
812db3f7 4821 BIC_PRESENT(BIC_Pkg_J);
86ba263d 4822 if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS)
812db3f7 4823 BIC_PRESENT(BIC_Cor_J);
86ba263d 4824 if (platform->rapl_msrs & RAPL_DRAM_ENERGY_STATUS)
812db3f7 4825 BIC_PRESENT(BIC_RAM_J);
86ba263d 4826 if (platform->rapl_msrs & RAPL_GFX_ENERGY_STATUS)
a98f8860
ZR
4827 BIC_PRESENT(BIC_GFX_J);
4828 } else {
86ba263d 4829 if (platform->rapl_msrs & RAPL_PKG_ENERGY_STATUS)
812db3f7 4830 BIC_PRESENT(BIC_PkgWatt);
86ba263d 4831 if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS)
812db3f7 4832 BIC_PRESENT(BIC_CorWatt);
86ba263d 4833 if (platform->rapl_msrs & RAPL_DRAM_ENERGY_STATUS)
812db3f7 4834 BIC_PRESENT(BIC_RAMWatt);
86ba263d 4835 if (platform->rapl_msrs & RAPL_GFX_ENERGY_STATUS)
a98f8860 4836 BIC_PRESENT(BIC_GFXWatt);
889facbe
LB
4837 }
4838
86ba263d 4839 if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS)
a98f8860 4840 BIC_PRESENT(BIC_PKG__);
86ba263d 4841 if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS)
a98f8860
ZR
4842 BIC_PRESENT(BIC_RAM__);
4843
889facbe 4844 /* units on package 0, verify later other packages match */
7ce7d5de 4845 if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr))
889facbe
LB
4846 return;
4847
4848 rapl_power_units = 1.0 / (1 << (msr & 0xF));
6d35b8c4 4849 if (platform->has_rapl_divisor)
144b44b1
LB
4850 rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
4851 else
4852 rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
889facbe 4853
9e6f3515
ZR
4854 if (platform->has_fixed_rapl_unit)
4855 rapl_dram_energy_units = (15.3 / 1000000);
4856 else
4857 rapl_dram_energy_units = rapl_energy_units;
40ee8e3b 4858
144b44b1
LB
4859 time_unit = msr >> 16 & 0xF;
4860 if (time_unit == 0)
4861 time_unit = 0xA;
889facbe 4862
144b44b1 4863 rapl_time_units = 1.0 / (1 << (time_unit));
889facbe 4864
bf1ad57c 4865 tdp = get_tdp_intel();
889facbe 4866
144b44b1 4867 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
96e47158 4868 if (!quiet)
b7d8c148 4869 fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
9392bd98 4870}
889facbe 4871
bf1ad57c 4872void rapl_probe_amd(void)
9392bd98
CW
4873{
4874 unsigned long long msr;
9392bd98
CW
4875 double tdp;
4876
33eb8225
KP
4877 if (rapl_joules) {
4878 BIC_PRESENT(BIC_Pkg_J);
4879 BIC_PRESENT(BIC_Cor_J);
4880 } else {
4881 BIC_PRESENT(BIC_PkgWatt);
4882 BIC_PRESENT(BIC_CorWatt);
9392bd98
CW
4883 }
4884
4885 if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
4886 return;
4887
4888 rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf));
4889 rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));
4890 rapl_power_units = ldexp(1.0, -(msr & 0xf));
4891
bf1ad57c 4892 tdp = get_tdp_amd();
9392bd98
CW
4893
4894 rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
4895 if (!quiet)
4896 fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
4897}
4898
889facbe
LB
4899void print_power_limit_msr(int cpu, unsigned long long msr, char *label)
4900{
6b398625 4901 fprintf(outf, "cpu%d: %s: %sabled (%0.3f Watts, %f sec, clamp %sabled)\n",
889facbe
LB
4902 cpu, label,
4903 ((msr >> 15) & 1) ? "EN" : "DIS",
4904 ((msr >> 0) & 0x7FFF) * rapl_power_units,
1b439f01 4905 (1.0 + (((msr >> 22) & 0x3) / 4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units,
889facbe
LB
4906 (((msr >> 16) & 1) ? "EN" : "DIS"));
4907
4908 return;
4909}
4910
4911int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4912{
4913 unsigned long long msr;
9392bd98 4914 const char *msr_name;
889facbe 4915 int cpu;
889facbe 4916
9878bf7a
LB
4917 UNUSED(c);
4918 UNUSED(p);
4919
86ba263d 4920 if (!platform->rapl_msrs)
889facbe
LB
4921 return 0;
4922
4923 /* RAPL counters are per package, so print only for 1st thread/package */
4924 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4925 return 0;
4926
4927 cpu = t->cpu_id;
4928 if (cpu_migrate(cpu)) {
3d7772ea 4929 fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);
889facbe
LB
4930 return -1;
4931 }
4932
86ba263d 4933 if (platform->rapl_msrs & RAPL_AMD_F17H) {
9392bd98
CW
4934 msr_name = "MSR_RAPL_PWR_UNIT";
4935 if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr))
4936 return -1;
4937 } else {
4938 msr_name = "MSR_RAPL_POWER_UNIT";
4939 if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))
4940 return -1;
4941 }
889facbe 4942
9392bd98 4943 fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr,
96e47158
LB
4944 rapl_power_units, rapl_energy_units, rapl_time_units);
4945
86ba263d 4946 if (platform->rapl_msrs & RAPL_PKG_POWER_INFO) {
144b44b1 4947
889facbe 4948 if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
1b439f01 4949 return -5;
889facbe 4950
b7d8c148 4951 fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
889facbe 4952 cpu, msr,
1b439f01 4953 ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
889facbe
LB
4954 ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4955 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4956 ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
4957
144b44b1 4958 }
86ba263d 4959 if (platform->rapl_msrs & RAPL_PKG) {
144b44b1 4960
889facbe
LB
4961 if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
4962 return -9;
4963
b7d8c148 4964 fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
96e47158 4965 cpu, msr, (msr >> 63) & 1 ? "" : "UN");
889facbe
LB
4966
4967 print_power_limit_msr(cpu, msr, "PKG Limit #1");
6b398625 4968 fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%0.3f Watts, %f* sec, clamp %sabled)\n",
889facbe
LB
4969 cpu,
4970 ((msr >> 47) & 1) ? "EN" : "DIS",
4971 ((msr >> 32) & 0x7FFF) * rapl_power_units,
1b439f01 4972 (1.0 + (((msr >> 54) & 0x3) / 4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units,
889facbe 4973 ((msr >> 48) & 1) ? "EN" : "DIS");
f52ba931
SP
4974
4975 if (get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr))
4976 return -9;
4977
4978 fprintf(outf, "cpu%d: MSR_VR_CURRENT_CONFIG: 0x%08llx\n", cpu, msr);
4979 fprintf(outf, "cpu%d: PKG Limit #4: %f Watts (%slocked)\n",
164d7a96 4980 cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN");
889facbe
LB
4981 }
4982
86ba263d 4983 if (platform->rapl_msrs & RAPL_DRAM_POWER_INFO) {
889facbe 4984 if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
1b439f01 4985 return -6;
889facbe 4986
b7d8c148 4987 fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
889facbe 4988 cpu, msr,
1b439f01 4989 ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
889facbe
LB
4990 ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4991 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4992 ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
0b2bb692 4993 }
86ba263d 4994 if (platform->rapl_msrs & RAPL_DRAM) {
889facbe
LB
4995 if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
4996 return -9;
b7d8c148 4997 fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
1b439f01 4998 cpu, msr, (msr >> 31) & 1 ? "" : "UN");
889facbe
LB
4999
5000 print_power_limit_msr(cpu, msr, "DRAM Limit");
5001 }
86ba263d 5002 if (platform->rapl_msrs & RAPL_CORE_POLICY) {
96e47158
LB
5003 if (get_msr(cpu, MSR_PP0_POLICY, &msr))
5004 return -7;
889facbe 5005
96e47158 5006 fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
144b44b1 5007 }
86ba263d 5008 if (platform->rapl_msrs & RAPL_CORE_POWER_LIMIT) {
96e47158
LB
5009 if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
5010 return -9;
5011 fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
1b439f01 5012 cpu, msr, (msr >> 31) & 1 ? "" : "UN");
96e47158 5013 print_power_limit_msr(cpu, msr, "Cores Limit");
889facbe 5014 }
86ba263d 5015 if (platform->rapl_msrs & RAPL_GFX) {
96e47158
LB
5016 if (get_msr(cpu, MSR_PP1_POLICY, &msr))
5017 return -8;
889facbe 5018
96e47158 5019 fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
889facbe 5020
96e47158
LB
5021 if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
5022 return -9;
5023 fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
1b439f01 5024 cpu, msr, (msr >> 31) & 1 ? "" : "UN");
96e47158 5025 print_power_limit_msr(cpu, msr, "GFX Limit");
889facbe
LB
5026 }
5027 return 0;
5028}
5029
ce7a32c2
ZR
5030/*
5031 * probe_rapl()
5032 *
5033 * sets rapl_power_units, rapl_energy_units, rapl_time_units
5034 */
5035void probe_rapl(void)
7ab5ff49 5036{
ce7a32c2
ZR
5037 if (!platform->rapl_msrs)
5038 return;
7ab5ff49 5039
ce7a32c2
ZR
5040 if (genuine_intel)
5041 rapl_probe_intel();
5042 if (authentic_amd || hygon_genuine)
5043 rapl_probe_amd();
5612b2c8
ZR
5044
5045 if (quiet)
5046 return;
5047
5048 for_all_cpus(print_rapl, ODD_COUNTERS);
7ab5ff49
ZR
5049}
5050
889facbe
LB
5051/*
5052 * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where
5053 * the Thermal Control Circuit (TCC) activates.
5054 * This is usually equal to tjMax.
5055 *
5056 * Older processors do not have this MSR, so there we guess,
5057 * but also allow cmdline over-ride with -T.
5058 *
5059 * Several MSR temperature values are in units of degrees-C
5060 * below this value, including the Digital Thermal Sensor (DTS),
5061 * Package Thermal Management Sensor (PTM), and thermal event thresholds.
5062 */
b2b94be7 5063int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
889facbe
LB
5064{
5065 unsigned long long msr;
55279aef 5066 unsigned int tcc_default, tcc_offset;
b2b94be7 5067 int cpu;
6ff7cb37 5068
9878bf7a
LB
5069 UNUSED(c);
5070 UNUSED(p);
5071
55279aef 5072 /* tj_max is used only for dts or ptm */
889facbe
LB
5073 if (!(do_dts || do_ptm))
5074 return 0;
5075
5076 /* this is a per-package concept */
5077 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
5078 return 0;
5079
b2b94be7
LB
5080 cpu = t->cpu_id;
5081 if (cpu_migrate(cpu)) {
5082 fprintf(outf, "Could not migrate to CPU %d\n", cpu);
5083 return -1;
5084 }
5085
55279aef
ZR
5086 if (tj_max_override != 0) {
5087 tj_max = tj_max_override;
1b439f01 5088 fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", cpu, tj_max);
889facbe
LB
5089 return 0;
5090 }
5091
b2b94be7 5092 /* Temperature Target MSR is Nehalem and newer only */
fcfa1ce0 5093 if (!platform->has_nhm_msrs)
b2b94be7
LB
5094 goto guess;
5095
5096 if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))
5097 goto guess;
5098
55279aef 5099 tcc_default = (msr >> 16) & 0xFF;
b2b94be7 5100
0b9a0b9b 5101 if (!quiet) {
d8e1623b
ZR
5102 int bits = platform->tcc_offset_bits;
5103 unsigned long long enabled = 0;
5104
5105 if (bits && !get_msr(base_cpu, MSR_PLATFORM_INFO, &enabled))
5106 enabled = (enabled >> 30) & 1;
5107
5108 if (bits && enabled) {
5109 tcc_offset = (msr >> 24) & GENMASK(bits - 1, 0);
0b9a0b9b 5110 fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n",
1b439f01 5111 cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset);
d8e1623b 5112 } else {
1b439f01 5113 fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, tcc_default);
0b9a0b9b
ZR
5114 }
5115 }
b2b94be7 5116
55279aef 5117 if (!tcc_default)
b2b94be7
LB
5118 goto guess;
5119
55279aef 5120 tj_max = tcc_default;
b2b94be7
LB
5121
5122 return 0;
889facbe 5123
b2b94be7 5124guess:
55279aef 5125 tj_max = TJMAX_DEFAULT;
1b439f01 5126 fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", cpu, tj_max);
889facbe
LB
5127
5128 return 0;
5129}
69807a63 5130
ce7a32c2
ZR
5131int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p)
5132{
5133 unsigned long long msr;
5134 unsigned int dts, dts2;
5135 int cpu;
5136
5137 UNUSED(c);
5138 UNUSED(p);
5139
5140 if (!(do_dts || do_ptm))
5141 return 0;
5142
5143 cpu = t->cpu_id;
5144
5145 /* DTS is per-core, no need to print for each thread */
5146 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
5147 return 0;
5148
5149 if (cpu_migrate(cpu)) {
5150 fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);
5151 return -1;
5152 }
5153
5154 if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) {
5155 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
5156 return 0;
5157
5158 dts = (msr >> 16) & 0x7F;
5159 fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts);
5160
5161 if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr))
5162 return 0;
5163
5164 dts = (msr >> 16) & 0x7F;
5165 dts2 = (msr >> 8) & 0x7F;
5166 fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
5167 cpu, msr, tj_max - dts, tj_max - dts2);
5168 }
5169
5170 if (do_dts && debug) {
5171 unsigned int resolution;
5172
5173 if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
5174 return 0;
5175
5176 dts = (msr >> 16) & 0x7F;
5177 resolution = (msr >> 27) & 0xF;
5178 fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
5179 cpu, msr, tj_max - dts, resolution);
5180
5181 if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr))
5182 return 0;
5183
5184 dts = (msr >> 16) & 0x7F;
5185 dts2 = (msr >> 8) & 0x7F;
5186 fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
5187 cpu, msr, tj_max - dts, tj_max - dts2);
5188 }
5189
5190 return 0;
5191}
5192
5193void probe_thermal(void)
5194{
5195 if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK))
5196 BIC_PRESENT(BIC_CORE_THROT_CNT);
5197 else
5198 BIC_NOT_PRESENT(BIC_CORE_THROT_CNT);
5612b2c8
ZR
5199
5200 for_all_cpus(set_temperature_target, ODD_COUNTERS);
5201
5202 if (quiet)
5203 return;
5204
5205 for_all_cpus(print_thermal, ODD_COUNTERS);
ce7a32c2
ZR
5206}
5207
5208int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p)
5209{
5210 unsigned int eax, ebx, ecx, edx;
5211
5212 UNUSED(c);
5213 UNUSED(p);
5214
5215 if (!genuine_intel)
5216 return 0;
5217
5218 if (cpu_migrate(t->cpu_id)) {
5219 fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id);
5220 return -1;
5221 }
5222
5223 if (max_level < 0x1a)
5224 return 0;
5225
5226 __cpuid(0x1a, eax, ebx, ecx, edx);
5227 eax = (eax >> 24) & 0xFF;
5228 if (eax == 0x20)
5229 t->is_atom = true;
5230 return 0;
5231}
5232
aa8d8cc7
LB
5233void decode_feature_control_msr(void)
5234{
5235 unsigned long long msr;
5236
f6505c88 5237 if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr))
aa8d8cc7 5238 fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
1b439f01 5239 base_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : "");
aa8d8cc7
LB
5240}
5241
69807a63
LB
5242void decode_misc_enable_msr(void)
5243{
5244 unsigned long long msr;
5245
f26b1519
LB
5246 if (!genuine_intel)
5247 return;
5248
69807a63 5249 if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
e6512624 5250 fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",
69807a63 5251 base_cpu, msr,
e6512624
LB
5252 msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",
5253 msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",
fd3933ca 5254 msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-",
e6512624
LB
5255 msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "",
5256 msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");
69807a63
LB
5257}
5258
33148d67
LB
5259void decode_misc_feature_control(void)
5260{
5261 unsigned long long msr;
5262
778fc34a 5263 if (!platform->has_msr_misc_feature_control)
33148d67
LB
5264 return;
5265
5266 if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))
1b439f01
LB
5267 fprintf(outf,
5268 "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
5269 base_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "",
5270 msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : "");
33148d67 5271}
1b439f01 5272
f0057310
LB
5273/*
5274 * Decode MSR_MISC_PWR_MGMT
5275 *
5276 * Decode the bits according to the Nehalem documentation
5277 * bit[0] seems to continue to have same meaning going forward
5278 * bit[1] less so...
5279 */
5280void decode_misc_pwr_mgmt_msr(void)
5281{
5282 unsigned long long msr;
5283
3dd0e754 5284 if (!platform->has_msr_misc_pwr_mgmt)
cf4cbe53
LB
5285 return;
5286
f0057310 5287 if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
ddadb8ad 5288 fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",
f0057310 5289 base_cpu, msr,
1b439f01 5290 msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS");
f0057310 5291}
1b439f01 5292
71616c8e
LB
5293/*
5294 * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
5295 *
5296 * This MSRs are present on Silvermont processors,
5297 * Intel Atom processor E3000 series (Baytrail), and friends.
5298 */
5299void decode_c6_demotion_policy_msr(void)
5300{
5301 unsigned long long msr;
5302
6c36882e
ZR
5303 if (!platform->has_msr_c6_demotion_policy_config)
5304 return;
5305
71616c8e
LB
5306 if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))
5307 fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",
5308 base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
5309
5310 if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))
5311 fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",
5312 base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
5313}
7f5c258e 5314
d76bb7a0
LB
5315void print_dev_latency(void)
5316{
5317 char *path = "/dev/cpu_dma_latency";
5318 int fd;
5319 int value;
5320 int retval;
5321
5322 fd = open(path, O_RDONLY);
5323 if (fd < 0) {
de7839ee 5324 warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", progname);
d76bb7a0
LB
5325 return;
5326 }
5327
5328 retval = read(fd, (void *)&value, sizeof(int));
5329 if (retval != sizeof(int)) {
6cbfedc7 5330 warn("read failed %s", path);
d76bb7a0
LB
5331 close(fd);
5332 return;
5333 }
1b439f01 5334 fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n", value, value == 2000000000 ? "default" : "constrained");
d76bb7a0
LB
5335
5336 close(fd);
5337}
5338
2af4f9b8 5339/*
2db0e5eb 5340 * Linux-perf manages the HW instructions-retired counter
2af4f9b8
LB
5341 * by enabling when requested, and hiding rollover
5342 */
5343void linux_perf_init(void)
5344{
5345 if (!BIC_IS_ENABLED(BIC_IPC))
5346 return;
5347
5348 if (access("/proc/sys/kernel/perf_event_paranoid", F_OK))
5349 return;
5350
5351 fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
5352 if (fd_instr_count_percpu == NULL)
5353 err(-1, "calloc fd_instr_count_percpu");
5354
5355 BIC_PRESENT(BIC_IPC);
5356}
5357
3c6a17b8
ZR
5358void probe_cstates(void)
5359{
5360 probe_cst_limit();
5361
5362 if (platform->supported_cstates & CC1)
5363 BIC_PRESENT(BIC_CPU_c1);
5364
5365 if (platform->supported_cstates & CC3)
5366 BIC_PRESENT(BIC_CPU_c3);
5367
5368 if (platform->supported_cstates & CC6)
5369 BIC_PRESENT(BIC_CPU_c6);
5370
5371 if (platform->supported_cstates & CC7)
5372 BIC_PRESENT(BIC_CPU_c7);
5373
5374 if (platform->supported_cstates & PC2 && (pkg_cstate_limit >= PCL__2))
5375 BIC_PRESENT(BIC_Pkgpc2);
5376
5377 if (platform->supported_cstates & PC3 && (pkg_cstate_limit >= PCL__3))
5378 BIC_PRESENT(BIC_Pkgpc3);
5379
5380 if (platform->supported_cstates & PC6 && (pkg_cstate_limit >= PCL__6))
5381 BIC_PRESENT(BIC_Pkgpc6);
5382
5383 if (platform->supported_cstates & PC7 && (pkg_cstate_limit >= PCL__7))
5384 BIC_PRESENT(BIC_Pkgpc7);
5385
5386 if (platform->supported_cstates & PC8 && (pkg_cstate_limit >= PCL__8))
5387 BIC_PRESENT(BIC_Pkgpc8);
5388
5389 if (platform->supported_cstates & PC9 && (pkg_cstate_limit >= PCL__9))
5390 BIC_PRESENT(BIC_Pkgpc9);
5391
5392 if (platform->supported_cstates & PC10 && (pkg_cstate_limit >= PCL_10))
5393 BIC_PRESENT(BIC_Pkgpc10);
045acf60
ZR
5394
5395 if (platform->has_msr_module_c6_res_ms)
5396 BIC_PRESENT(BIC_Mod_c6);
5397
5398 if (platform->has_ext_cst_msrs) {
5399 BIC_PRESENT(BIC_Totl_c0);
5400 BIC_PRESENT(BIC_Any_c0);
5401 BIC_PRESENT(BIC_GFX_c0);
5402 BIC_PRESENT(BIC_CPUGFX);
5403 }
5404
5405 if (quiet)
5406 return;
5407
5408 dump_power_ctl();
5409 dump_cst_cfg();
5410 decode_c6_demotion_policy_msr();
5411 print_dev_latency();
5412 dump_sysfs_cstate_config();
5612b2c8 5413 print_irtl();
3c6a17b8
ZR
5414}
5415
e7d7b82d
ZR
5416void probe_lpi(void)
5417{
5418 if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))
5419 BIC_PRESENT(BIC_CPU_LPI);
5420 else
5421 BIC_NOT_PRESENT(BIC_CPU_LPI);
5422
5423 if (!access(sys_lpi_file_sysfs, R_OK)) {
5424 sys_lpi_file = sys_lpi_file_sysfs;
5425 BIC_PRESENT(BIC_SYS_LPI);
5426 } else if (!access(sys_lpi_file_debugfs, R_OK)) {
5427 sys_lpi_file = sys_lpi_file_debugfs;
5428 BIC_PRESENT(BIC_SYS_LPI);
5429 } else {
5430 sys_lpi_file_sysfs = NULL;
5431 BIC_NOT_PRESENT(BIC_SYS_LPI);
5432 }
5433
5434}
5435
11cd9a09
ZR
5436void probe_pstates(void)
5437{
5438 probe_bclk();
5439
5440 if (quiet)
5441 return;
5442
5443 dump_platform_info();
5444 dump_turbo_ratio_info();
5445 dump_sysfs_pstate_config();
5446 decode_misc_pwr_mgmt_msr();
5612b2c8
ZR
5447
5448 for_all_cpus(print_hwp, ODD_COUNTERS);
5449 for_all_cpus(print_epb, ODD_COUNTERS);
5450 for_all_cpus(print_perf_limit, ODD_COUNTERS);
11cd9a09
ZR
5451}
5452
fcd17211 5453void process_cpuid()
103a8fea 5454{
34041551
LB
5455 unsigned int eax, ebx, ecx, edx;
5456 unsigned int fms, family, model, stepping, ecx_flags, edx_flags;
ed0757b8 5457 unsigned long long ucode_patch = 0;
103a8fea
LB
5458
5459 eax = ebx = ecx = edx = 0;
5460
5aea2f7f 5461 __cpuid(0, max_level, ebx, ecx, edx);
103a8fea 5462
34041551 5463 if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
103a8fea 5464 genuine_intel = 1;
34041551
LB
5465 else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
5466 authentic_amd = 1;
c1c10cc7
PW
5467 else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)
5468 hygon_genuine = 1;
103a8fea 5469
96e47158 5470 if (!quiet)
ed0757b8
LB
5471 fprintf(outf, "CPUID(0): %.4s%.4s%.4s 0x%x CPUID levels\n",
5472 (char *)&ebx, (char *)&edx, (char *)&ecx, max_level);
103a8fea 5473
5aea2f7f 5474 __cpuid(1, fms, ebx, ecx, edx);
103a8fea
LB
5475 family = (fms >> 8) & 0xf;
5476 model = (fms >> 4) & 0xf;
5477 stepping = fms & 0xf;
5aa3d1a2
CW
5478 if (family == 0xf)
5479 family += (fms >> 20) & 0xff;
5480 if (family >= 6)
103a8fea 5481 model += ((fms >> 16) & 0xf) << 4;
34041551
LB
5482 ecx_flags = ecx;
5483 edx_flags = edx;
103a8fea 5484
ed0757b8 5485 if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
6cbfedc7 5486 warnx("get_msr(UCODE)");
ed0757b8 5487
103a8fea
LB
5488 /*
5489 * check max extended function levels of CPUID.
5490 * This is needed to check for invariant TSC.
5491 * This check is valid for both Intel and AMD.
5492 */
5493 ebx = ecx = edx = 0;
5aea2f7f 5494 __cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
103a8fea 5495
34041551 5496 if (!quiet) {
ed0757b8 5497 fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d) microcode 0x%x\n",
1b439f01
LB
5498 family, model, stepping, family, model, stepping,
5499 (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
ed0757b8 5500 fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);
34041551
LB
5501 fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",
5502 ecx_flags & (1 << 0) ? "SSE3" : "-",
5503 ecx_flags & (1 << 3) ? "MONITOR" : "-",
5504 ecx_flags & (1 << 6) ? "SMX" : "-",
5505 ecx_flags & (1 << 7) ? "EIST" : "-",
5506 ecx_flags & (1 << 8) ? "TM2" : "-",
5507 edx_flags & (1 << 4) ? "TSC" : "-",
5508 edx_flags & (1 << 5) ? "MSR" : "-",
5509 edx_flags & (1 << 22) ? "ACPI-TM" : "-",
1b439f01 5510 edx_flags & (1 << 28) ? "HT" : "-", edx_flags & (1 << 29) ? "TM" : "-");
34041551 5511 }
b98a6d78 5512
45232ab1 5513 probe_platform_features(family, model);
34041551
LB
5514
5515 if (!(edx_flags & (1 << 5)))
5516 errx(1, "CPUID: no MSR");
5517
61a87ba7 5518 if (max_extended_level >= 0x80000007) {
103a8fea 5519
d7899447
LB
5520 /*
5521 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
5522 * this check is valid for both Intel and AMD
5523 */
5aea2f7f 5524 __cpuid(0x80000007, eax, ebx, ecx, edx);
d7899447
LB
5525 has_invariant_tsc = edx & (1 << 8);
5526 }
103a8fea
LB
5527
5528 /*
5529 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
5530 * this check is valid for both Intel and AMD
5531 */
5532
5aea2f7f 5533 __cpuid(0x6, eax, ebx, ecx, edx);
8209e054 5534 has_aperf = ecx & (1 << 0);
812db3f7
LB
5535 if (has_aperf) {
5536 BIC_PRESENT(BIC_Avg_MHz);
5537 BIC_PRESENT(BIC_Busy);
5538 BIC_PRESENT(BIC_Bzy_MHz);
5539 }
889facbe 5540 do_dts = eax & (1 << 0);
812db3f7
LB
5541 if (do_dts)
5542 BIC_PRESENT(BIC_CoreTmp);
b3a34e93 5543 has_turbo = eax & (1 << 1);
889facbe 5544 do_ptm = eax & (1 << 6);
812db3f7
LB
5545 if (do_ptm)
5546 BIC_PRESENT(BIC_PkgTmp);
7f5c258e
LB
5547 has_hwp = eax & (1 << 7);
5548 has_hwp_notify = eax & (1 << 8);
5549 has_hwp_activity_window = eax & (1 << 9);
5550 has_hwp_epp = eax & (1 << 10);
5551 has_hwp_pkg = eax & (1 << 11);
889facbe
LB
5552 has_epb = ecx & (1 << 3);
5553
96e47158 5554 if (!quiet)
b3a34e93 5555 fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "
7f5c258e
LB
5556 "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
5557 has_aperf ? "" : "No-",
b3a34e93 5558 has_turbo ? "" : "No-",
7f5c258e
LB
5559 do_dts ? "" : "No-",
5560 do_ptm ? "" : "No-",
5561 has_hwp ? "" : "No-",
5562 has_hwp_notify ? "" : "No-",
5563 has_hwp_activity_window ? "" : "No-",
1b439f01 5564 has_hwp_epp ? "" : "No-", has_hwp_pkg ? "" : "No-", has_epb ? "" : "No-");
103a8fea 5565
96e47158 5566 if (!quiet)
69807a63
LB
5567 decode_misc_enable_msr();
5568
96e47158 5569 if (max_level >= 0x7 && !quiet) {
aa8d8cc7 5570 int has_sgx;
103a8fea 5571
aa8d8cc7
LB
5572 ecx = 0;
5573
5574 __cpuid_count(0x7, 0, eax, ebx, ecx, edx);
5575
5576 has_sgx = ebx & (1 << 2);
774627c5
LB
5577
5578 is_hybrid = edx & (1 << 15);
5579
5580 fprintf(outf, "CPUID(7): %sSGX %sHybrid\n", has_sgx ? "" : "No-", is_hybrid ? "" : "No-");
aa8d8cc7
LB
5581
5582 if (has_sgx)
5583 decode_feature_control_msr();
5584 }
5585
61a87ba7 5586 if (max_level >= 0x15) {
8a5bdf41
LB
5587 unsigned int eax_crystal;
5588 unsigned int ebx_tsc;
5589
5590 /*
5591 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz
5592 */
5593 eax_crystal = ebx_tsc = crystal_hz = edx = 0;
5aea2f7f 5594 __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);
8a5bdf41
LB
5595
5596 if (ebx_tsc != 0) {
96e47158 5597 if (!quiet && (ebx != 0))
b7d8c148 5598 fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
8a5bdf41
LB
5599 eax_crystal, ebx_tsc, crystal_hz);
5600
5601 if (crystal_hz == 0)
a5d1ab93 5602 crystal_hz = platform->crystal_freq;
8a5bdf41
LB
5603
5604 if (crystal_hz) {
1b439f01 5605 tsc_hz = (unsigned long long)crystal_hz *ebx_tsc / eax_crystal;
96e47158 5606 if (!quiet)
b7d8c148 5607 fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
1b439f01 5608 tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
8a5bdf41
LB
5609 }
5610 }
5611 }
61a87ba7
LB
5612 if (max_level >= 0x16) {
5613 unsigned int base_mhz, max_mhz, bus_mhz, edx;
5614
5615 /*
5616 * CPUID 16H Base MHz, Max MHz, Bus MHz
5617 */
5618 base_mhz = max_mhz = bus_mhz = edx = 0;
5619
5aea2f7f 5620 __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
96e47158 5621 if (!quiet)
b7d8c148 5622 fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
61a87ba7
LB
5623 base_mhz, max_mhz, bus_mhz);
5624 }
8a5bdf41 5625
b2b34dfe 5626 if (has_aperf)
ed43247b 5627 aperf_mperf_multiplier = platform->need_perf_multiplier ? 1024 : 1;
b2b34dfe 5628
812db3f7
LB
5629 BIC_PRESENT(BIC_IRQ);
5630 BIC_PRESENT(BIC_TSC_MHz);
7ee39d8d 5631}
812db3f7 5632
7ee39d8d
ZR
5633void probe_pm_features(void)
5634{
11cd9a09
ZR
5635 probe_pstates();
5636
3c6a17b8
ZR
5637 probe_cstates();
5638
e7d7b82d
ZR
5639 probe_lpi();
5640
622c8f23
ZR
5641 probe_intel_uncore_frequency();
5642
2538d167
ZR
5643 probe_graphics();
5644
6cb13609
ZR
5645 probe_rapl();
5646
db735f8b
ZR
5647 probe_thermal();
5648
ce7ddf8a 5649 if (platform->has_nhm_msrs)
812db3f7 5650 BIC_PRESENT(BIC_SMI);
f0057310 5651
96e47158 5652 if (!quiet)
33148d67 5653 decode_misc_feature_control();
103a8fea
LB
5654}
5655
103a8fea
LB
5656/*
5657 * in /dev/cpu/ return success for names that are numbers
5658 * ie. filter out ".", "..", "microcode".
5659 */
5660int dir_filter(const struct dirent *dirp)
5661{
5662 if (isdigit(dirp->d_name[0]))
5663 return 1;
5664 else
5665 return 0;
5666}
5667
c98d5d94
LB
5668void topology_probe()
5669{
5670 int i;
5671 int max_core_id = 0;
5672 int max_package_id = 0;
6de68fe1 5673 int max_die_id = 0;
c98d5d94 5674 int max_siblings = 0;
c98d5d94
LB
5675
5676 /* Initialize num_cpus, max_cpu_num */
843c5791 5677 set_max_cpu_num();
c98d5d94 5678 topo.num_cpus = 0;
c98d5d94
LB
5679 for_all_proc_cpus(count_cpus);
5680 if (!summary_only && topo.num_cpus > 1)
812db3f7 5681 BIC_PRESENT(BIC_CPU);
c98d5d94 5682
d8af6f5f 5683 if (debug > 1)
b7d8c148 5684 fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
c98d5d94 5685
1b439f01 5686 cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));
b2c95d90
JT
5687 if (cpus == NULL)
5688 err(1, "calloc cpus");
c98d5d94
LB
5689
5690 /*
5691 * Allocate and initialize cpu_present_set
5692 */
5693 cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1));
b2c95d90
JT
5694 if (cpu_present_set == NULL)
5695 err(3, "CPU_ALLOC");
c98d5d94
LB
5696 cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
5697 CPU_ZERO_S(cpu_present_setsize, cpu_present_set);
5698 for_all_proc_cpus(mark_cpu_present);
5699
1ef7d21a
LB
5700 /*
5701 * Validate that all cpus in cpu_subset are also in cpu_present_set
5702 */
5703 for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {
5704 if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset))
5705 if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set))
5706 err(1, "cpu%d not present", i);
5707 }
5708
c98d5d94
LB
5709 /*
5710 * Allocate and initialize cpu_affinity_set
5711 */
5712 cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));
b2c95d90
JT
5713 if (cpu_affinity_set == NULL)
5714 err(3, "CPU_ALLOC");
c98d5d94
LB
5715 cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
5716 CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
5717
8cb48b32 5718 for_all_proc_cpus(init_thread_id);
c98d5d94
LB
5719
5720 /*
5721 * For online cpus
5722 * find max_core_id, max_package_id
5723 */
5724 for (i = 0; i <= topo.max_cpu_num; ++i) {
5725 int siblings;
5726
5727 if (cpu_is_not_present(i)) {
d8af6f5f 5728 if (debug > 1)
b7d8c148 5729 fprintf(outf, "cpu%d NOT PRESENT\n", i);
c98d5d94
LB
5730 continue;
5731 }
c98d5d94 5732
0e2d8f05
LB
5733 cpus[i].logical_cpu_id = i;
5734
5735 /* get package information */
c98d5d94
LB
5736 cpus[i].physical_package_id = get_physical_package_id(i);
5737 if (cpus[i].physical_package_id > max_package_id)
5738 max_package_id = cpus[i].physical_package_id;
5739
6de68fe1
LB
5740 /* get die information */
5741 cpus[i].die_id = get_die_id(i);
5742 if (cpus[i].die_id > max_die_id)
5743 max_die_id = cpus[i].die_id;
5744
0e2d8f05 5745 /* get numa node information */
ef605741
PB
5746 cpus[i].physical_node_id = get_physical_node_id(&cpus[i]);
5747 if (cpus[i].physical_node_id > topo.max_node_num)
5748 topo.max_node_num = cpus[i].physical_node_id;
0e2d8f05
LB
5749
5750 /* get core information */
5751 cpus[i].physical_core_id = get_core_id(i);
5752 if (cpus[i].physical_core_id > max_core_id)
5753 max_core_id = cpus[i].physical_core_id;
5754
5755 /* get thread information */
5756 siblings = get_thread_siblings(&cpus[i]);
c98d5d94
LB
5757 if (siblings > max_siblings)
5758 max_siblings = siblings;
4f206a0f 5759 if (cpus[i].thread_id == 0)
8cb48b32 5760 topo.num_cores++;
c98d5d94 5761 }
ef605741 5762
70a9c6e8 5763 topo.cores_per_node = max_core_id + 1;
d8af6f5f 5764 if (debug > 1)
1b439f01 5765 fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node);
70a9c6e8 5766 if (!summary_only && topo.cores_per_node > 1)
812db3f7 5767 BIC_PRESENT(BIC_Core);
c98d5d94 5768
6de68fe1
LB
5769 topo.num_die = max_die_id + 1;
5770 if (debug > 1)
1b439f01 5771 fprintf(outf, "max_die_id %d, sizing for %d die\n", max_die_id, topo.num_die);
6de68fe1
LB
5772 if (!summary_only && topo.num_die > 1)
5773 BIC_PRESENT(BIC_Die);
5774
c98d5d94 5775 topo.num_packages = max_package_id + 1;
d8af6f5f 5776 if (debug > 1)
1b439f01 5777 fprintf(outf, "max_package_id %d, sizing for %d packages\n", max_package_id, topo.num_packages);
7da6e3e2 5778 if (!summary_only && topo.num_packages > 1)
812db3f7 5779 BIC_PRESENT(BIC_Package);
c98d5d94 5780
ef605741
PB
5781 set_node_data();
5782 if (debug > 1)
70a9c6e8 5783 fprintf(outf, "nodes_per_pkg %d\n", topo.nodes_per_pkg);
01235041
PB
5784 if (!summary_only && topo.nodes_per_pkg > 1)
5785 BIC_PRESENT(BIC_Node);
ef605741 5786
70a9c6e8 5787 topo.threads_per_core = max_siblings;
d8af6f5f 5788 if (debug > 1)
b7d8c148 5789 fprintf(outf, "max_siblings %d\n", max_siblings);
2ffbb224
PB
5790
5791 if (debug < 1)
5792 return;
5793
5794 for (i = 0; i <= topo.max_cpu_num; ++i) {
0ec712e3
LB
5795 if (cpu_is_not_present(i))
5796 continue;
2ffbb224 5797 fprintf(outf,
6de68fe1
LB
5798 "cpu %d pkg %d die %d node %d lnode %d core %d thread %d\n",
5799 i, cpus[i].physical_package_id, cpus[i].die_id,
1b439f01 5800 cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].physical_core_id, cpus[i].thread_id);
2ffbb224
PB
5801 }
5802
c98d5d94
LB
5803}
5804
1b439f01 5805void allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p)
c98d5d94
LB
5806{
5807 int i;
1b439f01 5808 int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages;
40f5cfe7 5809 int num_threads = topo.threads_per_core * num_cores;
c98d5d94 5810
40f5cfe7 5811 *t = calloc(num_threads, sizeof(struct thread_data));
c98d5d94
LB
5812 if (*t == NULL)
5813 goto error;
5814
40f5cfe7 5815 for (i = 0; i < num_threads; i++)
c98d5d94
LB
5816 (*t)[i].cpu_id = -1;
5817
40f5cfe7 5818 *c = calloc(num_cores, sizeof(struct core_data));
c98d5d94
LB
5819 if (*c == NULL)
5820 goto error;
5821
40f5cfe7 5822 for (i = 0; i < num_cores; i++)
c98d5d94
LB
5823 (*c)[i].core_id = -1;
5824
678a3bd1 5825 *p = calloc(topo.num_packages, sizeof(struct pkg_data));
c98d5d94
LB
5826 if (*p == NULL)
5827 goto error;
5828
5829 for (i = 0; i < topo.num_packages; i++)
5830 (*p)[i].package_id = i;
5831
5832 return;
5833error:
b2c95d90 5834 err(1, "calloc counters");
c98d5d94 5835}
1b439f01 5836
c98d5d94
LB
5837/*
5838 * init_counter()
5839 *
c98d5d94 5840 * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE
c98d5d94 5841 */
1b439f01 5842void init_counter(struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base, int cpu_id)
c98d5d94 5843{
8cb48b32 5844 int pkg_id = cpus[cpu_id].physical_package_id;
40f5cfe7 5845 int node_id = cpus[cpu_id].logical_node_id;
8cb48b32
PB
5846 int core_id = cpus[cpu_id].physical_core_id;
5847 int thread_id = cpus[cpu_id].thread_id;
c98d5d94
LB
5848 struct thread_data *t;
5849 struct core_data *c;
5850 struct pkg_data *p;
5851
42dd4520
NC
5852 /* Workaround for systems where physical_node_id==-1
5853 * and logical_node_id==(-1 - topo.num_cpus)
5854 */
5855 if (node_id < 0)
5856 node_id = 0;
5857
40f5cfe7
PB
5858 t = GET_THREAD(thread_base, thread_id, core_id, node_id, pkg_id);
5859 c = GET_CORE(core_base, core_id, node_id, pkg_id);
8cb48b32 5860 p = GET_PKG(pkg_base, pkg_id);
c98d5d94
LB
5861
5862 t->cpu_id = cpu_id;
8cb48b32 5863 if (thread_id == 0) {
c98d5d94
LB
5864 t->flags |= CPU_IS_FIRST_THREAD_IN_CORE;
5865 if (cpu_is_first_core_in_package(cpu_id))
5866 t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE;
5867 }
5868
8cb48b32
PB
5869 c->core_id = core_id;
5870 p->package_id = pkg_id;
c98d5d94
LB
5871}
5872
c98d5d94
LB
5873int initialize_counters(int cpu_id)
5874{
8cb48b32
PB
5875 init_counter(EVEN_COUNTERS, cpu_id);
5876 init_counter(ODD_COUNTERS, cpu_id);
c98d5d94
LB
5877 return 0;
5878}
5879
5880void allocate_output_buffer()
5881{
eeb71c95 5882 output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);
c98d5d94 5883 outp = output_buffer;
b2c95d90
JT
5884 if (outp == NULL)
5885 err(-1, "calloc output buffer");
c98d5d94 5886}
1b439f01 5887
36229897
LB
5888void allocate_fd_percpu(void)
5889{
01a67adf 5890 fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
36229897
LB
5891 if (fd_percpu == NULL)
5892 err(-1, "calloc fd_percpu");
5893}
1b439f01 5894
562a2d37
LB
5895void allocate_irq_buffers(void)
5896{
5897 irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
5898 if (irq_column_2_cpu == NULL)
5899 err(-1, "calloc %d", topo.num_cpus);
c98d5d94 5900
01a67adf 5901 irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int));
562a2d37 5902 if (irqs_per_cpu == NULL)
01a67adf 5903 err(-1, "calloc %d", topo.max_cpu_num + 1);
562a2d37 5904}
1b439f01 5905
c98d5d94
LB
5906void setup_all_buffers(void)
5907{
5908 topology_probe();
562a2d37 5909 allocate_irq_buffers();
36229897 5910 allocate_fd_percpu();
c98d5d94
LB
5911 allocate_counters(&thread_even, &core_even, &package_even);
5912 allocate_counters(&thread_odd, &core_odd, &package_odd);
5913 allocate_output_buffer();
5914 for_all_proc_cpus(initialize_counters);
5915}
3b4d5c7f 5916
7ce7d5de
PB
5917void set_base_cpu(void)
5918{
5919 base_cpu = sched_getcpu();
5920 if (base_cpu < 0)
5921 err(-ENODEV, "No valid cpus found");
5922
5923 if (debug > 1)
b7d8c148 5924 fprintf(outf, "base_cpu = %d\n", base_cpu);
7ce7d5de
PB
5925}
5926
103a8fea
LB
5927void turbostat_init()
5928{
7ce7d5de
PB
5929 setup_all_buffers();
5930 set_base_cpu();
103a8fea 5931 check_dev_msr();
98481e79 5932 check_permissions();
fcd17211 5933 process_cpuid();
7ee39d8d 5934 probe_pm_features();
2af4f9b8 5935 linux_perf_init();
103a8fea 5936
7ab5ff49
ZR
5937 for_all_cpus(get_cpu_type, ODD_COUNTERS);
5938 for_all_cpus(get_cpu_type, EVEN_COUNTERS);
5939
164d7a96
LB
5940 if (DO_BIC(BIC_IPC))
5941 (void)get_instr_count_fd(base_cpu);
103a8fea
LB
5942}
5943
5944int fork_it(char **argv)
5945{
103a8fea 5946 pid_t child_pid;
d91bb17c 5947 int status;
d15cf7c1 5948
218f0e8d 5949 snapshot_proc_sysfs_files();
d91bb17c 5950 status = for_all_cpus(get_counters, EVEN_COUNTERS);
4c2122d4 5951 first_counter_read = 0;
d91bb17c
LB
5952 if (status)
5953 exit(status);
c98d5d94
LB
5954 /* clear affinity side-effect of get_counters() */
5955 sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
103a8fea
LB
5956 gettimeofday(&tv_even, (struct timezone *)NULL);
5957
5958 child_pid = fork();
5959 if (!child_pid) {
5960 /* child */
5961 execvp(argv[0], argv);
0815a3d0 5962 err(errno, "exec %s", argv[0]);
103a8fea 5963 } else {
103a8fea
LB
5964
5965 /* parent */
b2c95d90
JT
5966 if (child_pid == -1)
5967 err(1, "fork");
103a8fea
LB
5968
5969 signal(SIGINT, SIG_IGN);
5970 signal(SIGQUIT, SIG_IGN);
b2c95d90
JT
5971 if (waitpid(child_pid, &status, 0) == -1)
5972 err(status, "waitpid");
2a954966
DA
5973
5974 if (WIFEXITED(status))
5975 status = WEXITSTATUS(status);
103a8fea 5976 }
c98d5d94
LB
5977 /*
5978 * n.b. fork_it() does not check for errors from for_all_cpus()
5979 * because re-starting is problematic when forking
5980 */
218f0e8d 5981 snapshot_proc_sysfs_files();
c98d5d94 5982 for_all_cpus(get_counters, ODD_COUNTERS);
103a8fea 5983 gettimeofday(&tv_odd, (struct timezone *)NULL);
103a8fea 5984 timersub(&tv_odd, &tv_even, &tv_delta);
ba3dec99
LB
5985 if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS))
5986 fprintf(outf, "%s: Counter reset detected\n", progname);
5987 else {
5988 compute_average(EVEN_COUNTERS);
5989 format_all_counters(EVEN_COUNTERS);
5990 }
103a8fea 5991
1b439f01 5992 fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec / 1000000.0);
b7d8c148
LB
5993
5994 flush_output_stderr();
103a8fea 5995
d91bb17c 5996 return status;
103a8fea
LB
5997}
5998
3b4d5c7f
AS
5999int get_and_dump_counters(void)
6000{
6001 int status;
6002
218f0e8d 6003 snapshot_proc_sysfs_files();
3b4d5c7f
AS
6004 status = for_all_cpus(get_counters, ODD_COUNTERS);
6005 if (status)
6006 return status;
6007
6008 status = for_all_cpus(dump_counters, ODD_COUNTERS);
6009 if (status)
6010 return status;
6011
b7d8c148 6012 flush_output_stdout();
3b4d5c7f
AS
6013
6014 return status;
6015}
6016
1b439f01
LB
6017void print_version()
6018{
de7839ee 6019 fprintf(outf, "turbostat version 2023.03.17 - Len Brown <lenb@kernel.org>\n");
d8af6f5f
LB
6020}
6021
03331233
CY
6022#define COMMAND_LINE_SIZE 2048
6023
6024void print_bootcmd(void)
6025{
6026 char bootcmd[COMMAND_LINE_SIZE];
6027 FILE *fp;
6028 int ret;
6029
6030 memset(bootcmd, 0, COMMAND_LINE_SIZE);
6031 fp = fopen("/proc/cmdline", "r");
6032 if (!fp)
6033 return;
6034
6035 ret = fread(bootcmd, sizeof(char), COMMAND_LINE_SIZE - 1, fp);
6036 if (ret) {
6037 bootcmd[ret] = '\0';
6038 /* the last character is already '\n' */
6039 fprintf(outf, "Kernel command line: %s", bootcmd);
6040 }
6041
6042 fclose(fp);
6043}
6044
495c7654 6045int add_counter(unsigned int msr_num, char *path, char *name,
1b439f01
LB
6046 unsigned int width, enum counter_scope scope,
6047 enum counter_type type, enum counter_format format, int flags)
388e9c81
LB
6048{
6049 struct msr_counter *msrp;
6050
6051 msrp = calloc(1, sizeof(struct msr_counter));
6052 if (msrp == NULL) {
6053 perror("calloc");
6054 exit(1);
6055 }
6056
6057 msrp->msr_num = msr_num;
d8d005ba 6058 strncpy(msrp->name, name, NAME_BYTES - 1);
495c7654 6059 if (path)
d8d005ba 6060 strncpy(msrp->path, path, PATH_BYTES - 1);
388e9c81
LB
6061 msrp->width = width;
6062 msrp->type = type;
6063 msrp->format = format;
41618e63 6064 msrp->flags = flags;
388e9c81
LB
6065
6066 switch (scope) {
6067
6068 case SCOPE_CPU:
388e9c81
LB
6069 msrp->next = sys.tp;
6070 sys.tp = msrp;
678a3bd1 6071 sys.added_thread_counters++;
0748eaf0 6072 if (sys.added_thread_counters > MAX_ADDED_THREAD_COUNTERS) {
1b439f01 6073 fprintf(stderr, "exceeded max %d added thread counters\n", MAX_ADDED_COUNTERS);
678a3bd1
LB
6074 exit(-1);
6075 }
388e9c81
LB
6076 break;
6077
6078 case SCOPE_CORE:
388e9c81
LB
6079 msrp->next = sys.cp;
6080 sys.cp = msrp;
678a3bd1
LB
6081 sys.added_core_counters++;
6082 if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
1b439f01 6083 fprintf(stderr, "exceeded max %d added core counters\n", MAX_ADDED_COUNTERS);
678a3bd1
LB
6084 exit(-1);
6085 }
388e9c81
LB
6086 break;
6087
6088 case SCOPE_PACKAGE:
388e9c81
LB
6089 msrp->next = sys.pp;
6090 sys.pp = msrp;
678a3bd1
LB
6091 sys.added_package_counters++;
6092 if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
1b439f01 6093 fprintf(stderr, "exceeded max %d added package counters\n", MAX_ADDED_COUNTERS);
678a3bd1
LB
6094 exit(-1);
6095 }
388e9c81
LB
6096 break;
6097 }
6098
6099 return 0;
6100}
6101
6102void parse_add_command(char *add_command)
6103{
6104 int msr_num = 0;
495c7654 6105 char *path = NULL;
0f47c08d 6106 char name_buffer[NAME_BYTES] = "";
388e9c81
LB
6107 int width = 64;
6108 int fail = 0;
6109 enum counter_scope scope = SCOPE_CPU;
6110 enum counter_type type = COUNTER_CYCLES;
6111 enum counter_format format = FORMAT_DELTA;
6112
6113 while (add_command) {
6114
6115 if (sscanf(add_command, "msr0x%x", &msr_num) == 1)
6116 goto next;
6117
6118 if (sscanf(add_command, "msr%d", &msr_num) == 1)
6119 goto next;
6120
495c7654
LB
6121 if (*add_command == '/') {
6122 path = add_command;
6123 goto next;
6124 }
6125
388e9c81
LB
6126 if (sscanf(add_command, "u%d", &width) == 1) {
6127 if ((width == 32) || (width == 64))
6128 goto next;
6129 width = 64;
6130 }
6131 if (!strncmp(add_command, "cpu", strlen("cpu"))) {
6132 scope = SCOPE_CPU;
6133 goto next;
6134 }
6135 if (!strncmp(add_command, "core", strlen("core"))) {
6136 scope = SCOPE_CORE;
6137 goto next;
6138 }
6139 if (!strncmp(add_command, "package", strlen("package"))) {
6140 scope = SCOPE_PACKAGE;
6141 goto next;
6142 }
6143 if (!strncmp(add_command, "cycles", strlen("cycles"))) {
6144 type = COUNTER_CYCLES;
6145 goto next;
6146 }
6147 if (!strncmp(add_command, "seconds", strlen("seconds"))) {
6148 type = COUNTER_SECONDS;
6149 goto next;
6150 }
41618e63
LB
6151 if (!strncmp(add_command, "usec", strlen("usec"))) {
6152 type = COUNTER_USEC;
6153 goto next;
6154 }
388e9c81
LB
6155 if (!strncmp(add_command, "raw", strlen("raw"))) {
6156 format = FORMAT_RAW;
6157 goto next;
6158 }
6159 if (!strncmp(add_command, "delta", strlen("delta"))) {
6160 format = FORMAT_DELTA;
6161 goto next;
6162 }
6163 if (!strncmp(add_command, "percent", strlen("percent"))) {
6164 format = FORMAT_PERCENT;
6165 goto next;
6166 }
6167
6168 if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) { /* 18 < NAME_BYTES */
6169 char *eos;
6170
6171 eos = strchr(name_buffer, ',');
6172 if (eos)
6173 *eos = '\0';
6174 goto next;
6175 }
6176
6177next:
6178 add_command = strchr(add_command, ',');
495c7654
LB
6179 if (add_command) {
6180 *add_command = '\0';
388e9c81 6181 add_command++;
495c7654 6182 }
388e9c81
LB
6183
6184 }
495c7654
LB
6185 if ((msr_num == 0) && (path == NULL)) {
6186 fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter ) required\n");
388e9c81
LB
6187 fail++;
6188 }
6189
6190 /* generate default column header */
6191 if (*name_buffer == '\0') {
5f3aea57
LB
6192 if (width == 32)
6193 sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
6194 else
6195 sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
388e9c81
LB
6196 }
6197
41618e63 6198 if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0))
388e9c81
LB
6199 fail++;
6200
6201 if (fail) {
6202 help();
6203 exit(1);
6204 }
6205}
41618e63 6206
0fc521bc
ZLCH
6207int is_deferred_add(char *name)
6208{
6209 int i;
6210
6211 for (i = 0; i < deferred_add_index; ++i)
6212 if (!strcmp(name, deferred_add_names[i]))
6213 return 1;
6214 return 0;
6215}
6216
dd778a5e
LB
6217int is_deferred_skip(char *name)
6218{
6219 int i;
6220
6221 for (i = 0; i < deferred_skip_index; ++i)
6222 if (!strcmp(name, deferred_skip_names[i]))
6223 return 1;
6224 return 0;
6225}
6226
41618e63
LB
6227void probe_sysfs(void)
6228{
6229 char path[64];
6230 char name_buf[16];
6231 FILE *input;
6232 int state;
6233 char *sp;
6234
0748eaf0 6235 for (state = 10; state >= 0; --state) {
41618e63 6236
1b439f01 6237 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);
41618e63
LB
6238 input = fopen(path, "r");
6239 if (input == NULL)
6240 continue;
8173c336
BH
6241 if (!fgets(name_buf, sizeof(name_buf), input))
6242 err(1, "%s: failed to read file", path);
41618e63 6243
1b439f01 6244 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
41618e63
LB
6245 sp = strchr(name_buf, '-');
6246 if (!sp)
6247 sp = strchrnul(name_buf, '\n');
6248 *sp = '%';
6249 *(sp + 1) = '\0';
6250
fecb3bc8
DA
6251 remove_underbar(name_buf);
6252
41618e63
LB
6253 fclose(input);
6254
6255 sprintf(path, "cpuidle/state%d/time", state);
6256
0fc521bc
ZLCH
6257 if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf))
6258 continue;
6259
dd778a5e
LB
6260 if (is_deferred_skip(name_buf))
6261 continue;
6262
1b439f01 6263 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC, FORMAT_PERCENT, SYSFS_PERCPU);
41618e63
LB
6264 }
6265
0748eaf0 6266 for (state = 10; state >= 0; --state) {
41618e63 6267
1b439f01 6268 sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);
41618e63
LB
6269 input = fopen(path, "r");
6270 if (input == NULL)
6271 continue;
8173c336
BH
6272 if (!fgets(name_buf, sizeof(name_buf), input))
6273 err(1, "%s: failed to read file", path);
1b439f01 6274 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
41618e63
LB
6275 sp = strchr(name_buf, '-');
6276 if (!sp)
6277 sp = strchrnul(name_buf, '\n');
6278 *sp = '\0';
6279 fclose(input);
fecb3bc8
DA
6280
6281 remove_underbar(name_buf);
41618e63
LB
6282
6283 sprintf(path, "cpuidle/state%d/usage", state);
6284
0fc521bc
ZLCH
6285 if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf))
6286 continue;
6287
dd778a5e
LB
6288 if (is_deferred_skip(name_buf))
6289 continue;
6290
1b439f01 6291 add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU);
41618e63
LB
6292 }
6293
6294}
6295
1ef7d21a
LB
6296/*
6297 * parse cpuset with following syntax
6298 * 1,2,4..6,8-10 and set bits in cpu_subset
6299 */
6300void parse_cpu_command(char *optarg)
6301{
6302 unsigned int start, end;
6303 char *next;
6304
4e4e1e7c
LB
6305 if (!strcmp(optarg, "core")) {
6306 if (cpu_subset)
6307 goto error;
6308 show_core_only++;
6309 return;
6310 }
6311 if (!strcmp(optarg, "package")) {
6312 if (cpu_subset)
6313 goto error;
6314 show_pkg_only++;
6315 return;
6316 }
6317 if (show_core_only || show_pkg_only)
6318 goto error;
6319
1ef7d21a
LB
6320 cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);
6321 if (cpu_subset == NULL)
6322 err(3, "CPU_ALLOC");
6323 cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);
6324
6325 CPU_ZERO_S(cpu_subset_size, cpu_subset);
6326
6327 next = optarg;
6328
6329 while (next && *next) {
6330
6331 if (*next == '-') /* no negative cpu numbers */
6332 goto error;
6333
6334 start = strtoul(next, &next, 10);
6335
6336 if (start >= CPU_SUBSET_MAXCPUS)
6337 goto error;
6338 CPU_SET_S(start, cpu_subset_size, cpu_subset);
6339
6340 if (*next == '\0')
6341 break;
6342
6343 if (*next == ',') {
6344 next += 1;
6345 continue;
6346 }
6347
6348 if (*next == '-') {
6349 next += 1; /* start range */
6350 } else if (*next == '.') {
6351 next += 1;
6352 if (*next == '.')
6353 next += 1; /* start range */
6354 else
6355 goto error;
6356 }
6357
6358 end = strtoul(next, &next, 10);
6359 if (end <= start)
6360 goto error;
6361
6362 while (++start <= end) {
6363 if (start >= CPU_SUBSET_MAXCPUS)
6364 goto error;
6365 CPU_SET_S(start, cpu_subset_size, cpu_subset);
6366 }
6367
6368 if (*next == ',')
6369 next += 1;
6370 else if (*next != '\0')
6371 goto error;
6372 }
6373
6374 return;
6375
6376error:
4e4e1e7c
LB
6377 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
6378 help();
1ef7d21a
LB
6379 exit(-1);
6380}
6381
103a8fea
LB
6382void cmdline(int argc, char **argv)
6383{
6384 int opt;
d8af6f5f
LB
6385 int option_index = 0;
6386 static struct option long_options[] = {
1b439f01
LB
6387 { "add", required_argument, 0, 'a' },
6388 { "cpu", required_argument, 0, 'c' },
6389 { "Dump", no_argument, 0, 'D' },
6390 { "debug", no_argument, 0, 'd' }, /* internal, not documented */
6391 { "enable", required_argument, 0, 'e' },
6392 { "interval", required_argument, 0, 'i' },
6393 { "IPC", no_argument, 0, 'I' },
6394 { "num_iterations", required_argument, 0, 'n' },
c7e399f8 6395 { "header_iterations", required_argument, 0, 'N' },
1b439f01
LB
6396 { "help", no_argument, 0, 'h' },
6397 { "hide", required_argument, 0, 'H' }, // meh, -h taken by --help
6398 { "Joules", no_argument, 0, 'J' },
6399 { "list", no_argument, 0, 'l' },
6400 { "out", required_argument, 0, 'o' },
6401 { "quiet", no_argument, 0, 'q' },
6402 { "show", required_argument, 0, 's' },
6403 { "Summary", no_argument, 0, 'S' },
6404 { "TCC", required_argument, 0, 'T' },
6405 { "version", no_argument, 0, 'v' },
6406 { 0, 0, 0, 0 }
d8af6f5f 6407 };
103a8fea
LB
6408
6409 progname = argv[0];
6410
1b439f01 6411 while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qST:v", long_options, &option_index)) != -1) {
103a8fea 6412 switch (opt) {
388e9c81
LB
6413 case 'a':
6414 parse_add_command(optarg);
6415 break;
1ef7d21a
LB
6416 case 'c':
6417 parse_cpu_command(optarg);
6418 break;
d8af6f5f 6419 case 'D':
3b4d5c7f
AS
6420 dump_only++;
6421 break;
3f44a5c6
LB
6422 case 'e':
6423 /* --enable specified counter */
4c2122d4 6424 bic_enabled = bic_enabled | bic_lookup(optarg, SHOW_LIST);
3f44a5c6 6425 break;
d8af6f5f
LB
6426 case 'd':
6427 debug++;
3f44a5c6 6428 ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);
103a8fea 6429 break;
812db3f7 6430 case 'H':
3f44a5c6
LB
6431 /*
6432 * --hide: do not show those specified
6433 * multiple invocations simply clear more bits in enabled mask
6434 */
6435 bic_enabled &= ~bic_lookup(optarg, HIDE_LIST);
812db3f7 6436 break;
d8af6f5f
LB
6437 case 'h':
6438 default:
6439 help();
6440 exit(1);
103a8fea 6441 case 'i':
2a0609c0
LB
6442 {
6443 double interval = strtod(optarg, NULL);
6444
6445 if (interval < 0.001) {
1b439f01 6446 fprintf(outf, "interval %f seconds is too small\n", interval);
2a0609c0
LB
6447 exit(2);
6448 }
6449
47936f94 6450 interval_tv.tv_sec = interval_ts.tv_sec = interval;
b9ad8ee0 6451 interval_tv.tv_usec = (interval - interval_tv.tv_sec) * 1000000;
47936f94 6452 interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000;
2a0609c0 6453 }
103a8fea 6454 break;
d8af6f5f
LB
6455 case 'J':
6456 rapl_joules++;
8e180f3c 6457 break;
c8ade361 6458 case 'l':
3f44a5c6 6459 ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);
c8ade361
LB
6460 list_header_only++;
6461 quiet++;
6462 break;
b7d8c148
LB
6463 case 'o':
6464 outf = fopen_or_die(optarg, "w");
6465 break;
96e47158
LB
6466 case 'q':
6467 quiet = 1;
6468 break;
023fe0ac
CY
6469 case 'n':
6470 num_iterations = strtod(optarg, NULL);
6471
6472 if (num_iterations <= 0) {
1b439f01 6473 fprintf(outf, "iterations %d should be positive number\n", num_iterations);
023fe0ac
CY
6474 exit(2);
6475 }
6476 break;
c7e399f8
ZLCH
6477 case 'N':
6478 header_iterations = strtod(optarg, NULL);
6479
6480 if (header_iterations <= 0) {
164d7a96 6481 fprintf(outf, "iterations %d should be positive number\n", header_iterations);
c7e399f8 6482 exit(2);
023fe0ac
CY
6483 }
6484 break;
812db3f7 6485 case 's':
3f44a5c6
LB
6486 /*
6487 * --show: show only those specified
6488 * The 1st invocation will clear and replace the enabled mask
6489 * subsequent invocations can add to it.
6490 */
6491 if (shown == 0)
6492 bic_enabled = bic_lookup(optarg, SHOW_LIST);
6493 else
6494 bic_enabled |= bic_lookup(optarg, SHOW_LIST);
6495 shown = 1;
812db3f7 6496 break;
d8af6f5f
LB
6497 case 'S':
6498 summary_only++;
889facbe
LB
6499 break;
6500 case 'T':
55279aef 6501 tj_max_override = atoi(optarg);
889facbe 6502 break;
d8af6f5f
LB
6503 case 'v':
6504 print_version();
6505 exit(0);
5c56be9a 6506 break;
103a8fea
LB
6507 }
6508 }
6509}
6510
6511int main(int argc, char **argv)
6512{
b7d8c148 6513 outf = stderr;
103a8fea
LB
6514 cmdline(argc, argv);
6515
03331233 6516 if (!quiet) {
d8af6f5f 6517 print_version();
03331233
CY
6518 print_bootcmd();
6519 }
103a8fea 6520
41618e63
LB
6521 probe_sysfs();
6522
103a8fea
LB
6523 turbostat_init();
6524
6799ba84
DM
6525 msr_sum_record();
6526
3b4d5c7f
AS
6527 /* dump counters and exit */
6528 if (dump_only)
6529 return get_and_dump_counters();
6530
c8ade361
LB
6531 /* list header and exit */
6532 if (list_header_only) {
6533 print_header(",");
6534 flush_output_stdout();
6535 return 0;
6536 }
6537
103a8fea
LB
6538 /*
6539 * if any params left, it must be a command to fork
6540 */
6541 if (argc - optind)
6542 return fork_it(argv + optind);
6543 else
6544 turbostat_loop();
6545
6546 return 0;
6547}