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