1a61127c2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2103a8feaSLen Brown /*
3103a8feaSLen Brown  * turbostat -- show CPU frequency and C-state residency
434041551SLen Brown  * on modern Intel and AMD processors.
5103a8feaSLen Brown  *
6144b44b1SLen Brown  * Copyright (c) 2013 Intel Corporation.
7103a8feaSLen Brown  * Len Brown <len.brown@intel.com>
8103a8feaSLen Brown  */
9103a8feaSLen Brown 
1088c3281fSLen Brown #define _GNU_SOURCE
11b731f311SJosh Triplett #include MSRHEADER
12869ce69eSLen Brown #include INTEL_FAMILY_HEADER
1395aebc44SJosh Triplett #include <stdarg.h>
14103a8feaSLen Brown #include <stdio.h>
15b2c95d90SJosh Triplett #include <err.h>
16103a8feaSLen Brown #include <unistd.h>
17103a8feaSLen Brown #include <sys/types.h>
18103a8feaSLen Brown #include <sys/wait.h>
19103a8feaSLen Brown #include <sys/stat.h>
20b9ad8ee0SLen Brown #include <sys/select.h>
21103a8feaSLen Brown #include <sys/resource.h>
22103a8feaSLen Brown #include <fcntl.h>
23103a8feaSLen Brown #include <signal.h>
24103a8feaSLen Brown #include <sys/time.h>
25103a8feaSLen Brown #include <stdlib.h>
26d8af6f5fSLen Brown #include <getopt.h>
27103a8feaSLen Brown #include <dirent.h>
28103a8feaSLen Brown #include <string.h>
29103a8feaSLen Brown #include <ctype.h>
3088c3281fSLen Brown #include <sched.h>
312a0609c0SLen Brown #include <time.h>
322b92865eSJosh Triplett #include <cpuid.h>
33fcaa681cSLen Brown #include <sys/capability.h>
3498481e79SLen Brown #include <errno.h>
359392bd98SCalvin Walton #include <math.h>
362af4f9b8SLen Brown #include <linux/perf_event.h>
372af4f9b8SLen Brown #include <asm/unistd.h>
38103a8feaSLen Brown 
39103a8feaSLen Brown char *proc_stat = "/proc/stat";
40b7d8c148SLen Brown FILE *outf;
4136229897SLen Brown int *fd_percpu;
422af4f9b8SLen Brown int *fd_instr_count_percpu;
43b9ad8ee0SLen Brown struct timeval interval_tv = {5, 0};
4447936f94SArtem Bityutskiy struct timespec interval_ts = {5, 0};
45023fe0acSChen Yu unsigned int num_iterations;
46d8af6f5fSLen Brown unsigned int debug;
4796e47158SLen Brown unsigned int quiet;
483f44a5c6SLen Brown unsigned int shown;
490de6c0dfSLen Brown unsigned int sums_need_wide_columns;
50d8af6f5fSLen Brown unsigned int rapl_joules;
51d8af6f5fSLen Brown unsigned int summary_only;
52c8ade361SLen Brown unsigned int list_header_only;
53d8af6f5fSLen Brown unsigned int dump_only;
54103a8feaSLen Brown unsigned int do_snb_cstates;
55fb5d4327SDasaratharaman Chandramouli unsigned int do_knl_cstates;
56144b44b1SLen Brown unsigned int do_slm_cstates;
57144b44b1SLen Brown unsigned int use_c1_residency_msr;
58103a8feaSLen Brown unsigned int has_aperf;
59889facbeSLen Brown unsigned int has_epb;
605a63426eSLen Brown unsigned int do_irtl_snb;
615a63426eSLen Brown unsigned int do_irtl_hsw;
62fc04cc67SLen Brown unsigned int units = 1000000;	/* MHz etc */
63103a8feaSLen Brown unsigned int genuine_intel;
6434041551SLen Brown unsigned int authentic_amd;
65c1c10cc7SPu Wen unsigned int hygon_genuine;
6634041551SLen Brown unsigned int max_level, max_extended_level;
67103a8feaSLen Brown unsigned int has_invariant_tsc;
68d7899447SLen Brown unsigned int do_nhm_platform_info;
69cf4cbe53SLen Brown unsigned int no_MSR_MISC_PWR_MGMT;
70b2b34dfeSHubert Chrzaniuk unsigned int aperf_mperf_multiplier = 1;
71103a8feaSLen Brown double bclk;
72a2b7b749SLen Brown double base_hz;
7321ed5574SLen Brown unsigned int has_base_hz;
74a2b7b749SLen Brown double tsc_tweak = 1.0;
75c98d5d94SLen Brown unsigned int show_pkg_only;
76c98d5d94SLen Brown unsigned int show_core_only;
77c98d5d94SLen Brown char *output_buffer, *outp;
78889facbeSLen Brown unsigned int do_rapl;
79889facbeSLen Brown unsigned int do_dts;
80889facbeSLen Brown unsigned int do_ptm;
812af4f9b8SLen Brown unsigned int do_ipc;
82fdf676e5SLen Brown unsigned long long  gfx_cur_rc6_ms;
83be0e54c4SLen Brown unsigned long long cpuidle_cur_cpu_lpi_us;
84be0e54c4SLen Brown unsigned long long cpuidle_cur_sys_lpi_us;
8527d47356SLen Brown unsigned int gfx_cur_mhz;
86b4b91569SRafael Antognolli unsigned int gfx_act_mhz;
87889facbeSLen Brown unsigned int tcc_activation_temp;
88889facbeSLen Brown unsigned int tcc_activation_temp_override;
8940ee8e3bSAndrey Semin double rapl_power_units, rapl_time_units;
9040ee8e3bSAndrey Semin double rapl_dram_energy_units, rapl_energy_units;
91889facbeSLen Brown double rapl_joule_counter_range;
923a9a941dSLen Brown unsigned int do_core_perf_limit_reasons;
93ac980e13SArtem Bityutskiy unsigned int has_automatic_cstate_conversion;
943a9a941dSLen Brown unsigned int do_gfx_perf_limit_reasons;
953a9a941dSLen Brown unsigned int do_ring_perf_limit_reasons;
968a5bdf41SLen Brown unsigned int crystal_hz;
978a5bdf41SLen Brown unsigned long long tsc_hz;
987ce7d5deSPrarit Bhargava int base_cpu;
9921ed5574SLen Brown double discover_bclk(unsigned int family, unsigned int model);
1007f5c258eSLen Brown unsigned int has_hwp;	/* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
1017f5c258eSLen Brown 			/* IA32_HWP_REQUEST, IA32_HWP_STATUS */
1027f5c258eSLen Brown unsigned int has_hwp_notify;		/* IA32_HWP_INTERRUPT */
1037f5c258eSLen Brown unsigned int has_hwp_activity_window;	/* IA32_HWP_REQUEST[bits 41:32] */
1047f5c258eSLen Brown unsigned int has_hwp_epp;		/* IA32_HWP_REQUEST[bits 31:24] */
1057f5c258eSLen Brown unsigned int has_hwp_pkg;		/* IA32_HWP_REQUEST_PKG */
10633148d67SLen Brown unsigned int has_misc_feature_control;
1074c2122d4SLen Brown unsigned int first_counter_read = 1;
108c026c236SArtem Bityutskiy int ignore_stdin;
109889facbeSLen Brown 
110889facbeSLen Brown #define RAPL_PKG		(1 << 0)
111e6f9bb3cSLen Brown 					/* 0x610 MSR_PKG_POWER_LIMIT */
112e6f9bb3cSLen Brown 					/* 0x611 MSR_PKG_ENERGY_STATUS */
113e6f9bb3cSLen Brown #define RAPL_PKG_PERF_STATUS	(1 << 1)
114e6f9bb3cSLen Brown 					/* 0x613 MSR_PKG_PERF_STATUS */
115e6f9bb3cSLen Brown #define RAPL_PKG_POWER_INFO	(1 << 2)
116e6f9bb3cSLen Brown 					/* 0x614 MSR_PKG_POWER_INFO */
117e6f9bb3cSLen Brown 
118889facbeSLen Brown #define RAPL_DRAM		(1 << 3)
119e6f9bb3cSLen Brown 					/* 0x618 MSR_DRAM_POWER_LIMIT */
120e6f9bb3cSLen Brown 					/* 0x619 MSR_DRAM_ENERGY_STATUS */
121e6f9bb3cSLen Brown #define RAPL_DRAM_PERF_STATUS	(1 << 4)
122e6f9bb3cSLen Brown 					/* 0x61b MSR_DRAM_PERF_STATUS */
1230b2bb692SLen Brown #define RAPL_DRAM_POWER_INFO	(1 << 5)
1240b2bb692SLen Brown 					/* 0x61c MSR_DRAM_POWER_INFO */
125e6f9bb3cSLen Brown 
1269148494cSJacob Pan #define RAPL_CORES_POWER_LIMIT	(1 << 6)
127e6f9bb3cSLen Brown 					/* 0x638 MSR_PP0_POWER_LIMIT */
1280b2bb692SLen Brown #define RAPL_CORE_POLICY	(1 << 7)
129e6f9bb3cSLen Brown 					/* 0x63a MSR_PP0_POLICY */
130e6f9bb3cSLen Brown 
1310b2bb692SLen Brown #define RAPL_GFX		(1 << 8)
132e6f9bb3cSLen Brown 					/* 0x640 MSR_PP1_POWER_LIMIT */
133e6f9bb3cSLen Brown 					/* 0x641 MSR_PP1_ENERGY_STATUS */
134e6f9bb3cSLen Brown 					/* 0x642 MSR_PP1_POLICY */
1359148494cSJacob Pan 
1369148494cSJacob Pan #define RAPL_CORES_ENERGY_STATUS	(1 << 9)
1379148494cSJacob Pan 					/* 0x639 MSR_PP0_ENERGY_STATUS */
1389392bd98SCalvin Walton #define RAPL_PER_CORE_ENERGY	(1 << 10)
1399392bd98SCalvin Walton 					/* Indicates cores energy collection is per-core,
1409392bd98SCalvin Walton 					 * not per-package. */
1419392bd98SCalvin Walton #define RAPL_AMD_F17H		(1 << 11)
1429392bd98SCalvin Walton 					/* 0xc0010299 MSR_RAPL_PWR_UNIT */
1439392bd98SCalvin Walton 					/* 0xc001029a MSR_CORE_ENERGY_STAT */
1449392bd98SCalvin Walton 					/* 0xc001029b MSR_PKG_ENERGY_STAT */
1459148494cSJacob Pan #define RAPL_CORES (RAPL_CORES_ENERGY_STATUS | RAPL_CORES_POWER_LIMIT)
146889facbeSLen Brown #define	TJMAX_DEFAULT	100
147889facbeSLen Brown 
1489392bd98SCalvin Walton /* MSRs that are not yet in the kernel-provided header. */
1499392bd98SCalvin Walton #define MSR_RAPL_PWR_UNIT	0xc0010299
1509392bd98SCalvin Walton #define MSR_CORE_ENERGY_STAT	0xc001029a
1519392bd98SCalvin Walton #define MSR_PKG_ENERGY_STAT	0xc001029b
1529392bd98SCalvin Walton 
153889facbeSLen Brown #define MAX(a, b) ((a) > (b) ? (a) : (b))
154103a8feaSLen Brown 
155388e9c81SLen Brown /*
156388e9c81SLen Brown  * buffer size used by sscanf() for added column names
157388e9c81SLen Brown  * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
158388e9c81SLen Brown  */
159388e9c81SLen Brown #define	NAME_BYTES 20
160495c7654SLen Brown #define PATH_BYTES 128
161388e9c81SLen Brown 
162103a8feaSLen Brown int backwards_count;
163103a8feaSLen Brown char *progname;
164103a8feaSLen Brown 
1651ef7d21aSLen Brown #define CPU_SUBSET_MAXCPUS	1024	/* need to use before probe... */
1661ef7d21aSLen Brown cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset;
1671ef7d21aSLen Brown size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
1680748eaf0SLen Brown #define MAX_ADDED_COUNTERS 8
1690748eaf0SLen Brown #define MAX_ADDED_THREAD_COUNTERS 24
1700e2d8f05SLen Brown #define BITMASK_SIZE 32
171c98d5d94SLen Brown 
172c98d5d94SLen Brown struct thread_data {
173f4fdf2b4SLen Brown 	struct timeval tv_begin;
174f4fdf2b4SLen Brown 	struct timeval tv_end;
175d4794f25SYazen Ghannam 	struct timeval tv_delta;
176c98d5d94SLen Brown 	unsigned long long tsc;
177c98d5d94SLen Brown 	unsigned long long aperf;
178c98d5d94SLen Brown 	unsigned long long mperf;
179144b44b1SLen Brown 	unsigned long long c1;
1802af4f9b8SLen Brown 	unsigned long long instr_count;
1810de6c0dfSLen Brown 	unsigned long long  irq_count;
1821ed51011SLen Brown 	unsigned int smi_count;
183c98d5d94SLen Brown 	unsigned int cpu_id;
1844c2122d4SLen Brown 	unsigned int apic_id;
1854c2122d4SLen Brown 	unsigned int x2apic_id;
186c98d5d94SLen Brown 	unsigned int flags;
187c98d5d94SLen Brown #define CPU_IS_FIRST_THREAD_IN_CORE	0x2
188c98d5d94SLen Brown #define CPU_IS_FIRST_CORE_IN_PACKAGE	0x4
1890748eaf0SLen Brown 	unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];
190c98d5d94SLen Brown } *thread_even, *thread_odd;
191c98d5d94SLen Brown 
192c98d5d94SLen Brown struct core_data {
193c98d5d94SLen Brown 	unsigned long long c3;
194c98d5d94SLen Brown 	unsigned long long c6;
195c98d5d94SLen Brown 	unsigned long long c7;
1960539ba11SLen Brown 	unsigned long long mc6_us;	/* duplicate as per-core for now, even though per module */
197889facbeSLen Brown 	unsigned int core_temp_c;
1989392bd98SCalvin Walton 	unsigned int core_energy;	/* MSR_CORE_ENERGY_STAT */
199c98d5d94SLen Brown 	unsigned int core_id;
200678a3bd1SLen Brown 	unsigned long long counter[MAX_ADDED_COUNTERS];
201c98d5d94SLen Brown } *core_even, *core_odd;
202c98d5d94SLen Brown 
203c98d5d94SLen Brown struct pkg_data {
204c98d5d94SLen Brown 	unsigned long long pc2;
205c98d5d94SLen Brown 	unsigned long long pc3;
206c98d5d94SLen Brown 	unsigned long long pc6;
207c98d5d94SLen Brown 	unsigned long long pc7;
208ca58710fSKristen Carlson Accardi 	unsigned long long pc8;
209ca58710fSKristen Carlson Accardi 	unsigned long long pc9;
210ca58710fSKristen Carlson Accardi 	unsigned long long pc10;
211be0e54c4SLen Brown 	unsigned long long cpu_lpi;
212be0e54c4SLen Brown 	unsigned long long sys_lpi;
2130b2bb692SLen Brown 	unsigned long long pkg_wtd_core_c0;
2140b2bb692SLen Brown 	unsigned long long pkg_any_core_c0;
2150b2bb692SLen Brown 	unsigned long long pkg_any_gfxe_c0;
2160b2bb692SLen Brown 	unsigned long long pkg_both_core_gfxe_c0;
2179185e988SLen Brown 	long long gfx_rc6_ms;
21827d47356SLen Brown 	unsigned int gfx_mhz;
219b4b91569SRafael Antognolli 	unsigned int gfx_act_mhz;
220c98d5d94SLen Brown 	unsigned int package_id;
2217c2ccc50SChen Yu 	unsigned long long energy_pkg;	/* MSR_PKG_ENERGY_STATUS */
2227c2ccc50SChen Yu 	unsigned long long energy_dram;	/* MSR_DRAM_ENERGY_STATUS */
2237c2ccc50SChen Yu 	unsigned long long energy_cores;	/* MSR_PP0_ENERGY_STATUS */
2247c2ccc50SChen Yu 	unsigned long long energy_gfx;	/* MSR_PP1_ENERGY_STATUS */
2257c2ccc50SChen Yu 	unsigned long long rapl_pkg_perf_status;	/* MSR_PKG_PERF_STATUS */
2267c2ccc50SChen Yu 	unsigned long long rapl_dram_perf_status;	/* MSR_DRAM_PERF_STATUS */
227889facbeSLen Brown 	unsigned int pkg_temp_c;
228678a3bd1SLen Brown 	unsigned long long counter[MAX_ADDED_COUNTERS];
229c98d5d94SLen Brown } *package_even, *package_odd;
230c98d5d94SLen Brown 
231c98d5d94SLen Brown #define ODD_COUNTERS thread_odd, core_odd, package_odd
232c98d5d94SLen Brown #define EVEN_COUNTERS thread_even, core_even, package_even
233c98d5d94SLen Brown 
23440f5cfe7SPrarit Bhargava #define GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no)	      \
23540f5cfe7SPrarit Bhargava 	((thread_base) +						      \
23640f5cfe7SPrarit Bhargava 	 ((pkg_no) *							      \
23740f5cfe7SPrarit Bhargava 	  topo.nodes_per_pkg * topo.cores_per_node * topo.threads_per_core) + \
23840f5cfe7SPrarit Bhargava 	 ((node_no) * topo.cores_per_node * topo.threads_per_core) +	      \
23940f5cfe7SPrarit Bhargava 	 ((core_no) * topo.threads_per_core) +				      \
24040f5cfe7SPrarit Bhargava 	 (thread_no))
24140f5cfe7SPrarit Bhargava 
24240f5cfe7SPrarit Bhargava #define GET_CORE(core_base, core_no, node_no, pkg_no)			\
24340f5cfe7SPrarit Bhargava 	((core_base) +							\
24440f5cfe7SPrarit Bhargava 	 ((pkg_no) *  topo.nodes_per_pkg * topo.cores_per_node) +	\
24540f5cfe7SPrarit Bhargava 	 ((node_no) * topo.cores_per_node) +				\
24640f5cfe7SPrarit Bhargava 	 (core_no))
24740f5cfe7SPrarit Bhargava 
24840f5cfe7SPrarit Bhargava 
249c98d5d94SLen Brown #define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
250c98d5d94SLen Brown 
251388e9c81SLen Brown enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE};
25241618e63SLen Brown enum counter_type {COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC};
253388e9c81SLen Brown enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT};
254388e9c81SLen Brown 
255388e9c81SLen Brown struct msr_counter {
256388e9c81SLen Brown 	unsigned int msr_num;
257388e9c81SLen Brown 	char name[NAME_BYTES];
258495c7654SLen Brown 	char path[PATH_BYTES];
259388e9c81SLen Brown 	unsigned int width;
260388e9c81SLen Brown 	enum counter_type type;
261388e9c81SLen Brown 	enum counter_format format;
262388e9c81SLen Brown 	struct msr_counter *next;
263812db3f7SLen Brown 	unsigned int flags;
264812db3f7SLen Brown #define	FLAGS_HIDE	(1 << 0)
265812db3f7SLen Brown #define	FLAGS_SHOW	(1 << 1)
26641618e63SLen Brown #define	SYSFS_PERCPU	(1 << 1)
267388e9c81SLen Brown };
268388e9c81SLen Brown 
26987e15da9SChen Yu /*
27087e15da9SChen Yu  * The accumulated sum of MSR is defined as a monotonic
27187e15da9SChen Yu  * increasing MSR, it will be accumulated periodically,
27287e15da9SChen Yu  * despite its register's bit width.
27387e15da9SChen Yu  */
27487e15da9SChen Yu enum {
27587e15da9SChen Yu 	IDX_PKG_ENERGY,
27687e15da9SChen Yu 	IDX_DRAM_ENERGY,
27787e15da9SChen Yu 	IDX_PP0_ENERGY,
27887e15da9SChen Yu 	IDX_PP1_ENERGY,
27987e15da9SChen Yu 	IDX_PKG_PERF,
28087e15da9SChen Yu 	IDX_DRAM_PERF,
28187e15da9SChen Yu 	IDX_COUNT,
28287e15da9SChen Yu };
28387e15da9SChen Yu 
28487e15da9SChen Yu int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);
28587e15da9SChen Yu 
28687e15da9SChen Yu struct msr_sum_array {
28787e15da9SChen Yu 	/* get_msr_sum() = sum + (get_msr() - last) */
28887e15da9SChen Yu 	struct {
28987e15da9SChen Yu 		/*The accumulated MSR value is updated by the timer*/
29087e15da9SChen Yu 		unsigned long long sum;
29187e15da9SChen Yu 		/*The MSR footprint recorded in last timer*/
29287e15da9SChen Yu 		unsigned long long last;
29387e15da9SChen Yu 	} entries[IDX_COUNT];
29487e15da9SChen Yu };
29587e15da9SChen Yu 
29687e15da9SChen Yu /* The percpu MSR sum array.*/
29787e15da9SChen Yu struct msr_sum_array *per_cpu_msr_sum;
29887e15da9SChen Yu 
29987e15da9SChen Yu int idx_to_offset(int idx)
30087e15da9SChen Yu {
30187e15da9SChen Yu 	int offset;
30287e15da9SChen Yu 
30387e15da9SChen Yu 	switch (idx) {
30487e15da9SChen Yu 	case IDX_PKG_ENERGY:
30587e15da9SChen Yu 		offset = MSR_PKG_ENERGY_STATUS;
30687e15da9SChen Yu 		break;
30787e15da9SChen Yu 	case IDX_DRAM_ENERGY:
30887e15da9SChen Yu 		offset = MSR_DRAM_ENERGY_STATUS;
30987e15da9SChen Yu 		break;
31087e15da9SChen Yu 	case IDX_PP0_ENERGY:
31187e15da9SChen Yu 		offset = MSR_PP0_ENERGY_STATUS;
31287e15da9SChen Yu 		break;
31387e15da9SChen Yu 	case IDX_PP1_ENERGY:
31487e15da9SChen Yu 		offset = MSR_PP1_ENERGY_STATUS;
31587e15da9SChen Yu 		break;
31687e15da9SChen Yu 	case IDX_PKG_PERF:
31787e15da9SChen Yu 		offset = MSR_PKG_PERF_STATUS;
31887e15da9SChen Yu 		break;
31987e15da9SChen Yu 	case IDX_DRAM_PERF:
32087e15da9SChen Yu 		offset = MSR_DRAM_PERF_STATUS;
32187e15da9SChen Yu 		break;
32287e15da9SChen Yu 	default:
32387e15da9SChen Yu 		offset = -1;
32487e15da9SChen Yu 	}
32587e15da9SChen Yu 	return offset;
32687e15da9SChen Yu }
32787e15da9SChen Yu 
32887e15da9SChen Yu int offset_to_idx(int offset)
32987e15da9SChen Yu {
33087e15da9SChen Yu 	int idx;
33187e15da9SChen Yu 
33287e15da9SChen Yu 	switch (offset) {
33387e15da9SChen Yu 	case MSR_PKG_ENERGY_STATUS:
33487e15da9SChen Yu 		idx = IDX_PKG_ENERGY;
33587e15da9SChen Yu 		break;
33687e15da9SChen Yu 	case MSR_DRAM_ENERGY_STATUS:
33787e15da9SChen Yu 		idx = IDX_DRAM_ENERGY;
33887e15da9SChen Yu 		break;
33987e15da9SChen Yu 	case MSR_PP0_ENERGY_STATUS:
34087e15da9SChen Yu 		idx = IDX_PP0_ENERGY;
34187e15da9SChen Yu 		break;
34287e15da9SChen Yu 	case MSR_PP1_ENERGY_STATUS:
34387e15da9SChen Yu 		idx = IDX_PP1_ENERGY;
34487e15da9SChen Yu 		break;
34587e15da9SChen Yu 	case MSR_PKG_PERF_STATUS:
34687e15da9SChen Yu 		idx = IDX_PKG_PERF;
34787e15da9SChen Yu 		break;
34887e15da9SChen Yu 	case MSR_DRAM_PERF_STATUS:
34987e15da9SChen Yu 		idx = IDX_DRAM_PERF;
35087e15da9SChen Yu 		break;
35187e15da9SChen Yu 	default:
35287e15da9SChen Yu 		idx = -1;
35387e15da9SChen Yu 	}
35487e15da9SChen Yu 	return idx;
35587e15da9SChen Yu }
35687e15da9SChen Yu 
35787e15da9SChen Yu int idx_valid(int idx)
35887e15da9SChen Yu {
35987e15da9SChen Yu 	switch (idx) {
36087e15da9SChen Yu 	case IDX_PKG_ENERGY:
36187e15da9SChen Yu 		return do_rapl & RAPL_PKG;
36287e15da9SChen Yu 	case IDX_DRAM_ENERGY:
36387e15da9SChen Yu 		return do_rapl & RAPL_DRAM;
36487e15da9SChen Yu 	case IDX_PP0_ENERGY:
36587e15da9SChen Yu 		return do_rapl & RAPL_CORES_ENERGY_STATUS;
36687e15da9SChen Yu 	case IDX_PP1_ENERGY:
36787e15da9SChen Yu 		return do_rapl & RAPL_GFX;
36887e15da9SChen Yu 	case IDX_PKG_PERF:
36987e15da9SChen Yu 		return do_rapl & RAPL_PKG_PERF_STATUS;
37087e15da9SChen Yu 	case IDX_DRAM_PERF:
37187e15da9SChen Yu 		return do_rapl & RAPL_DRAM_PERF_STATUS;
37287e15da9SChen Yu 	default:
37387e15da9SChen Yu 		return 0;
37487e15da9SChen Yu 	}
37587e15da9SChen Yu }
376388e9c81SLen Brown struct sys_counters {
377678a3bd1SLen Brown 	unsigned int added_thread_counters;
378678a3bd1SLen Brown 	unsigned int added_core_counters;
379678a3bd1SLen Brown 	unsigned int added_package_counters;
380388e9c81SLen Brown 	struct msr_counter *tp;
381388e9c81SLen Brown 	struct msr_counter *cp;
382388e9c81SLen Brown 	struct msr_counter *pp;
383388e9c81SLen Brown } sys;
384388e9c81SLen Brown 
385c98d5d94SLen Brown struct system_summary {
386c98d5d94SLen Brown 	struct thread_data threads;
387c98d5d94SLen Brown 	struct core_data cores;
388c98d5d94SLen Brown 	struct pkg_data packages;
389388e9c81SLen Brown } average;
390c98d5d94SLen Brown 
3910e2d8f05SLen Brown struct cpu_topology {
3920e2d8f05SLen Brown 	int physical_package_id;
3936de68fe1SLen Brown 	int die_id;
3940e2d8f05SLen Brown 	int logical_cpu_id;
395ef605741SPrarit Bhargava 	int physical_node_id;
396ef605741SPrarit Bhargava 	int logical_node_id;	/* 0-based count within the package */
3970e2d8f05SLen Brown 	int physical_core_id;
3988cb48b32SPrarit Bhargava 	int thread_id;
3990e2d8f05SLen Brown 	cpu_set_t *put_ids; /* Processing Unit/Thread IDs */
4000e2d8f05SLen Brown } *cpus;
401c98d5d94SLen Brown 
402c98d5d94SLen Brown struct topo_params {
403c98d5d94SLen Brown 	int num_packages;
4046de68fe1SLen Brown 	int num_die;
405103a8feaSLen Brown 	int num_cpus;
406c98d5d94SLen Brown 	int num_cores;
407c98d5d94SLen Brown 	int max_cpu_num;
408ef605741SPrarit Bhargava 	int max_node_num;
40970a9c6e8SPrarit Bhargava 	int nodes_per_pkg;
41070a9c6e8SPrarit Bhargava 	int cores_per_node;
41170a9c6e8SPrarit Bhargava 	int threads_per_core;
412c98d5d94SLen Brown } topo;
413103a8feaSLen Brown 
414c98d5d94SLen Brown struct timeval tv_even, tv_odd, tv_delta;
415103a8feaSLen Brown 
416562a2d37SLen Brown int *irq_column_2_cpu;	/* /proc/interrupts column numbers */
417562a2d37SLen Brown int *irqs_per_cpu;		/* indexed by cpu_num */
418562a2d37SLen Brown 
419c98d5d94SLen Brown void setup_all_buffers(void);
420103a8feaSLen Brown 
4211f81c5efSLen Brown char *sys_lpi_file;
4221f81c5efSLen Brown char *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us";
4231f81c5efSLen Brown char *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec";
4241f81c5efSLen Brown 
425c98d5d94SLen Brown int cpu_is_not_present(int cpu)
426d15cf7c1SLen Brown {
427c98d5d94SLen Brown 	return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);
428c98d5d94SLen Brown }
429c98d5d94SLen Brown /*
430c98d5d94SLen Brown  * run func(thread, core, package) in topology order
431c98d5d94SLen Brown  * skip non-present cpus
432c98d5d94SLen Brown  */
433c98d5d94SLen Brown 
434c98d5d94SLen Brown int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *),
435c98d5d94SLen Brown 	struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
436c98d5d94SLen Brown {
43740f5cfe7SPrarit Bhargava 	int retval, pkg_no, core_no, thread_no, node_no;
438c98d5d94SLen Brown 
439c98d5d94SLen Brown 	for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
440df2f677dSLen Brown 		for (node_no = 0; node_no < topo.nodes_per_pkg; node_no++) {
44170a9c6e8SPrarit Bhargava 			for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {
442c98d5d94SLen Brown 				for (thread_no = 0; thread_no <
44370a9c6e8SPrarit Bhargava 					topo.threads_per_core; ++thread_no) {
444c98d5d94SLen Brown 					struct thread_data *t;
445c98d5d94SLen Brown 					struct core_data *c;
446c98d5d94SLen Brown 					struct pkg_data *p;
447c98d5d94SLen Brown 
44840f5cfe7SPrarit Bhargava 					t = GET_THREAD(thread_base, thread_no,
44940f5cfe7SPrarit Bhargava 						       core_no, node_no,
45040f5cfe7SPrarit Bhargava 						       pkg_no);
451c98d5d94SLen Brown 
452c98d5d94SLen Brown 					if (cpu_is_not_present(t->cpu_id))
453c98d5d94SLen Brown 						continue;
454c98d5d94SLen Brown 
45540f5cfe7SPrarit Bhargava 					c = GET_CORE(core_base, core_no,
45640f5cfe7SPrarit Bhargava 						     node_no, pkg_no);
457c98d5d94SLen Brown 					p = GET_PKG(pkg_base, pkg_no);
458c98d5d94SLen Brown 
459c98d5d94SLen Brown 					retval = func(t, c, p);
460c98d5d94SLen Brown 					if (retval)
461c98d5d94SLen Brown 						return retval;
462c98d5d94SLen Brown 				}
463c98d5d94SLen Brown 			}
464c98d5d94SLen Brown 		}
46540f5cfe7SPrarit Bhargava 	}
466d15cf7c1SLen Brown 	return 0;
467d15cf7c1SLen Brown }
468d15cf7c1SLen Brown 
46988c3281fSLen Brown int cpu_migrate(int cpu)
47088c3281fSLen Brown {
471c98d5d94SLen Brown 	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
472c98d5d94SLen Brown 	CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
473c98d5d94SLen Brown 	if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)
47488c3281fSLen Brown 		return -1;
47588c3281fSLen Brown 	else
47688c3281fSLen Brown 		return 0;
47788c3281fSLen Brown }
47836229897SLen Brown int get_msr_fd(int cpu)
479103a8feaSLen Brown {
480103a8feaSLen Brown 	char pathname[32];
481103a8feaSLen Brown 	int fd;
482103a8feaSLen Brown 
48336229897SLen Brown 	fd = fd_percpu[cpu];
48436229897SLen Brown 
48536229897SLen Brown 	if (fd)
48636229897SLen Brown 		return fd;
48736229897SLen Brown 
488103a8feaSLen Brown 	sprintf(pathname, "/dev/cpu/%d/msr", cpu);
489103a8feaSLen Brown 	fd = open(pathname, O_RDONLY);
49015aaa346SLen Brown 	if (fd < 0)
49198481e79SLen Brown 		err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
492103a8feaSLen Brown 
49336229897SLen Brown 	fd_percpu[cpu] = fd;
49436229897SLen Brown 
49536229897SLen Brown 	return fd;
49636229897SLen Brown }
49736229897SLen Brown 
4982af4f9b8SLen Brown static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)
4992af4f9b8SLen Brown {
5002af4f9b8SLen Brown 	return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
5012af4f9b8SLen Brown }
5022af4f9b8SLen Brown 
5032af4f9b8SLen Brown static int perf_instr_count_open(int cpu_num)
5042af4f9b8SLen Brown {
5052af4f9b8SLen Brown 	struct perf_event_attr pea;
5062af4f9b8SLen Brown 	int fd;
5072af4f9b8SLen Brown 
5082af4f9b8SLen Brown 	memset(&pea, 0, sizeof(struct perf_event_attr));
5092af4f9b8SLen Brown 	pea.type = PERF_TYPE_HARDWARE;
5102af4f9b8SLen Brown 	pea.size = sizeof(struct perf_event_attr);
5112af4f9b8SLen Brown 	pea.config = PERF_COUNT_HW_INSTRUCTIONS;
5122af4f9b8SLen Brown 
5132af4f9b8SLen Brown 	/* counter for cpu_num, including user + kernel and all processes */
5142af4f9b8SLen Brown 	fd = perf_event_open(&pea, -1, cpu_num, -1, 0);
5152af4f9b8SLen Brown 	if (fd == -1)
5162af4f9b8SLen Brown 		err(-1, "cpu%d: perf instruction counter\n", cpu_num);
5172af4f9b8SLen Brown 
5182af4f9b8SLen Brown 	return fd;
5192af4f9b8SLen Brown }
5202af4f9b8SLen Brown 
5212af4f9b8SLen Brown int get_instr_count_fd(int cpu)
5222af4f9b8SLen Brown {
5232af4f9b8SLen Brown 	if (fd_instr_count_percpu[cpu])
5242af4f9b8SLen Brown 		return fd_instr_count_percpu[cpu];
5252af4f9b8SLen Brown 
5262af4f9b8SLen Brown 	fd_instr_count_percpu[cpu] = perf_instr_count_open(cpu);
5272af4f9b8SLen Brown 
5282af4f9b8SLen Brown 	return fd_instr_count_percpu[cpu];
5292af4f9b8SLen Brown }
5302af4f9b8SLen Brown 
53136229897SLen Brown int get_msr(int cpu, off_t offset, unsigned long long *msr)
53236229897SLen Brown {
53336229897SLen Brown 	ssize_t retval;
53436229897SLen Brown 
53536229897SLen Brown 	retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
53615aaa346SLen Brown 
53798481e79SLen Brown 	if (retval != sizeof *msr)
538cf4cbe53SLen Brown 		err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
53915aaa346SLen Brown 
54015aaa346SLen Brown 	return 0;
541103a8feaSLen Brown }
542103a8feaSLen Brown 
543fc04cc67SLen Brown /*
544bdd5ae3aSLen Brown  * This list matches the column headers, except
545bdd5ae3aSLen Brown  * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
546bdd5ae3aSLen Brown  * 2. Core and CPU are moved to the end, we can't have strings that contain them
547bdd5ae3aSLen Brown  *    matching on them for --show and --hide.
548fc04cc67SLen Brown  */
549812db3f7SLen Brown struct msr_counter bic[] = {
5503f44a5c6SLen Brown 	{ 0x0, "usec" },
5513f44a5c6SLen Brown 	{ 0x0, "Time_Of_Day_Seconds" },
552812db3f7SLen Brown 	{ 0x0, "Package" },
553bdd5ae3aSLen Brown 	{ 0x0, "Node" },
554812db3f7SLen Brown 	{ 0x0, "Avg_MHz" },
555bdd5ae3aSLen Brown 	{ 0x0, "Busy%" },
556812db3f7SLen Brown 	{ 0x0, "Bzy_MHz" },
557812db3f7SLen Brown 	{ 0x0, "TSC_MHz" },
558812db3f7SLen Brown 	{ 0x0, "IRQ" },
559495c7654SLen Brown 	{ 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL},
560bdd5ae3aSLen Brown 	{ 0x0, "sysfs" },
561812db3f7SLen Brown 	{ 0x0, "CPU%c1" },
562812db3f7SLen Brown 	{ 0x0, "CPU%c3" },
563812db3f7SLen Brown 	{ 0x0, "CPU%c6" },
564812db3f7SLen Brown 	{ 0x0, "CPU%c7" },
565812db3f7SLen Brown 	{ 0x0, "ThreadC" },
566812db3f7SLen Brown 	{ 0x0, "CoreTmp" },
567812db3f7SLen Brown 	{ 0x0, "CoreCnt" },
568812db3f7SLen Brown 	{ 0x0, "PkgTmp" },
569812db3f7SLen Brown 	{ 0x0, "GFX%rc6" },
570812db3f7SLen Brown 	{ 0x0, "GFXMHz" },
571812db3f7SLen Brown 	{ 0x0, "Pkg%pc2" },
572812db3f7SLen Brown 	{ 0x0, "Pkg%pc3" },
573812db3f7SLen Brown 	{ 0x0, "Pkg%pc6" },
574812db3f7SLen Brown 	{ 0x0, "Pkg%pc7" },
5750f47c08dSLen Brown 	{ 0x0, "Pkg%pc8" },
5760f47c08dSLen Brown 	{ 0x0, "Pkg%pc9" },
5774bd1f8f2SLen Brown 	{ 0x0, "Pk%pc10" },
578be0e54c4SLen Brown 	{ 0x0, "CPU%LPI" },
579be0e54c4SLen Brown 	{ 0x0, "SYS%LPI" },
580812db3f7SLen Brown 	{ 0x0, "PkgWatt" },
581812db3f7SLen Brown 	{ 0x0, "CorWatt" },
582812db3f7SLen Brown 	{ 0x0, "GFXWatt" },
583812db3f7SLen Brown 	{ 0x0, "PkgCnt" },
584812db3f7SLen Brown 	{ 0x0, "RAMWatt" },
585812db3f7SLen Brown 	{ 0x0, "PKG_%" },
586812db3f7SLen Brown 	{ 0x0, "RAM_%" },
587812db3f7SLen Brown 	{ 0x0, "Pkg_J" },
588812db3f7SLen Brown 	{ 0x0, "Cor_J" },
589812db3f7SLen Brown 	{ 0x0, "GFX_J" },
590812db3f7SLen Brown 	{ 0x0, "RAM_J" },
5910539ba11SLen Brown 	{ 0x0, "Mod%c6" },
592a99d8730SLen Brown 	{ 0x0, "Totl%C0" },
593a99d8730SLen Brown 	{ 0x0, "Any%C0" },
594a99d8730SLen Brown 	{ 0x0, "GFX%C0" },
595a99d8730SLen Brown 	{ 0x0, "CPUGFX%" },
596bdd5ae3aSLen Brown 	{ 0x0, "Core" },
597bdd5ae3aSLen Brown 	{ 0x0, "CPU" },
5984c2122d4SLen Brown 	{ 0x0, "APIC" },
5994c2122d4SLen Brown 	{ 0x0, "X2APIC" },
6006de68fe1SLen Brown 	{ 0x0, "Die" },
601b4b91569SRafael Antognolli 	{ 0x0, "GFXAMHz" },
6022af4f9b8SLen Brown 	{ 0x0, "IPC" },
603812db3f7SLen Brown };
604812db3f7SLen Brown 
605812db3f7SLen Brown #define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
6063f44a5c6SLen Brown #define	BIC_USEC	(1ULL << 0)
6073f44a5c6SLen Brown #define	BIC_TOD		(1ULL << 1)
6083f44a5c6SLen Brown #define	BIC_Package	(1ULL << 2)
609bdd5ae3aSLen Brown #define	BIC_Node	(1ULL << 3)
610bdd5ae3aSLen Brown #define	BIC_Avg_MHz	(1ULL << 4)
611bdd5ae3aSLen Brown #define	BIC_Busy	(1ULL << 5)
612bdd5ae3aSLen Brown #define	BIC_Bzy_MHz	(1ULL << 6)
613bdd5ae3aSLen Brown #define	BIC_TSC_MHz	(1ULL << 7)
614bdd5ae3aSLen Brown #define	BIC_IRQ		(1ULL << 8)
615bdd5ae3aSLen Brown #define	BIC_SMI		(1ULL << 9)
616bdd5ae3aSLen Brown #define	BIC_sysfs	(1ULL << 10)
617bdd5ae3aSLen Brown #define	BIC_CPU_c1	(1ULL << 11)
618bdd5ae3aSLen Brown #define	BIC_CPU_c3	(1ULL << 12)
619bdd5ae3aSLen Brown #define	BIC_CPU_c6	(1ULL << 13)
620bdd5ae3aSLen Brown #define	BIC_CPU_c7	(1ULL << 14)
621bdd5ae3aSLen Brown #define	BIC_ThreadC	(1ULL << 15)
622bdd5ae3aSLen Brown #define	BIC_CoreTmp	(1ULL << 16)
623bdd5ae3aSLen Brown #define	BIC_CoreCnt	(1ULL << 17)
624bdd5ae3aSLen Brown #define	BIC_PkgTmp	(1ULL << 18)
625bdd5ae3aSLen Brown #define	BIC_GFX_rc6	(1ULL << 19)
626bdd5ae3aSLen Brown #define	BIC_GFXMHz	(1ULL << 20)
627bdd5ae3aSLen Brown #define	BIC_Pkgpc2	(1ULL << 21)
628bdd5ae3aSLen Brown #define	BIC_Pkgpc3	(1ULL << 22)
629bdd5ae3aSLen Brown #define	BIC_Pkgpc6	(1ULL << 23)
630bdd5ae3aSLen Brown #define	BIC_Pkgpc7	(1ULL << 24)
631bdd5ae3aSLen Brown #define	BIC_Pkgpc8	(1ULL << 25)
632bdd5ae3aSLen Brown #define	BIC_Pkgpc9	(1ULL << 26)
633bdd5ae3aSLen Brown #define	BIC_Pkgpc10	(1ULL << 27)
634bdd5ae3aSLen Brown #define BIC_CPU_LPI	(1ULL << 28)
635bdd5ae3aSLen Brown #define BIC_SYS_LPI	(1ULL << 29)
636bdd5ae3aSLen Brown #define	BIC_PkgWatt	(1ULL << 30)
637bdd5ae3aSLen Brown #define	BIC_CorWatt	(1ULL << 31)
638bdd5ae3aSLen Brown #define	BIC_GFXWatt	(1ULL << 32)
639bdd5ae3aSLen Brown #define	BIC_PkgCnt	(1ULL << 33)
640bdd5ae3aSLen Brown #define	BIC_RAMWatt	(1ULL << 34)
641bdd5ae3aSLen Brown #define	BIC_PKG__	(1ULL << 35)
642bdd5ae3aSLen Brown #define	BIC_RAM__	(1ULL << 36)
643bdd5ae3aSLen Brown #define	BIC_Pkg_J	(1ULL << 37)
644bdd5ae3aSLen Brown #define	BIC_Cor_J	(1ULL << 38)
645bdd5ae3aSLen Brown #define	BIC_GFX_J	(1ULL << 39)
646bdd5ae3aSLen Brown #define	BIC_RAM_J	(1ULL << 40)
647bdd5ae3aSLen Brown #define	BIC_Mod_c6	(1ULL << 41)
648bdd5ae3aSLen Brown #define	BIC_Totl_c0	(1ULL << 42)
649bdd5ae3aSLen Brown #define	BIC_Any_c0	(1ULL << 43)
650bdd5ae3aSLen Brown #define	BIC_GFX_c0	(1ULL << 44)
651bdd5ae3aSLen Brown #define	BIC_CPUGFX	(1ULL << 45)
652bdd5ae3aSLen Brown #define	BIC_Core	(1ULL << 46)
653bdd5ae3aSLen Brown #define	BIC_CPU		(1ULL << 47)
6544c2122d4SLen Brown #define	BIC_APIC	(1ULL << 48)
6554c2122d4SLen Brown #define	BIC_X2APIC	(1ULL << 49)
6566de68fe1SLen Brown #define	BIC_Die		(1ULL << 50)
657b4b91569SRafael Antognolli #define	BIC_GFXACTMHz	(1ULL << 51)
6582af4f9b8SLen Brown #define	BIC_IPC		(1ULL << 52)
659812db3f7SLen Brown 
6604c2122d4SLen Brown #define BIC_DISABLED_BY_DEFAULT	(BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
6613f44a5c6SLen Brown 
6623f44a5c6SLen Brown unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
6634c2122d4SLen Brown unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
664812db3f7SLen Brown 
665812db3f7SLen Brown #define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
6661e9042b9SSrinivas Pandruvada #define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
6673f44a5c6SLen Brown #define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
668812db3f7SLen Brown #define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
6690f47c08dSLen Brown #define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
6702af4f9b8SLen Brown #define BIC_IS_ENABLED(COUNTER_BIT) (bic_enabled & COUNTER_BIT)
671812db3f7SLen Brown 
6723f44a5c6SLen Brown 
673dd778a5eSLen Brown #define MAX_DEFERRED 16
674dd778a5eSLen Brown char *deferred_skip_names[MAX_DEFERRED];
675dd778a5eSLen Brown int deferred_skip_index;
676dd778a5eSLen Brown 
677dd778a5eSLen Brown /*
678dd778a5eSLen Brown  * HIDE_LIST - hide this list of counters, show the rest [default]
679dd778a5eSLen Brown  * SHOW_LIST - show this list of counters, hide the rest
680dd778a5eSLen Brown  */
681dd778a5eSLen Brown enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
682dd778a5eSLen Brown 
683dd778a5eSLen Brown void help(void)
684dd778a5eSLen Brown {
685dd778a5eSLen Brown 	fprintf(outf,
686dd778a5eSLen Brown 	"Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
687dd778a5eSLen Brown 	"\n"
688dd778a5eSLen Brown 	"Turbostat forks the specified COMMAND and prints statistics\n"
689dd778a5eSLen Brown 	"when COMMAND completes.\n"
690dd778a5eSLen Brown 	"If no COMMAND is specified, turbostat wakes every 5-seconds\n"
691dd778a5eSLen Brown 	"to print statistics, until interrupted.\n"
692cc481650SNathan Ciobanu 	"  -a, --add	add a counter\n"
693dd778a5eSLen Brown 	"		  eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
694cc481650SNathan Ciobanu 	"  -c, --cpu	cpu-set	limit output to summary plus cpu-set:\n"
695dd778a5eSLen Brown 	"		  {core | package | j,k,l..m,n-p }\n"
6969ce80578SNathan Ciobanu 	"  -d, --debug	displays usec, Time_Of_Day_Seconds and more debugging\n"
6979ce80578SNathan Ciobanu 	"  -D, --Dump	displays the raw counter values\n"
6989ce80578SNathan Ciobanu 	"  -e, --enable	[all | column]\n"
6999ce80578SNathan Ciobanu 	"		shows all or the specified disabled column\n"
7009ce80578SNathan Ciobanu 	"  -H, --hide [column|column,column,...]\n"
7019ce80578SNathan Ciobanu 	"		hide the specified column(s)\n"
702cc481650SNathan Ciobanu 	"  -i, --interval sec.subsec\n"
703cc481650SNathan Ciobanu 	"		Override default 5-second measurement interval\n"
7049ce80578SNathan Ciobanu 	"  -J, --Joules	displays energy in Joules instead of Watts\n"
705cc481650SNathan Ciobanu 	"  -l, --list	list column headers only\n"
706cc481650SNathan Ciobanu 	"  -n, --num_iterations num\n"
707cc481650SNathan Ciobanu 	"		number of the measurement iterations\n"
708cc481650SNathan Ciobanu 	"  -o, --out file\n"
709cc481650SNathan Ciobanu 	"		create or truncate \"file\" for all output\n"
710cc481650SNathan Ciobanu 	"  -q, --quiet	skip decoding system configuration header\n"
7119ce80578SNathan Ciobanu 	"  -s, --show [column|column,column,...]\n"
7129ce80578SNathan Ciobanu 	"		show only the specified column(s)\n"
7139ce80578SNathan Ciobanu 	"  -S, --Summary\n"
7149ce80578SNathan Ciobanu 	"		limits output to 1-line system summary per interval\n"
7159ce80578SNathan Ciobanu 	"  -T, --TCC temperature\n"
7169ce80578SNathan Ciobanu 	"		sets the Thermal Control Circuit temperature in\n"
7179ce80578SNathan Ciobanu 	"		  degrees Celsius\n"
718cc481650SNathan Ciobanu 	"  -h, --help	print this help message\n"
719cc481650SNathan Ciobanu 	"  -v, --version	print version information\n"
720dd778a5eSLen Brown 	"\n"
721dd778a5eSLen Brown 	"For more help, run \"man turbostat\"\n");
722dd778a5eSLen Brown }
723dd778a5eSLen Brown 
724812db3f7SLen Brown /*
725812db3f7SLen Brown  * bic_lookup
726812db3f7SLen Brown  * for all the strings in comma separate name_list,
727812db3f7SLen Brown  * set the approprate bit in return value.
728812db3f7SLen Brown  */
729dd778a5eSLen Brown unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
730812db3f7SLen Brown {
731812db3f7SLen Brown 	int i;
732812db3f7SLen Brown 	unsigned long long retval = 0;
733812db3f7SLen Brown 
734812db3f7SLen Brown 	while (name_list) {
735812db3f7SLen Brown 		char *comma;
736812db3f7SLen Brown 
737812db3f7SLen Brown 		comma = strchr(name_list, ',');
738812db3f7SLen Brown 
739812db3f7SLen Brown 		if (comma)
740812db3f7SLen Brown 			*comma = '\0';
741812db3f7SLen Brown 
7423f44a5c6SLen Brown 		if (!strcmp(name_list, "all"))
7433f44a5c6SLen Brown 			return ~0;
7443f44a5c6SLen Brown 
745812db3f7SLen Brown 		for (i = 0; i < MAX_BIC; ++i) {
746812db3f7SLen Brown 			if (!strcmp(name_list, bic[i].name)) {
747812db3f7SLen Brown 				retval |= (1ULL << i);
748812db3f7SLen Brown 				break;
749812db3f7SLen Brown 			}
750812db3f7SLen Brown 		}
751812db3f7SLen Brown 		if (i == MAX_BIC) {
752dd778a5eSLen Brown 			if (mode == SHOW_LIST) {
753812db3f7SLen Brown 				fprintf(stderr, "Invalid counter name: %s\n", name_list);
754812db3f7SLen Brown 				exit(-1);
755812db3f7SLen Brown 			}
756dd778a5eSLen Brown 			deferred_skip_names[deferred_skip_index++] = name_list;
757dd778a5eSLen Brown 			if (debug)
758dd778a5eSLen Brown 				fprintf(stderr, "deferred \"%s\"\n", name_list);
759dd778a5eSLen Brown 			if (deferred_skip_index >= MAX_DEFERRED) {
760dd778a5eSLen Brown 				fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
761dd778a5eSLen Brown 					MAX_DEFERRED, name_list);
762dd778a5eSLen Brown 				help();
763dd778a5eSLen Brown 				exit(1);
764dd778a5eSLen Brown 			}
765dd778a5eSLen Brown 		}
766812db3f7SLen Brown 
767812db3f7SLen Brown 		name_list = comma;
768812db3f7SLen Brown 		if (name_list)
769812db3f7SLen Brown 			name_list++;
770812db3f7SLen Brown 
771812db3f7SLen Brown 	}
772812db3f7SLen Brown 	return retval;
773812db3f7SLen Brown }
774fc04cc67SLen Brown 
775dd778a5eSLen Brown 
776c8ade361SLen Brown void print_header(char *delim)
777103a8feaSLen Brown {
778388e9c81SLen Brown 	struct msr_counter *mp;
7796168c2e0SLen Brown 	int printed = 0;
780388e9c81SLen Brown 
7813f44a5c6SLen Brown 	if (DO_BIC(BIC_USEC))
7823f44a5c6SLen Brown 		outp += sprintf(outp, "%susec", (printed++ ? delim : ""));
7833f44a5c6SLen Brown 	if (DO_BIC(BIC_TOD))
7843f44a5c6SLen Brown 		outp += sprintf(outp, "%sTime_Of_Day_Seconds", (printed++ ? delim : ""));
785812db3f7SLen Brown 	if (DO_BIC(BIC_Package))
7866168c2e0SLen Brown 		outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));
7876de68fe1SLen Brown 	if (DO_BIC(BIC_Die))
7886de68fe1SLen Brown 		outp += sprintf(outp, "%sDie", (printed++ ? delim : ""));
78901235041SPrarit Bhargava 	if (DO_BIC(BIC_Node))
79001235041SPrarit Bhargava 		outp += sprintf(outp, "%sNode", (printed++ ? delim : ""));
791812db3f7SLen Brown 	if (DO_BIC(BIC_Core))
7926168c2e0SLen Brown 		outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
793812db3f7SLen Brown 	if (DO_BIC(BIC_CPU))
7946168c2e0SLen Brown 		outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
7954c2122d4SLen Brown 	if (DO_BIC(BIC_APIC))
7964c2122d4SLen Brown 		outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));
7974c2122d4SLen Brown 	if (DO_BIC(BIC_X2APIC))
7984c2122d4SLen Brown 		outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));
799812db3f7SLen Brown 	if (DO_BIC(BIC_Avg_MHz))
8006168c2e0SLen Brown 		outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
801812db3f7SLen Brown 	if (DO_BIC(BIC_Busy))
8026168c2e0SLen Brown 		outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));
803812db3f7SLen Brown 	if (DO_BIC(BIC_Bzy_MHz))
8046168c2e0SLen Brown 		outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));
805812db3f7SLen Brown 	if (DO_BIC(BIC_TSC_MHz))
8066168c2e0SLen Brown 		outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));
8071cc21f7bSLen Brown 
8082af4f9b8SLen Brown 	if (DO_BIC(BIC_IPC))
8092af4f9b8SLen Brown 		outp += sprintf(outp, "%sIPC", (printed++ ? delim : ""));
8102af4f9b8SLen Brown 
8110de6c0dfSLen Brown 	if (DO_BIC(BIC_IRQ)) {
8120de6c0dfSLen Brown 		if (sums_need_wide_columns)
8136168c2e0SLen Brown 			outp += sprintf(outp, "%s     IRQ", (printed++ ? delim : ""));
8140de6c0dfSLen Brown 		else
8156168c2e0SLen Brown 			outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));
8160de6c0dfSLen Brown 	}
8170de6c0dfSLen Brown 
818812db3f7SLen Brown 	if (DO_BIC(BIC_SMI))
8196168c2e0SLen Brown 		outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));
8201cc21f7bSLen Brown 
821388e9c81SLen Brown 	for (mp = sys.tp; mp; mp = mp->next) {
822dd778a5eSLen Brown 
823388e9c81SLen Brown 		if (mp->format == FORMAT_RAW) {
824388e9c81SLen Brown 			if (mp->width == 64)
825dd778a5eSLen Brown 				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), mp->name);
826388e9c81SLen Brown 			else
827dd778a5eSLen Brown 				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), mp->name);
828388e9c81SLen Brown 		} else {
8290de6c0dfSLen Brown 			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
830dd778a5eSLen Brown 				outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), mp->name);
8310de6c0dfSLen Brown 			else
832dd778a5eSLen Brown 				outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), mp->name);
833388e9c81SLen Brown 		}
834388e9c81SLen Brown 	}
835388e9c81SLen Brown 
83641618e63SLen Brown 	if (DO_BIC(BIC_CPU_c1))
8376168c2e0SLen Brown 		outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));
838562855eeSLen Brown 	if (DO_BIC(BIC_CPU_c3))
8396168c2e0SLen Brown 		outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));
840812db3f7SLen Brown 	if (DO_BIC(BIC_CPU_c6))
8416168c2e0SLen Brown 		outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));
842812db3f7SLen Brown 	if (DO_BIC(BIC_CPU_c7))
8436168c2e0SLen Brown 		outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));
844678a3bd1SLen Brown 
8450539ba11SLen Brown 	if (DO_BIC(BIC_Mod_c6))
8466168c2e0SLen Brown 		outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));
847678a3bd1SLen Brown 
848812db3f7SLen Brown 	if (DO_BIC(BIC_CoreTmp))
8496168c2e0SLen Brown 		outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));
850388e9c81SLen Brown 
8519392bd98SCalvin Walton 	if (do_rapl && !rapl_joules) {
8529392bd98SCalvin Walton 		if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
8539392bd98SCalvin Walton 			outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
8549392bd98SCalvin Walton 	} else if (do_rapl && rapl_joules) {
8559392bd98SCalvin Walton 		if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY))
8569392bd98SCalvin Walton 			outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
8579392bd98SCalvin Walton 	}
8589392bd98SCalvin Walton 
859388e9c81SLen Brown 	for (mp = sys.cp; mp; mp = mp->next) {
860388e9c81SLen Brown 		if (mp->format == FORMAT_RAW) {
861388e9c81SLen Brown 			if (mp->width == 64)
862c8ade361SLen Brown 				outp += sprintf(outp, "%s%18.18s", delim, mp->name);
863388e9c81SLen Brown 			else
864c8ade361SLen Brown 				outp += sprintf(outp, "%s%10.10s", delim, mp->name);
865388e9c81SLen Brown 		} else {
8660de6c0dfSLen Brown 			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
8670de6c0dfSLen Brown 				outp += sprintf(outp, "%s%8s", delim, mp->name);
8680de6c0dfSLen Brown 			else
869c8ade361SLen Brown 				outp += sprintf(outp, "%s%s", delim, mp->name);
870388e9c81SLen Brown 		}
871388e9c81SLen Brown 	}
872388e9c81SLen Brown 
873812db3f7SLen Brown 	if (DO_BIC(BIC_PkgTmp))
8746168c2e0SLen Brown 		outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));
875889facbeSLen Brown 
876812db3f7SLen Brown 	if (DO_BIC(BIC_GFX_rc6))
8776168c2e0SLen Brown 		outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));
878fdf676e5SLen Brown 
879812db3f7SLen Brown 	if (DO_BIC(BIC_GFXMHz))
8806168c2e0SLen Brown 		outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
88127d47356SLen Brown 
882b4b91569SRafael Antognolli 	if (DO_BIC(BIC_GFXACTMHz))
883b4b91569SRafael Antognolli 		outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));
884b4b91569SRafael Antognolli 
885a99d8730SLen Brown 	if (DO_BIC(BIC_Totl_c0))
8866168c2e0SLen Brown 		outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
887a99d8730SLen Brown 	if (DO_BIC(BIC_Any_c0))
8886168c2e0SLen Brown 		outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));
889a99d8730SLen Brown 	if (DO_BIC(BIC_GFX_c0))
8906168c2e0SLen Brown 		outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));
891a99d8730SLen Brown 	if (DO_BIC(BIC_CPUGFX))
8926168c2e0SLen Brown 		outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));
8930b2bb692SLen Brown 
8940f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc2))
8956168c2e0SLen Brown 		outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));
8960f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
8976168c2e0SLen Brown 		outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));
8980f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6))
8996168c2e0SLen Brown 		outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));
9000f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
9016168c2e0SLen Brown 		outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));
9020f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc8))
9036168c2e0SLen Brown 		outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));
9040f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc9))
9056168c2e0SLen Brown 		outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));
9060f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc10))
9076168c2e0SLen Brown 		outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));
908be0e54c4SLen Brown 	if (DO_BIC(BIC_CPU_LPI))
909be0e54c4SLen Brown 		outp += sprintf(outp, "%sCPU%%LPI", (printed++ ? delim : ""));
910be0e54c4SLen Brown 	if (DO_BIC(BIC_SYS_LPI))
911be0e54c4SLen Brown 		outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));
912103a8feaSLen Brown 
9135c56be9aSDirk Brandewie 	if (do_rapl && !rapl_joules) {
914812db3f7SLen Brown 		if (DO_BIC(BIC_PkgWatt))
9156168c2e0SLen Brown 			outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
9169392bd98SCalvin Walton 		if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY))
9176168c2e0SLen Brown 			outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
918812db3f7SLen Brown 		if (DO_BIC(BIC_GFXWatt))
9196168c2e0SLen Brown 			outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));
920812db3f7SLen Brown 		if (DO_BIC(BIC_RAMWatt))
9216168c2e0SLen Brown 			outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));
922812db3f7SLen Brown 		if (DO_BIC(BIC_PKG__))
9236168c2e0SLen Brown 			outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
924812db3f7SLen Brown 		if (DO_BIC(BIC_RAM__))
9256168c2e0SLen Brown 			outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
926d7899447SLen Brown 	} else if (do_rapl && rapl_joules) {
927812db3f7SLen Brown 		if (DO_BIC(BIC_Pkg_J))
9286168c2e0SLen Brown 			outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
9299392bd98SCalvin Walton 		if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY))
9306168c2e0SLen Brown 			outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
931812db3f7SLen Brown 		if (DO_BIC(BIC_GFX_J))
9326168c2e0SLen Brown 			outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));
933812db3f7SLen Brown 		if (DO_BIC(BIC_RAM_J))
9346168c2e0SLen Brown 			outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));
935812db3f7SLen Brown 		if (DO_BIC(BIC_PKG__))
9366168c2e0SLen Brown 			outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
937812db3f7SLen Brown 		if (DO_BIC(BIC_RAM__))
9386168c2e0SLen Brown 			outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
9395c56be9aSDirk Brandewie 	}
940388e9c81SLen Brown 	for (mp = sys.pp; mp; mp = mp->next) {
941388e9c81SLen Brown 		if (mp->format == FORMAT_RAW) {
942388e9c81SLen Brown 			if (mp->width == 64)
943c8ade361SLen Brown 				outp += sprintf(outp, "%s%18.18s", delim, mp->name);
944388e9c81SLen Brown 			else
945c8ade361SLen Brown 				outp += sprintf(outp, "%s%10.10s", delim, mp->name);
946388e9c81SLen Brown 		} else {
9470de6c0dfSLen Brown 			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
9480de6c0dfSLen Brown 				outp += sprintf(outp, "%s%8s", delim, mp->name);
9490de6c0dfSLen Brown 			else
950c8ade361SLen Brown 				outp += sprintf(outp, "%s%s", delim, mp->name);
951388e9c81SLen Brown 		}
952388e9c81SLen Brown 	}
953388e9c81SLen Brown 
954c98d5d94SLen Brown 	outp += sprintf(outp, "\n");
955103a8feaSLen Brown }
956103a8feaSLen Brown 
957c98d5d94SLen Brown int dump_counters(struct thread_data *t, struct core_data *c,
958c98d5d94SLen Brown 	struct pkg_data *p)
959103a8feaSLen Brown {
960388e9c81SLen Brown 	int i;
961388e9c81SLen Brown 	struct msr_counter *mp;
962388e9c81SLen Brown 
9633b4d5c7fSAndy Shevchenko 	outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);
964c98d5d94SLen Brown 
965c98d5d94SLen Brown 	if (t) {
9663b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "CPU: %d flags 0x%x\n",
9673b4d5c7fSAndy Shevchenko 			t->cpu_id, t->flags);
9683b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "TSC: %016llX\n", t->tsc);
9693b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "aperf: %016llX\n", t->aperf);
9703b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "mperf: %016llX\n", t->mperf);
9713b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "c1: %016llX\n", t->c1);
9726886fee4SLen Brown 
9732af4f9b8SLen Brown 		if (DO_BIC(BIC_IPC))
9742af4f9b8SLen Brown 			outp += sprintf(outp, "IPC: %lld\n", t->instr_count);
9752af4f9b8SLen Brown 
976812db3f7SLen Brown 		if (DO_BIC(BIC_IRQ))
9770de6c0dfSLen Brown 			outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);
978812db3f7SLen Brown 		if (DO_BIC(BIC_SMI))
979218f0e8dSLen Brown 			outp += sprintf(outp, "SMI: %d\n", t->smi_count);
980388e9c81SLen Brown 
981388e9c81SLen Brown 		for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
982388e9c81SLen Brown 			outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n",
983388e9c81SLen Brown 				i, mp->msr_num, t->counter[i]);
984388e9c81SLen Brown 		}
985103a8feaSLen Brown 	}
986103a8feaSLen Brown 
987c98d5d94SLen Brown 	if (c) {
9883b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "core: %d\n", c->core_id);
9893b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "c3: %016llX\n", c->c3);
9903b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "c6: %016llX\n", c->c6);
9913b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "c7: %016llX\n", c->c7);
9923b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c);
9939392bd98SCalvin Walton 		outp += sprintf(outp, "Joules: %0X\n", c->core_energy);
994388e9c81SLen Brown 
995388e9c81SLen Brown 		for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
996388e9c81SLen Brown 			outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n",
997388e9c81SLen Brown 				i, mp->msr_num, c->counter[i]);
998388e9c81SLen Brown 		}
9990539ba11SLen Brown 		outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);
1000c98d5d94SLen Brown 	}
1001103a8feaSLen Brown 
1002c98d5d94SLen Brown 	if (p) {
10033b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "package: %d\n", p->package_id);
10040b2bb692SLen Brown 
10050b2bb692SLen Brown 		outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0);
10060b2bb692SLen Brown 		outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0);
10070b2bb692SLen Brown 		outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0);
10080b2bb692SLen Brown 		outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);
10090b2bb692SLen Brown 
10103b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
10110f47c08dSLen Brown 		if (DO_BIC(BIC_Pkgpc3))
10123b4d5c7fSAndy Shevchenko 			outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
10130f47c08dSLen Brown 		if (DO_BIC(BIC_Pkgpc6))
10143b4d5c7fSAndy Shevchenko 			outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
10150f47c08dSLen Brown 		if (DO_BIC(BIC_Pkgpc7))
10163b4d5c7fSAndy Shevchenko 			outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
10173b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
10183b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
10193b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
1020be0e54c4SLen Brown 		outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
1021be0e54c4SLen Brown 		outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
10227c2ccc50SChen Yu 		outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg);
10237c2ccc50SChen Yu 		outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores);
10247c2ccc50SChen Yu 		outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx);
10257c2ccc50SChen Yu 		outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram);
10267c2ccc50SChen Yu 		outp += sprintf(outp, "Throttle PKG: %0llX\n",
10273b4d5c7fSAndy Shevchenko 			p->rapl_pkg_perf_status);
10287c2ccc50SChen Yu 		outp += sprintf(outp, "Throttle RAM: %0llX\n",
10293b4d5c7fSAndy Shevchenko 			p->rapl_dram_perf_status);
10303b4d5c7fSAndy Shevchenko 		outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
1031388e9c81SLen Brown 
1032388e9c81SLen Brown 		for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1033388e9c81SLen Brown 			outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n",
1034388e9c81SLen Brown 				i, mp->msr_num, p->counter[i]);
1035388e9c81SLen Brown 		}
1036c98d5d94SLen Brown 	}
10373b4d5c7fSAndy Shevchenko 
10383b4d5c7fSAndy Shevchenko 	outp += sprintf(outp, "\n");
10393b4d5c7fSAndy Shevchenko 
1040c98d5d94SLen Brown 	return 0;
1041103a8feaSLen Brown }
1042103a8feaSLen Brown 
1043e23da037SLen Brown /*
1044e23da037SLen Brown  * column formatting convention & formats
1045e23da037SLen Brown  */
1046c98d5d94SLen Brown int format_counters(struct thread_data *t, struct core_data *c,
1047c98d5d94SLen Brown 	struct pkg_data *p)
1048103a8feaSLen Brown {
1049008d396eSLen Brown 	double interval_float, tsc;
1050fc04cc67SLen Brown 	char *fmt8;
1051388e9c81SLen Brown 	int i;
1052388e9c81SLen Brown 	struct msr_counter *mp;
10536168c2e0SLen Brown 	char *delim = "\t";
10546168c2e0SLen Brown 	int printed = 0;
1055103a8feaSLen Brown 
1056c98d5d94SLen Brown 	 /* if showing only 1st thread in core and this isn't one, bail out */
1057c98d5d94SLen Brown 	if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1058c98d5d94SLen Brown 		return 0;
1059c98d5d94SLen Brown 
1060c98d5d94SLen Brown 	 /* if showing only 1st thread in pkg and this isn't one, bail out */
1061c98d5d94SLen Brown 	if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1062c98d5d94SLen Brown 		return 0;
1063c98d5d94SLen Brown 
10641ef7d21aSLen Brown 	/*if not summary line and --cpu is used */
10651ef7d21aSLen Brown 	if ((t != &average.threads) &&
10661ef7d21aSLen Brown 		(cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
10671ef7d21aSLen Brown 		return 0;
10681ef7d21aSLen Brown 
10693f44a5c6SLen Brown 	if (DO_BIC(BIC_USEC)) {
1070f4fdf2b4SLen Brown 		/* on each row, print how many usec each timestamp took to gather */
1071f4fdf2b4SLen Brown 		struct timeval tv;
1072f4fdf2b4SLen Brown 
1073f4fdf2b4SLen Brown 		timersub(&t->tv_end, &t->tv_begin, &tv);
1074f4fdf2b4SLen Brown 		outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec);
1075f4fdf2b4SLen Brown 	}
1076f4fdf2b4SLen Brown 
10773f44a5c6SLen Brown 	/* Time_Of_Day_Seconds: on each row, print sec.usec last timestamp taken */
10783f44a5c6SLen Brown 	if (DO_BIC(BIC_TOD))
10793f44a5c6SLen Brown 		outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
10803f44a5c6SLen Brown 
1081d4794f25SYazen Ghannam 	interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0;
1082103a8feaSLen Brown 
1083008d396eSLen Brown 	tsc = t->tsc * tsc_tweak;
1084008d396eSLen Brown 
1085c98d5d94SLen Brown 	/* topo columns, print blanks on 1st (average) line */
1086c98d5d94SLen Brown 	if (t == &average.threads) {
1087812db3f7SLen Brown 		if (DO_BIC(BIC_Package))
10886168c2e0SLen Brown 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10896de68fe1SLen Brown 		if (DO_BIC(BIC_Die))
10906de68fe1SLen Brown 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
109101235041SPrarit Bhargava 		if (DO_BIC(BIC_Node))
109201235041SPrarit Bhargava 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1093812db3f7SLen Brown 		if (DO_BIC(BIC_Core))
10946168c2e0SLen Brown 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1095812db3f7SLen Brown 		if (DO_BIC(BIC_CPU))
10966168c2e0SLen Brown 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10974c2122d4SLen Brown 		if (DO_BIC(BIC_APIC))
10984c2122d4SLen Brown 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10994c2122d4SLen Brown 		if (DO_BIC(BIC_X2APIC))
11004c2122d4SLen Brown 			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1101103a8feaSLen Brown 	} else {
1102812db3f7SLen Brown 		if (DO_BIC(BIC_Package)) {
1103c98d5d94SLen Brown 			if (p)
11046168c2e0SLen Brown 				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id);
1105c98d5d94SLen Brown 			else
11066168c2e0SLen Brown 				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1107c98d5d94SLen Brown 		}
11086de68fe1SLen Brown 		if (DO_BIC(BIC_Die)) {
11096de68fe1SLen Brown 			if (c)
11106de68fe1SLen Brown 				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].die_id);
11116de68fe1SLen Brown 			else
11126de68fe1SLen Brown 				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
11136de68fe1SLen Brown 		}
111401235041SPrarit Bhargava 		if (DO_BIC(BIC_Node)) {
111501235041SPrarit Bhargava 			if (t)
111601235041SPrarit Bhargava 				outp += sprintf(outp, "%s%d",
111701235041SPrarit Bhargava 						(printed++ ? delim : ""),
111801235041SPrarit Bhargava 					      cpus[t->cpu_id].physical_node_id);
111901235041SPrarit Bhargava 			else
112001235041SPrarit Bhargava 				outp += sprintf(outp, "%s-",
112101235041SPrarit Bhargava 						(printed++ ? delim : ""));
112201235041SPrarit Bhargava 		}
1123812db3f7SLen Brown 		if (DO_BIC(BIC_Core)) {
1124c98d5d94SLen Brown 			if (c)
11256168c2e0SLen Brown 				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id);
1126c98d5d94SLen Brown 			else
11276168c2e0SLen Brown 				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
1128c98d5d94SLen Brown 		}
1129812db3f7SLen Brown 		if (DO_BIC(BIC_CPU))
11306168c2e0SLen Brown 			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
11314c2122d4SLen Brown 		if (DO_BIC(BIC_APIC))
11324c2122d4SLen Brown 			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);
11334c2122d4SLen Brown 		if (DO_BIC(BIC_X2APIC))
11344c2122d4SLen Brown 			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);
1135103a8feaSLen Brown 	}
1136fc04cc67SLen Brown 
1137812db3f7SLen Brown 	if (DO_BIC(BIC_Avg_MHz))
11386168c2e0SLen Brown 		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
1139fc04cc67SLen Brown 			1.0 / units * t->aperf / interval_float);
1140fc04cc67SLen Brown 
1141812db3f7SLen Brown 	if (DO_BIC(BIC_Busy))
11426168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf/tsc);
1143103a8feaSLen Brown 
1144812db3f7SLen Brown 	if (DO_BIC(BIC_Bzy_MHz)) {
114521ed5574SLen Brown 		if (has_base_hz)
11466168c2e0SLen Brown 			outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
114721ed5574SLen Brown 		else
11486168c2e0SLen Brown 			outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
1149008d396eSLen Brown 				tsc / units * t->aperf / t->mperf / interval_float);
115021ed5574SLen Brown 	}
1151103a8feaSLen Brown 
1152812db3f7SLen Brown 	if (DO_BIC(BIC_TSC_MHz))
11536168c2e0SLen Brown 		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc/units/interval_float);
1154103a8feaSLen Brown 
11552af4f9b8SLen Brown 	if (DO_BIC(BIC_IPC))
11562af4f9b8SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 1.0 * t->instr_count / t->aperf);
11572af4f9b8SLen Brown 
1158562a2d37SLen Brown 	/* IRQ */
11590de6c0dfSLen Brown 	if (DO_BIC(BIC_IRQ)) {
11600de6c0dfSLen Brown 		if (sums_need_wide_columns)
11616168c2e0SLen Brown 			outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);
11620de6c0dfSLen Brown 		else
11636168c2e0SLen Brown 			outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);
11640de6c0dfSLen Brown 	}
1165562a2d37SLen Brown 
11661cc21f7bSLen Brown 	/* SMI */
1167812db3f7SLen Brown 	if (DO_BIC(BIC_SMI))
11686168c2e0SLen Brown 		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);
11691cc21f7bSLen Brown 
1170678a3bd1SLen Brown 	/* Added counters */
1171678a3bd1SLen Brown 	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1172678a3bd1SLen Brown 		if (mp->format == FORMAT_RAW) {
1173678a3bd1SLen Brown 			if (mp->width == 32)
11745f3aea57SLen Brown 				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) t->counter[i]);
1175678a3bd1SLen Brown 			else
11766168c2e0SLen Brown 				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
1177678a3bd1SLen Brown 		} else if (mp->format == FORMAT_DELTA) {
11780de6c0dfSLen Brown 			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
11796168c2e0SLen Brown 				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->counter[i]);
11800de6c0dfSLen Brown 			else
11816168c2e0SLen Brown 				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);
1182678a3bd1SLen Brown 		} else if (mp->format == FORMAT_PERCENT) {
118341618e63SLen Brown 			if (mp->type == COUNTER_USEC)
11846168c2e0SLen Brown 				outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), t->counter[i]/interval_float/10000);
118541618e63SLen Brown 			else
11866168c2e0SLen Brown 				outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i]/tsc);
1187678a3bd1SLen Brown 		}
1188678a3bd1SLen Brown 	}
1189678a3bd1SLen Brown 
119041618e63SLen Brown 	/* C1 */
119141618e63SLen Brown 	if (DO_BIC(BIC_CPU_c1))
11926168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1/tsc);
119341618e63SLen Brown 
119441618e63SLen Brown 
1195c98d5d94SLen Brown 	/* print per-core data only for 1st thread in core */
1196c98d5d94SLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1197c98d5d94SLen Brown 		goto done;
1198c98d5d94SLen Brown 
1199562855eeSLen Brown 	if (DO_BIC(BIC_CPU_c3))
12006168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3/tsc);
1201812db3f7SLen Brown 	if (DO_BIC(BIC_CPU_c6))
12026168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6/tsc);
1203812db3f7SLen Brown 	if (DO_BIC(BIC_CPU_c7))
12046168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7/tsc);
1205c98d5d94SLen Brown 
12060539ba11SLen Brown 	/* Mod%c6 */
12070539ba11SLen Brown 	if (DO_BIC(BIC_Mod_c6))
12086168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->mc6_us / tsc);
12090539ba11SLen Brown 
1210812db3f7SLen Brown 	if (DO_BIC(BIC_CoreTmp))
12116168c2e0SLen Brown 		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
1212889facbeSLen Brown 
1213388e9c81SLen Brown 	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1214388e9c81SLen Brown 		if (mp->format == FORMAT_RAW) {
1215388e9c81SLen Brown 			if (mp->width == 32)
12165f3aea57SLen Brown 				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) c->counter[i]);
1217388e9c81SLen Brown 			else
12186168c2e0SLen Brown 				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
1219388e9c81SLen Brown 		} else if (mp->format == FORMAT_DELTA) {
12200de6c0dfSLen Brown 			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
12216168c2e0SLen Brown 				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->counter[i]);
12220de6c0dfSLen Brown 			else
12236168c2e0SLen Brown 				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);
1224388e9c81SLen Brown 		} else if (mp->format == FORMAT_PERCENT) {
12256168c2e0SLen Brown 			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i]/tsc);
1226388e9c81SLen Brown 		}
1227388e9c81SLen Brown 	}
1228388e9c81SLen Brown 
12299392bd98SCalvin Walton 	fmt8 = "%s%.2f";
12309392bd98SCalvin Walton 
12319392bd98SCalvin Walton 	if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
12329392bd98SCalvin Walton 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
12339392bd98SCalvin Walton 	if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY))
12349392bd98SCalvin Walton 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units);
12359392bd98SCalvin Walton 
1236c98d5d94SLen Brown 	/* print per-package data only for 1st core in package */
1237c98d5d94SLen Brown 	if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1238c98d5d94SLen Brown 		goto done;
1239c98d5d94SLen Brown 
12400b2bb692SLen Brown 	/* PkgTmp */
1241812db3f7SLen Brown 	if (DO_BIC(BIC_PkgTmp))
12426168c2e0SLen Brown 		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);
1243889facbeSLen Brown 
1244fdf676e5SLen Brown 	/* GFXrc6 */
1245812db3f7SLen Brown 	if (DO_BIC(BIC_GFX_rc6)) {
1246ba3dec99SLen Brown 		if (p->gfx_rc6_ms == -1) {	/* detect GFX counter reset */
12476168c2e0SLen Brown 			outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
12489185e988SLen Brown 		} else {
12496168c2e0SLen Brown 			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
12509185e988SLen Brown 				p->gfx_rc6_ms / 10.0 / interval_float);
12519185e988SLen Brown 		}
12529185e988SLen Brown 	}
1253fdf676e5SLen Brown 
125427d47356SLen Brown 	/* GFXMHz */
1255812db3f7SLen Brown 	if (DO_BIC(BIC_GFXMHz))
12566168c2e0SLen Brown 		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
125727d47356SLen Brown 
1258b4b91569SRafael Antognolli 	/* GFXACTMHz */
1259b4b91569SRafael Antognolli 	if (DO_BIC(BIC_GFXACTMHz))
1260b4b91569SRafael Antognolli 		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);
1261b4b91569SRafael Antognolli 
12620b2bb692SLen Brown 	/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
1263a99d8730SLen Brown 	if (DO_BIC(BIC_Totl_c0))
12646168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
1265a99d8730SLen Brown 	if (DO_BIC(BIC_Any_c0))
12666168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc);
1267a99d8730SLen Brown 	if (DO_BIC(BIC_GFX_c0))
12686168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc);
1269a99d8730SLen Brown 	if (DO_BIC(BIC_CPUGFX))
12706168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc);
12710b2bb692SLen Brown 
12720f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc2))
12736168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc);
12740f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
12756168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3/tsc);
12760f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6))
12776168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6/tsc);
12780f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
12796168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7/tsc);
12800f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc8))
12816168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8/tsc);
12820f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc9))
12836168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9/tsc);
12840f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc10))
12856168c2e0SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10/tsc);
1286889facbeSLen Brown 
1287be0e54c4SLen Brown 	if (DO_BIC(BIC_CPU_LPI))
1288be0e54c4SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
1289be0e54c4SLen Brown 	if (DO_BIC(BIC_SYS_LPI))
1290be0e54c4SLen Brown 		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float);
1291be0e54c4SLen Brown 
1292812db3f7SLen Brown 	if (DO_BIC(BIC_PkgWatt))
12936168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
12949392bd98SCalvin Walton 	if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY))
12956168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
1296812db3f7SLen Brown 	if (DO_BIC(BIC_GFXWatt))
12976168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
1298812db3f7SLen Brown 	if (DO_BIC(BIC_RAMWatt))
12996168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units / interval_float);
1300812db3f7SLen Brown 	if (DO_BIC(BIC_Pkg_J))
13016168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units);
13029392bd98SCalvin Walton 	if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY))
13036168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units);
1304812db3f7SLen Brown 	if (DO_BIC(BIC_GFX_J))
13056168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units);
1306812db3f7SLen Brown 	if (DO_BIC(BIC_RAM_J))
13076168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units);
1308812db3f7SLen Brown 	if (DO_BIC(BIC_PKG__))
13096168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
1310812db3f7SLen Brown 	if (DO_BIC(BIC_RAM__))
13116168c2e0SLen Brown 		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
1312812db3f7SLen Brown 
1313388e9c81SLen Brown 	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1314388e9c81SLen Brown 		if (mp->format == FORMAT_RAW) {
1315388e9c81SLen Brown 			if (mp->width == 32)
13165f3aea57SLen Brown 				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) p->counter[i]);
1317388e9c81SLen Brown 			else
13186168c2e0SLen Brown 				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
1319388e9c81SLen Brown 		} else if (mp->format == FORMAT_DELTA) {
13200de6c0dfSLen Brown 			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
13216168c2e0SLen Brown 				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->counter[i]);
13220de6c0dfSLen Brown 			else
13236168c2e0SLen Brown 				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);
1324388e9c81SLen Brown 		} else if (mp->format == FORMAT_PERCENT) {
13256168c2e0SLen Brown 			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i]/tsc);
1326388e9c81SLen Brown 		}
1327388e9c81SLen Brown 	}
1328388e9c81SLen Brown 
1329c98d5d94SLen Brown done:
133094d6ab4bSLen Brown 	if (*(outp - 1) != '\n')
1331c98d5d94SLen Brown 		outp += sprintf(outp, "\n");
1332c98d5d94SLen Brown 
1333c98d5d94SLen Brown 	return 0;
1334103a8feaSLen Brown }
1335103a8feaSLen Brown 
1336b7d8c148SLen Brown void flush_output_stdout(void)
1337103a8feaSLen Brown {
1338b7d8c148SLen Brown 	FILE *filep;
1339b7d8c148SLen Brown 
1340b7d8c148SLen Brown 	if (outf == stderr)
1341b7d8c148SLen Brown 		filep = stdout;
1342b7d8c148SLen Brown 	else
1343b7d8c148SLen Brown 		filep = outf;
1344b7d8c148SLen Brown 
1345b7d8c148SLen Brown 	fputs(output_buffer, filep);
1346b7d8c148SLen Brown 	fflush(filep);
1347b7d8c148SLen Brown 
1348c98d5d94SLen Brown 	outp = output_buffer;
1349c98d5d94SLen Brown }
1350b7d8c148SLen Brown void flush_output_stderr(void)
1351c98d5d94SLen Brown {
1352b7d8c148SLen Brown 	fputs(output_buffer, outf);
1353b7d8c148SLen Brown 	fflush(outf);
1354c98d5d94SLen Brown 	outp = output_buffer;
1355c98d5d94SLen Brown }
1356c98d5d94SLen Brown void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1357c98d5d94SLen Brown {
1358e23da037SLen Brown 	static int printed;
1359103a8feaSLen Brown 
1360e23da037SLen Brown 	if (!printed || !summary_only)
1361c8ade361SLen Brown 		print_header("\t");
1362103a8feaSLen Brown 
13639d83601aSLen Brown 	format_counters(&average.threads, &average.cores, &average.packages);
1364103a8feaSLen Brown 
1365e23da037SLen Brown 	printed = 1;
1366e23da037SLen Brown 
1367e23da037SLen Brown 	if (summary_only)
1368e23da037SLen Brown 		return;
1369e23da037SLen Brown 
1370c98d5d94SLen Brown 	for_all_cpus(format_counters, t, c, p);
1371103a8feaSLen Brown }
1372103a8feaSLen Brown 
1373889facbeSLen Brown #define DELTA_WRAP32(new, old)			\
13747c2ccc50SChen Yu 	old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);
1375889facbeSLen Brown 
1376ba3dec99SLen Brown int
1377c98d5d94SLen Brown delta_package(struct pkg_data *new, struct pkg_data *old)
1378103a8feaSLen Brown {
1379388e9c81SLen Brown 	int i;
1380388e9c81SLen Brown 	struct msr_counter *mp;
13810b2bb692SLen Brown 
1382a99d8730SLen Brown 
1383a99d8730SLen Brown 	if (DO_BIC(BIC_Totl_c0))
13840b2bb692SLen Brown 		old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;
1385a99d8730SLen Brown 	if (DO_BIC(BIC_Any_c0))
13860b2bb692SLen Brown 		old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;
1387a99d8730SLen Brown 	if (DO_BIC(BIC_GFX_c0))
13880b2bb692SLen Brown 		old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;
1389a99d8730SLen Brown 	if (DO_BIC(BIC_CPUGFX))
13900b2bb692SLen Brown 		old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
1391a99d8730SLen Brown 
1392c98d5d94SLen Brown 	old->pc2 = new->pc2 - old->pc2;
13930f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
1394c98d5d94SLen Brown 		old->pc3 = new->pc3 - old->pc3;
13950f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6))
1396c98d5d94SLen Brown 		old->pc6 = new->pc6 - old->pc6;
13970f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
1398c98d5d94SLen Brown 		old->pc7 = new->pc7 - old->pc7;
1399ca58710fSKristen Carlson Accardi 	old->pc8 = new->pc8 - old->pc8;
1400ca58710fSKristen Carlson Accardi 	old->pc9 = new->pc9 - old->pc9;
1401ca58710fSKristen Carlson Accardi 	old->pc10 = new->pc10 - old->pc10;
1402be0e54c4SLen Brown 	old->cpu_lpi = new->cpu_lpi - old->cpu_lpi;
1403be0e54c4SLen Brown 	old->sys_lpi = new->sys_lpi - old->sys_lpi;
1404889facbeSLen Brown 	old->pkg_temp_c = new->pkg_temp_c;
1405889facbeSLen Brown 
14069185e988SLen Brown 	/* flag an error when rc6 counter resets/wraps */
14079185e988SLen Brown 	if (old->gfx_rc6_ms >  new->gfx_rc6_ms)
14089185e988SLen Brown 		old->gfx_rc6_ms = -1;
14099185e988SLen Brown 	else
1410fdf676e5SLen Brown 		old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
14119185e988SLen Brown 
141227d47356SLen Brown 	old->gfx_mhz = new->gfx_mhz;
1413b4b91569SRafael Antognolli 	old->gfx_act_mhz = new->gfx_act_mhz;
141427d47356SLen Brown 
141587e15da9SChen Yu 	old->energy_pkg = new->energy_pkg - old->energy_pkg;
141687e15da9SChen Yu 	old->energy_cores = new->energy_cores - old->energy_cores;
141787e15da9SChen Yu 	old->energy_gfx = new->energy_gfx - old->energy_gfx;
141887e15da9SChen Yu 	old->energy_dram = new->energy_dram - old->energy_dram;
141987e15da9SChen Yu 	old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status;
142087e15da9SChen Yu 	old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status;
1421ba3dec99SLen Brown 
1422388e9c81SLen Brown 	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1423388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1424388e9c81SLen Brown 			old->counter[i] = new->counter[i];
1425388e9c81SLen Brown 		else
1426388e9c81SLen Brown 			old->counter[i] = new->counter[i] - old->counter[i];
1427388e9c81SLen Brown 	}
1428388e9c81SLen Brown 
1429ba3dec99SLen Brown 	return 0;
1430103a8feaSLen Brown }
1431103a8feaSLen Brown 
1432c98d5d94SLen Brown void
1433c98d5d94SLen Brown delta_core(struct core_data *new, struct core_data *old)
1434c98d5d94SLen Brown {
1435388e9c81SLen Brown 	int i;
1436388e9c81SLen Brown 	struct msr_counter *mp;
1437388e9c81SLen Brown 
1438c98d5d94SLen Brown 	old->c3 = new->c3 - old->c3;
1439c98d5d94SLen Brown 	old->c6 = new->c6 - old->c6;
1440c98d5d94SLen Brown 	old->c7 = new->c7 - old->c7;
1441889facbeSLen Brown 	old->core_temp_c = new->core_temp_c;
14420539ba11SLen Brown 	old->mc6_us = new->mc6_us - old->mc6_us;
1443388e9c81SLen Brown 
14449392bd98SCalvin Walton 	DELTA_WRAP32(new->core_energy, old->core_energy);
14459392bd98SCalvin Walton 
1446388e9c81SLen Brown 	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1447388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1448388e9c81SLen Brown 			old->counter[i] = new->counter[i];
1449388e9c81SLen Brown 		else
1450388e9c81SLen Brown 			old->counter[i] = new->counter[i] - old->counter[i];
1451388e9c81SLen Brown 	}
1452103a8feaSLen Brown }
1453c98d5d94SLen Brown 
14541e9042b9SSrinivas Pandruvada int soft_c1_residency_display(int bic)
14551e9042b9SSrinivas Pandruvada {
14561e9042b9SSrinivas Pandruvada 	if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr)
14571e9042b9SSrinivas Pandruvada 		return 0;
14581e9042b9SSrinivas Pandruvada 
14591e9042b9SSrinivas Pandruvada 	return DO_BIC_READ(bic);
14601e9042b9SSrinivas Pandruvada }
14611e9042b9SSrinivas Pandruvada 
1462c3ae331dSLen Brown /*
1463c3ae331dSLen Brown  * old = new - old
1464c3ae331dSLen Brown  */
1465ba3dec99SLen Brown int
1466c98d5d94SLen Brown delta_thread(struct thread_data *new, struct thread_data *old,
1467c98d5d94SLen Brown 	struct core_data *core_delta)
1468c98d5d94SLen Brown {
1469388e9c81SLen Brown 	int i;
1470388e9c81SLen Brown 	struct msr_counter *mp;
1471388e9c81SLen Brown 
14724c2122d4SLen Brown 	/* we run cpuid just the 1st time, copy the results */
14734c2122d4SLen Brown 	if (DO_BIC(BIC_APIC))
14744c2122d4SLen Brown 		new->apic_id = old->apic_id;
14754c2122d4SLen Brown 	if (DO_BIC(BIC_X2APIC))
14764c2122d4SLen Brown 		new->x2apic_id = old->x2apic_id;
14774c2122d4SLen Brown 
14783f44a5c6SLen Brown 	/*
14793f44a5c6SLen Brown 	 * the timestamps from start of measurement interval are in "old"
14803f44a5c6SLen Brown 	 * the timestamp from end of measurement interval are in "new"
14813f44a5c6SLen Brown 	 * over-write old w/ new so we can print end of interval values
14823f44a5c6SLen Brown 	 */
14833f44a5c6SLen Brown 
1484d4794f25SYazen Ghannam 	timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
14853f44a5c6SLen Brown 	old->tv_begin = new->tv_begin;
14863f44a5c6SLen Brown 	old->tv_end = new->tv_end;
14873f44a5c6SLen Brown 
1488c98d5d94SLen Brown 	old->tsc = new->tsc - old->tsc;
1489c98d5d94SLen Brown 
1490103a8feaSLen Brown 	/* check for TSC < 1 Mcycles over interval */
1491b2c95d90SJosh Triplett 	if (old->tsc < (1000 * 1000))
1492b2c95d90SJosh Triplett 		errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n"
1493b2c95d90SJosh Triplett 		     "You can disable all c-states by booting with \"idle=poll\"\n"
1494b2c95d90SJosh Triplett 		     "or just the deep ones with \"processor.max_cstate=1\"");
1495103a8feaSLen Brown 
1496c98d5d94SLen Brown 	old->c1 = new->c1 - old->c1;
1497c98d5d94SLen Brown 
14981e9042b9SSrinivas Pandruvada 	if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
14991e9042b9SSrinivas Pandruvada 	    soft_c1_residency_display(BIC_Avg_MHz)) {
1500c98d5d94SLen Brown 		if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
1501c98d5d94SLen Brown 			old->aperf = new->aperf - old->aperf;
1502c98d5d94SLen Brown 			old->mperf = new->mperf - old->mperf;
1503c98d5d94SLen Brown 		} else {
1504ba3dec99SLen Brown 			return -1;
1505103a8feaSLen Brown 		}
1506a729617cSLen Brown 	}
1507103a8feaSLen Brown 
1508c98d5d94SLen Brown 
1509144b44b1SLen Brown 	if (use_c1_residency_msr) {
1510144b44b1SLen Brown 		/*
1511144b44b1SLen Brown 		 * Some models have a dedicated C1 residency MSR,
1512144b44b1SLen Brown 		 * which should be more accurate than the derivation below.
1513144b44b1SLen Brown 		 */
1514144b44b1SLen Brown 	} else {
1515103a8feaSLen Brown 		/*
1516c3ae331dSLen Brown 		 * As counter collection is not atomic,
1517c3ae331dSLen Brown 		 * it is possible for mperf's non-halted cycles + idle states
1518103a8feaSLen Brown 		 * to exceed TSC's all cycles: show c1 = 0% in that case.
1519103a8feaSLen Brown 		 */
152095149369SLen Brown 		if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > (old->tsc * tsc_tweak))
1521c98d5d94SLen Brown 			old->c1 = 0;
1522c98d5d94SLen Brown 		else {
1523c98d5d94SLen Brown 			/* normal case, derive c1 */
1524008d396eSLen Brown 			old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3
1525c98d5d94SLen Brown 				- core_delta->c6 - core_delta->c7;
1526c98d5d94SLen Brown 		}
1527144b44b1SLen Brown 	}
1528c3ae331dSLen Brown 
1529c98d5d94SLen Brown 	if (old->mperf == 0) {
1530b7d8c148SLen Brown 		if (debug > 1)
1531b7d8c148SLen Brown 			fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);
1532c98d5d94SLen Brown 		old->mperf = 1;	/* divide by 0 protection */
1533c98d5d94SLen Brown 	}
1534103a8feaSLen Brown 
15352af4f9b8SLen Brown 	if (DO_BIC(BIC_IPC))
15362af4f9b8SLen Brown 		old->instr_count = new->instr_count - old->instr_count;
15372af4f9b8SLen Brown 
1538812db3f7SLen Brown 	if (DO_BIC(BIC_IRQ))
1539562a2d37SLen Brown 		old->irq_count = new->irq_count - old->irq_count;
1540562a2d37SLen Brown 
1541812db3f7SLen Brown 	if (DO_BIC(BIC_SMI))
15421ed51011SLen Brown 		old->smi_count = new->smi_count - old->smi_count;
1543ba3dec99SLen Brown 
1544388e9c81SLen Brown 	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1545388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1546388e9c81SLen Brown 			old->counter[i] = new->counter[i];
1547388e9c81SLen Brown 		else
1548388e9c81SLen Brown 			old->counter[i] = new->counter[i] - old->counter[i];
1549388e9c81SLen Brown 	}
1550ba3dec99SLen Brown 	return 0;
1551103a8feaSLen Brown }
1552c98d5d94SLen Brown 
1553c98d5d94SLen Brown int delta_cpu(struct thread_data *t, struct core_data *c,
1554c98d5d94SLen Brown 	struct pkg_data *p, struct thread_data *t2,
1555c98d5d94SLen Brown 	struct core_data *c2, struct pkg_data *p2)
1556c98d5d94SLen Brown {
1557ba3dec99SLen Brown 	int retval = 0;
1558ba3dec99SLen Brown 
1559c98d5d94SLen Brown 	/* calculate core delta only for 1st thread in core */
1560c98d5d94SLen Brown 	if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE)
1561c98d5d94SLen Brown 		delta_core(c, c2);
1562c98d5d94SLen Brown 
1563c98d5d94SLen Brown 	/* always calculate thread delta */
1564ba3dec99SLen Brown 	retval = delta_thread(t, t2, c2);	/* c2 is core delta */
1565ba3dec99SLen Brown 	if (retval)
1566ba3dec99SLen Brown 		return retval;
1567c98d5d94SLen Brown 
1568c98d5d94SLen Brown 	/* calculate package delta only for 1st core in package */
1569c98d5d94SLen Brown 	if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)
1570ba3dec99SLen Brown 		retval = delta_package(p, p2);
1571c98d5d94SLen Brown 
1572ba3dec99SLen Brown 	return retval;
1573103a8feaSLen Brown }
1574103a8feaSLen Brown 
1575c98d5d94SLen Brown void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1576103a8feaSLen Brown {
1577388e9c81SLen Brown 	int i;
1578388e9c81SLen Brown 	struct msr_counter  *mp;
1579388e9c81SLen Brown 
15803f44a5c6SLen Brown 	t->tv_begin.tv_sec = 0;
15813f44a5c6SLen Brown 	t->tv_begin.tv_usec = 0;
15823f44a5c6SLen Brown 	t->tv_end.tv_sec = 0;
15833f44a5c6SLen Brown 	t->tv_end.tv_usec = 0;
1584d4794f25SYazen Ghannam 	t->tv_delta.tv_sec = 0;
1585d4794f25SYazen Ghannam 	t->tv_delta.tv_usec = 0;
15863f44a5c6SLen Brown 
1587c98d5d94SLen Brown 	t->tsc = 0;
1588c98d5d94SLen Brown 	t->aperf = 0;
1589c98d5d94SLen Brown 	t->mperf = 0;
1590c98d5d94SLen Brown 	t->c1 = 0;
1591103a8feaSLen Brown 
15922af4f9b8SLen Brown 	t->instr_count = 0;
15932af4f9b8SLen Brown 
1594562a2d37SLen Brown 	t->irq_count = 0;
1595562a2d37SLen Brown 	t->smi_count = 0;
1596562a2d37SLen Brown 
1597c98d5d94SLen Brown 	/* tells format_counters to dump all fields from this set */
1598c98d5d94SLen Brown 	t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
1599c98d5d94SLen Brown 
1600c98d5d94SLen Brown 	c->c3 = 0;
1601c98d5d94SLen Brown 	c->c6 = 0;
1602c98d5d94SLen Brown 	c->c7 = 0;
16030539ba11SLen Brown 	c->mc6_us = 0;
1604889facbeSLen Brown 	c->core_temp_c = 0;
16059392bd98SCalvin Walton 	c->core_energy = 0;
1606c98d5d94SLen Brown 
16070b2bb692SLen Brown 	p->pkg_wtd_core_c0 = 0;
16080b2bb692SLen Brown 	p->pkg_any_core_c0 = 0;
16090b2bb692SLen Brown 	p->pkg_any_gfxe_c0 = 0;
16100b2bb692SLen Brown 	p->pkg_both_core_gfxe_c0 = 0;
16110b2bb692SLen Brown 
1612c98d5d94SLen Brown 	p->pc2 = 0;
16130f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
1614c98d5d94SLen Brown 		p->pc3 = 0;
16150f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6))
1616c98d5d94SLen Brown 		p->pc6 = 0;
16170f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
1618c98d5d94SLen Brown 		p->pc7 = 0;
1619ca58710fSKristen Carlson Accardi 	p->pc8 = 0;
1620ca58710fSKristen Carlson Accardi 	p->pc9 = 0;
1621ca58710fSKristen Carlson Accardi 	p->pc10 = 0;
1622be0e54c4SLen Brown 	p->cpu_lpi = 0;
1623be0e54c4SLen Brown 	p->sys_lpi = 0;
1624889facbeSLen Brown 
1625889facbeSLen Brown 	p->energy_pkg = 0;
1626889facbeSLen Brown 	p->energy_dram = 0;
1627889facbeSLen Brown 	p->energy_cores = 0;
1628889facbeSLen Brown 	p->energy_gfx = 0;
1629889facbeSLen Brown 	p->rapl_pkg_perf_status = 0;
1630889facbeSLen Brown 	p->rapl_dram_perf_status = 0;
1631889facbeSLen Brown 	p->pkg_temp_c = 0;
163227d47356SLen Brown 
1633fdf676e5SLen Brown 	p->gfx_rc6_ms = 0;
163427d47356SLen Brown 	p->gfx_mhz = 0;
1635b4b91569SRafael Antognolli 	p->gfx_act_mhz = 0;
1636388e9c81SLen Brown 	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
1637388e9c81SLen Brown 		t->counter[i] = 0;
1638388e9c81SLen Brown 
1639388e9c81SLen Brown 	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next)
1640388e9c81SLen Brown 		c->counter[i] = 0;
1641388e9c81SLen Brown 
1642388e9c81SLen Brown 	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next)
1643388e9c81SLen Brown 		p->counter[i] = 0;
1644103a8feaSLen Brown }
1645c98d5d94SLen Brown int sum_counters(struct thread_data *t, struct core_data *c,
1646c98d5d94SLen Brown 	struct pkg_data *p)
1647103a8feaSLen Brown {
1648388e9c81SLen Brown 	int i;
1649388e9c81SLen Brown 	struct msr_counter *mp;
1650388e9c81SLen Brown 
16514c2122d4SLen Brown 	/* copy un-changing apic_id's */
16524c2122d4SLen Brown 	if (DO_BIC(BIC_APIC))
16534c2122d4SLen Brown 		average.threads.apic_id = t->apic_id;
16544c2122d4SLen Brown 	if (DO_BIC(BIC_X2APIC))
16554c2122d4SLen Brown 		average.threads.x2apic_id = t->x2apic_id;
16564c2122d4SLen Brown 
16573f44a5c6SLen Brown 	/* remember first tv_begin */
16583f44a5c6SLen Brown 	if (average.threads.tv_begin.tv_sec == 0)
16593f44a5c6SLen Brown 		average.threads.tv_begin = t->tv_begin;
16603f44a5c6SLen Brown 
16613f44a5c6SLen Brown 	/* remember last tv_end */
16623f44a5c6SLen Brown 	average.threads.tv_end = t->tv_end;
16633f44a5c6SLen Brown 
1664c98d5d94SLen Brown 	average.threads.tsc += t->tsc;
1665c98d5d94SLen Brown 	average.threads.aperf += t->aperf;
1666c98d5d94SLen Brown 	average.threads.mperf += t->mperf;
1667c98d5d94SLen Brown 	average.threads.c1 += t->c1;
166815aaa346SLen Brown 
16692af4f9b8SLen Brown 	average.threads.instr_count += t->instr_count;
16702af4f9b8SLen Brown 
1671562a2d37SLen Brown 	average.threads.irq_count += t->irq_count;
1672562a2d37SLen Brown 	average.threads.smi_count += t->smi_count;
1673562a2d37SLen Brown 
1674388e9c81SLen Brown 	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1675388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1676388e9c81SLen Brown 			continue;
1677388e9c81SLen Brown 		average.threads.counter[i] += t->counter[i];
1678388e9c81SLen Brown 	}
1679388e9c81SLen Brown 
1680c98d5d94SLen Brown 	/* sum per-core values only for 1st thread in core */
1681c98d5d94SLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
1682c98d5d94SLen Brown 		return 0;
1683c98d5d94SLen Brown 
1684c98d5d94SLen Brown 	average.cores.c3 += c->c3;
1685c98d5d94SLen Brown 	average.cores.c6 += c->c6;
1686c98d5d94SLen Brown 	average.cores.c7 += c->c7;
16870539ba11SLen Brown 	average.cores.mc6_us += c->mc6_us;
1688c98d5d94SLen Brown 
1689889facbeSLen Brown 	average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);
1690889facbeSLen Brown 
16919392bd98SCalvin Walton 	average.cores.core_energy += c->core_energy;
16929392bd98SCalvin Walton 
1693388e9c81SLen Brown 	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1694388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1695388e9c81SLen Brown 			continue;
1696388e9c81SLen Brown 		average.cores.counter[i] += c->counter[i];
1697388e9c81SLen Brown 	}
1698388e9c81SLen Brown 
1699c98d5d94SLen Brown 	/* sum per-pkg values only for 1st core in pkg */
1700c98d5d94SLen Brown 	if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
1701c98d5d94SLen Brown 		return 0;
1702c98d5d94SLen Brown 
1703a99d8730SLen Brown 	if (DO_BIC(BIC_Totl_c0))
17040b2bb692SLen Brown 		average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0;
1705a99d8730SLen Brown 	if (DO_BIC(BIC_Any_c0))
17060b2bb692SLen Brown 		average.packages.pkg_any_core_c0 += p->pkg_any_core_c0;
1707a99d8730SLen Brown 	if (DO_BIC(BIC_GFX_c0))
17080b2bb692SLen Brown 		average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;
1709a99d8730SLen Brown 	if (DO_BIC(BIC_CPUGFX))
17100b2bb692SLen Brown 		average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;
17110b2bb692SLen Brown 
1712c98d5d94SLen Brown 	average.packages.pc2 += p->pc2;
17130f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
1714c98d5d94SLen Brown 		average.packages.pc3 += p->pc3;
17150f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6))
1716c98d5d94SLen Brown 		average.packages.pc6 += p->pc6;
17170f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
1718c98d5d94SLen Brown 		average.packages.pc7 += p->pc7;
1719ca58710fSKristen Carlson Accardi 	average.packages.pc8 += p->pc8;
1720ca58710fSKristen Carlson Accardi 	average.packages.pc9 += p->pc9;
1721ca58710fSKristen Carlson Accardi 	average.packages.pc10 += p->pc10;
1722c98d5d94SLen Brown 
1723be0e54c4SLen Brown 	average.packages.cpu_lpi = p->cpu_lpi;
1724be0e54c4SLen Brown 	average.packages.sys_lpi = p->sys_lpi;
1725be0e54c4SLen Brown 
1726889facbeSLen Brown 	average.packages.energy_pkg += p->energy_pkg;
1727889facbeSLen Brown 	average.packages.energy_dram += p->energy_dram;
1728889facbeSLen Brown 	average.packages.energy_cores += p->energy_cores;
1729889facbeSLen Brown 	average.packages.energy_gfx += p->energy_gfx;
1730889facbeSLen Brown 
1731fdf676e5SLen Brown 	average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
173227d47356SLen Brown 	average.packages.gfx_mhz = p->gfx_mhz;
1733b4b91569SRafael Antognolli 	average.packages.gfx_act_mhz = p->gfx_act_mhz;
173427d47356SLen Brown 
1735889facbeSLen Brown 	average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
1736889facbeSLen Brown 
1737889facbeSLen Brown 	average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status;
1738889facbeSLen Brown 	average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status;
1739388e9c81SLen Brown 
1740388e9c81SLen Brown 	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1741388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1742388e9c81SLen Brown 			continue;
1743388e9c81SLen Brown 		average.packages.counter[i] += p->counter[i];
1744388e9c81SLen Brown 	}
1745c98d5d94SLen Brown 	return 0;
1746c98d5d94SLen Brown }
1747c98d5d94SLen Brown /*
1748c98d5d94SLen Brown  * sum the counters for all cpus in the system
1749c98d5d94SLen Brown  * compute the weighted average
1750c98d5d94SLen Brown  */
1751c98d5d94SLen Brown void compute_average(struct thread_data *t, struct core_data *c,
1752c98d5d94SLen Brown 	struct pkg_data *p)
1753c98d5d94SLen Brown {
1754388e9c81SLen Brown 	int i;
1755388e9c81SLen Brown 	struct msr_counter *mp;
1756388e9c81SLen Brown 
1757c98d5d94SLen Brown 	clear_counters(&average.threads, &average.cores, &average.packages);
1758c98d5d94SLen Brown 
1759c98d5d94SLen Brown 	for_all_cpus(sum_counters, t, c, p);
1760c98d5d94SLen Brown 
1761d4794f25SYazen Ghannam 	/* Use the global time delta for the average. */
1762d4794f25SYazen Ghannam 	average.threads.tv_delta = tv_delta;
1763d4794f25SYazen Ghannam 
1764c98d5d94SLen Brown 	average.threads.tsc /= topo.num_cpus;
1765c98d5d94SLen Brown 	average.threads.aperf /= topo.num_cpus;
1766c98d5d94SLen Brown 	average.threads.mperf /= topo.num_cpus;
17672af4f9b8SLen Brown 	average.threads.instr_count /= topo.num_cpus;
1768c98d5d94SLen Brown 	average.threads.c1 /= topo.num_cpus;
1769c98d5d94SLen Brown 
17700de6c0dfSLen Brown 	if (average.threads.irq_count > 9999999)
17710de6c0dfSLen Brown 		sums_need_wide_columns = 1;
17720de6c0dfSLen Brown 
1773c98d5d94SLen Brown 	average.cores.c3 /= topo.num_cores;
1774c98d5d94SLen Brown 	average.cores.c6 /= topo.num_cores;
1775c98d5d94SLen Brown 	average.cores.c7 /= topo.num_cores;
17760539ba11SLen Brown 	average.cores.mc6_us /= topo.num_cores;
1777c98d5d94SLen Brown 
1778a99d8730SLen Brown 	if (DO_BIC(BIC_Totl_c0))
17790b2bb692SLen Brown 		average.packages.pkg_wtd_core_c0 /= topo.num_packages;
1780a99d8730SLen Brown 	if (DO_BIC(BIC_Any_c0))
17810b2bb692SLen Brown 		average.packages.pkg_any_core_c0 /= topo.num_packages;
1782a99d8730SLen Brown 	if (DO_BIC(BIC_GFX_c0))
17830b2bb692SLen Brown 		average.packages.pkg_any_gfxe_c0 /= topo.num_packages;
1784a99d8730SLen Brown 	if (DO_BIC(BIC_CPUGFX))
17850b2bb692SLen Brown 		average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages;
17860b2bb692SLen Brown 
1787c98d5d94SLen Brown 	average.packages.pc2 /= topo.num_packages;
17880f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
1789c98d5d94SLen Brown 		average.packages.pc3 /= topo.num_packages;
17900f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6))
1791c98d5d94SLen Brown 		average.packages.pc6 /= topo.num_packages;
17920f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
1793c98d5d94SLen Brown 		average.packages.pc7 /= topo.num_packages;
1794ca58710fSKristen Carlson Accardi 
1795ca58710fSKristen Carlson Accardi 	average.packages.pc8 /= topo.num_packages;
1796ca58710fSKristen Carlson Accardi 	average.packages.pc9 /= topo.num_packages;
1797ca58710fSKristen Carlson Accardi 	average.packages.pc10 /= topo.num_packages;
1798388e9c81SLen Brown 
1799388e9c81SLen Brown 	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
1800388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1801388e9c81SLen Brown 			continue;
18020de6c0dfSLen Brown 		if (mp->type == COUNTER_ITEMS) {
18030de6c0dfSLen Brown 			if (average.threads.counter[i] > 9999999)
18040de6c0dfSLen Brown 				sums_need_wide_columns = 1;
180541618e63SLen Brown 			continue;
18060de6c0dfSLen Brown 		}
1807388e9c81SLen Brown 		average.threads.counter[i] /= topo.num_cpus;
1808388e9c81SLen Brown 	}
1809388e9c81SLen Brown 	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
1810388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1811388e9c81SLen Brown 			continue;
18120de6c0dfSLen Brown 		if (mp->type == COUNTER_ITEMS) {
18130de6c0dfSLen Brown 			if (average.cores.counter[i] > 9999999)
18140de6c0dfSLen Brown 				sums_need_wide_columns = 1;
18150de6c0dfSLen Brown 		}
1816388e9c81SLen Brown 		average.cores.counter[i] /= topo.num_cores;
1817388e9c81SLen Brown 	}
1818388e9c81SLen Brown 	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
1819388e9c81SLen Brown 		if (mp->format == FORMAT_RAW)
1820388e9c81SLen Brown 			continue;
18210de6c0dfSLen Brown 		if (mp->type == COUNTER_ITEMS) {
18220de6c0dfSLen Brown 			if (average.packages.counter[i] > 9999999)
18230de6c0dfSLen Brown 				sums_need_wide_columns = 1;
18240de6c0dfSLen Brown 		}
1825388e9c81SLen Brown 		average.packages.counter[i] /= topo.num_packages;
1826388e9c81SLen Brown 	}
1827c98d5d94SLen Brown }
1828c98d5d94SLen Brown 
1829c98d5d94SLen Brown static unsigned long long rdtsc(void)
1830c98d5d94SLen Brown {
1831c98d5d94SLen Brown 	unsigned int low, high;
1832c98d5d94SLen Brown 
1833c98d5d94SLen Brown 	asm volatile("rdtsc" : "=a" (low), "=d" (high));
1834c98d5d94SLen Brown 
1835c98d5d94SLen Brown 	return low | ((unsigned long long)high) << 32;
1836c98d5d94SLen Brown }
1837c98d5d94SLen Brown 
1838c98d5d94SLen Brown /*
1839495c7654SLen Brown  * Open a file, and exit on failure
1840495c7654SLen Brown  */
1841495c7654SLen Brown FILE *fopen_or_die(const char *path, const char *mode)
1842495c7654SLen Brown {
1843495c7654SLen Brown 	FILE *filep = fopen(path, mode);
1844495c7654SLen Brown 
1845495c7654SLen Brown 	if (!filep)
1846495c7654SLen Brown 		err(1, "%s: open failed", path);
1847495c7654SLen Brown 	return filep;
1848495c7654SLen Brown }
1849495c7654SLen Brown /*
1850495c7654SLen Brown  * snapshot_sysfs_counter()
1851495c7654SLen Brown  *
1852495c7654SLen Brown  * return snapshot of given counter
1853495c7654SLen Brown  */
1854495c7654SLen Brown unsigned long long snapshot_sysfs_counter(char *path)
1855495c7654SLen Brown {
1856495c7654SLen Brown 	FILE *fp;
1857495c7654SLen Brown 	int retval;
1858495c7654SLen Brown 	unsigned long long counter;
1859495c7654SLen Brown 
1860495c7654SLen Brown 	fp = fopen_or_die(path, "r");
1861495c7654SLen Brown 
1862495c7654SLen Brown 	retval = fscanf(fp, "%lld", &counter);
1863495c7654SLen Brown 	if (retval != 1)
1864495c7654SLen Brown 		err(1, "snapshot_sysfs_counter(%s)", path);
1865495c7654SLen Brown 
1866495c7654SLen Brown 	fclose(fp);
1867495c7654SLen Brown 
1868495c7654SLen Brown 	return counter;
1869495c7654SLen Brown }
1870495c7654SLen Brown 
1871495c7654SLen Brown int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
1872495c7654SLen Brown {
1873495c7654SLen Brown 	if (mp->msr_num != 0) {
1874495c7654SLen Brown 		if (get_msr(cpu, mp->msr_num, counterp))
1875495c7654SLen Brown 			return -1;
1876495c7654SLen Brown 	} else {
187746c27978SLen Brown 		char path[128 + PATH_BYTES];
187841618e63SLen Brown 
187941618e63SLen Brown 		if (mp->flags & SYSFS_PERCPU) {
188041618e63SLen Brown 			sprintf(path, "/sys/devices/system/cpu/cpu%d/%s",
188141618e63SLen Brown 				 cpu, mp->path);
188241618e63SLen Brown 
188341618e63SLen Brown 			*counterp = snapshot_sysfs_counter(path);
188441618e63SLen Brown 		} else {
1885495c7654SLen Brown 			*counterp = snapshot_sysfs_counter(mp->path);
1886495c7654SLen Brown 		}
188741618e63SLen Brown 	}
1888495c7654SLen Brown 
1889495c7654SLen Brown 	return 0;
1890495c7654SLen Brown }
1891495c7654SLen Brown 
18926d6501d9SBorislav Petkov int get_epb(int cpu)
18936d6501d9SBorislav Petkov {
18946d6501d9SBorislav Petkov 	char path[128 + PATH_BYTES];
18957f1b11baSBorislav Petkov 	unsigned long long msr;
18966d6501d9SBorislav Petkov 	int ret, epb = -1;
18976d6501d9SBorislav Petkov 	FILE *fp;
18986d6501d9SBorislav Petkov 
18996d6501d9SBorislav Petkov 	sprintf(path, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", cpu);
19006d6501d9SBorislav Petkov 
19017f1b11baSBorislav Petkov 	fp = fopen(path, "r");
19027f1b11baSBorislav Petkov 	if (!fp)
19037f1b11baSBorislav Petkov 		goto msr_fallback;
19046d6501d9SBorislav Petkov 
19056d6501d9SBorislav Petkov 	ret = fscanf(fp, "%d", &epb);
19066d6501d9SBorislav Petkov 	if (ret != 1)
19076d6501d9SBorislav Petkov 		err(1, "%s(%s)", __func__, path);
19086d6501d9SBorislav Petkov 
19096d6501d9SBorislav Petkov 	fclose(fp);
19106d6501d9SBorislav Petkov 
19116d6501d9SBorislav Petkov 	return epb;
19127f1b11baSBorislav Petkov 
19137f1b11baSBorislav Petkov msr_fallback:
19147f1b11baSBorislav Petkov 	get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
19157f1b11baSBorislav Petkov 
19167f1b11baSBorislav Petkov 	return msr & 0xf;
19176d6501d9SBorislav Petkov }
19186d6501d9SBorislav Petkov 
19194c2122d4SLen Brown void get_apic_id(struct thread_data *t)
19204c2122d4SLen Brown {
192134041551SLen Brown 	unsigned int eax, ebx, ecx, edx;
192234041551SLen Brown 
192334041551SLen Brown 	if (DO_BIC(BIC_APIC)) {
192434041551SLen Brown 		eax = ebx = ecx = edx = 0;
192534041551SLen Brown 		__cpuid(1, eax, ebx, ecx, edx);
192634041551SLen Brown 
192734041551SLen Brown 		t->apic_id = (ebx >> 24) & 0xff;
192834041551SLen Brown 	}
192934041551SLen Brown 
193034041551SLen Brown 	if (!DO_BIC(BIC_X2APIC))
193134041551SLen Brown 		return;
193234041551SLen Brown 
1933c1c10cc7SPu Wen 	if (authentic_amd || hygon_genuine) {
193434041551SLen Brown 		unsigned int topology_extensions;
193534041551SLen Brown 
193634041551SLen Brown 		if (max_extended_level < 0x8000001e)
193734041551SLen Brown 			return;
19384c2122d4SLen Brown 
19394c2122d4SLen Brown 		eax = ebx = ecx = edx = 0;
194034041551SLen Brown 		__cpuid(0x80000001, eax, ebx, ecx, edx);
194134041551SLen Brown 			topology_extensions = ecx & (1 << 22);
194234041551SLen Brown 
194334041551SLen Brown 		if (topology_extensions == 0)
194434041551SLen Brown 			return;
194534041551SLen Brown 
194634041551SLen Brown 		eax = ebx = ecx = edx = 0;
194734041551SLen Brown 		__cpuid(0x8000001e, eax, ebx, ecx, edx);
194834041551SLen Brown 
194934041551SLen Brown 		t->x2apic_id = eax;
195034041551SLen Brown 		return;
195134041551SLen Brown 	}
19524c2122d4SLen Brown 
19534c2122d4SLen Brown 	if (!genuine_intel)
19544c2122d4SLen Brown 		return;
19554c2122d4SLen Brown 
19564c2122d4SLen Brown 	if (max_level < 0xb)
19574c2122d4SLen Brown 		return;
19584c2122d4SLen Brown 
19594c2122d4SLen Brown 	ecx = 0;
19604c2122d4SLen Brown 	__cpuid(0xb, eax, ebx, ecx, edx);
19614c2122d4SLen Brown 	t->x2apic_id = edx;
19624c2122d4SLen Brown 
196334041551SLen Brown 	if (debug && (t->apic_id != (t->x2apic_id & 0xff)))
196434041551SLen Brown 		fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n",
196534041551SLen Brown 				t->cpu_id, t->apic_id, t->x2apic_id);
19664c2122d4SLen Brown }
19674c2122d4SLen Brown 
1968495c7654SLen Brown /*
1969c98d5d94SLen Brown  * get_counters(...)
1970c98d5d94SLen Brown  * migrate to cpu
1971c98d5d94SLen Brown  * acquire and record local counters for that cpu
1972c98d5d94SLen Brown  */
1973c98d5d94SLen Brown int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1974c98d5d94SLen Brown {
1975c98d5d94SLen Brown 	int cpu = t->cpu_id;
1976889facbeSLen Brown 	unsigned long long msr;
19770102b067SLen Brown 	int aperf_mperf_retry_count = 0;
1978388e9c81SLen Brown 	struct msr_counter *mp;
1979388e9c81SLen Brown 	int i;
1980c98d5d94SLen Brown 
1981e52966c0SLen Brown 	if (cpu_migrate(cpu)) {
19823d7772eaSLen Brown 		fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu);
198315aaa346SLen Brown 		return -1;
1984e52966c0SLen Brown 	}
198515aaa346SLen Brown 
1986d4794f25SYazen Ghannam 	gettimeofday(&t->tv_begin, (struct timezone *)NULL);
1987d4794f25SYazen Ghannam 
19884c2122d4SLen Brown 	if (first_counter_read)
19894c2122d4SLen Brown 		get_apic_id(t);
19900102b067SLen Brown retry:
1991c98d5d94SLen Brown 	t->tsc = rdtsc();	/* we are running on local CPU of interest */
199215aaa346SLen Brown 
19931e9042b9SSrinivas Pandruvada 	if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
19941e9042b9SSrinivas Pandruvada 	    soft_c1_residency_display(BIC_Avg_MHz)) {
19950102b067SLen Brown 		unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
19960102b067SLen Brown 
19970102b067SLen Brown 		/*
19980102b067SLen Brown 		 * The TSC, APERF and MPERF must be read together for
19990102b067SLen Brown 		 * APERF/MPERF and MPERF/TSC to give accurate results.
20000102b067SLen Brown 		 *
20010102b067SLen Brown 		 * Unfortunately, APERF and MPERF are read by
20020102b067SLen Brown 		 * individual system call, so delays may occur
20030102b067SLen Brown 		 * between them.  If the time to read them
20040102b067SLen Brown 		 * varies by a large amount, we re-read them.
20050102b067SLen Brown 		 */
20060102b067SLen Brown 
20070102b067SLen Brown 		/*
20080102b067SLen Brown 		 * This initial dummy APERF read has been seen to
20090102b067SLen Brown 		 * reduce jitter in the subsequent reads.
20100102b067SLen Brown 		 */
20110102b067SLen Brown 
20129c63a650SLen Brown 		if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
2013c98d5d94SLen Brown 			return -3;
20140102b067SLen Brown 
20150102b067SLen Brown 		t->tsc = rdtsc();	/* re-read close to APERF */
20160102b067SLen Brown 
20170102b067SLen Brown 		tsc_before = t->tsc;
20180102b067SLen Brown 
20190102b067SLen Brown 		if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
20200102b067SLen Brown 			return -3;
20210102b067SLen Brown 
20220102b067SLen Brown 		tsc_between = rdtsc();
20230102b067SLen Brown 
20249c63a650SLen Brown 		if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf))
2025c98d5d94SLen Brown 			return -4;
20260102b067SLen Brown 
20270102b067SLen Brown 		tsc_after = rdtsc();
20280102b067SLen Brown 
20290102b067SLen Brown 		aperf_time = tsc_between - tsc_before;
20300102b067SLen Brown 		mperf_time = tsc_after - tsc_between;
20310102b067SLen Brown 
20320102b067SLen Brown 		/*
20330102b067SLen Brown 		 * If the system call latency to read APERF and MPERF
20340102b067SLen Brown 		 * differ by more than 2x, then try again.
20350102b067SLen Brown 		 */
20360102b067SLen Brown 		if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) {
20370102b067SLen Brown 			aperf_mperf_retry_count++;
20380102b067SLen Brown 			if (aperf_mperf_retry_count < 5)
20390102b067SLen Brown 				goto retry;
20400102b067SLen Brown 			else
20410102b067SLen Brown 				warnx("cpu%d jitter %lld %lld",
20420102b067SLen Brown 					cpu, aperf_time, mperf_time);
20430102b067SLen Brown 		}
20440102b067SLen Brown 		aperf_mperf_retry_count = 0;
20450102b067SLen Brown 
2046b2b34dfeSHubert Chrzaniuk 		t->aperf = t->aperf * aperf_mperf_multiplier;
2047b2b34dfeSHubert Chrzaniuk 		t->mperf = t->mperf * aperf_mperf_multiplier;
204888c3281fSLen Brown 	}
204988c3281fSLen Brown 
20502af4f9b8SLen Brown 	if (DO_BIC(BIC_IPC))
20512af4f9b8SLen Brown 		if (read(get_instr_count_fd(cpu), &t->instr_count, sizeof(long long)) != sizeof(long long))
20522af4f9b8SLen Brown 			return -4;
20532af4f9b8SLen Brown 
2054812db3f7SLen Brown 	if (DO_BIC(BIC_IRQ))
2055562a2d37SLen Brown 		t->irq_count = irqs_per_cpu[cpu];
2056812db3f7SLen Brown 	if (DO_BIC(BIC_SMI)) {
20571ed51011SLen Brown 		if (get_msr(cpu, MSR_SMI_COUNT, &msr))
20581ed51011SLen Brown 			return -5;
20591ed51011SLen Brown 		t->smi_count = msr & 0xFFFFFFFF;
20601ed51011SLen Brown 	}
20610539ba11SLen Brown 	if (DO_BIC(BIC_CPU_c1) && use_c1_residency_msr) {
2062144b44b1SLen Brown 		if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
2063144b44b1SLen Brown 			return -6;
2064144b44b1SLen Brown 	}
2065144b44b1SLen Brown 
2066388e9c81SLen Brown 	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
2067495c7654SLen Brown 		if (get_mp(cpu, mp, &t->counter[i]))
2068388e9c81SLen Brown 			return -10;
2069388e9c81SLen Brown 	}
2070388e9c81SLen Brown 
2071c98d5d94SLen Brown 	/* collect core counters only for 1st thread in core */
2072c98d5d94SLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
2073f4fdf2b4SLen Brown 		goto done;
2074c98d5d94SLen Brown 
20751e9042b9SSrinivas Pandruvada 	if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) {
2076c98d5d94SLen Brown 		if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
2077c98d5d94SLen Brown 			return -6;
2078144b44b1SLen Brown 	}
2079144b44b1SLen Brown 
20801e9042b9SSrinivas Pandruvada 	if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) {
2081c98d5d94SLen Brown 		if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
2082c98d5d94SLen Brown 			return -7;
20831e9042b9SSrinivas Pandruvada 	} else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) {
2084fb5d4327SDasaratharaman Chandramouli 		if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
2085fb5d4327SDasaratharaman Chandramouli 			return -7;
2086103a8feaSLen Brown 	}
208715aaa346SLen Brown 
20881e9042b9SSrinivas Pandruvada 	if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7))
2089c98d5d94SLen Brown 		if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
2090c98d5d94SLen Brown 			return -8;
2091c98d5d94SLen Brown 
20920539ba11SLen Brown 	if (DO_BIC(BIC_Mod_c6))
20930539ba11SLen Brown 		if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))
20940539ba11SLen Brown 			return -8;
20950539ba11SLen Brown 
2096812db3f7SLen Brown 	if (DO_BIC(BIC_CoreTmp)) {
2097889facbeSLen Brown 		if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
2098889facbeSLen Brown 			return -9;
2099889facbeSLen Brown 		c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
2100889facbeSLen Brown 	}
2101889facbeSLen Brown 
21029392bd98SCalvin Walton 	if (do_rapl & RAPL_AMD_F17H) {
21039392bd98SCalvin Walton 		if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr))
21049392bd98SCalvin Walton 			return -14;
21059392bd98SCalvin Walton 		c->core_energy = msr & 0xFFFFFFFF;
21069392bd98SCalvin Walton 	}
21079392bd98SCalvin Walton 
2108388e9c81SLen Brown 	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
2109495c7654SLen Brown 		if (get_mp(cpu, mp, &c->counter[i]))
2110388e9c81SLen Brown 			return -10;
2111388e9c81SLen Brown 	}
2112889facbeSLen Brown 
2113c98d5d94SLen Brown 	/* collect package counters only for 1st core in package */
2114c98d5d94SLen Brown 	if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
2115f4fdf2b4SLen Brown 		goto done;
211615aaa346SLen Brown 
2117a99d8730SLen Brown 	if (DO_BIC(BIC_Totl_c0)) {
21180b2bb692SLen Brown 		if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))
21190b2bb692SLen Brown 			return -10;
2120a99d8730SLen Brown 	}
2121a99d8730SLen Brown 	if (DO_BIC(BIC_Any_c0)) {
21220b2bb692SLen Brown 		if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))
21230b2bb692SLen Brown 			return -11;
2124a99d8730SLen Brown 	}
2125a99d8730SLen Brown 	if (DO_BIC(BIC_GFX_c0)) {
21260b2bb692SLen Brown 		if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))
21270b2bb692SLen Brown 			return -12;
2128a99d8730SLen Brown 	}
2129a99d8730SLen Brown 	if (DO_BIC(BIC_CPUGFX)) {
21300b2bb692SLen Brown 		if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
21310b2bb692SLen Brown 			return -13;
21320b2bb692SLen Brown 	}
21330f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc3))
2134c98d5d94SLen Brown 		if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
2135c98d5d94SLen Brown 			return -9;
21360f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc6)) {
21370539ba11SLen Brown 		if (do_slm_cstates) {
21380539ba11SLen Brown 			if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6))
21390539ba11SLen Brown 				return -10;
21400539ba11SLen Brown 		} else {
2141c98d5d94SLen Brown 			if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
2142c98d5d94SLen Brown 				return -10;
21430539ba11SLen Brown 		}
21440539ba11SLen Brown 	}
21450539ba11SLen Brown 
21460f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc2))
2147c98d5d94SLen Brown 		if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
2148c98d5d94SLen Brown 			return -11;
21490f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc7))
2150c98d5d94SLen Brown 		if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
2151c98d5d94SLen Brown 			return -12;
21520f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc8))
2153ca58710fSKristen Carlson Accardi 		if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
2154ca58710fSKristen Carlson Accardi 			return -13;
21550f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc9))
2156ca58710fSKristen Carlson Accardi 		if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9))
2157ca58710fSKristen Carlson Accardi 			return -13;
21580f47c08dSLen Brown 	if (DO_BIC(BIC_Pkgpc10))
2159ca58710fSKristen Carlson Accardi 		if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10))
2160ca58710fSKristen Carlson Accardi 			return -13;
21610f47c08dSLen Brown 
2162be0e54c4SLen Brown 	if (DO_BIC(BIC_CPU_LPI))
2163be0e54c4SLen Brown 		p->cpu_lpi = cpuidle_cur_cpu_lpi_us;
2164be0e54c4SLen Brown 	if (DO_BIC(BIC_SYS_LPI))
2165be0e54c4SLen Brown 		p->sys_lpi = cpuidle_cur_sys_lpi_us;
2166be0e54c4SLen Brown 
2167889facbeSLen Brown 	if (do_rapl & RAPL_PKG) {
21689972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr))
2169889facbeSLen Brown 			return -13;
21709972d5d8SChen Yu 		p->energy_pkg = msr;
2171889facbeSLen Brown 	}
21729148494cSJacob Pan 	if (do_rapl & RAPL_CORES_ENERGY_STATUS) {
21739972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr))
2174889facbeSLen Brown 			return -14;
21759972d5d8SChen Yu 		p->energy_cores = msr;
2176889facbeSLen Brown 	}
2177889facbeSLen Brown 	if (do_rapl & RAPL_DRAM) {
21789972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
2179889facbeSLen Brown 			return -15;
21809972d5d8SChen Yu 		p->energy_dram = msr;
2181889facbeSLen Brown 	}
2182889facbeSLen Brown 	if (do_rapl & RAPL_GFX) {
21839972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr))
2184889facbeSLen Brown 			return -16;
21859972d5d8SChen Yu 		p->energy_gfx = msr;
2186889facbeSLen Brown 	}
2187889facbeSLen Brown 	if (do_rapl & RAPL_PKG_PERF_STATUS) {
21889972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr))
2189889facbeSLen Brown 			return -16;
21909972d5d8SChen Yu 		p->rapl_pkg_perf_status = msr;
2191889facbeSLen Brown 	}
2192889facbeSLen Brown 	if (do_rapl & RAPL_DRAM_PERF_STATUS) {
21939972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr))
2194889facbeSLen Brown 			return -16;
21959972d5d8SChen Yu 		p->rapl_dram_perf_status = msr;
2196889facbeSLen Brown 	}
21973316f99aSCalvin Walton 	if (do_rapl & RAPL_AMD_F17H) {
21989972d5d8SChen Yu 		if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr))
21993316f99aSCalvin Walton 			return -13;
22009972d5d8SChen Yu 		p->energy_pkg = msr;
22013316f99aSCalvin Walton 	}
2202812db3f7SLen Brown 	if (DO_BIC(BIC_PkgTmp)) {
2203889facbeSLen Brown 		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
2204889facbeSLen Brown 			return -17;
2205889facbeSLen Brown 		p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
2206889facbeSLen Brown 	}
2207fdf676e5SLen Brown 
2208812db3f7SLen Brown 	if (DO_BIC(BIC_GFX_rc6))
2209fdf676e5SLen Brown 		p->gfx_rc6_ms = gfx_cur_rc6_ms;
2210fdf676e5SLen Brown 
2211812db3f7SLen Brown 	if (DO_BIC(BIC_GFXMHz))
221227d47356SLen Brown 		p->gfx_mhz = gfx_cur_mhz;
221327d47356SLen Brown 
2214b4b91569SRafael Antognolli 	if (DO_BIC(BIC_GFXACTMHz))
2215b4b91569SRafael Antognolli 		p->gfx_act_mhz = gfx_act_mhz;
2216b4b91569SRafael Antognolli 
2217388e9c81SLen Brown 	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
2218495c7654SLen Brown 		if (get_mp(cpu, mp, &p->counter[i]))
2219388e9c81SLen Brown 			return -10;
2220388e9c81SLen Brown 	}
2221f4fdf2b4SLen Brown done:
2222f4fdf2b4SLen Brown 	gettimeofday(&t->tv_end, (struct timezone *)NULL);
2223388e9c81SLen Brown 
222415aaa346SLen Brown 	return 0;
2225103a8feaSLen Brown }
2226103a8feaSLen Brown 
2227ee7e38e3SLen Brown /*
2228ee7e38e3SLen Brown  * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:
2229ee7e38e3SLen Brown  * If you change the values, note they are used both in comparisons
2230ee7e38e3SLen Brown  * (>= PCL__7) and to index pkg_cstate_limit_strings[].
2231ee7e38e3SLen Brown  */
2232ee7e38e3SLen Brown 
2233ee7e38e3SLen Brown #define PCLUKN 0 /* Unknown */
2234ee7e38e3SLen Brown #define PCLRSV 1 /* Reserved */
2235ee7e38e3SLen Brown #define PCL__0 2 /* PC0 */
2236ee7e38e3SLen Brown #define PCL__1 3 /* PC1 */
2237ee7e38e3SLen Brown #define PCL__2 4 /* PC2 */
2238ee7e38e3SLen Brown #define PCL__3 5 /* PC3 */
2239ee7e38e3SLen Brown #define PCL__4 6 /* PC4 */
2240ee7e38e3SLen Brown #define PCL__6 7 /* PC6 */
2241ee7e38e3SLen Brown #define PCL_6N 8 /* PC6 No Retention */
2242ee7e38e3SLen Brown #define PCL_6R 9 /* PC6 Retention */
2243ee7e38e3SLen Brown #define PCL__7 10 /* PC7 */
2244ee7e38e3SLen Brown #define PCL_7S 11 /* PC7 Shrink */
22450b2bb692SLen Brown #define PCL__8 12 /* PC8 */
22460b2bb692SLen Brown #define PCL__9 13 /* PC9 */
2247445640a5SLen Brown #define PCL_10 14 /* PC10 */
2248445640a5SLen Brown #define PCLUNL 15 /* Unlimited */
2249ee7e38e3SLen Brown 
2250ee7e38e3SLen Brown int pkg_cstate_limit = PCLUKN;
2251ee7e38e3SLen Brown char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
2252445640a5SLen Brown 	"pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"};
2253ee7e38e3SLen Brown 
2254e9257f5fSLen Brown int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
2255e9257f5fSLen Brown int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
2256e9257f5fSLen Brown int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
22570539ba11SLen Brown int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
2258f2642888SLen Brown int amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
2259e9257f5fSLen Brown int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
2260445640a5SLen Brown int glm_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
22612085e124SArtem Bityutskiy int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
2262ee7e38e3SLen Brown 
2263a2b7b749SLen Brown 
2264a2b7b749SLen Brown static void
2265a2b7b749SLen Brown calculate_tsc_tweak()
2266a2b7b749SLen Brown {
2267a2b7b749SLen Brown 	tsc_tweak = base_hz / tsc_hz;
2268a2b7b749SLen Brown }
2269a2b7b749SLen Brown 
2270fcd17211SLen Brown static void
2271fcd17211SLen Brown dump_nhm_platform_info(void)
2272103a8feaSLen Brown {
2273103a8feaSLen Brown 	unsigned long long msr;
2274103a8feaSLen Brown 	unsigned int ratio;
2275103a8feaSLen Brown 
2276ec0adc53SLen Brown 	get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
2277103a8feaSLen Brown 
2278b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
22796574a5d5SLen Brown 
2280103a8feaSLen Brown 	ratio = (msr >> 40) & 0xFF;
2281710f273bSLen Brown 	fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n",
2282103a8feaSLen Brown 		ratio, bclk, ratio * bclk);
2283103a8feaSLen Brown 
2284103a8feaSLen Brown 	ratio = (msr >> 8) & 0xFF;
2285710f273bSLen Brown 	fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
2286103a8feaSLen Brown 		ratio, bclk, ratio * bclk);
2287103a8feaSLen Brown 
22887ce7d5deSPrarit Bhargava 	get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
2289b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
2290bfae2052SLen Brown 		base_cpu, msr, msr & 0x2 ? "EN" : "DIS");
229167920418SLen Brown 
2292fcd17211SLen Brown 	return;
2293fcd17211SLen Brown }
2294fcd17211SLen Brown 
2295fcd17211SLen Brown static void
2296fcd17211SLen Brown dump_hsw_turbo_ratio_limits(void)
2297fcd17211SLen Brown {
2298fcd17211SLen Brown 	unsigned long long msr;
2299fcd17211SLen Brown 	unsigned int ratio;
2300fcd17211SLen Brown 
23017ce7d5deSPrarit Bhargava 	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);
2302fcd17211SLen Brown 
2303b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);
2304fcd17211SLen Brown 
2305fcd17211SLen Brown 	ratio = (msr >> 8) & 0xFF;
2306fcd17211SLen Brown 	if (ratio)
2307710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n",
2308fcd17211SLen Brown 			ratio, bclk, ratio * bclk);
2309fcd17211SLen Brown 
2310fcd17211SLen Brown 	ratio = (msr >> 0) & 0xFF;
2311fcd17211SLen Brown 	if (ratio)
2312710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n",
2313fcd17211SLen Brown 			ratio, bclk, ratio * bclk);
2314fcd17211SLen Brown 	return;
2315fcd17211SLen Brown }
2316fcd17211SLen Brown 
2317fcd17211SLen Brown static void
2318fcd17211SLen Brown dump_ivt_turbo_ratio_limits(void)
2319fcd17211SLen Brown {
2320fcd17211SLen Brown 	unsigned long long msr;
2321fcd17211SLen Brown 	unsigned int ratio;
23226574a5d5SLen Brown 
23237ce7d5deSPrarit Bhargava 	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);
23246574a5d5SLen Brown 
2325b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);
23266574a5d5SLen Brown 
23276574a5d5SLen Brown 	ratio = (msr >> 56) & 0xFF;
23286574a5d5SLen Brown 	if (ratio)
2329710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n",
23306574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23316574a5d5SLen Brown 
23326574a5d5SLen Brown 	ratio = (msr >> 48) & 0xFF;
23336574a5d5SLen Brown 	if (ratio)
2334710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n",
23356574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23366574a5d5SLen Brown 
23376574a5d5SLen Brown 	ratio = (msr >> 40) & 0xFF;
23386574a5d5SLen Brown 	if (ratio)
2339710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n",
23406574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23416574a5d5SLen Brown 
23426574a5d5SLen Brown 	ratio = (msr >> 32) & 0xFF;
23436574a5d5SLen Brown 	if (ratio)
2344710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n",
23456574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23466574a5d5SLen Brown 
23476574a5d5SLen Brown 	ratio = (msr >> 24) & 0xFF;
23486574a5d5SLen Brown 	if (ratio)
2349710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n",
23506574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23516574a5d5SLen Brown 
23526574a5d5SLen Brown 	ratio = (msr >> 16) & 0xFF;
23536574a5d5SLen Brown 	if (ratio)
2354710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n",
23556574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23566574a5d5SLen Brown 
23576574a5d5SLen Brown 	ratio = (msr >> 8) & 0xFF;
23586574a5d5SLen Brown 	if (ratio)
2359710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n",
23606574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
23616574a5d5SLen Brown 
23626574a5d5SLen Brown 	ratio = (msr >> 0) & 0xFF;
23636574a5d5SLen Brown 	if (ratio)
2364710f273bSLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n",
23656574a5d5SLen Brown 			ratio, bclk, ratio * bclk);
2366103a8feaSLen Brown 	return;
2367fcd17211SLen Brown }
236831e07522SLen Brown int has_turbo_ratio_group_limits(int family, int model)
236931e07522SLen Brown {
237031e07522SLen Brown 
237131e07522SLen Brown 	if (!genuine_intel)
237231e07522SLen Brown 		return 0;
237331e07522SLen Brown 
237431e07522SLen Brown 	switch (model) {
237531e07522SLen Brown 	case INTEL_FAM6_ATOM_GOLDMONT:
237631e07522SLen Brown 	case INTEL_FAM6_SKYLAKE_X:
23775ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_D:
237820de0dabSAntti Laakso 	case INTEL_FAM6_ATOM_TREMONT_D:
237931e07522SLen Brown 		return 1;
238031e07522SLen Brown 	}
238131e07522SLen Brown 	return 0;
238231e07522SLen Brown }
2383fcd17211SLen Brown 
2384fcd17211SLen Brown static void
238531e07522SLen Brown dump_turbo_ratio_limits(int family, int model)
2386fcd17211SLen Brown {
238731e07522SLen Brown 	unsigned long long msr, core_counts;
238831e07522SLen Brown 	unsigned int ratio, group_size;
2389103a8feaSLen Brown 
23907ce7d5deSPrarit Bhargava 	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
2391b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
23926574a5d5SLen Brown 
239331e07522SLen Brown 	if (has_turbo_ratio_group_limits(family, model)) {
239431e07522SLen Brown 		get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
239531e07522SLen Brown 		fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts);
239631e07522SLen Brown 	} else {
239731e07522SLen Brown 		core_counts = 0x0807060504030201;
239831e07522SLen Brown 	}
239931e07522SLen Brown 
24006574a5d5SLen Brown 	ratio = (msr >> 56) & 0xFF;
240131e07522SLen Brown 	group_size = (core_counts >> 56) & 0xFF;
24026574a5d5SLen Brown 	if (ratio)
240331e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
240431e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
24056574a5d5SLen Brown 
24066574a5d5SLen Brown 	ratio = (msr >> 48) & 0xFF;
240731e07522SLen Brown 	group_size = (core_counts >> 48) & 0xFF;
24086574a5d5SLen Brown 	if (ratio)
240931e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
241031e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
24116574a5d5SLen Brown 
24126574a5d5SLen Brown 	ratio = (msr >> 40) & 0xFF;
241331e07522SLen Brown 	group_size = (core_counts >> 40) & 0xFF;
24146574a5d5SLen Brown 	if (ratio)
241531e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
241631e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
24176574a5d5SLen Brown 
24186574a5d5SLen Brown 	ratio = (msr >> 32) & 0xFF;
241931e07522SLen Brown 	group_size = (core_counts >> 32) & 0xFF;
24206574a5d5SLen Brown 	if (ratio)
242131e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
242231e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
24236574a5d5SLen Brown 
2424103a8feaSLen Brown 	ratio = (msr >> 24) & 0xFF;
242531e07522SLen Brown 	group_size = (core_counts >> 24) & 0xFF;
2426103a8feaSLen Brown 	if (ratio)
242731e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
242831e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
2429103a8feaSLen Brown 
2430103a8feaSLen Brown 	ratio = (msr >> 16) & 0xFF;
243131e07522SLen Brown 	group_size = (core_counts >> 16) & 0xFF;
2432103a8feaSLen Brown 	if (ratio)
243331e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
243431e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
2435103a8feaSLen Brown 
2436103a8feaSLen Brown 	ratio = (msr >> 8) & 0xFF;
243731e07522SLen Brown 	group_size = (core_counts >> 8) & 0xFF;
2438103a8feaSLen Brown 	if (ratio)
243931e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
244031e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
2441103a8feaSLen Brown 
2442103a8feaSLen Brown 	ratio = (msr >> 0) & 0xFF;
244331e07522SLen Brown 	group_size = (core_counts >> 0) & 0xFF;
2444103a8feaSLen Brown 	if (ratio)
244531e07522SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
244631e07522SLen Brown 			ratio, bclk, ratio * bclk, group_size);
2447fcd17211SLen Brown 	return;
2448fcd17211SLen Brown }
24493a9a941dSLen Brown 
2450fcd17211SLen Brown static void
24510f7887c4SLen Brown dump_atom_turbo_ratio_limits(void)
24520f7887c4SLen Brown {
24530f7887c4SLen Brown 	unsigned long long msr;
24540f7887c4SLen Brown 	unsigned int ratio;
24550f7887c4SLen Brown 
24560f7887c4SLen Brown 	get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);
24570f7887c4SLen Brown 	fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
24580f7887c4SLen Brown 
24590f7887c4SLen Brown 	ratio = (msr >> 0) & 0x3F;
24600f7887c4SLen Brown 	if (ratio)
24610f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n",
24620f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24630f7887c4SLen Brown 
24640f7887c4SLen Brown 	ratio = (msr >> 8) & 0x3F;
24650f7887c4SLen Brown 	if (ratio)
24660f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n",
24670f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24680f7887c4SLen Brown 
24690f7887c4SLen Brown 	ratio = (msr >> 16) & 0x3F;
24700f7887c4SLen Brown 	if (ratio)
24710f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
24720f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24730f7887c4SLen Brown 
24740f7887c4SLen Brown 	get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
24750f7887c4SLen Brown 	fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
24760f7887c4SLen Brown 
24770f7887c4SLen Brown 	ratio = (msr >> 24) & 0x3F;
24780f7887c4SLen Brown 	if (ratio)
24790f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
24800f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24810f7887c4SLen Brown 
24820f7887c4SLen Brown 	ratio = (msr >> 16) & 0x3F;
24830f7887c4SLen Brown 	if (ratio)
24840f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
24850f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24860f7887c4SLen Brown 
24870f7887c4SLen Brown 	ratio = (msr >> 8) & 0x3F;
24880f7887c4SLen Brown 	if (ratio)
24890f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
24900f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24910f7887c4SLen Brown 
24920f7887c4SLen Brown 	ratio = (msr >> 0) & 0x3F;
24930f7887c4SLen Brown 	if (ratio)
24940f7887c4SLen Brown 		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n",
24950f7887c4SLen Brown 			ratio, bclk, ratio * bclk);
24960f7887c4SLen Brown }
24970f7887c4SLen Brown 
24980f7887c4SLen Brown static void
2499fb5d4327SDasaratharaman Chandramouli dump_knl_turbo_ratio_limits(void)
2500fb5d4327SDasaratharaman Chandramouli {
2501cbf97abaSHubert Chrzaniuk 	const unsigned int buckets_no = 7;
2502cbf97abaSHubert Chrzaniuk 
2503fb5d4327SDasaratharaman Chandramouli 	unsigned long long msr;
2504cbf97abaSHubert Chrzaniuk 	int delta_cores, delta_ratio;
2505cbf97abaSHubert Chrzaniuk 	int i, b_nr;
2506cbf97abaSHubert Chrzaniuk 	unsigned int cores[buckets_no];
2507cbf97abaSHubert Chrzaniuk 	unsigned int ratio[buckets_no];
2508fb5d4327SDasaratharaman Chandramouli 
2509ebf5926aSSrinivas Pandruvada 	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
2510fb5d4327SDasaratharaman Chandramouli 
2511b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
2512bfae2052SLen Brown 		base_cpu, msr);
2513fb5d4327SDasaratharaman Chandramouli 
2514fb5d4327SDasaratharaman Chandramouli 	/**
2515fb5d4327SDasaratharaman Chandramouli 	 * Turbo encoding in KNL is as follows:
2516cbf97abaSHubert Chrzaniuk 	 * [0] -- Reserved
2517cbf97abaSHubert Chrzaniuk 	 * [7:1] -- Base value of number of active cores of bucket 1.
2518fb5d4327SDasaratharaman Chandramouli 	 * [15:8] -- Base value of freq ratio of bucket 1.
2519fb5d4327SDasaratharaman Chandramouli 	 * [20:16] -- +ve delta of number of active cores of bucket 2.
2520fb5d4327SDasaratharaman Chandramouli 	 * i.e. active cores of bucket 2 =
2521fb5d4327SDasaratharaman Chandramouli 	 * active cores of bucket 1 + delta
2522fb5d4327SDasaratharaman Chandramouli 	 * [23:21] -- Negative delta of freq ratio of bucket 2.
2523fb5d4327SDasaratharaman Chandramouli 	 * i.e. freq ratio of bucket 2 =
2524fb5d4327SDasaratharaman Chandramouli 	 * freq ratio of bucket 1 - delta
2525fb5d4327SDasaratharaman Chandramouli 	 * [28:24]-- +ve delta of number of active cores of bucket 3.
2526fb5d4327SDasaratharaman Chandramouli 	 * [31:29]-- -ve delta of freq ratio of bucket 3.
2527fb5d4327SDasaratharaman Chandramouli 	 * [36:32]-- +ve delta of number of active cores of bucket 4.
2528fb5d4327SDasaratharaman Chandramouli 	 * [39:37]-- -ve delta of freq ratio of bucket 4.
2529fb5d4327SDasaratharaman Chandramouli 	 * [44:40]-- +ve delta of number of active cores of bucket 5.
2530fb5d4327SDasaratharaman Chandramouli 	 * [47:45]-- -ve delta of freq ratio of bucket 5.
2531fb5d4327SDasaratharaman Chandramouli 	 * [52:48]-- +ve delta of number of active cores of bucket 6.
2532fb5d4327SDasaratharaman Chandramouli 	 * [55:53]-- -ve delta of freq ratio of bucket 6.
2533fb5d4327SDasaratharaman Chandramouli 	 * [60:56]-- +ve delta of number of active cores of bucket 7.
2534fb5d4327SDasaratharaman Chandramouli 	 * [63:61]-- -ve delta of freq ratio of bucket 7.
2535fb5d4327SDasaratharaman Chandramouli 	 */
2536fb5d4327SDasaratharaman Chandramouli 
2537cbf97abaSHubert Chrzaniuk 	b_nr = 0;
2538cbf97abaSHubert Chrzaniuk 	cores[b_nr] = (msr & 0xFF) >> 1;
2539cbf97abaSHubert Chrzaniuk 	ratio[b_nr] = (msr >> 8) & 0xFF;
2540cbf97abaSHubert Chrzaniuk 
2541cbf97abaSHubert Chrzaniuk 	for (i = 16; i < 64; i += 8) {
2542fb5d4327SDasaratharaman Chandramouli 		delta_cores = (msr >> i) & 0x1F;
2543cbf97abaSHubert Chrzaniuk 		delta_ratio = (msr >> (i + 5)) & 0x7;
2544fb5d4327SDasaratharaman Chandramouli 
2545cbf97abaSHubert Chrzaniuk 		cores[b_nr + 1] = cores[b_nr] + delta_cores;
2546cbf97abaSHubert Chrzaniuk 		ratio[b_nr + 1] = ratio[b_nr] - delta_ratio;
2547cbf97abaSHubert Chrzaniuk 		b_nr++;
2548fb5d4327SDasaratharaman Chandramouli 	}
2549cbf97abaSHubert Chrzaniuk 
2550cbf97abaSHubert Chrzaniuk 	for (i = buckets_no - 1; i >= 0; i--)
2551cbf97abaSHubert Chrzaniuk 		if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
2552b7d8c148SLen Brown 			fprintf(outf,
2553710f273bSLen Brown 				"%d * %.1f = %.1f MHz max turbo %d active cores\n",
2554cbf97abaSHubert Chrzaniuk 				ratio[i], bclk, ratio[i] * bclk, cores[i]);
2555fb5d4327SDasaratharaman Chandramouli }
2556fb5d4327SDasaratharaman Chandramouli 
2557fb5d4327SDasaratharaman Chandramouli static void
2558fcd17211SLen Brown dump_nhm_cst_cfg(void)
2559fcd17211SLen Brown {
2560fcd17211SLen Brown 	unsigned long long msr;
2561fcd17211SLen Brown 
25621df2e55aSLen Brown 	get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
2563fcd17211SLen Brown 
25641df2e55aSLen Brown 	fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr);
2565fcd17211SLen Brown 
25663e8b62bfSArtem Bityutskiy 	fprintf(outf, " (%s%s%s%s%slocked, pkg-cstate-limit=%d (%s)",
2567fcd17211SLen Brown 		(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
2568fcd17211SLen Brown 		(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
2569fcd17211SLen Brown 		(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
2570fcd17211SLen Brown 		(msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
2571fcd17211SLen Brown 		(msr & (1 << 15)) ? "" : "UN",
25726c34f160SLen Brown 		(unsigned int)msr & 0xF,
2573fcd17211SLen Brown 		pkg_cstate_limit_strings[pkg_cstate_limit]);
2574ac980e13SArtem Bityutskiy 
2575ac980e13SArtem Bityutskiy #define AUTOMATIC_CSTATE_CONVERSION		(1UL << 16)
2576ac980e13SArtem Bityutskiy 	if (has_automatic_cstate_conversion) {
2577ac980e13SArtem Bityutskiy 		fprintf(outf, ", automatic c-state conversion=%s",
2578ac980e13SArtem Bityutskiy 			(msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");
2579ac980e13SArtem Bityutskiy 	}
2580ac980e13SArtem Bityutskiy 
2581ac980e13SArtem Bityutskiy 	fprintf(outf, ")\n");
2582ac980e13SArtem Bityutskiy 
2583fcd17211SLen Brown 	return;
2584103a8feaSLen Brown }
2585103a8feaSLen Brown 
25866fb3143bSLen Brown static void
25876fb3143bSLen Brown dump_config_tdp(void)
25886fb3143bSLen Brown {
25896fb3143bSLen Brown 	unsigned long long msr;
25906fb3143bSLen Brown 
25916fb3143bSLen Brown 	get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);
2592b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
2593685b535bSChen Yu 	fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);
25946fb3143bSLen Brown 
25956fb3143bSLen Brown 	get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);
2596b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
25976fb3143bSLen Brown 	if (msr) {
2598685b535bSChen Yu 		fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
2599685b535bSChen Yu 		fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
2600685b535bSChen Yu 		fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
2601685b535bSChen Yu 		fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);
26026fb3143bSLen Brown 	}
2603b7d8c148SLen Brown 	fprintf(outf, ")\n");
26046fb3143bSLen Brown 
26056fb3143bSLen Brown 	get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);
2606b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
26076fb3143bSLen Brown 	if (msr) {
2608685b535bSChen Yu 		fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
2609685b535bSChen Yu 		fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
2610685b535bSChen Yu 		fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
2611685b535bSChen Yu 		fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);
26126fb3143bSLen Brown 	}
2613b7d8c148SLen Brown 	fprintf(outf, ")\n");
26146fb3143bSLen Brown 
26156fb3143bSLen Brown 	get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr);
2616b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);
26176fb3143bSLen Brown 	if ((msr) & 0x3)
2618b7d8c148SLen Brown 		fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);
2619b7d8c148SLen Brown 	fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
2620b7d8c148SLen Brown 	fprintf(outf, ")\n");
26216fb3143bSLen Brown 
26226fb3143bSLen Brown 	get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
2623b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
2624685b535bSChen Yu 	fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);
2625b7d8c148SLen Brown 	fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
2626b7d8c148SLen Brown 	fprintf(outf, ")\n");
26276fb3143bSLen Brown }
26285a63426eSLen Brown 
26295a63426eSLen Brown unsigned int irtl_time_units[] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
26305a63426eSLen Brown 
26315a63426eSLen Brown void print_irtl(void)
26325a63426eSLen Brown {
26335a63426eSLen Brown 	unsigned long long msr;
26345a63426eSLen Brown 
26355a63426eSLen Brown 	get_msr(base_cpu, MSR_PKGC3_IRTL, &msr);
26365a63426eSLen Brown 	fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr);
26375a63426eSLen Brown 	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
26385a63426eSLen Brown 		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
26395a63426eSLen Brown 
26405a63426eSLen Brown 	get_msr(base_cpu, MSR_PKGC6_IRTL, &msr);
26415a63426eSLen Brown 	fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr);
26425a63426eSLen Brown 	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
26435a63426eSLen Brown 		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
26445a63426eSLen Brown 
26455a63426eSLen Brown 	get_msr(base_cpu, MSR_PKGC7_IRTL, &msr);
26465a63426eSLen Brown 	fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr);
26475a63426eSLen Brown 	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
26485a63426eSLen Brown 		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
26495a63426eSLen Brown 
26505a63426eSLen Brown 	if (!do_irtl_hsw)
26515a63426eSLen Brown 		return;
26525a63426eSLen Brown 
26535a63426eSLen Brown 	get_msr(base_cpu, MSR_PKGC8_IRTL, &msr);
26545a63426eSLen Brown 	fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr);
26555a63426eSLen Brown 	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
26565a63426eSLen Brown 		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
26575a63426eSLen Brown 
26585a63426eSLen Brown 	get_msr(base_cpu, MSR_PKGC9_IRTL, &msr);
26595a63426eSLen Brown 	fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr);
26605a63426eSLen Brown 	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
26615a63426eSLen Brown 		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
26625a63426eSLen Brown 
26635a63426eSLen Brown 	get_msr(base_cpu, MSR_PKGC10_IRTL, &msr);
26645a63426eSLen Brown 	fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr);
26655a63426eSLen Brown 	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
26665a63426eSLen Brown 		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
26675a63426eSLen Brown 
26685a63426eSLen Brown }
266936229897SLen Brown void free_fd_percpu(void)
267036229897SLen Brown {
267136229897SLen Brown 	int i;
267236229897SLen Brown 
267301a67adfSMika Westerberg 	for (i = 0; i < topo.max_cpu_num + 1; ++i) {
267436229897SLen Brown 		if (fd_percpu[i] != 0)
267536229897SLen Brown 			close(fd_percpu[i]);
267636229897SLen Brown 	}
267736229897SLen Brown 
267836229897SLen Brown 	free(fd_percpu);
26796fb3143bSLen Brown }
26806fb3143bSLen Brown 
2681c98d5d94SLen Brown void free_all_buffers(void)
2682103a8feaSLen Brown {
26830e2d8f05SLen Brown 	int i;
26840e2d8f05SLen Brown 
2685c98d5d94SLen Brown 	CPU_FREE(cpu_present_set);
2686c98d5d94SLen Brown 	cpu_present_set = NULL;
268736229897SLen Brown 	cpu_present_setsize = 0;
2688103a8feaSLen Brown 
2689c98d5d94SLen Brown 	CPU_FREE(cpu_affinity_set);
2690c98d5d94SLen Brown 	cpu_affinity_set = NULL;
2691c98d5d94SLen Brown 	cpu_affinity_setsize = 0;
2692103a8feaSLen Brown 
2693c98d5d94SLen Brown 	free(thread_even);
2694c98d5d94SLen Brown 	free(core_even);
2695c98d5d94SLen Brown 	free(package_even);
2696103a8feaSLen Brown 
2697c98d5d94SLen Brown 	thread_even = NULL;
2698c98d5d94SLen Brown 	core_even = NULL;
2699c98d5d94SLen Brown 	package_even = NULL;
2700103a8feaSLen Brown 
2701c98d5d94SLen Brown 	free(thread_odd);
2702c98d5d94SLen Brown 	free(core_odd);
2703c98d5d94SLen Brown 	free(package_odd);
2704103a8feaSLen Brown 
2705c98d5d94SLen Brown 	thread_odd = NULL;
2706c98d5d94SLen Brown 	core_odd = NULL;
2707c98d5d94SLen Brown 	package_odd = NULL;
2708103a8feaSLen Brown 
2709c98d5d94SLen Brown 	free(output_buffer);
2710c98d5d94SLen Brown 	output_buffer = NULL;
2711c98d5d94SLen Brown 	outp = NULL;
271236229897SLen Brown 
271336229897SLen Brown 	free_fd_percpu();
2714562a2d37SLen Brown 
2715562a2d37SLen Brown 	free(irq_column_2_cpu);
2716562a2d37SLen Brown 	free(irqs_per_cpu);
27170e2d8f05SLen Brown 
27180e2d8f05SLen Brown 	for (i = 0; i <= topo.max_cpu_num; ++i) {
27190e2d8f05SLen Brown 		if (cpus[i].put_ids)
27200e2d8f05SLen Brown 			CPU_FREE(cpus[i].put_ids);
27210e2d8f05SLen Brown 	}
27220e2d8f05SLen Brown 	free(cpus);
2723103a8feaSLen Brown }
2724103a8feaSLen Brown 
272557a42a34SJosh Triplett 
272657a42a34SJosh Triplett /*
272795aebc44SJosh Triplett  * Parse a file containing a single int.
27286de68fe1SLen Brown  * Return 0 if file can not be opened
27296de68fe1SLen Brown  * Exit if file can be opened, but can not be parsed
273095aebc44SJosh Triplett  */
273195aebc44SJosh Triplett int parse_int_file(const char *fmt, ...)
273295aebc44SJosh Triplett {
273395aebc44SJosh Triplett 	va_list args;
273495aebc44SJosh Triplett 	char path[PATH_MAX];
273595aebc44SJosh Triplett 	FILE *filep;
273695aebc44SJosh Triplett 	int value;
273795aebc44SJosh Triplett 
273895aebc44SJosh Triplett 	va_start(args, fmt);
273995aebc44SJosh Triplett 	vsnprintf(path, sizeof(path), fmt, args);
274095aebc44SJosh Triplett 	va_end(args);
27416de68fe1SLen Brown 	filep = fopen(path, "r");
27426de68fe1SLen Brown 	if (!filep)
27436de68fe1SLen Brown 		return 0;
2744b2c95d90SJosh Triplett 	if (fscanf(filep, "%d", &value) != 1)
2745b2c95d90SJosh Triplett 		err(1, "%s: failed to parse number from file", path);
274695aebc44SJosh Triplett 	fclose(filep);
274795aebc44SJosh Triplett 	return value;
274895aebc44SJosh Triplett }
274995aebc44SJosh Triplett 
275095aebc44SJosh Triplett /*
2751c98d5d94SLen Brown  * cpu_is_first_core_in_package(cpu)
2752c98d5d94SLen Brown  * return 1 if given CPU is 1st core in package
2753c98d5d94SLen Brown  */
2754c98d5d94SLen Brown int cpu_is_first_core_in_package(int cpu)
2755c98d5d94SLen Brown {
275695aebc44SJosh Triplett 	return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu);
2757103a8feaSLen Brown }
2758103a8feaSLen Brown 
2759103a8feaSLen Brown int get_physical_package_id(int cpu)
2760103a8feaSLen Brown {
276195aebc44SJosh Triplett 	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
2762103a8feaSLen Brown }
2763103a8feaSLen Brown 
27646de68fe1SLen Brown int get_die_id(int cpu)
27656de68fe1SLen Brown {
27666de68fe1SLen Brown 	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/die_id", cpu);
27676de68fe1SLen Brown }
27686de68fe1SLen Brown 
2769103a8feaSLen Brown int get_core_id(int cpu)
2770103a8feaSLen Brown {
277195aebc44SJosh Triplett 	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
2772103a8feaSLen Brown }
2773103a8feaSLen Brown 
2774ef605741SPrarit Bhargava void set_node_data(void)
2775ef605741SPrarit Bhargava {
27762ffbb224SPrarit Bhargava 	int pkg, node, lnode, cpu, cpux;
27772ffbb224SPrarit Bhargava 	int cpu_count;
2778ef605741SPrarit Bhargava 
27792ffbb224SPrarit Bhargava 	/* initialize logical_node_id */
27802ffbb224SPrarit Bhargava 	for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu)
27812ffbb224SPrarit Bhargava 		cpus[cpu].logical_node_id = -1;
2782ef605741SPrarit Bhargava 
27832ffbb224SPrarit Bhargava 	cpu_count = 0;
27842ffbb224SPrarit Bhargava 	for (pkg = 0; pkg < topo.num_packages; pkg++) {
27852ffbb224SPrarit Bhargava 		lnode = 0;
27862ffbb224SPrarit Bhargava 		for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {
27872ffbb224SPrarit Bhargava 			if (cpus[cpu].physical_package_id != pkg)
2788ef605741SPrarit Bhargava 				continue;
27892ffbb224SPrarit Bhargava 			/* find a cpu with an unset logical_node_id */
27902ffbb224SPrarit Bhargava 			if (cpus[cpu].logical_node_id != -1)
27912ffbb224SPrarit Bhargava 				continue;
27922ffbb224SPrarit Bhargava 			cpus[cpu].logical_node_id = lnode;
2793ef605741SPrarit Bhargava 			node = cpus[cpu].physical_node_id;
27942ffbb224SPrarit Bhargava 			cpu_count++;
27952ffbb224SPrarit Bhargava 			/*
27962ffbb224SPrarit Bhargava 			 * find all matching cpus on this pkg and set
27972ffbb224SPrarit Bhargava 			 * the logical_node_id
27982ffbb224SPrarit Bhargava 			 */
27992ffbb224SPrarit Bhargava 			for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) {
28002ffbb224SPrarit Bhargava 				if ((cpus[cpux].physical_package_id == pkg) &&
28012ffbb224SPrarit Bhargava 				   (cpus[cpux].physical_node_id == node)) {
28022ffbb224SPrarit Bhargava 					cpus[cpux].logical_node_id = lnode;
28032ffbb224SPrarit Bhargava 					cpu_count++;
2804ef605741SPrarit Bhargava 				}
28052ffbb224SPrarit Bhargava 			}
28062ffbb224SPrarit Bhargava 			lnode++;
28072ffbb224SPrarit Bhargava 			if (lnode > topo.nodes_per_pkg)
28082ffbb224SPrarit Bhargava 				topo.nodes_per_pkg = lnode;
28092ffbb224SPrarit Bhargava 		}
28102ffbb224SPrarit Bhargava 		if (cpu_count >= topo.max_cpu_num)
28112ffbb224SPrarit Bhargava 			break;
28122ffbb224SPrarit Bhargava 	}
2813ef605741SPrarit Bhargava }
2814ef605741SPrarit Bhargava 
2815ef605741SPrarit Bhargava int get_physical_node_id(struct cpu_topology *thiscpu)
2816c98d5d94SLen Brown {
2817c98d5d94SLen Brown 	char path[80];
2818c98d5d94SLen Brown 	FILE *filep;
28190e2d8f05SLen Brown 	int i;
28200e2d8f05SLen Brown 	int cpu = thiscpu->logical_cpu_id;
2821c98d5d94SLen Brown 
28220e2d8f05SLen Brown 	for (i = 0; i <= topo.max_cpu_num; i++) {
28230e2d8f05SLen Brown 		sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist",
28240e2d8f05SLen Brown 			cpu, i);
28250e2d8f05SLen Brown 		filep = fopen(path, "r");
28260e2d8f05SLen Brown 		if (!filep)
28270e2d8f05SLen Brown 			continue;
28280e2d8f05SLen Brown 		fclose(filep);
28290e2d8f05SLen Brown 		return i;
28300e2d8f05SLen Brown 	}
28310e2d8f05SLen Brown 	return -1;
2832e275b388SDasaratharaman Chandramouli }
2833c98d5d94SLen Brown 
28340e2d8f05SLen Brown int get_thread_siblings(struct cpu_topology *thiscpu)
28350e2d8f05SLen Brown {
28360e2d8f05SLen Brown 	char path[80], character;
28370e2d8f05SLen Brown 	FILE *filep;
28380e2d8f05SLen Brown 	unsigned long map;
28398cb48b32SPrarit Bhargava 	int so, shift, sib_core;
28400e2d8f05SLen Brown 	int cpu = thiscpu->logical_cpu_id;
28410e2d8f05SLen Brown 	int offset = topo.max_cpu_num + 1;
28420e2d8f05SLen Brown 	size_t size;
28438cb48b32SPrarit Bhargava 	int thread_id = 0;
28440e2d8f05SLen Brown 
28450e2d8f05SLen Brown 	thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1));
28468cb48b32SPrarit Bhargava 	if (thiscpu->thread_id < 0)
28478cb48b32SPrarit Bhargava 		thiscpu->thread_id = thread_id++;
28480e2d8f05SLen Brown 	if (!thiscpu->put_ids)
28490e2d8f05SLen Brown 		return -1;
28500e2d8f05SLen Brown 
28510e2d8f05SLen Brown 	size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
28520e2d8f05SLen Brown 	CPU_ZERO_S(size, thiscpu->put_ids);
28530e2d8f05SLen Brown 
28540e2d8f05SLen Brown 	sprintf(path,
28550e2d8f05SLen Brown 		"/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
28563d7772eaSLen Brown 	filep = fopen(path, "r");
28573d7772eaSLen Brown 
28583d7772eaSLen Brown 	if (!filep) {
28593d7772eaSLen Brown 		warnx("%s: open failed", path);
28603d7772eaSLen Brown 		return -1;
28613d7772eaSLen Brown 	}
28620e2d8f05SLen Brown 	do {
28630e2d8f05SLen Brown 		offset -= BITMASK_SIZE;
28648173c336SBen Hutchings 		if (fscanf(filep, "%lx%c", &map, &character) != 2)
28658173c336SBen Hutchings 			err(1, "%s: failed to parse file", path);
28660e2d8f05SLen Brown 		for (shift = 0; shift < BITMASK_SIZE; shift++) {
28670e2d8f05SLen Brown 			if ((map >> shift) & 0x1) {
28688cb48b32SPrarit Bhargava 				so = shift + offset;
28698cb48b32SPrarit Bhargava 				sib_core = get_core_id(so);
28708cb48b32SPrarit Bhargava 				if (sib_core == thiscpu->physical_core_id) {
28718cb48b32SPrarit Bhargava 					CPU_SET_S(so, size, thiscpu->put_ids);
28728cb48b32SPrarit Bhargava 					if ((so != cpu) &&
28738cb48b32SPrarit Bhargava 					    (cpus[so].thread_id < 0))
28748cb48b32SPrarit Bhargava 						cpus[so].thread_id =
28758cb48b32SPrarit Bhargava 								    thread_id++;
28768cb48b32SPrarit Bhargava 				}
28770e2d8f05SLen Brown 			}
28780e2d8f05SLen Brown 		}
28790e2d8f05SLen Brown 	} while (!strncmp(&character, ",", 1));
2880c98d5d94SLen Brown 	fclose(filep);
28810e2d8f05SLen Brown 
28820e2d8f05SLen Brown 	return CPU_COUNT_S(size, thiscpu->put_ids);
2883c98d5d94SLen Brown }
2884c98d5d94SLen Brown 
2885c98d5d94SLen Brown /*
2886c98d5d94SLen Brown  * run func(thread, core, package) in topology order
2887c98d5d94SLen Brown  * skip non-present cpus
2888103a8feaSLen Brown  */
2889103a8feaSLen Brown 
2890c98d5d94SLen Brown int for_all_cpus_2(int (func)(struct thread_data *, struct core_data *,
2891c98d5d94SLen Brown 	struct pkg_data *, struct thread_data *, struct core_data *,
2892c98d5d94SLen Brown 	struct pkg_data *), struct thread_data *thread_base,
2893c98d5d94SLen Brown 	struct core_data *core_base, struct pkg_data *pkg_base,
2894c98d5d94SLen Brown 	struct thread_data *thread_base2, struct core_data *core_base2,
2895c98d5d94SLen Brown 	struct pkg_data *pkg_base2)
2896c98d5d94SLen Brown {
289740f5cfe7SPrarit Bhargava 	int retval, pkg_no, node_no, core_no, thread_no;
2898c98d5d94SLen Brown 
2899c98d5d94SLen Brown 	for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
290040f5cfe7SPrarit Bhargava 		for (node_no = 0; node_no < topo.nodes_per_pkg; ++node_no) {
290140f5cfe7SPrarit Bhargava 			for (core_no = 0; core_no < topo.cores_per_node;
290240f5cfe7SPrarit Bhargava 			     ++core_no) {
2903c98d5d94SLen Brown 				for (thread_no = 0; thread_no <
290470a9c6e8SPrarit Bhargava 					topo.threads_per_core; ++thread_no) {
2905c98d5d94SLen Brown 					struct thread_data *t, *t2;
2906c98d5d94SLen Brown 					struct core_data *c, *c2;
2907c98d5d94SLen Brown 					struct pkg_data *p, *p2;
2908c98d5d94SLen Brown 
290940f5cfe7SPrarit Bhargava 					t = GET_THREAD(thread_base, thread_no,
291040f5cfe7SPrarit Bhargava 						       core_no, node_no,
291140f5cfe7SPrarit Bhargava 						       pkg_no);
2912c98d5d94SLen Brown 
2913c98d5d94SLen Brown 					if (cpu_is_not_present(t->cpu_id))
2914c98d5d94SLen Brown 						continue;
2915c98d5d94SLen Brown 
291640f5cfe7SPrarit Bhargava 					t2 = GET_THREAD(thread_base2, thread_no,
291740f5cfe7SPrarit Bhargava 							core_no, node_no,
291840f5cfe7SPrarit Bhargava 							pkg_no);
2919c98d5d94SLen Brown 
292040f5cfe7SPrarit Bhargava 					c = GET_CORE(core_base, core_no,
292140f5cfe7SPrarit Bhargava 						     node_no, pkg_no);
292240f5cfe7SPrarit Bhargava 					c2 = GET_CORE(core_base2, core_no,
292340f5cfe7SPrarit Bhargava 						      node_no,
292440f5cfe7SPrarit Bhargava 						      pkg_no);
2925c98d5d94SLen Brown 
2926c98d5d94SLen Brown 					p = GET_PKG(pkg_base, pkg_no);
2927c98d5d94SLen Brown 					p2 = GET_PKG(pkg_base2, pkg_no);
2928c98d5d94SLen Brown 
2929c98d5d94SLen Brown 					retval = func(t, c, p, t2, c2, p2);
2930c98d5d94SLen Brown 					if (retval)
2931c98d5d94SLen Brown 						return retval;
2932c98d5d94SLen Brown 				}
2933c98d5d94SLen Brown 			}
2934c98d5d94SLen Brown 		}
293540f5cfe7SPrarit Bhargava 	}
2936c98d5d94SLen Brown 	return 0;
2937c98d5d94SLen Brown }
2938c98d5d94SLen Brown 
2939c98d5d94SLen Brown /*
2940c98d5d94SLen Brown  * run func(cpu) on every cpu in /proc/stat
2941c98d5d94SLen Brown  * return max_cpu number
2942c98d5d94SLen Brown  */
2943c98d5d94SLen Brown int for_all_proc_cpus(int (func)(int))
2944103a8feaSLen Brown {
2945103a8feaSLen Brown 	FILE *fp;
2946c98d5d94SLen Brown 	int cpu_num;
2947103a8feaSLen Brown 	int retval;
2948103a8feaSLen Brown 
294957a42a34SJosh Triplett 	fp = fopen_or_die(proc_stat, "r");
2950103a8feaSLen Brown 
2951103a8feaSLen Brown 	retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
2952b2c95d90SJosh Triplett 	if (retval != 0)
2953b2c95d90SJosh Triplett 		err(1, "%s: failed to parse format", proc_stat);
2954103a8feaSLen Brown 
2955c98d5d94SLen Brown 	while (1) {
2956c98d5d94SLen Brown 		retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
2957103a8feaSLen Brown 		if (retval != 1)
2958103a8feaSLen Brown 			break;
2959103a8feaSLen Brown 
2960c98d5d94SLen Brown 		retval = func(cpu_num);
2961c98d5d94SLen Brown 		if (retval) {
2962c98d5d94SLen Brown 			fclose(fp);
2963c98d5d94SLen Brown 			return(retval);
2964c98d5d94SLen Brown 		}
2965103a8feaSLen Brown 	}
2966103a8feaSLen Brown 	fclose(fp);
2967c98d5d94SLen Brown 	return 0;
2968103a8feaSLen Brown }
2969103a8feaSLen Brown 
2970103a8feaSLen Brown void re_initialize(void)
2971103a8feaSLen Brown {
2972c98d5d94SLen Brown 	free_all_buffers();
2973c98d5d94SLen Brown 	setup_all_buffers();
29743d7772eaSLen Brown 	fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
2975103a8feaSLen Brown }
2976103a8feaSLen Brown 
2977843c5791SPrarit Bhargava void set_max_cpu_num(void)
2978843c5791SPrarit Bhargava {
2979843c5791SPrarit Bhargava 	FILE *filep;
29808201a028SPrarit Bhargava 	int base_cpu;
2981843c5791SPrarit Bhargava 	unsigned long dummy;
29828201a028SPrarit Bhargava 	char pathname[64];
2983843c5791SPrarit Bhargava 
29848201a028SPrarit Bhargava 	base_cpu = sched_getcpu();
29858201a028SPrarit Bhargava 	if (base_cpu < 0)
29868201a028SPrarit Bhargava 		err(1, "cannot find calling cpu ID");
29878201a028SPrarit Bhargava 	sprintf(pathname,
29888201a028SPrarit Bhargava 		"/sys/devices/system/cpu/cpu%d/topology/thread_siblings",
29898201a028SPrarit Bhargava 		base_cpu);
29908201a028SPrarit Bhargava 
29918201a028SPrarit Bhargava 	filep = fopen_or_die(pathname, "r");
2992843c5791SPrarit Bhargava 	topo.max_cpu_num = 0;
2993843c5791SPrarit Bhargava 	while (fscanf(filep, "%lx,", &dummy) == 1)
29940e2d8f05SLen Brown 		topo.max_cpu_num += BITMASK_SIZE;
2995843c5791SPrarit Bhargava 	fclose(filep);
2996843c5791SPrarit Bhargava 	topo.max_cpu_num--; /* 0 based */
2997843c5791SPrarit Bhargava }
2998c98d5d94SLen Brown 
2999103a8feaSLen Brown /*
3000c98d5d94SLen Brown  * count_cpus()
3001c98d5d94SLen Brown  * remember the last one seen, it will be the max
3002103a8feaSLen Brown  */
3003c98d5d94SLen Brown int count_cpus(int cpu)
3004103a8feaSLen Brown {
3005843c5791SPrarit Bhargava 	topo.num_cpus++;
3006c98d5d94SLen Brown 	return 0;
3007103a8feaSLen Brown }
3008c98d5d94SLen Brown int mark_cpu_present(int cpu)
3009c98d5d94SLen Brown {
3010c98d5d94SLen Brown 	CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
301115aaa346SLen Brown 	return 0;
3012103a8feaSLen Brown }
3013103a8feaSLen Brown 
30148cb48b32SPrarit Bhargava int init_thread_id(int cpu)
30158cb48b32SPrarit Bhargava {
30168cb48b32SPrarit Bhargava 	cpus[cpu].thread_id = -1;
30178cb48b32SPrarit Bhargava 	return 0;
30188cb48b32SPrarit Bhargava }
30198cb48b32SPrarit Bhargava 
3020562a2d37SLen Brown /*
3021562a2d37SLen Brown  * snapshot_proc_interrupts()
3022562a2d37SLen Brown  *
3023562a2d37SLen Brown  * read and record summary of /proc/interrupts
3024562a2d37SLen Brown  *
3025562a2d37SLen Brown  * return 1 if config change requires a restart, else return 0
3026562a2d37SLen Brown  */
3027562a2d37SLen Brown int snapshot_proc_interrupts(void)
3028562a2d37SLen Brown {
3029562a2d37SLen Brown 	static FILE *fp;
3030562a2d37SLen Brown 	int column, retval;
3031562a2d37SLen Brown 
3032562a2d37SLen Brown 	if (fp == NULL)
3033562a2d37SLen Brown 		fp = fopen_or_die("/proc/interrupts", "r");
3034562a2d37SLen Brown 	else
3035562a2d37SLen Brown 		rewind(fp);
3036562a2d37SLen Brown 
3037562a2d37SLen Brown 	/* read 1st line of /proc/interrupts to get cpu* name for each column */
3038562a2d37SLen Brown 	for (column = 0; column < topo.num_cpus; ++column) {
3039562a2d37SLen Brown 		int cpu_number;
3040562a2d37SLen Brown 
3041562a2d37SLen Brown 		retval = fscanf(fp, " CPU%d", &cpu_number);
3042562a2d37SLen Brown 		if (retval != 1)
3043562a2d37SLen Brown 			break;
3044562a2d37SLen Brown 
3045562a2d37SLen Brown 		if (cpu_number > topo.max_cpu_num) {
3046562a2d37SLen Brown 			warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);
3047562a2d37SLen Brown 			return 1;
3048562a2d37SLen Brown 		}
3049562a2d37SLen Brown 
3050562a2d37SLen Brown 		irq_column_2_cpu[column] = cpu_number;
3051562a2d37SLen Brown 		irqs_per_cpu[cpu_number] = 0;
3052562a2d37SLen Brown 	}
3053562a2d37SLen Brown 
3054562a2d37SLen Brown 	/* read /proc/interrupt count lines and sum up irqs per cpu */
3055562a2d37SLen Brown 	while (1) {
3056562a2d37SLen Brown 		int column;
3057562a2d37SLen Brown 		char buf[64];
3058562a2d37SLen Brown 
3059562a2d37SLen Brown 		retval = fscanf(fp, " %s:", buf);	/* flush irq# "N:" */
3060562a2d37SLen Brown 		if (retval != 1)
3061562a2d37SLen Brown 			break;
3062562a2d37SLen Brown 
3063562a2d37SLen Brown 		/* read the count per cpu */
3064562a2d37SLen Brown 		for (column = 0; column < topo.num_cpus; ++column) {
3065562a2d37SLen Brown 
3066562a2d37SLen Brown 			int cpu_number, irq_count;
3067562a2d37SLen Brown 
3068562a2d37SLen Brown 			retval = fscanf(fp, " %d", &irq_count);
3069562a2d37SLen Brown 			if (retval != 1)
3070562a2d37SLen Brown 				break;
3071562a2d37SLen Brown 
3072562a2d37SLen Brown 			cpu_number = irq_column_2_cpu[column];
3073562a2d37SLen Brown 			irqs_per_cpu[cpu_number] += irq_count;
3074562a2d37SLen Brown 
3075562a2d37SLen Brown 		}
3076562a2d37SLen Brown 
3077562a2d37SLen Brown 		while (getc(fp) != '\n')
3078562a2d37SLen Brown 			;	/* flush interrupt description */
3079562a2d37SLen Brown 
3080562a2d37SLen Brown 	}
3081562a2d37SLen Brown 	return 0;
3082562a2d37SLen Brown }
308327d47356SLen Brown /*
3084fdf676e5SLen Brown  * snapshot_gfx_rc6_ms()
3085fdf676e5SLen Brown  *
3086fdf676e5SLen Brown  * record snapshot of
3087fdf676e5SLen Brown  * /sys/class/drm/card0/power/rc6_residency_ms
3088fdf676e5SLen Brown  *
3089fdf676e5SLen Brown  * return 1 if config change requires a restart, else return 0
3090fdf676e5SLen Brown  */
3091fdf676e5SLen Brown int snapshot_gfx_rc6_ms(void)
3092fdf676e5SLen Brown {
3093fdf676e5SLen Brown 	FILE *fp;
3094fdf676e5SLen Brown 	int retval;
3095fdf676e5SLen Brown 
3096fdf676e5SLen Brown 	fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r");
3097fdf676e5SLen Brown 
3098fdf676e5SLen Brown 	retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms);
3099fdf676e5SLen Brown 	if (retval != 1)
3100fdf676e5SLen Brown 		err(1, "GFX rc6");
3101fdf676e5SLen Brown 
3102fdf676e5SLen Brown 	fclose(fp);
3103fdf676e5SLen Brown 
3104fdf676e5SLen Brown 	return 0;
3105fdf676e5SLen Brown }
3106fdf676e5SLen Brown /*
310727d47356SLen Brown  * snapshot_gfx_mhz()
310827d47356SLen Brown  *
310927d47356SLen Brown  * record snapshot of
311027d47356SLen Brown  * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz
311127d47356SLen Brown  *
311227d47356SLen Brown  * return 1 if config change requires a restart, else return 0
311327d47356SLen Brown  */
311427d47356SLen Brown int snapshot_gfx_mhz(void)
311527d47356SLen Brown {
311627d47356SLen Brown 	static FILE *fp;
311727d47356SLen Brown 	int retval;
311827d47356SLen Brown 
311927d47356SLen Brown 	if (fp == NULL)
312027d47356SLen Brown 		fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r");
312122048c54SLen Brown 	else {
312227d47356SLen Brown 		rewind(fp);
312322048c54SLen Brown 		fflush(fp);
312422048c54SLen Brown 	}
312527d47356SLen Brown 
312627d47356SLen Brown 	retval = fscanf(fp, "%d", &gfx_cur_mhz);
312727d47356SLen Brown 	if (retval != 1)
312827d47356SLen Brown 		err(1, "GFX MHz");
312927d47356SLen Brown 
313027d47356SLen Brown 	return 0;
313127d47356SLen Brown }
3132562a2d37SLen Brown 
3133562a2d37SLen Brown /*
3134b4b91569SRafael Antognolli  * snapshot_gfx_cur_mhz()
3135b4b91569SRafael Antognolli  *
3136b4b91569SRafael Antognolli  * record snapshot of
3137b4b91569SRafael Antognolli  * /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz
3138b4b91569SRafael Antognolli  *
3139b4b91569SRafael Antognolli  * return 1 if config change requires a restart, else return 0
3140b4b91569SRafael Antognolli  */
3141b4b91569SRafael Antognolli int snapshot_gfx_act_mhz(void)
3142b4b91569SRafael Antognolli {
3143b4b91569SRafael Antognolli 	static FILE *fp;
3144b4b91569SRafael Antognolli 	int retval;
3145b4b91569SRafael Antognolli 
3146b4b91569SRafael Antognolli 	if (fp == NULL)
3147b4b91569SRafael Antognolli 		fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r");
3148b4b91569SRafael Antognolli 	else {
3149b4b91569SRafael Antognolli 		rewind(fp);
3150b4b91569SRafael Antognolli 		fflush(fp);
3151b4b91569SRafael Antognolli 	}
3152b4b91569SRafael Antognolli 
3153b4b91569SRafael Antognolli 	retval = fscanf(fp, "%d", &gfx_act_mhz);
3154b4b91569SRafael Antognolli 	if (retval != 1)
3155b4b91569SRafael Antognolli 		err(1, "GFX ACT MHz");
3156b4b91569SRafael Antognolli 
3157b4b91569SRafael Antognolli 	return 0;
3158b4b91569SRafael Antognolli }
3159b4b91569SRafael Antognolli 
3160b4b91569SRafael Antognolli /*
3161be0e54c4SLen Brown  * snapshot_cpu_lpi()
3162be0e54c4SLen Brown  *
3163be0e54c4SLen Brown  * record snapshot of
3164be0e54c4SLen Brown  * /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us
3165be0e54c4SLen Brown  */
3166be0e54c4SLen Brown int snapshot_cpu_lpi_us(void)
3167be0e54c4SLen Brown {
3168be0e54c4SLen Brown 	FILE *fp;
3169be0e54c4SLen Brown 	int retval;
3170be0e54c4SLen Brown 
3171be0e54c4SLen Brown 	fp = fopen_or_die("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", "r");
3172be0e54c4SLen Brown 
3173be0e54c4SLen Brown 	retval = fscanf(fp, "%lld", &cpuidle_cur_cpu_lpi_us);
31745ea7647bSPrarit Bhargava 	if (retval != 1) {
31755ea7647bSPrarit Bhargava 		fprintf(stderr, "Disabling Low Power Idle CPU output\n");
31765ea7647bSPrarit Bhargava 		BIC_NOT_PRESENT(BIC_CPU_LPI);
3177605736c6SGustavo A. R. Silva 		fclose(fp);
31785ea7647bSPrarit Bhargava 		return -1;
31795ea7647bSPrarit Bhargava 	}
3180be0e54c4SLen Brown 
3181be0e54c4SLen Brown 	fclose(fp);
3182be0e54c4SLen Brown 
3183be0e54c4SLen Brown 	return 0;
3184be0e54c4SLen Brown }
3185be0e54c4SLen Brown /*
3186be0e54c4SLen Brown  * snapshot_sys_lpi()
3187be0e54c4SLen Brown  *
31881f81c5efSLen Brown  * record snapshot of sys_lpi_file
3189be0e54c4SLen Brown  */
3190be0e54c4SLen Brown int snapshot_sys_lpi_us(void)
3191be0e54c4SLen Brown {
3192be0e54c4SLen Brown 	FILE *fp;
3193be0e54c4SLen Brown 	int retval;
3194be0e54c4SLen Brown 
31951f81c5efSLen Brown 	fp = fopen_or_die(sys_lpi_file, "r");
3196be0e54c4SLen Brown 
3197be0e54c4SLen Brown 	retval = fscanf(fp, "%lld", &cpuidle_cur_sys_lpi_us);
31985ea7647bSPrarit Bhargava 	if (retval != 1) {
31995ea7647bSPrarit Bhargava 		fprintf(stderr, "Disabling Low Power Idle System output\n");
32005ea7647bSPrarit Bhargava 		BIC_NOT_PRESENT(BIC_SYS_LPI);
320115423b95SColin Ian King 		fclose(fp);
32025ea7647bSPrarit Bhargava 		return -1;
32035ea7647bSPrarit Bhargava 	}
3204be0e54c4SLen Brown 	fclose(fp);
3205be0e54c4SLen Brown 
3206be0e54c4SLen Brown 	return 0;
3207be0e54c4SLen Brown }
3208be0e54c4SLen Brown /*
3209562a2d37SLen Brown  * snapshot /proc and /sys files
3210562a2d37SLen Brown  *
3211562a2d37SLen Brown  * return 1 if configuration restart needed, else return 0
3212562a2d37SLen Brown  */
3213562a2d37SLen Brown int snapshot_proc_sysfs_files(void)
3214562a2d37SLen Brown {
3215218f0e8dSLen Brown 	if (DO_BIC(BIC_IRQ))
3216562a2d37SLen Brown 		if (snapshot_proc_interrupts())
3217562a2d37SLen Brown 			return 1;
3218562a2d37SLen Brown 
3219812db3f7SLen Brown 	if (DO_BIC(BIC_GFX_rc6))
3220fdf676e5SLen Brown 		snapshot_gfx_rc6_ms();
3221fdf676e5SLen Brown 
3222812db3f7SLen Brown 	if (DO_BIC(BIC_GFXMHz))
322327d47356SLen Brown 		snapshot_gfx_mhz();
322427d47356SLen Brown 
3225b4b91569SRafael Antognolli 	if (DO_BIC(BIC_GFXACTMHz))
3226b4b91569SRafael Antognolli 		snapshot_gfx_act_mhz();
3227b4b91569SRafael Antognolli 
3228be0e54c4SLen Brown 	if (DO_BIC(BIC_CPU_LPI))
3229be0e54c4SLen Brown 		snapshot_cpu_lpi_us();
3230be0e54c4SLen Brown 
3231be0e54c4SLen Brown 	if (DO_BIC(BIC_SYS_LPI))
3232be0e54c4SLen Brown 		snapshot_sys_lpi_us();
3233be0e54c4SLen Brown 
3234562a2d37SLen Brown 	return 0;
3235562a2d37SLen Brown }
3236562a2d37SLen Brown 
32378aa2ed0bSLen Brown int exit_requested;
32388aa2ed0bSLen Brown 
32398aa2ed0bSLen Brown static void signal_handler (int signal)
32408aa2ed0bSLen Brown {
32418aa2ed0bSLen Brown 	switch (signal) {
32428aa2ed0bSLen Brown 	case SIGINT:
32438aa2ed0bSLen Brown 		exit_requested = 1;
32448aa2ed0bSLen Brown 		if (debug)
32458aa2ed0bSLen Brown 			fprintf(stderr, " SIGINT\n");
32468aa2ed0bSLen Brown 		break;
324707211960SLen Brown 	case SIGUSR1:
324807211960SLen Brown 		if (debug > 1)
324907211960SLen Brown 			fprintf(stderr, "SIGUSR1\n");
325007211960SLen Brown 		break;
32518aa2ed0bSLen Brown 	}
32528aa2ed0bSLen Brown }
32538aa2ed0bSLen Brown 
32548aa2ed0bSLen Brown void setup_signal_handler(void)
32558aa2ed0bSLen Brown {
32568aa2ed0bSLen Brown 	struct sigaction sa;
32578aa2ed0bSLen Brown 
32588aa2ed0bSLen Brown 	memset(&sa, 0, sizeof(sa));
32598aa2ed0bSLen Brown 
32608aa2ed0bSLen Brown 	sa.sa_handler = &signal_handler;
32618aa2ed0bSLen Brown 
32628aa2ed0bSLen Brown 	if (sigaction(SIGINT, &sa, NULL) < 0)
32638aa2ed0bSLen Brown 		err(1, "sigaction SIGINT");
326407211960SLen Brown 	if (sigaction(SIGUSR1, &sa, NULL) < 0)
326507211960SLen Brown 		err(1, "sigaction SIGUSR1");
32668aa2ed0bSLen Brown }
3267b9ad8ee0SLen Brown 
326847936f94SArtem Bityutskiy void do_sleep(void)
3269b9ad8ee0SLen Brown {
3270c026c236SArtem Bityutskiy 	struct timeval tout;
3271c026c236SArtem Bityutskiy 	struct timespec rest;
3272b9ad8ee0SLen Brown 	fd_set readfds;
3273b9ad8ee0SLen Brown 	int retval;
3274b9ad8ee0SLen Brown 
3275b9ad8ee0SLen Brown 	FD_ZERO(&readfds);
3276b9ad8ee0SLen Brown 	FD_SET(0, &readfds);
3277b9ad8ee0SLen Brown 
3278c026c236SArtem Bityutskiy 	if (ignore_stdin) {
327947936f94SArtem Bityutskiy 		nanosleep(&interval_ts, NULL);
328047936f94SArtem Bityutskiy 		return;
328147936f94SArtem Bityutskiy 	}
3282b9ad8ee0SLen Brown 
3283c026c236SArtem Bityutskiy 	tout = interval_tv;
3284c026c236SArtem Bityutskiy 	retval = select(1, &readfds, NULL, NULL, &tout);
3285b9ad8ee0SLen Brown 
3286b9ad8ee0SLen Brown 	if (retval == 1) {
3287b9ad8ee0SLen Brown 		switch (getc(stdin)) {
3288b9ad8ee0SLen Brown 		case 'q':
3289b9ad8ee0SLen Brown 			exit_requested = 1;
3290b9ad8ee0SLen Brown 			break;
3291c026c236SArtem Bityutskiy 		case EOF:
3292c026c236SArtem Bityutskiy 			/*
3293c026c236SArtem Bityutskiy 			 * 'stdin' is a pipe closed on the other end. There
3294c026c236SArtem Bityutskiy 			 * won't be any further input.
3295c026c236SArtem Bityutskiy 			 */
3296c026c236SArtem Bityutskiy 			ignore_stdin = 1;
3297c026c236SArtem Bityutskiy 			/* Sleep the rest of the time */
3298c026c236SArtem Bityutskiy 			rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);
3299c026c236SArtem Bityutskiy 			rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;
3300c026c236SArtem Bityutskiy 			nanosleep(&rest, NULL);
3301b9ad8ee0SLen Brown 		}
3302b9ad8ee0SLen Brown 	}
3303b9ad8ee0SLen Brown }
330447936f94SArtem Bityutskiy 
330587e15da9SChen Yu int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)
330687e15da9SChen Yu {
330787e15da9SChen Yu 	int ret, idx;
330887e15da9SChen Yu 	unsigned long long msr_cur, msr_last;
330987e15da9SChen Yu 
331087e15da9SChen Yu 	if (!per_cpu_msr_sum)
331187e15da9SChen Yu 		return 1;
331287e15da9SChen Yu 
331387e15da9SChen Yu 	idx = offset_to_idx(offset);
331487e15da9SChen Yu 	if (idx < 0)
331587e15da9SChen Yu 		return idx;
331687e15da9SChen Yu 	/* get_msr_sum() = sum + (get_msr() - last) */
331787e15da9SChen Yu 	ret = get_msr(cpu, offset, &msr_cur);
331887e15da9SChen Yu 	if (ret)
331987e15da9SChen Yu 		return ret;
332087e15da9SChen Yu 	msr_last = per_cpu_msr_sum[cpu].entries[idx].last;
332187e15da9SChen Yu 	DELTA_WRAP32(msr_cur, msr_last);
332287e15da9SChen Yu 	*msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;
332387e15da9SChen Yu 
332487e15da9SChen Yu 	return 0;
332587e15da9SChen Yu }
332687e15da9SChen Yu 
332787e15da9SChen Yu timer_t timerid;
332887e15da9SChen Yu 
332987e15da9SChen Yu /* Timer callback, update the sum of MSRs periodically. */
333087e15da9SChen Yu static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)
333187e15da9SChen Yu {
333287e15da9SChen Yu 	int i, ret;
333387e15da9SChen Yu 	int cpu = t->cpu_id;
333487e15da9SChen Yu 
333587e15da9SChen Yu 	for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {
333687e15da9SChen Yu 		unsigned long long msr_cur, msr_last;
333787e15da9SChen Yu 		int offset;
333887e15da9SChen Yu 
333987e15da9SChen Yu 		if (!idx_valid(i))
334087e15da9SChen Yu 			continue;
334187e15da9SChen Yu 		offset = idx_to_offset(i);
334287e15da9SChen Yu 		if (offset < 0)
334387e15da9SChen Yu 			continue;
334487e15da9SChen Yu 		ret = get_msr(cpu, offset, &msr_cur);
334587e15da9SChen Yu 		if (ret) {
334687e15da9SChen Yu 			fprintf(outf, "Can not update msr(0x%x)\n", offset);
334787e15da9SChen Yu 			continue;
334887e15da9SChen Yu 		}
334987e15da9SChen Yu 
335087e15da9SChen Yu 		msr_last = per_cpu_msr_sum[cpu].entries[i].last;
335187e15da9SChen Yu 		per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;
335287e15da9SChen Yu 
335387e15da9SChen Yu 		DELTA_WRAP32(msr_cur, msr_last);
335487e15da9SChen Yu 		per_cpu_msr_sum[cpu].entries[i].sum += msr_last;
335587e15da9SChen Yu 	}
335687e15da9SChen Yu 	return 0;
335787e15da9SChen Yu }
335887e15da9SChen Yu 
335987e15da9SChen Yu static void
336087e15da9SChen Yu msr_record_handler(union sigval v)
336187e15da9SChen Yu {
336287e15da9SChen Yu 	for_all_cpus(update_msr_sum, EVEN_COUNTERS);
336387e15da9SChen Yu }
336487e15da9SChen Yu 
336587e15da9SChen Yu void msr_sum_record(void)
336687e15da9SChen Yu {
336787e15da9SChen Yu 	struct itimerspec its;
336887e15da9SChen Yu 	struct sigevent sev;
336987e15da9SChen Yu 
337087e15da9SChen Yu 	per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));
337187e15da9SChen Yu 	if (!per_cpu_msr_sum) {
337287e15da9SChen Yu 		fprintf(outf, "Can not allocate memory for long time MSR.\n");
337387e15da9SChen Yu 		return;
337487e15da9SChen Yu 	}
337587e15da9SChen Yu 	/*
337687e15da9SChen Yu 	 * Signal handler might be restricted, so use thread notifier instead.
337787e15da9SChen Yu 	 */
337887e15da9SChen Yu 	memset(&sev, 0, sizeof(struct sigevent));
337987e15da9SChen Yu 	sev.sigev_notify = SIGEV_THREAD;
338087e15da9SChen Yu 	sev.sigev_notify_function = msr_record_handler;
338187e15da9SChen Yu 
338287e15da9SChen Yu 	sev.sigev_value.sival_ptr = &timerid;
338387e15da9SChen Yu 	if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
338487e15da9SChen Yu 		fprintf(outf, "Can not create timer.\n");
338587e15da9SChen Yu 		goto release_msr;
338687e15da9SChen Yu 	}
338787e15da9SChen Yu 
338887e15da9SChen Yu 	its.it_value.tv_sec = 0;
338987e15da9SChen Yu 	its.it_value.tv_nsec = 1;
339087e15da9SChen Yu 	/*
339187e15da9SChen Yu 	 * A wraparound time has been calculated early.
339287e15da9SChen Yu 	 * Some sources state that the peak power for a
339387e15da9SChen Yu 	 * microprocessor is usually 1.5 times the TDP rating,
339487e15da9SChen Yu 	 * use 2 * TDP for safety.
339587e15da9SChen Yu 	 */
339687e15da9SChen Yu 	its.it_interval.tv_sec = rapl_joule_counter_range / 2;
339787e15da9SChen Yu 	its.it_interval.tv_nsec = 0;
339887e15da9SChen Yu 
339987e15da9SChen Yu 	if (timer_settime(timerid, 0, &its, NULL) == -1) {
340087e15da9SChen Yu 		fprintf(outf, "Can not set timer.\n");
340187e15da9SChen Yu 		goto release_timer;
340287e15da9SChen Yu 	}
340387e15da9SChen Yu 	return;
340487e15da9SChen Yu 
340587e15da9SChen Yu  release_timer:
340687e15da9SChen Yu 	timer_delete(timerid);
340787e15da9SChen Yu  release_msr:
340887e15da9SChen Yu 	free(per_cpu_msr_sum);
340987e15da9SChen Yu }
34104c2122d4SLen Brown 
3411103a8feaSLen Brown void turbostat_loop()
3412103a8feaSLen Brown {
3413c98d5d94SLen Brown 	int retval;
3414e52966c0SLen Brown 	int restarted = 0;
3415023fe0acSChen Yu 	int done_iters = 0;
3416c98d5d94SLen Brown 
34178aa2ed0bSLen Brown 	setup_signal_handler();
34188aa2ed0bSLen Brown 
3419103a8feaSLen Brown restart:
3420e52966c0SLen Brown 	restarted++;
3421e52966c0SLen Brown 
3422562a2d37SLen Brown 	snapshot_proc_sysfs_files();
3423c98d5d94SLen Brown 	retval = for_all_cpus(get_counters, EVEN_COUNTERS);
34244c2122d4SLen Brown 	first_counter_read = 0;
3425d91bb17cSLen Brown 	if (retval < -1) {
3426d91bb17cSLen Brown 		exit(retval);
3427d91bb17cSLen Brown 	} else if (retval == -1) {
34283d7772eaSLen Brown 		if (restarted > 10) {
3429e52966c0SLen Brown 			exit(retval);
3430e52966c0SLen Brown 		}
3431c98d5d94SLen Brown 		re_initialize();
3432c98d5d94SLen Brown 		goto restart;
3433c98d5d94SLen Brown 	}
3434e52966c0SLen Brown 	restarted = 0;
3435023fe0acSChen Yu 	done_iters = 0;
3436103a8feaSLen Brown 	gettimeofday(&tv_even, (struct timezone *)NULL);
3437103a8feaSLen Brown 
3438103a8feaSLen Brown 	while (1) {
3439c98d5d94SLen Brown 		if (for_all_proc_cpus(cpu_is_not_present)) {
3440103a8feaSLen Brown 			re_initialize();
3441103a8feaSLen Brown 			goto restart;
3442103a8feaSLen Brown 		}
3443b9ad8ee0SLen Brown 		do_sleep();
3444562a2d37SLen Brown 		if (snapshot_proc_sysfs_files())
3445562a2d37SLen Brown 			goto restart;
3446c98d5d94SLen Brown 		retval = for_all_cpus(get_counters, ODD_COUNTERS);
3447d91bb17cSLen Brown 		if (retval < -1) {
3448d91bb17cSLen Brown 			exit(retval);
3449d91bb17cSLen Brown 		} else if (retval == -1) {
345015aaa346SLen Brown 			re_initialize();
345115aaa346SLen Brown 			goto restart;
345215aaa346SLen Brown 		}
3453103a8feaSLen Brown 		gettimeofday(&tv_odd, (struct timezone *)NULL);
3454103a8feaSLen Brown 		timersub(&tv_odd, &tv_even, &tv_delta);
3455ba3dec99SLen Brown 		if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) {
3456ba3dec99SLen Brown 			re_initialize();
3457ba3dec99SLen Brown 			goto restart;
3458ba3dec99SLen Brown 		}
3459c98d5d94SLen Brown 		compute_average(EVEN_COUNTERS);
3460c98d5d94SLen Brown 		format_all_counters(EVEN_COUNTERS);
3461b7d8c148SLen Brown 		flush_output_stdout();
34628aa2ed0bSLen Brown 		if (exit_requested)
34638aa2ed0bSLen Brown 			break;
3464023fe0acSChen Yu 		if (num_iterations && ++done_iters >= num_iterations)
3465023fe0acSChen Yu 			break;
3466b9ad8ee0SLen Brown 		do_sleep();
3467562a2d37SLen Brown 		if (snapshot_proc_sysfs_files())
3468562a2d37SLen Brown 			goto restart;
3469c98d5d94SLen Brown 		retval = for_all_cpus(get_counters, EVEN_COUNTERS);
3470d91bb17cSLen Brown 		if (retval < -1) {
3471d91bb17cSLen Brown 			exit(retval);
3472d91bb17cSLen Brown 		} else if (retval == -1) {
3473103a8feaSLen Brown 			re_initialize();
3474103a8feaSLen Brown 			goto restart;
3475103a8feaSLen Brown 		}
3476103a8feaSLen Brown 		gettimeofday(&tv_even, (struct timezone *)NULL);
3477103a8feaSLen Brown 		timersub(&tv_even, &tv_odd, &tv_delta);
3478ba3dec99SLen Brown 		if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) {
3479ba3dec99SLen Brown 			re_initialize();
3480ba3dec99SLen Brown 			goto restart;
3481ba3dec99SLen Brown 		}
3482c98d5d94SLen Brown 		compute_average(ODD_COUNTERS);
3483c98d5d94SLen Brown 		format_all_counters(ODD_COUNTERS);
3484b7d8c148SLen Brown 		flush_output_stdout();
34858aa2ed0bSLen Brown 		if (exit_requested)
34868aa2ed0bSLen Brown 			break;
3487023fe0acSChen Yu 		if (num_iterations && ++done_iters >= num_iterations)
3488023fe0acSChen Yu 			break;
3489103a8feaSLen Brown 	}
3490103a8feaSLen Brown }
3491103a8feaSLen Brown 
3492103a8feaSLen Brown void check_dev_msr()
3493103a8feaSLen Brown {
3494103a8feaSLen Brown 	struct stat sb;
34957ce7d5deSPrarit Bhargava 	char pathname[32];
3496103a8feaSLen Brown 
34977ce7d5deSPrarit Bhargava 	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
34987ce7d5deSPrarit Bhargava 	if (stat(pathname, &sb))
3499a21d38c8SLen Brown  		if (system("/sbin/modprobe msr > /dev/null 2>&1"))
3500d7899447SLen Brown 			err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
3501103a8feaSLen Brown }
3502103a8feaSLen Brown 
3503fcaa681cSLen Brown /*
3504fcaa681cSLen Brown  * check for CAP_SYS_RAWIO
3505fcaa681cSLen Brown  * return 0 on success
3506fcaa681cSLen Brown  * return 1 on fail
3507fcaa681cSLen Brown  */
3508fcaa681cSLen Brown int check_for_cap_sys_rawio(void)
3509103a8feaSLen Brown {
3510fcaa681cSLen Brown 	cap_t caps;
3511fcaa681cSLen Brown 	cap_flag_value_t cap_flag_value;
3512fcaa681cSLen Brown 
3513fcaa681cSLen Brown 	caps = cap_get_proc();
3514fcaa681cSLen Brown 	if (caps == NULL)
3515fcaa681cSLen Brown 		err(-6, "cap_get_proc\n");
3516fcaa681cSLen Brown 
3517fcaa681cSLen Brown 	if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value))
3518fcaa681cSLen Brown 		err(-6, "cap_get\n");
3519fcaa681cSLen Brown 
3520fcaa681cSLen Brown 	if (cap_flag_value != CAP_SET) {
3521fcaa681cSLen Brown 		warnx("capget(CAP_SYS_RAWIO) failed,"
3522fcaa681cSLen Brown 			" try \"# setcap cap_sys_rawio=ep %s\"", progname);
3523fcaa681cSLen Brown 		return 1;
3524fcaa681cSLen Brown 	}
3525fcaa681cSLen Brown 
3526fcaa681cSLen Brown 	if (cap_free(caps) == -1)
3527fcaa681cSLen Brown 		err(-6, "cap_free\n");
3528fcaa681cSLen Brown 
3529fcaa681cSLen Brown 	return 0;
3530fcaa681cSLen Brown }
3531fcaa681cSLen Brown void check_permissions(void)
3532fcaa681cSLen Brown {
353398481e79SLen Brown 	int do_exit = 0;
35347ce7d5deSPrarit Bhargava 	char pathname[32];
353598481e79SLen Brown 
353698481e79SLen Brown 	/* check for CAP_SYS_RAWIO */
3537fcaa681cSLen Brown 	do_exit += check_for_cap_sys_rawio();
353898481e79SLen Brown 
353998481e79SLen Brown 	/* test file permissions */
35407ce7d5deSPrarit Bhargava 	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
35417ce7d5deSPrarit Bhargava 	if (euidaccess(pathname, R_OK)) {
354298481e79SLen Brown 		do_exit++;
354398481e79SLen Brown 		warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr");
354498481e79SLen Brown 	}
354598481e79SLen Brown 
354698481e79SLen Brown 	/* if all else fails, thell them to be root */
354798481e79SLen Brown 	if (do_exit)
3548b2c95d90SJosh Triplett 		if (getuid() != 0)
3549d7899447SLen Brown 			warnx("... or simply run as root");
355098481e79SLen Brown 
355198481e79SLen Brown 	if (do_exit)
355298481e79SLen Brown 		exit(-6);
3553103a8feaSLen Brown }
3554103a8feaSLen Brown 
3555d7899447SLen Brown /*
3556d7899447SLen Brown  * NHM adds support for additional MSRs:
3557d7899447SLen Brown  *
3558d7899447SLen Brown  * MSR_SMI_COUNT                   0x00000034
3559d7899447SLen Brown  *
3560ec0adc53SLen Brown  * MSR_PLATFORM_INFO               0x000000ce
35611df2e55aSLen Brown  * MSR_PKG_CST_CONFIG_CONTROL     0x000000e2
3562d7899447SLen Brown  *
3563cf4cbe53SLen Brown  * MSR_MISC_PWR_MGMT               0x000001aa
3564cf4cbe53SLen Brown  *
3565d7899447SLen Brown  * MSR_PKG_C3_RESIDENCY            0x000003f8
3566d7899447SLen Brown  * MSR_PKG_C6_RESIDENCY            0x000003f9
3567d7899447SLen Brown  * MSR_CORE_C3_RESIDENCY           0x000003fc
3568d7899447SLen Brown  * MSR_CORE_C6_RESIDENCY           0x000003fd
3569d7899447SLen Brown  *
3570ee7e38e3SLen Brown  * Side effect:
35711df2e55aSLen Brown  * sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL
357233148d67SLen Brown  * sets has_misc_feature_control
3573d7899447SLen Brown  */
3574ee7e38e3SLen Brown int probe_nhm_msrs(unsigned int family, unsigned int model)
3575103a8feaSLen Brown {
3576ee7e38e3SLen Brown 	unsigned long long msr;
357721ed5574SLen Brown 	unsigned int base_ratio;
3578ee7e38e3SLen Brown 	int *pkg_cstate_limits;
3579ee7e38e3SLen Brown 
3580103a8feaSLen Brown 	if (!genuine_intel)
3581103a8feaSLen Brown 		return 0;
3582103a8feaSLen Brown 
3583103a8feaSLen Brown 	if (family != 6)
3584103a8feaSLen Brown 		return 0;
3585103a8feaSLen Brown 
358621ed5574SLen Brown 	bclk = discover_bclk(family, model);
358721ed5574SLen Brown 
3588103a8feaSLen Brown 	switch (model) {
3589869ce69eSLen Brown 	case INTEL_FAM6_NEHALEM:	/* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
3590869ce69eSLen Brown 	case INTEL_FAM6_NEHALEM_EX:	/* Nehalem-EX Xeon - Beckton */
3591ee7e38e3SLen Brown 		pkg_cstate_limits = nhm_pkg_cstate_limits;
3592ee7e38e3SLen Brown 		break;
3593869ce69eSLen Brown 	case INTEL_FAM6_SANDYBRIDGE:	/* SNB */
3594869ce69eSLen Brown 	case INTEL_FAM6_SANDYBRIDGE_X:	/* SNB Xeon */
3595869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE:	/* IVB */
3596869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE_X:	/* IVB Xeon */
3597ee7e38e3SLen Brown 		pkg_cstate_limits = snb_pkg_cstate_limits;
359833148d67SLen Brown 		has_misc_feature_control = 1;
3599ee7e38e3SLen Brown 		break;
3600c66f78a6SPeter Zijlstra 	case INTEL_FAM6_HASWELL:	/* HSW */
36015e741407SPeter Zijlstra 	case INTEL_FAM6_HASWELL_G:	/* HSW */
3602869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSX */
360377e5517cSIngo Molnar 	case INTEL_FAM6_HASWELL_L:	/* HSW */
3604c66f78a6SPeter Zijlstra 	case INTEL_FAM6_BROADWELL:	/* BDW */
36055e741407SPeter Zijlstra 	case INTEL_FAM6_BROADWELL_G:	/* BDW */
3606869ce69eSLen Brown 	case INTEL_FAM6_BROADWELL_X:	/* BDX */
3607af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
3608af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
3609ee7e38e3SLen Brown 		pkg_cstate_limits = hsw_pkg_cstate_limits;
361033148d67SLen Brown 		has_misc_feature_control = 1;
3611ee7e38e3SLen Brown 		break;
3612d8ebb442SLen Brown 	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
3613d8ebb442SLen Brown 		pkg_cstate_limits = skx_pkg_cstate_limits;
361433148d67SLen Brown 		has_misc_feature_control = 1;
3615d8ebb442SLen Brown 		break;
3616f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT:	/* BYT */
3617cf4cbe53SLen Brown 		no_MSR_MISC_PWR_MGMT = 1;
36185ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT_D:	/* AVN */
3619ee7e38e3SLen Brown 		pkg_cstate_limits = slv_pkg_cstate_limits;
3620ee7e38e3SLen Brown 		break;
3621869ce69eSLen Brown 	case INTEL_FAM6_ATOM_AIRMONT:	/* AMT */
3622ee7e38e3SLen Brown 		pkg_cstate_limits = amt_pkg_cstate_limits;
3623cf4cbe53SLen Brown 		no_MSR_MISC_PWR_MGMT = 1;
3624ee7e38e3SLen Brown 		break;
3625869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* PHI */
3626ee7e38e3SLen Brown 		pkg_cstate_limits = phi_pkg_cstate_limits;
3627ee7e38e3SLen Brown 		break;
3628869ce69eSLen Brown 	case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
3629f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
36305ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
3631f6708400SChen Yu 	case INTEL_FAM6_ATOM_TREMONT:	/* EHL */
363220de0dabSAntti Laakso 	case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
3633445640a5SLen Brown 		pkg_cstate_limits = glm_pkg_cstate_limits;
3634e4085d54SLen Brown 		break;
3635103a8feaSLen Brown 	default:
3636103a8feaSLen Brown 		return 0;
3637103a8feaSLen Brown 	}
36381df2e55aSLen Brown 	get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
3639e9257f5fSLen Brown 	pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
3640ee7e38e3SLen Brown 
3641ec0adc53SLen Brown 	get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
364221ed5574SLen Brown 	base_ratio = (msr >> 8) & 0xFF;
364321ed5574SLen Brown 
364421ed5574SLen Brown 	base_hz = base_ratio * bclk * 1000000;
364521ed5574SLen Brown 	has_base_hz = 1;
3646ee7e38e3SLen Brown 	return 1;
3647103a8feaSLen Brown }
36480f7887c4SLen Brown /*
3649495c7654SLen Brown  * SLV client has support for unique MSRs:
36500f7887c4SLen Brown  *
36510f7887c4SLen Brown  * MSR_CC6_DEMOTION_POLICY_CONFIG
36520f7887c4SLen Brown  * MSR_MC6_DEMOTION_POLICY_CONFIG
36530f7887c4SLen Brown  */
36540f7887c4SLen Brown 
36550f7887c4SLen Brown int has_slv_msrs(unsigned int family, unsigned int model)
36560f7887c4SLen Brown {
36570f7887c4SLen Brown 	if (!genuine_intel)
36580f7887c4SLen Brown 		return 0;
36590f7887c4SLen Brown 
36600f7887c4SLen Brown 	switch (model) {
3661f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT:
3662f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT_MID:
3663f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_AIRMONT_MID:
36640f7887c4SLen Brown 		return 1;
36650f7887c4SLen Brown 	}
36660f7887c4SLen Brown 	return 0;
36670f7887c4SLen Brown }
36687170a374SLen Brown int is_dnv(unsigned int family, unsigned int model)
36697170a374SLen Brown {
36707170a374SLen Brown 
36717170a374SLen Brown 	if (!genuine_intel)
36727170a374SLen Brown 		return 0;
36737170a374SLen Brown 
36747170a374SLen Brown 	switch (model) {
36755ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_D:
36767170a374SLen Brown 		return 1;
36777170a374SLen Brown 	}
36787170a374SLen Brown 	return 0;
36797170a374SLen Brown }
3680ade0ebacSLen Brown int is_bdx(unsigned int family, unsigned int model)
3681ade0ebacSLen Brown {
3682ade0ebacSLen Brown 
3683ade0ebacSLen Brown 	if (!genuine_intel)
3684ade0ebacSLen Brown 		return 0;
3685ade0ebacSLen Brown 
3686ade0ebacSLen Brown 	switch (model) {
3687ade0ebacSLen Brown 	case INTEL_FAM6_BROADWELL_X:
3688ade0ebacSLen Brown 		return 1;
3689ade0ebacSLen Brown 	}
3690ade0ebacSLen Brown 	return 0;
3691ade0ebacSLen Brown }
369234c76197SLen Brown int is_skx(unsigned int family, unsigned int model)
369334c76197SLen Brown {
369434c76197SLen Brown 
369534c76197SLen Brown 	if (!genuine_intel)
369634c76197SLen Brown 		return 0;
369734c76197SLen Brown 
369834c76197SLen Brown 	switch (model) {
369934c76197SLen Brown 	case INTEL_FAM6_SKYLAKE_X:
370034c76197SLen Brown 		return 1;
370134c76197SLen Brown 	}
370234c76197SLen Brown 	return 0;
370334c76197SLen Brown }
3704f6708400SChen Yu int is_ehl(unsigned int family, unsigned int model)
3705f6708400SChen Yu {
3706f6708400SChen Yu 	if (!genuine_intel)
3707f6708400SChen Yu 		return 0;
3708f6708400SChen Yu 
3709f6708400SChen Yu 	switch (model) {
3710f6708400SChen Yu 	case INTEL_FAM6_ATOM_TREMONT:
3711f6708400SChen Yu 		return 1;
3712f6708400SChen Yu 	}
3713f6708400SChen Yu 	return 0;
3714f6708400SChen Yu }
371520de0dabSAntti Laakso int is_jvl(unsigned int family, unsigned int model)
371620de0dabSAntti Laakso {
371720de0dabSAntti Laakso 	if (!genuine_intel)
371820de0dabSAntti Laakso 		return 0;
371920de0dabSAntti Laakso 
372020de0dabSAntti Laakso 	switch (model) {
372120de0dabSAntti Laakso 	case INTEL_FAM6_ATOM_TREMONT_D:
372220de0dabSAntti Laakso 		return 1;
372320de0dabSAntti Laakso 	}
372420de0dabSAntti Laakso 	return 0;
372520de0dabSAntti Laakso }
37260f7887c4SLen Brown 
372731e07522SLen Brown int has_turbo_ratio_limit(unsigned int family, unsigned int model)
3728d7899447SLen Brown {
37290f7887c4SLen Brown 	if (has_slv_msrs(family, model))
37300f7887c4SLen Brown 		return 0;
37310f7887c4SLen Brown 
3732d7899447SLen Brown 	switch (model) {
3733d7899447SLen Brown 	/* Nehalem compatible, but do not include turbo-ratio limit support */
3734869ce69eSLen Brown 	case INTEL_FAM6_NEHALEM_EX:	/* Nehalem-EX Xeon - Beckton */
3735869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* PHI - Knights Landing (different MSR definition) */
3736d7899447SLen Brown 		return 0;
3737d7899447SLen Brown 	default:
3738d7899447SLen Brown 		return 1;
3739d7899447SLen Brown 	}
3740d7899447SLen Brown }
37410f7887c4SLen Brown int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
37420f7887c4SLen Brown {
37430f7887c4SLen Brown 	if (has_slv_msrs(family, model))
37440f7887c4SLen Brown 		return 1;
37450f7887c4SLen Brown 
37460f7887c4SLen Brown 	return 0;
37470f7887c4SLen Brown }
37486574a5d5SLen Brown int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
37496574a5d5SLen Brown {
37506574a5d5SLen Brown 	if (!genuine_intel)
37516574a5d5SLen Brown 		return 0;
37526574a5d5SLen Brown 
37536574a5d5SLen Brown 	if (family != 6)
37546574a5d5SLen Brown 		return 0;
37556574a5d5SLen Brown 
37566574a5d5SLen Brown 	switch (model) {
3757869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE_X:	/* IVB Xeon */
3758869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSW Xeon */
37596574a5d5SLen Brown 		return 1;
37606574a5d5SLen Brown 	default:
37616574a5d5SLen Brown 		return 0;
37626574a5d5SLen Brown 	}
37636574a5d5SLen Brown }
3764fcd17211SLen Brown int has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model)
3765fcd17211SLen Brown {
3766fcd17211SLen Brown 	if (!genuine_intel)
3767fcd17211SLen Brown 		return 0;
3768fcd17211SLen Brown 
3769fcd17211SLen Brown 	if (family != 6)
3770fcd17211SLen Brown 		return 0;
3771fcd17211SLen Brown 
3772fcd17211SLen Brown 	switch (model) {
3773869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSW Xeon */
3774fcd17211SLen Brown 		return 1;
3775fcd17211SLen Brown 	default:
3776fcd17211SLen Brown 		return 0;
3777fcd17211SLen Brown 	}
3778fcd17211SLen Brown }
3779fcd17211SLen Brown 
3780fb5d4327SDasaratharaman Chandramouli int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model)
3781fb5d4327SDasaratharaman Chandramouli {
3782fb5d4327SDasaratharaman Chandramouli 	if (!genuine_intel)
3783fb5d4327SDasaratharaman Chandramouli 		return 0;
3784fb5d4327SDasaratharaman Chandramouli 
3785fb5d4327SDasaratharaman Chandramouli 	if (family != 6)
3786fb5d4327SDasaratharaman Chandramouli 		return 0;
3787fb5d4327SDasaratharaman Chandramouli 
3788fb5d4327SDasaratharaman Chandramouli 	switch (model) {
3789869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* Knights Landing */
3790fb5d4327SDasaratharaman Chandramouli 		return 1;
3791fb5d4327SDasaratharaman Chandramouli 	default:
3792fb5d4327SDasaratharaman Chandramouli 		return 0;
3793fb5d4327SDasaratharaman Chandramouli 	}
3794fb5d4327SDasaratharaman Chandramouli }
379531e07522SLen Brown int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model)
379631e07522SLen Brown {
379731e07522SLen Brown 	if (!genuine_intel)
379831e07522SLen Brown 		return 0;
379931e07522SLen Brown 
380031e07522SLen Brown 	if (family != 6)
380131e07522SLen Brown 		return 0;
380231e07522SLen Brown 
380331e07522SLen Brown 	switch (model) {
380431e07522SLen Brown 	case INTEL_FAM6_ATOM_GOLDMONT:
380531e07522SLen Brown 	case INTEL_FAM6_SKYLAKE_X:
380631e07522SLen Brown 		return 1;
380731e07522SLen Brown 	default:
380831e07522SLen Brown 		return 0;
380931e07522SLen Brown 	}
381031e07522SLen Brown }
38116fb3143bSLen Brown int has_config_tdp(unsigned int family, unsigned int model)
38126fb3143bSLen Brown {
38136fb3143bSLen Brown 	if (!genuine_intel)
38146fb3143bSLen Brown 		return 0;
38156fb3143bSLen Brown 
38166fb3143bSLen Brown 	if (family != 6)
38176fb3143bSLen Brown 		return 0;
38186fb3143bSLen Brown 
38196fb3143bSLen Brown 	switch (model) {
3820869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE:	/* IVB */
3821c66f78a6SPeter Zijlstra 	case INTEL_FAM6_HASWELL:	/* HSW */
3822869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSX */
382377e5517cSIngo Molnar 	case INTEL_FAM6_HASWELL_L:	/* HSW */
38245e741407SPeter Zijlstra 	case INTEL_FAM6_HASWELL_G:	/* HSW */
3825c66f78a6SPeter Zijlstra 	case INTEL_FAM6_BROADWELL:	/* BDW */
38265e741407SPeter Zijlstra 	case INTEL_FAM6_BROADWELL_G:	/* BDW */
3827869ce69eSLen Brown 	case INTEL_FAM6_BROADWELL_X:	/* BDX */
3828af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
3829af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
3830869ce69eSLen Brown 	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
38316fb3143bSLen Brown 
3832869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* Knights Landing */
38336fb3143bSLen Brown 		return 1;
38346fb3143bSLen Brown 	default:
38356fb3143bSLen Brown 		return 0;
38366fb3143bSLen Brown 	}
38376fb3143bSLen Brown }
38386fb3143bSLen Brown 
3839fcd17211SLen Brown static void
3840fecb3bc8SDavid Arcari remove_underbar(char *s)
3841fecb3bc8SDavid Arcari {
3842fecb3bc8SDavid Arcari 	char *to = s;
3843fecb3bc8SDavid Arcari 
3844fecb3bc8SDavid Arcari 	while (*s) {
3845fecb3bc8SDavid Arcari 		if (*s != '_')
3846fecb3bc8SDavid Arcari 			*to++ = *s;
3847fecb3bc8SDavid Arcari 		s++;
3848fecb3bc8SDavid Arcari 	}
3849fecb3bc8SDavid Arcari 
3850fecb3bc8SDavid Arcari 	*to = 0;
3851fecb3bc8SDavid Arcari }
3852fecb3bc8SDavid Arcari 
3853fecb3bc8SDavid Arcari static void
38541b69317dSColin Ian King dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
3855fcd17211SLen Brown {
3856fcd17211SLen Brown 	if (!do_nhm_platform_info)
3857fcd17211SLen Brown 		return;
3858fcd17211SLen Brown 
3859fcd17211SLen Brown 	dump_nhm_platform_info();
3860fcd17211SLen Brown 
3861fcd17211SLen Brown 	if (has_hsw_turbo_ratio_limit(family, model))
3862fcd17211SLen Brown 		dump_hsw_turbo_ratio_limits();
3863fcd17211SLen Brown 
3864fcd17211SLen Brown 	if (has_ivt_turbo_ratio_limit(family, model))
3865fcd17211SLen Brown 		dump_ivt_turbo_ratio_limits();
3866fcd17211SLen Brown 
386731e07522SLen Brown 	if (has_turbo_ratio_limit(family, model))
386831e07522SLen Brown 		dump_turbo_ratio_limits(family, model);
3869fcd17211SLen Brown 
38700f7887c4SLen Brown 	if (has_atom_turbo_ratio_limit(family, model))
38710f7887c4SLen Brown 		dump_atom_turbo_ratio_limits();
38720f7887c4SLen Brown 
3873fb5d4327SDasaratharaman Chandramouli 	if (has_knl_turbo_ratio_limit(family, model))
3874fb5d4327SDasaratharaman Chandramouli 		dump_knl_turbo_ratio_limits();
3875fb5d4327SDasaratharaman Chandramouli 
38766fb3143bSLen Brown 	if (has_config_tdp(family, model))
38776fb3143bSLen Brown 		dump_config_tdp();
38786fb3143bSLen Brown 
3879fcd17211SLen Brown 	dump_nhm_cst_cfg();
3880fcd17211SLen Brown }
3881fcd17211SLen Brown 
3882abdcbdb2SLen Brown static void dump_sysfs_file(char *path)
3883abdcbdb2SLen Brown {
3884abdcbdb2SLen Brown 	FILE *input;
3885abdcbdb2SLen Brown 	char cpuidle_buf[64];
3886abdcbdb2SLen Brown 
3887abdcbdb2SLen Brown 	input = fopen(path, "r");
3888abdcbdb2SLen Brown 	if (input == NULL) {
3889abdcbdb2SLen Brown 		if (debug)
3890abdcbdb2SLen Brown 			fprintf(outf, "NSFOD %s\n", path);
3891abdcbdb2SLen Brown 		return;
3892abdcbdb2SLen Brown 	}
3893abdcbdb2SLen Brown 	if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input))
3894abdcbdb2SLen Brown 		err(1, "%s: failed to read file", path);
3895abdcbdb2SLen Brown 	fclose(input);
3896abdcbdb2SLen Brown 
3897abdcbdb2SLen Brown 	fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);
3898abdcbdb2SLen Brown }
389941618e63SLen Brown static void
390041618e63SLen Brown dump_sysfs_cstate_config(void)
390141618e63SLen Brown {
390241618e63SLen Brown 	char path[64];
390341618e63SLen Brown 	char name_buf[16];
390441618e63SLen Brown 	char desc[64];
390541618e63SLen Brown 	FILE *input;
390641618e63SLen Brown 	int state;
390741618e63SLen Brown 	char *sp;
390841618e63SLen Brown 
3909abdcbdb2SLen Brown 	if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {
3910abdcbdb2SLen Brown 		fprintf(outf, "cpuidle not loaded\n");
3911abdcbdb2SLen Brown 		return;
3912abdcbdb2SLen Brown 	}
3913abdcbdb2SLen Brown 
3914abdcbdb2SLen Brown 	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver");
3915abdcbdb2SLen Brown 	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor");
3916abdcbdb2SLen Brown 	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro");
3917abdcbdb2SLen Brown 
391841618e63SLen Brown 	for (state = 0; state < 10; ++state) {
391941618e63SLen Brown 
392041618e63SLen Brown 		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
392141618e63SLen Brown 			base_cpu, state);
392241618e63SLen Brown 		input = fopen(path, "r");
392341618e63SLen Brown 		if (input == NULL)
392441618e63SLen Brown 			continue;
39258173c336SBen Hutchings 		if (!fgets(name_buf, sizeof(name_buf), input))
39268173c336SBen Hutchings 			err(1, "%s: failed to read file", path);
392741618e63SLen Brown 
392841618e63SLen Brown 		 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
392941618e63SLen Brown 		sp = strchr(name_buf, '-');
393041618e63SLen Brown 		if (!sp)
393141618e63SLen Brown 			sp = strchrnul(name_buf, '\n');
393241618e63SLen Brown 		*sp = '\0';
393341618e63SLen Brown 		fclose(input);
393441618e63SLen Brown 
3935fecb3bc8SDavid Arcari 		remove_underbar(name_buf);
3936fecb3bc8SDavid Arcari 
393741618e63SLen Brown 		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
393841618e63SLen Brown 			base_cpu, state);
393941618e63SLen Brown 		input = fopen(path, "r");
394041618e63SLen Brown 		if (input == NULL)
394141618e63SLen Brown 			continue;
39428173c336SBen Hutchings 		if (!fgets(desc, sizeof(desc), input))
39438173c336SBen Hutchings 			err(1, "%s: failed to read file", path);
394441618e63SLen Brown 
394541618e63SLen Brown 		fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc);
394641618e63SLen Brown 		fclose(input);
394741618e63SLen Brown 	}
394841618e63SLen Brown }
39497293fccdSLen Brown static void
39507293fccdSLen Brown dump_sysfs_pstate_config(void)
39517293fccdSLen Brown {
39527293fccdSLen Brown 	char path[64];
39537293fccdSLen Brown 	char driver_buf[64];
39547293fccdSLen Brown 	char governor_buf[64];
39557293fccdSLen Brown 	FILE *input;
39567293fccdSLen Brown 	int turbo;
39577293fccdSLen Brown 
39587293fccdSLen Brown 	sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver",
39597293fccdSLen Brown 			base_cpu);
39607293fccdSLen Brown 	input = fopen(path, "r");
39617293fccdSLen Brown 	if (input == NULL) {
39620a42d235SPrarit Bhargava 		fprintf(outf, "NSFOD %s\n", path);
39637293fccdSLen Brown 		return;
39647293fccdSLen Brown 	}
39658173c336SBen Hutchings 	if (!fgets(driver_buf, sizeof(driver_buf), input))
39668173c336SBen Hutchings 		err(1, "%s: failed to read file", path);
39677293fccdSLen Brown 	fclose(input);
39687293fccdSLen Brown 
39697293fccdSLen Brown 	sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor",
39707293fccdSLen Brown 			base_cpu);
39717293fccdSLen Brown 	input = fopen(path, "r");
39727293fccdSLen Brown 	if (input == NULL) {
39730a42d235SPrarit Bhargava 		fprintf(outf, "NSFOD %s\n", path);
39747293fccdSLen Brown 		return;
39757293fccdSLen Brown 	}
39768173c336SBen Hutchings 	if (!fgets(governor_buf, sizeof(governor_buf), input))
39778173c336SBen Hutchings 		err(1, "%s: failed to read file", path);
39787293fccdSLen Brown 	fclose(input);
39797293fccdSLen Brown 
39807293fccdSLen Brown 	fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf);
39817293fccdSLen Brown 	fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf);
39827293fccdSLen Brown 
39837293fccdSLen Brown 	sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");
39847293fccdSLen Brown 	input = fopen(path, "r");
39857293fccdSLen Brown 	if (input != NULL) {
39868173c336SBen Hutchings 		if (fscanf(input, "%d", &turbo) != 1)
39878173c336SBen Hutchings 			err(1, "%s: failed to parse number from file", path);
39887293fccdSLen Brown 		fprintf(outf, "cpufreq boost: %d\n", turbo);
39897293fccdSLen Brown 		fclose(input);
39907293fccdSLen Brown 	}
39917293fccdSLen Brown 
39927293fccdSLen Brown 	sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");
39937293fccdSLen Brown 	input = fopen(path, "r");
39947293fccdSLen Brown 	if (input != NULL) {
39958173c336SBen Hutchings 		if (fscanf(input, "%d", &turbo) != 1)
39968173c336SBen Hutchings 			err(1, "%s: failed to parse number from file", path);
39977293fccdSLen Brown 		fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);
39987293fccdSLen Brown 		fclose(input);
39997293fccdSLen Brown 	}
40007293fccdSLen Brown }
400141618e63SLen Brown 
40026574a5d5SLen Brown 
4003889facbeSLen Brown /*
4004889facbeSLen Brown  * print_epb()
4005889facbeSLen Brown  * Decode the ENERGY_PERF_BIAS MSR
4006889facbeSLen Brown  */
4007889facbeSLen Brown int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4008889facbeSLen Brown {
4009889facbeSLen Brown 	char *epb_string;
40106d6501d9SBorislav Petkov 	int cpu, epb;
4011889facbeSLen Brown 
4012889facbeSLen Brown 	if (!has_epb)
4013889facbeSLen Brown 		return 0;
4014889facbeSLen Brown 
4015889facbeSLen Brown 	cpu = t->cpu_id;
4016889facbeSLen Brown 
4017889facbeSLen Brown 	/* EPB is per-package */
4018889facbeSLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4019889facbeSLen Brown 		return 0;
4020889facbeSLen Brown 
4021889facbeSLen Brown 	if (cpu_migrate(cpu)) {
40223d7772eaSLen Brown 		fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);
4023889facbeSLen Brown 		return -1;
4024889facbeSLen Brown 	}
4025889facbeSLen Brown 
40266d6501d9SBorislav Petkov 	epb = get_epb(cpu);
40276d6501d9SBorislav Petkov 	if (epb < 0)
4028889facbeSLen Brown 		return 0;
4029889facbeSLen Brown 
40306d6501d9SBorislav Petkov 	switch (epb) {
4031889facbeSLen Brown 	case ENERGY_PERF_BIAS_PERFORMANCE:
4032889facbeSLen Brown 		epb_string = "performance";
4033889facbeSLen Brown 		break;
4034889facbeSLen Brown 	case ENERGY_PERF_BIAS_NORMAL:
4035889facbeSLen Brown 		epb_string = "balanced";
4036889facbeSLen Brown 		break;
4037889facbeSLen Brown 	case ENERGY_PERF_BIAS_POWERSAVE:
4038889facbeSLen Brown 		epb_string = "powersave";
4039889facbeSLen Brown 		break;
4040889facbeSLen Brown 	default:
4041889facbeSLen Brown 		epb_string = "custom";
4042889facbeSLen Brown 		break;
4043889facbeSLen Brown 	}
40446d6501d9SBorislav Petkov 	fprintf(outf, "cpu%d: EPB: %d (%s)\n", cpu, epb, epb_string);
4045889facbeSLen Brown 
4046889facbeSLen Brown 	return 0;
4047889facbeSLen Brown }
40487f5c258eSLen Brown /*
40497f5c258eSLen Brown  * print_hwp()
40507f5c258eSLen Brown  * Decode the MSR_HWP_CAPABILITIES
40517f5c258eSLen Brown  */
40527f5c258eSLen Brown int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
40537f5c258eSLen Brown {
40547f5c258eSLen Brown 	unsigned long long msr;
40557f5c258eSLen Brown 	int cpu;
40567f5c258eSLen Brown 
40577f5c258eSLen Brown 	if (!has_hwp)
40587f5c258eSLen Brown 		return 0;
40597f5c258eSLen Brown 
40607f5c258eSLen Brown 	cpu = t->cpu_id;
40617f5c258eSLen Brown 
40627f5c258eSLen Brown 	/* MSR_HWP_CAPABILITIES is per-package */
40637f5c258eSLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
40647f5c258eSLen Brown 		return 0;
40657f5c258eSLen Brown 
40667f5c258eSLen Brown 	if (cpu_migrate(cpu)) {
40673d7772eaSLen Brown 		fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);
40687f5c258eSLen Brown 		return -1;
40697f5c258eSLen Brown 	}
40707f5c258eSLen Brown 
40717f5c258eSLen Brown 	if (get_msr(cpu, MSR_PM_ENABLE, &msr))
40727f5c258eSLen Brown 		return 0;
40737f5c258eSLen Brown 
4074b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n",
40757f5c258eSLen Brown 		cpu, msr, (msr & (1 << 0)) ? "" : "No-");
40767f5c258eSLen Brown 
40777f5c258eSLen Brown 	/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
40787f5c258eSLen Brown 	if ((msr & (1 << 0)) == 0)
40797f5c258eSLen Brown 		return 0;
40807f5c258eSLen Brown 
40817f5c258eSLen Brown 	if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))
40827f5c258eSLen Brown 		return 0;
40837f5c258eSLen Brown 
4084b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "
40856dbd25a2SLen Brown 			"(high %d guar %d eff %d low %d)\n",
40867f5c258eSLen Brown 			cpu, msr,
40877f5c258eSLen Brown 			(unsigned int)HWP_HIGHEST_PERF(msr),
40887f5c258eSLen Brown 			(unsigned int)HWP_GUARANTEED_PERF(msr),
40897f5c258eSLen Brown 			(unsigned int)HWP_MOSTEFFICIENT_PERF(msr),
40907f5c258eSLen Brown 			(unsigned int)HWP_LOWEST_PERF(msr));
40917f5c258eSLen Brown 
40927f5c258eSLen Brown 	if (get_msr(cpu, MSR_HWP_REQUEST, &msr))
40937f5c258eSLen Brown 		return 0;
40947f5c258eSLen Brown 
4095b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "
40966dbd25a2SLen Brown 			"(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",
40977f5c258eSLen Brown 			cpu, msr,
40987f5c258eSLen Brown 			(unsigned int)(((msr) >> 0) & 0xff),
40997f5c258eSLen Brown 			(unsigned int)(((msr) >> 8) & 0xff),
41007f5c258eSLen Brown 			(unsigned int)(((msr) >> 16) & 0xff),
41017f5c258eSLen Brown 			(unsigned int)(((msr) >> 24) & 0xff),
41027f5c258eSLen Brown 			(unsigned int)(((msr) >> 32) & 0xff3),
41037f5c258eSLen Brown 			(unsigned int)(((msr) >> 42) & 0x1));
41047f5c258eSLen Brown 
41057f5c258eSLen Brown 	if (has_hwp_pkg) {
41067f5c258eSLen Brown 		if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))
41077f5c258eSLen Brown 			return 0;
41087f5c258eSLen Brown 
4109b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "
41106dbd25a2SLen Brown 			"(min %d max %d des %d epp 0x%x window 0x%x)\n",
41117f5c258eSLen Brown 			cpu, msr,
41127f5c258eSLen Brown 			(unsigned int)(((msr) >> 0) & 0xff),
41137f5c258eSLen Brown 			(unsigned int)(((msr) >> 8) & 0xff),
41147f5c258eSLen Brown 			(unsigned int)(((msr) >> 16) & 0xff),
41157f5c258eSLen Brown 			(unsigned int)(((msr) >> 24) & 0xff),
41167f5c258eSLen Brown 			(unsigned int)(((msr) >> 32) & 0xff3));
41177f5c258eSLen Brown 	}
41187f5c258eSLen Brown 	if (has_hwp_notify) {
41197f5c258eSLen Brown 		if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))
41207f5c258eSLen Brown 			return 0;
41217f5c258eSLen Brown 
4122b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "
41237f5c258eSLen Brown 			"(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",
41247f5c258eSLen Brown 			cpu, msr,
41257f5c258eSLen Brown 			((msr) & 0x1) ? "EN" : "Dis",
41267f5c258eSLen Brown 			((msr) & 0x2) ? "EN" : "Dis");
41277f5c258eSLen Brown 	}
41287f5c258eSLen Brown 	if (get_msr(cpu, MSR_HWP_STATUS, &msr))
41297f5c258eSLen Brown 		return 0;
41307f5c258eSLen Brown 
4131b7d8c148SLen Brown 	fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
41327f5c258eSLen Brown 			"(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
41337f5c258eSLen Brown 			cpu, msr,
41347f5c258eSLen Brown 			((msr) & 0x1) ? "" : "No-",
41357f5c258eSLen Brown 			((msr) & 0x2) ? "" : "No-");
4136889facbeSLen Brown 
4137889facbeSLen Brown 	return 0;
4138889facbeSLen Brown }
4139889facbeSLen Brown 
41403a9a941dSLen Brown /*
41413a9a941dSLen Brown  * print_perf_limit()
41423a9a941dSLen Brown  */
41433a9a941dSLen Brown int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p)
41443a9a941dSLen Brown {
41453a9a941dSLen Brown 	unsigned long long msr;
41463a9a941dSLen Brown 	int cpu;
41473a9a941dSLen Brown 
41483a9a941dSLen Brown 	cpu = t->cpu_id;
41493a9a941dSLen Brown 
41503a9a941dSLen Brown 	/* per-package */
41513a9a941dSLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
41523a9a941dSLen Brown 		return 0;
41533a9a941dSLen Brown 
41543a9a941dSLen Brown 	if (cpu_migrate(cpu)) {
41553d7772eaSLen Brown 		fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);
41563a9a941dSLen Brown 		return -1;
41573a9a941dSLen Brown 	}
41583a9a941dSLen Brown 
41593a9a941dSLen Brown 	if (do_core_perf_limit_reasons) {
41603a9a941dSLen Brown 		get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
4161b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
4162b7d8c148SLen Brown 		fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
4163e33cbe85SLen Brown 			(msr & 1 << 15) ? "bit15, " : "",
41643a9a941dSLen Brown 			(msr & 1 << 14) ? "bit14, " : "",
4165e33cbe85SLen Brown 			(msr & 1 << 13) ? "Transitions, " : "",
4166e33cbe85SLen Brown 			(msr & 1 << 12) ? "MultiCoreTurbo, " : "",
4167e33cbe85SLen Brown 			(msr & 1 << 11) ? "PkgPwrL2, " : "",
4168e33cbe85SLen Brown 			(msr & 1 << 10) ? "PkgPwrL1, " : "",
4169e33cbe85SLen Brown 			(msr & 1 << 9) ? "CorePwr, " : "",
4170e33cbe85SLen Brown 			(msr & 1 << 8) ? "Amps, " : "",
4171e33cbe85SLen Brown 			(msr & 1 << 6) ? "VR-Therm, " : "",
4172e33cbe85SLen Brown 			(msr & 1 << 5) ? "Auto-HWP, " : "",
4173e33cbe85SLen Brown 			(msr & 1 << 4) ? "Graphics, " : "",
4174e33cbe85SLen Brown 			(msr & 1 << 2) ? "bit2, " : "",
4175e33cbe85SLen Brown 			(msr & 1 << 1) ? "ThermStatus, " : "",
4176e33cbe85SLen Brown 			(msr & 1 << 0) ? "PROCHOT, " : "");
4177b7d8c148SLen Brown 		fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
4178e33cbe85SLen Brown 			(msr & 1 << 31) ? "bit31, " : "",
41793a9a941dSLen Brown 			(msr & 1 << 30) ? "bit30, " : "",
4180e33cbe85SLen Brown 			(msr & 1 << 29) ? "Transitions, " : "",
4181e33cbe85SLen Brown 			(msr & 1 << 28) ? "MultiCoreTurbo, " : "",
4182e33cbe85SLen Brown 			(msr & 1 << 27) ? "PkgPwrL2, " : "",
4183e33cbe85SLen Brown 			(msr & 1 << 26) ? "PkgPwrL1, " : "",
4184e33cbe85SLen Brown 			(msr & 1 << 25) ? "CorePwr, " : "",
4185e33cbe85SLen Brown 			(msr & 1 << 24) ? "Amps, " : "",
4186e33cbe85SLen Brown 			(msr & 1 << 22) ? "VR-Therm, " : "",
4187e33cbe85SLen Brown 			(msr & 1 << 21) ? "Auto-HWP, " : "",
4188e33cbe85SLen Brown 			(msr & 1 << 20) ? "Graphics, " : "",
4189e33cbe85SLen Brown 			(msr & 1 << 18) ? "bit18, " : "",
4190e33cbe85SLen Brown 			(msr & 1 << 17) ? "ThermStatus, " : "",
4191e33cbe85SLen Brown 			(msr & 1 << 16) ? "PROCHOT, " : "");
41923a9a941dSLen Brown 
41933a9a941dSLen Brown 	}
41943a9a941dSLen Brown 	if (do_gfx_perf_limit_reasons) {
41953a9a941dSLen Brown 		get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);
4196b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
4197b7d8c148SLen Brown 		fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",
41983a9a941dSLen Brown 			(msr & 1 << 0) ? "PROCHOT, " : "",
41993a9a941dSLen Brown 			(msr & 1 << 1) ? "ThermStatus, " : "",
42003a9a941dSLen Brown 			(msr & 1 << 4) ? "Graphics, " : "",
42013a9a941dSLen Brown 			(msr & 1 << 6) ? "VR-Therm, " : "",
42023a9a941dSLen Brown 			(msr & 1 << 8) ? "Amps, " : "",
42033a9a941dSLen Brown 			(msr & 1 << 9) ? "GFXPwr, " : "",
42043a9a941dSLen Brown 			(msr & 1 << 10) ? "PkgPwrL1, " : "",
42053a9a941dSLen Brown 			(msr & 1 << 11) ? "PkgPwrL2, " : "");
4206b7d8c148SLen Brown 		fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",
42073a9a941dSLen Brown 			(msr & 1 << 16) ? "PROCHOT, " : "",
42083a9a941dSLen Brown 			(msr & 1 << 17) ? "ThermStatus, " : "",
42093a9a941dSLen Brown 			(msr & 1 << 20) ? "Graphics, " : "",
42103a9a941dSLen Brown 			(msr & 1 << 22) ? "VR-Therm, " : "",
42113a9a941dSLen Brown 			(msr & 1 << 24) ? "Amps, " : "",
42123a9a941dSLen Brown 			(msr & 1 << 25) ? "GFXPwr, " : "",
42133a9a941dSLen Brown 			(msr & 1 << 26) ? "PkgPwrL1, " : "",
42143a9a941dSLen Brown 			(msr & 1 << 27) ? "PkgPwrL2, " : "");
42153a9a941dSLen Brown 	}
42163a9a941dSLen Brown 	if (do_ring_perf_limit_reasons) {
42173a9a941dSLen Brown 		get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
4218b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
4219b7d8c148SLen Brown 		fprintf(outf, " (Active: %s%s%s%s%s%s)",
42203a9a941dSLen Brown 			(msr & 1 << 0) ? "PROCHOT, " : "",
42213a9a941dSLen Brown 			(msr & 1 << 1) ? "ThermStatus, " : "",
42223a9a941dSLen Brown 			(msr & 1 << 6) ? "VR-Therm, " : "",
42233a9a941dSLen Brown 			(msr & 1 << 8) ? "Amps, " : "",
42243a9a941dSLen Brown 			(msr & 1 << 10) ? "PkgPwrL1, " : "",
42253a9a941dSLen Brown 			(msr & 1 << 11) ? "PkgPwrL2, " : "");
4226b7d8c148SLen Brown 		fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",
42273a9a941dSLen Brown 			(msr & 1 << 16) ? "PROCHOT, " : "",
42283a9a941dSLen Brown 			(msr & 1 << 17) ? "ThermStatus, " : "",
42293a9a941dSLen Brown 			(msr & 1 << 22) ? "VR-Therm, " : "",
42303a9a941dSLen Brown 			(msr & 1 << 24) ? "Amps, " : "",
42313a9a941dSLen Brown 			(msr & 1 << 26) ? "PkgPwrL1, " : "",
42323a9a941dSLen Brown 			(msr & 1 << 27) ? "PkgPwrL2, " : "");
42333a9a941dSLen Brown 	}
42343a9a941dSLen Brown 	return 0;
42353a9a941dSLen Brown }
42363a9a941dSLen Brown 
4237889facbeSLen Brown #define	RAPL_POWER_GRANULARITY	0x7FFF	/* 15 bit power granularity */
4238889facbeSLen Brown #define	RAPL_TIME_GRANULARITY	0x3F /* 6 bit time granularity */
4239889facbeSLen Brown 
42409392bd98SCalvin Walton double get_tdp_intel(unsigned int model)
4241144b44b1SLen Brown {
4242144b44b1SLen Brown 	unsigned long long msr;
4243144b44b1SLen Brown 
4244144b44b1SLen Brown 	if (do_rapl & RAPL_PKG_POWER_INFO)
42457ce7d5deSPrarit Bhargava 		if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr))
4246144b44b1SLen Brown 			return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;
4247144b44b1SLen Brown 
4248144b44b1SLen Brown 	switch (model) {
4249f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT:
42505ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT_D:
4251144b44b1SLen Brown 		return 30.0;
4252144b44b1SLen Brown 	default:
4253144b44b1SLen Brown 		return 135.0;
4254144b44b1SLen Brown 	}
4255144b44b1SLen Brown }
4256144b44b1SLen Brown 
42579392bd98SCalvin Walton double get_tdp_amd(unsigned int family)
42589392bd98SCalvin Walton {
425933eb8225SKim Phillips 	/* This is the max stock TDP of HEDT/Server Fam17h+ chips */
426033eb8225SKim Phillips 	return 280.0;
42619392bd98SCalvin Walton }
42629392bd98SCalvin Walton 
426340ee8e3bSAndrey Semin /*
426440ee8e3bSAndrey Semin  * rapl_dram_energy_units_probe()
426540ee8e3bSAndrey Semin  * Energy units are either hard-coded, or come from RAPL Energy Unit MSR.
426640ee8e3bSAndrey Semin  */
426740ee8e3bSAndrey Semin static double
426840ee8e3bSAndrey Semin rapl_dram_energy_units_probe(int  model, double rapl_energy_units)
426940ee8e3bSAndrey Semin {
427040ee8e3bSAndrey Semin 	/* only called for genuine_intel, family 6 */
427140ee8e3bSAndrey Semin 
427240ee8e3bSAndrey Semin 	switch (model) {
4273869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSX */
4274869ce69eSLen Brown 	case INTEL_FAM6_BROADWELL_X:	/* BDX */
4275*abdc75abSZhang Rui 	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
4276869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* KNL */
427740ee8e3bSAndrey Semin 		return (rapl_dram_energy_units = 15.3 / 1000000);
427840ee8e3bSAndrey Semin 	default:
427940ee8e3bSAndrey Semin 		return (rapl_energy_units);
428040ee8e3bSAndrey Semin 	}
428140ee8e3bSAndrey Semin }
428240ee8e3bSAndrey Semin 
42839392bd98SCalvin Walton void rapl_probe_intel(unsigned int family, unsigned int model)
4284889facbeSLen Brown {
4285889facbeSLen Brown 	unsigned long long msr;
4286144b44b1SLen Brown 	unsigned int time_unit;
4287889facbeSLen Brown 	double tdp;
4288889facbeSLen Brown 
4289889facbeSLen Brown 	if (family != 6)
4290889facbeSLen Brown 		return;
4291889facbeSLen Brown 
4292889facbeSLen Brown 	switch (model) {
4293869ce69eSLen Brown 	case INTEL_FAM6_SANDYBRIDGE:
4294869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE:
4295c66f78a6SPeter Zijlstra 	case INTEL_FAM6_HASWELL:	/* HSW */
429677e5517cSIngo Molnar 	case INTEL_FAM6_HASWELL_L:	/* HSW */
42975e741407SPeter Zijlstra 	case INTEL_FAM6_HASWELL_G:	/* HSW */
4298c66f78a6SPeter Zijlstra 	case INTEL_FAM6_BROADWELL:	/* BDW */
42995e741407SPeter Zijlstra 	case INTEL_FAM6_BROADWELL_G:	/* BDW */
4300144b44b1SLen Brown 		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
4301812db3f7SLen Brown 		if (rapl_joules) {
4302812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4303812db3f7SLen Brown 			BIC_PRESENT(BIC_Cor_J);
4304812db3f7SLen Brown 			BIC_PRESENT(BIC_GFX_J);
4305812db3f7SLen Brown 		} else {
4306812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4307812db3f7SLen Brown 			BIC_PRESENT(BIC_CorWatt);
4308812db3f7SLen Brown 			BIC_PRESENT(BIC_GFXWatt);
4309812db3f7SLen Brown 		}
4310889facbeSLen Brown 		break;
4311869ce69eSLen Brown 	case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
4312f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
4313e4085d54SLen Brown 		do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO;
4314812db3f7SLen Brown 		if (rapl_joules)
4315812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4316812db3f7SLen Brown 		else
4317812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4318e4085d54SLen Brown 		break;
4319f6708400SChen Yu 	case INTEL_FAM6_ATOM_TREMONT:	/* EHL */
4320f6708400SChen Yu 		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
4321f6708400SChen Yu 		if (rapl_joules) {
4322f6708400SChen Yu 			BIC_PRESENT(BIC_Pkg_J);
4323f6708400SChen Yu 			BIC_PRESENT(BIC_Cor_J);
4324f6708400SChen Yu 			BIC_PRESENT(BIC_RAM_J);
4325f6708400SChen Yu 			BIC_PRESENT(BIC_GFX_J);
4326f6708400SChen Yu 		} else {
4327f6708400SChen Yu 			BIC_PRESENT(BIC_PkgWatt);
4328f6708400SChen Yu 			BIC_PRESENT(BIC_CorWatt);
4329f6708400SChen Yu 			BIC_PRESENT(BIC_RAMWatt);
4330f6708400SChen Yu 			BIC_PRESENT(BIC_GFXWatt);
4331f6708400SChen Yu 		}
4332f6708400SChen Yu 		break;
433320de0dabSAntti Laakso 	case INTEL_FAM6_ATOM_TREMONT_D:	/* JVL */
433420de0dabSAntti Laakso 		do_rapl = RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
433520de0dabSAntti Laakso 		BIC_PRESENT(BIC_PKG__);
433620de0dabSAntti Laakso 		if (rapl_joules)
433720de0dabSAntti Laakso 			BIC_PRESENT(BIC_Pkg_J);
433820de0dabSAntti Laakso 		else
433920de0dabSAntti Laakso 			BIC_PRESENT(BIC_PkgWatt);
434020de0dabSAntti Laakso 		break;
4341af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
4342af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
434381824921SLen Brown 		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
4344812db3f7SLen Brown 		BIC_PRESENT(BIC_PKG__);
4345812db3f7SLen Brown 		BIC_PRESENT(BIC_RAM__);
4346812db3f7SLen Brown 		if (rapl_joules) {
4347812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4348812db3f7SLen Brown 			BIC_PRESENT(BIC_Cor_J);
4349812db3f7SLen Brown 			BIC_PRESENT(BIC_RAM_J);
435081824921SLen Brown 			BIC_PRESENT(BIC_GFX_J);
4351812db3f7SLen Brown 		} else {
4352812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4353812db3f7SLen Brown 			BIC_PRESENT(BIC_CorWatt);
4354812db3f7SLen Brown 			BIC_PRESENT(BIC_RAMWatt);
435581824921SLen Brown 			BIC_PRESENT(BIC_GFXWatt);
4356812db3f7SLen Brown 		}
43570b2bb692SLen Brown 		break;
4358869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSX */
4359869ce69eSLen Brown 	case INTEL_FAM6_BROADWELL_X:	/* BDX */
4360869ce69eSLen Brown 	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
4361869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* KNL */
43620b2bb692SLen Brown 		do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
4363812db3f7SLen Brown 		BIC_PRESENT(BIC_PKG__);
4364812db3f7SLen Brown 		BIC_PRESENT(BIC_RAM__);
4365812db3f7SLen Brown 		if (rapl_joules) {
4366812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4367812db3f7SLen Brown 			BIC_PRESENT(BIC_RAM_J);
4368812db3f7SLen Brown 		} else {
4369812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4370812db3f7SLen Brown 			BIC_PRESENT(BIC_RAMWatt);
4371812db3f7SLen Brown 		}
4372e6f9bb3cSLen Brown 		break;
4373869ce69eSLen Brown 	case INTEL_FAM6_SANDYBRIDGE_X:
4374869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE_X:
43750b2bb692SLen Brown 		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
4376812db3f7SLen Brown 		BIC_PRESENT(BIC_PKG__);
4377812db3f7SLen Brown 		BIC_PRESENT(BIC_RAM__);
4378812db3f7SLen Brown 		if (rapl_joules) {
4379812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4380812db3f7SLen Brown 			BIC_PRESENT(BIC_Cor_J);
4381812db3f7SLen Brown 			BIC_PRESENT(BIC_RAM_J);
4382812db3f7SLen Brown 		} else {
4383812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4384812db3f7SLen Brown 			BIC_PRESENT(BIC_CorWatt);
4385812db3f7SLen Brown 			BIC_PRESENT(BIC_RAMWatt);
4386812db3f7SLen Brown 		}
4387144b44b1SLen Brown 		break;
4388f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT:	/* BYT */
43895ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT_D:	/* AVN */
4390144b44b1SLen Brown 		do_rapl = RAPL_PKG | RAPL_CORES;
4391812db3f7SLen Brown 		if (rapl_joules) {
4392812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4393812db3f7SLen Brown 			BIC_PRESENT(BIC_Cor_J);
4394812db3f7SLen Brown 		} else {
4395812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4396812db3f7SLen Brown 			BIC_PRESENT(BIC_CorWatt);
4397812db3f7SLen Brown 		}
4398889facbeSLen Brown 		break;
43995ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
44000f644909SJacob Pan 		do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
4401812db3f7SLen Brown 		BIC_PRESENT(BIC_PKG__);
4402812db3f7SLen Brown 		BIC_PRESENT(BIC_RAM__);
4403812db3f7SLen Brown 		if (rapl_joules) {
4404812db3f7SLen Brown 			BIC_PRESENT(BIC_Pkg_J);
4405812db3f7SLen Brown 			BIC_PRESENT(BIC_Cor_J);
4406812db3f7SLen Brown 			BIC_PRESENT(BIC_RAM_J);
4407812db3f7SLen Brown 		} else {
4408812db3f7SLen Brown 			BIC_PRESENT(BIC_PkgWatt);
4409812db3f7SLen Brown 			BIC_PRESENT(BIC_CorWatt);
4410812db3f7SLen Brown 			BIC_PRESENT(BIC_RAMWatt);
4411812db3f7SLen Brown 		}
44120f644909SJacob Pan 		break;
4413889facbeSLen Brown 	default:
4414889facbeSLen Brown 		return;
4415889facbeSLen Brown 	}
4416889facbeSLen Brown 
4417889facbeSLen Brown 	/* units on package 0, verify later other packages match */
44187ce7d5deSPrarit Bhargava 	if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr))
4419889facbeSLen Brown 		return;
4420889facbeSLen Brown 
4421889facbeSLen Brown 	rapl_power_units = 1.0 / (1 << (msr & 0xF));
4422f2c4db1bSPeter Zijlstra 	if (model == INTEL_FAM6_ATOM_SILVERMONT)
4423144b44b1SLen Brown 		rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
4424144b44b1SLen Brown 	else
4425889facbeSLen Brown 		rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
4426889facbeSLen Brown 
442740ee8e3bSAndrey Semin 	rapl_dram_energy_units = rapl_dram_energy_units_probe(model, rapl_energy_units);
442840ee8e3bSAndrey Semin 
4429144b44b1SLen Brown 	time_unit = msr >> 16 & 0xF;
4430144b44b1SLen Brown 	if (time_unit == 0)
4431144b44b1SLen Brown 		time_unit = 0xA;
4432889facbeSLen Brown 
4433144b44b1SLen Brown 	rapl_time_units = 1.0 / (1 << (time_unit));
4434144b44b1SLen Brown 
44359392bd98SCalvin Walton 	tdp = get_tdp_intel(model);
4436889facbeSLen Brown 
4437889facbeSLen Brown 	rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
443896e47158SLen Brown 	if (!quiet)
4439b7d8c148SLen Brown 		fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
44409392bd98SCalvin Walton }
4441889facbeSLen Brown 
44429392bd98SCalvin Walton void rapl_probe_amd(unsigned int family, unsigned int model)
44439392bd98SCalvin Walton {
44449392bd98SCalvin Walton 	unsigned long long msr;
44459392bd98SCalvin Walton 	unsigned int eax, ebx, ecx, edx;
44469392bd98SCalvin Walton 	unsigned int has_rapl = 0;
44479392bd98SCalvin Walton 	double tdp;
44489392bd98SCalvin Walton 
44499392bd98SCalvin Walton 	if (max_extended_level >= 0x80000007) {
44509392bd98SCalvin Walton 		__cpuid(0x80000007, eax, ebx, ecx, edx);
445133eb8225SKim Phillips 		/* RAPL (Fam 17h+) */
44529392bd98SCalvin Walton 		has_rapl = edx & (1 << 14);
44539392bd98SCalvin Walton 	}
44549392bd98SCalvin Walton 
445533eb8225SKim Phillips 	if (!has_rapl || family < 0x17)
4456889facbeSLen Brown 		return;
44579392bd98SCalvin Walton 
44589392bd98SCalvin Walton 	do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
44593316f99aSCalvin Walton 	if (rapl_joules) {
44603316f99aSCalvin Walton 		BIC_PRESENT(BIC_Pkg_J);
44619392bd98SCalvin Walton 		BIC_PRESENT(BIC_Cor_J);
44623316f99aSCalvin Walton 	} else {
44633316f99aSCalvin Walton 		BIC_PRESENT(BIC_PkgWatt);
44649392bd98SCalvin Walton 		BIC_PRESENT(BIC_CorWatt);
44653316f99aSCalvin Walton 	}
44669392bd98SCalvin Walton 
44679392bd98SCalvin Walton 	if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
44689392bd98SCalvin Walton 		return;
44699392bd98SCalvin Walton 
44709392bd98SCalvin Walton 	rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf));
44719392bd98SCalvin Walton 	rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));
44729392bd98SCalvin Walton 	rapl_power_units = ldexp(1.0, -(msr & 0xf));
44739392bd98SCalvin Walton 
44749cfa8e04SPu Wen 	tdp = get_tdp_amd(family);
44759392bd98SCalvin Walton 
44769392bd98SCalvin Walton 	rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
44779392bd98SCalvin Walton 	if (!quiet)
44789392bd98SCalvin Walton 		fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
44799392bd98SCalvin Walton }
44809392bd98SCalvin Walton 
44819392bd98SCalvin Walton /*
44829392bd98SCalvin Walton  * rapl_probe()
44839392bd98SCalvin Walton  *
44849392bd98SCalvin Walton  * sets do_rapl, rapl_power_units, rapl_energy_units, rapl_time_units
44859392bd98SCalvin Walton  */
44869392bd98SCalvin Walton void rapl_probe(unsigned int family, unsigned int model)
44879392bd98SCalvin Walton {
44889392bd98SCalvin Walton 	if (genuine_intel)
44899392bd98SCalvin Walton 		rapl_probe_intel(family, model);
4490c1c10cc7SPu Wen 	if (authentic_amd || hygon_genuine)
44919392bd98SCalvin Walton 		rapl_probe_amd(family, model);
4492889facbeSLen Brown }
4493889facbeSLen Brown 
44941b69317dSColin Ian King void perf_limit_reasons_probe(unsigned int family, unsigned int model)
44953a9a941dSLen Brown {
44963a9a941dSLen Brown 	if (!genuine_intel)
44973a9a941dSLen Brown 		return;
44983a9a941dSLen Brown 
44993a9a941dSLen Brown 	if (family != 6)
45003a9a941dSLen Brown 		return;
45013a9a941dSLen Brown 
45023a9a941dSLen Brown 	switch (model) {
4503c66f78a6SPeter Zijlstra 	case INTEL_FAM6_HASWELL:	/* HSW */
450477e5517cSIngo Molnar 	case INTEL_FAM6_HASWELL_L:	/* HSW */
45055e741407SPeter Zijlstra 	case INTEL_FAM6_HASWELL_G:	/* HSW */
45063a9a941dSLen Brown 		do_gfx_perf_limit_reasons = 1;
4507869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:	/* HSX */
45083a9a941dSLen Brown 		do_core_perf_limit_reasons = 1;
45093a9a941dSLen Brown 		do_ring_perf_limit_reasons = 1;
45103a9a941dSLen Brown 	default:
45113a9a941dSLen Brown 		return;
45123a9a941dSLen Brown 	}
45133a9a941dSLen Brown }
45143a9a941dSLen Brown 
4515ac980e13SArtem Bityutskiy void automatic_cstate_conversion_probe(unsigned int family, unsigned int model)
4516ac980e13SArtem Bityutskiy {
4517ac980e13SArtem Bityutskiy 	if (is_skx(family, model) || is_bdx(family, model))
4518ac980e13SArtem Bityutskiy 		has_automatic_cstate_conversion = 1;
4519ac980e13SArtem Bityutskiy }
4520ac980e13SArtem Bityutskiy 
4521889facbeSLen Brown int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4522889facbeSLen Brown {
4523889facbeSLen Brown 	unsigned long long msr;
4524f4896fa5SLen Brown 	unsigned int dts, dts2;
4525889facbeSLen Brown 	int cpu;
4526889facbeSLen Brown 
4527889facbeSLen Brown 	if (!(do_dts || do_ptm))
4528889facbeSLen Brown 		return 0;
4529889facbeSLen Brown 
4530889facbeSLen Brown 	cpu = t->cpu_id;
4531889facbeSLen Brown 
4532889facbeSLen Brown 	/* DTS is per-core, no need to print for each thread */
4533889facbeSLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
4534889facbeSLen Brown 		return 0;
4535889facbeSLen Brown 
4536889facbeSLen Brown 	if (cpu_migrate(cpu)) {
45373d7772eaSLen Brown 		fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);
4538889facbeSLen Brown 		return -1;
4539889facbeSLen Brown 	}
4540889facbeSLen Brown 
4541889facbeSLen Brown 	if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) {
4542889facbeSLen Brown 		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
4543889facbeSLen Brown 			return 0;
4544889facbeSLen Brown 
4545889facbeSLen Brown 		dts = (msr >> 16) & 0x7F;
4546b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n",
4547889facbeSLen Brown 			cpu, msr, tcc_activation_temp - dts);
4548889facbeSLen Brown 
4549889facbeSLen Brown 		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr))
4550889facbeSLen Brown 			return 0;
4551889facbeSLen Brown 
4552889facbeSLen Brown 		dts = (msr >> 16) & 0x7F;
4553889facbeSLen Brown 		dts2 = (msr >> 8) & 0x7F;
4554b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
4555889facbeSLen Brown 			cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
4556889facbeSLen Brown 	}
4557889facbeSLen Brown 
4558889facbeSLen Brown 
4559f4896fa5SLen Brown 	if (do_dts && debug) {
4560889facbeSLen Brown 		unsigned int resolution;
4561889facbeSLen Brown 
4562889facbeSLen Brown 		if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
4563889facbeSLen Brown 			return 0;
4564889facbeSLen Brown 
4565889facbeSLen Brown 		dts = (msr >> 16) & 0x7F;
4566889facbeSLen Brown 		resolution = (msr >> 27) & 0xF;
4567b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
4568889facbeSLen Brown 			cpu, msr, tcc_activation_temp - dts, resolution);
4569889facbeSLen Brown 
4570889facbeSLen Brown 		if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr))
4571889facbeSLen Brown 			return 0;
4572889facbeSLen Brown 
4573889facbeSLen Brown 		dts = (msr >> 16) & 0x7F;
4574889facbeSLen Brown 		dts2 = (msr >> 8) & 0x7F;
4575b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
4576889facbeSLen Brown 			cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
4577889facbeSLen Brown 	}
4578889facbeSLen Brown 
4579889facbeSLen Brown 	return 0;
4580889facbeSLen Brown }
4581889facbeSLen Brown 
4582889facbeSLen Brown void print_power_limit_msr(int cpu, unsigned long long msr, char *label)
4583889facbeSLen Brown {
4584b7d8c148SLen Brown 	fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n",
4585889facbeSLen Brown 		cpu, label,
4586889facbeSLen Brown 		((msr >> 15) & 1) ? "EN" : "DIS",
4587889facbeSLen Brown 		((msr >> 0) & 0x7FFF) * rapl_power_units,
4588889facbeSLen Brown 		(1.0 + (((msr >> 22) & 0x3)/4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units,
4589889facbeSLen Brown 		(((msr >> 16) & 1) ? "EN" : "DIS"));
4590889facbeSLen Brown 
4591889facbeSLen Brown 	return;
4592889facbeSLen Brown }
4593889facbeSLen Brown 
4594889facbeSLen Brown int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
4595889facbeSLen Brown {
4596889facbeSLen Brown 	unsigned long long msr;
45979392bd98SCalvin Walton 	const char *msr_name;
4598889facbeSLen Brown 	int cpu;
4599889facbeSLen Brown 
4600889facbeSLen Brown 	if (!do_rapl)
4601889facbeSLen Brown 		return 0;
4602889facbeSLen Brown 
4603889facbeSLen Brown 	/* RAPL counters are per package, so print only for 1st thread/package */
4604889facbeSLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4605889facbeSLen Brown 		return 0;
4606889facbeSLen Brown 
4607889facbeSLen Brown 	cpu = t->cpu_id;
4608889facbeSLen Brown 	if (cpu_migrate(cpu)) {
46093d7772eaSLen Brown 		fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);
4610889facbeSLen Brown 		return -1;
4611889facbeSLen Brown 	}
4612889facbeSLen Brown 
46139392bd98SCalvin Walton 	if (do_rapl & RAPL_AMD_F17H) {
46149392bd98SCalvin Walton 		msr_name = "MSR_RAPL_PWR_UNIT";
46159392bd98SCalvin Walton 		if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr))
46169392bd98SCalvin Walton 			return -1;
46179392bd98SCalvin Walton 	} else {
46189392bd98SCalvin Walton 		msr_name = "MSR_RAPL_POWER_UNIT";
4619889facbeSLen Brown 		if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))
4620889facbeSLen Brown 			return -1;
46219392bd98SCalvin Walton 	}
4622889facbeSLen Brown 
46239392bd98SCalvin Walton 	fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr,
4624144b44b1SLen Brown 		rapl_power_units, rapl_energy_units, rapl_time_units);
462596e47158SLen Brown 
4626144b44b1SLen Brown 	if (do_rapl & RAPL_PKG_POWER_INFO) {
4627144b44b1SLen Brown 
4628889facbeSLen Brown 		if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
4629889facbeSLen Brown                 	return -5;
4630889facbeSLen Brown 
4631889facbeSLen Brown 
4632b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
4633889facbeSLen Brown 			cpu, msr,
4634889facbeSLen Brown 			((msr >>  0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4635889facbeSLen Brown 			((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4636889facbeSLen Brown 			((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4637889facbeSLen Brown 			((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
4638889facbeSLen Brown 
4639144b44b1SLen Brown 	}
4640144b44b1SLen Brown 	if (do_rapl & RAPL_PKG) {
4641144b44b1SLen Brown 
4642889facbeSLen Brown 		if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
4643889facbeSLen Brown 			return -9;
4644889facbeSLen Brown 
4645b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
4646889facbeSLen Brown 			cpu, msr, (msr >> 63) & 1 ? "" : "UN");
4647889facbeSLen Brown 
4648889facbeSLen Brown 		print_power_limit_msr(cpu, msr, "PKG Limit #1");
4649b7d8c148SLen Brown 		fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
4650889facbeSLen Brown 			cpu,
4651889facbeSLen Brown 			((msr >> 47) & 1) ? "EN" : "DIS",
4652889facbeSLen Brown 			((msr >> 32) & 0x7FFF) * rapl_power_units,
4653889facbeSLen Brown 			(1.0 + (((msr >> 54) & 0x3)/4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units,
4654889facbeSLen Brown 			((msr >> 48) & 1) ? "EN" : "DIS");
4655889facbeSLen Brown 	}
4656889facbeSLen Brown 
46570b2bb692SLen Brown 	if (do_rapl & RAPL_DRAM_POWER_INFO) {
4658889facbeSLen Brown 		if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
4659889facbeSLen Brown                 	return -6;
4660889facbeSLen Brown 
4661b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
4662889facbeSLen Brown 			cpu, msr,
4663889facbeSLen Brown 			((msr >>  0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4664889facbeSLen Brown 			((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4665889facbeSLen Brown 			((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
4666889facbeSLen Brown 			((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
46670b2bb692SLen Brown 	}
46680b2bb692SLen Brown 	if (do_rapl & RAPL_DRAM) {
4669889facbeSLen Brown 		if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
4670889facbeSLen Brown 			return -9;
4671b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
4672889facbeSLen Brown 				cpu, msr, (msr >> 31) & 1 ? "" : "UN");
4673889facbeSLen Brown 
4674889facbeSLen Brown 		print_power_limit_msr(cpu, msr, "DRAM Limit");
4675889facbeSLen Brown 	}
4676144b44b1SLen Brown 	if (do_rapl & RAPL_CORE_POLICY) {
4677889facbeSLen Brown 		if (get_msr(cpu, MSR_PP0_POLICY, &msr))
4678889facbeSLen Brown 			return -7;
4679889facbeSLen Brown 
4680b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
4681144b44b1SLen Brown 	}
46829148494cSJacob Pan 	if (do_rapl & RAPL_CORES_POWER_LIMIT) {
4683889facbeSLen Brown 		if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
4684889facbeSLen Brown 			return -9;
4685b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
4686889facbeSLen Brown 				cpu, msr, (msr >> 31) & 1 ? "" : "UN");
4687889facbeSLen Brown 		print_power_limit_msr(cpu, msr, "Cores Limit");
4688889facbeSLen Brown 	}
4689889facbeSLen Brown 	if (do_rapl & RAPL_GFX) {
4690889facbeSLen Brown 		if (get_msr(cpu, MSR_PP1_POLICY, &msr))
4691889facbeSLen Brown 			return -8;
4692889facbeSLen Brown 
4693b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
4694889facbeSLen Brown 
4695889facbeSLen Brown 		if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
4696889facbeSLen Brown 			return -9;
4697b7d8c148SLen Brown 		fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
4698889facbeSLen Brown 				cpu, msr, (msr >> 31) & 1 ? "" : "UN");
4699889facbeSLen Brown 		print_power_limit_msr(cpu, msr, "GFX Limit");
4700889facbeSLen Brown 	}
4701889facbeSLen Brown 	return 0;
4702889facbeSLen Brown }
4703889facbeSLen Brown 
4704d7899447SLen Brown /*
4705d7899447SLen Brown  * SNB adds support for additional MSRs:
4706d7899447SLen Brown  *
4707d7899447SLen Brown  * MSR_PKG_C7_RESIDENCY            0x000003fa
4708d7899447SLen Brown  * MSR_CORE_C7_RESIDENCY           0x000003fe
4709d7899447SLen Brown  * MSR_PKG_C2_RESIDENCY            0x0000060d
4710d7899447SLen Brown  */
4711103a8feaSLen Brown 
4712d7899447SLen Brown int has_snb_msrs(unsigned int family, unsigned int model)
4713103a8feaSLen Brown {
4714103a8feaSLen Brown 	if (!genuine_intel)
4715103a8feaSLen Brown 		return 0;
4716103a8feaSLen Brown 
4717103a8feaSLen Brown 	switch (model) {
4718869ce69eSLen Brown 	case INTEL_FAM6_SANDYBRIDGE:
4719869ce69eSLen Brown 	case INTEL_FAM6_SANDYBRIDGE_X:
4720869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE:		/* IVB */
4721869ce69eSLen Brown 	case INTEL_FAM6_IVYBRIDGE_X:		/* IVB Xeon */
4722c66f78a6SPeter Zijlstra 	case INTEL_FAM6_HASWELL:		/* HSW */
4723869ce69eSLen Brown 	case INTEL_FAM6_HASWELL_X:		/* HSW */
472477e5517cSIngo Molnar 	case INTEL_FAM6_HASWELL_L:		/* HSW */
47255e741407SPeter Zijlstra 	case INTEL_FAM6_HASWELL_G:		/* HSW */
4726c66f78a6SPeter Zijlstra 	case INTEL_FAM6_BROADWELL:		/* BDW */
47275e741407SPeter Zijlstra 	case INTEL_FAM6_BROADWELL_G:		/* BDW */
4728869ce69eSLen Brown 	case INTEL_FAM6_BROADWELL_X:		/* BDX */
4729af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:		/* SKL */
4730af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L:		/* CNL */
4731869ce69eSLen Brown 	case INTEL_FAM6_SKYLAKE_X:		/* SKX */
4732869ce69eSLen Brown 	case INTEL_FAM6_ATOM_GOLDMONT:		/* BXT */
4733f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
47345ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
4735f6708400SChen Yu 	case INTEL_FAM6_ATOM_TREMONT:		/* EHL */
473620de0dabSAntti Laakso 	case INTEL_FAM6_ATOM_TREMONT_D:		/* JVL */
4737103a8feaSLen Brown 		return 1;
4738103a8feaSLen Brown 	}
4739103a8feaSLen Brown 	return 0;
4740103a8feaSLen Brown }
4741103a8feaSLen Brown 
4742d7899447SLen Brown /*
4743570992fcSLen Brown  * HSW ULT added support for C8/C9/C10 MSRs:
4744d7899447SLen Brown  *
4745d7899447SLen Brown  * MSR_PKG_C8_RESIDENCY		0x00000630
4746d7899447SLen Brown  * MSR_PKG_C9_RESIDENCY		0x00000631
4747d7899447SLen Brown  * MSR_PKG_C10_RESIDENCY	0x00000632
47485a63426eSLen Brown  *
47495a63426eSLen Brown  * MSR_PKGC8_IRTL		0x00000633
47505a63426eSLen Brown  * MSR_PKGC9_IRTL		0x00000634
47515a63426eSLen Brown  * MSR_PKGC10_IRTL		0x00000635
47525a63426eSLen Brown  *
4753d7899447SLen Brown  */
4754570992fcSLen Brown int has_c8910_msrs(unsigned int family, unsigned int model)
4755ca58710fSKristen Carlson Accardi {
4756ca58710fSKristen Carlson Accardi 	if (!genuine_intel)
4757ca58710fSKristen Carlson Accardi 		return 0;
4758ca58710fSKristen Carlson Accardi 
4759ca58710fSKristen Carlson Accardi 	switch (model) {
476077e5517cSIngo Molnar 	case INTEL_FAM6_HASWELL_L:	/* HSW */
4761c66f78a6SPeter Zijlstra 	case INTEL_FAM6_BROADWELL:	/* BDW */
4762af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
4763af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
4764869ce69eSLen Brown 	case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
4765f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
4766f6708400SChen Yu 	case INTEL_FAM6_ATOM_TREMONT:	/* EHL */
4767ca58710fSKristen Carlson Accardi 		return 1;
4768ca58710fSKristen Carlson Accardi 	}
4769ca58710fSKristen Carlson Accardi 	return 0;
4770ca58710fSKristen Carlson Accardi }
4771ca58710fSKristen Carlson Accardi 
47720b2bb692SLen Brown /*
47730b2bb692SLen Brown  * SKL adds support for additional MSRS:
47740b2bb692SLen Brown  *
47750b2bb692SLen Brown  * MSR_PKG_WEIGHTED_CORE_C0_RES    0x00000658
47760b2bb692SLen Brown  * MSR_PKG_ANY_CORE_C0_RES         0x00000659
47770b2bb692SLen Brown  * MSR_PKG_ANY_GFXE_C0_RES         0x0000065A
47780b2bb692SLen Brown  * MSR_PKG_BOTH_CORE_GFXE_C0_RES   0x0000065B
47790b2bb692SLen Brown  */
47800b2bb692SLen Brown int has_skl_msrs(unsigned int family, unsigned int model)
47810b2bb692SLen Brown {
47820b2bb692SLen Brown 	if (!genuine_intel)
47830b2bb692SLen Brown 		return 0;
47840b2bb692SLen Brown 
47850b2bb692SLen Brown 	switch (model) {
4786af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
4787af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
47880b2bb692SLen Brown 		return 1;
47890b2bb692SLen Brown 	}
47900b2bb692SLen Brown 	return 0;
47910b2bb692SLen Brown }
47920b2bb692SLen Brown 
4793144b44b1SLen Brown int is_slm(unsigned int family, unsigned int model)
4794144b44b1SLen Brown {
4795144b44b1SLen Brown 	if (!genuine_intel)
4796144b44b1SLen Brown 		return 0;
4797144b44b1SLen Brown 	switch (model) {
4798f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT:	/* BYT */
47995ebb34edSPeter Zijlstra 	case INTEL_FAM6_ATOM_SILVERMONT_D:	/* AVN */
4800144b44b1SLen Brown 		return 1;
4801144b44b1SLen Brown 	}
4802144b44b1SLen Brown 	return 0;
4803144b44b1SLen Brown }
4804144b44b1SLen Brown 
4805fb5d4327SDasaratharaman Chandramouli int is_knl(unsigned int family, unsigned int model)
4806fb5d4327SDasaratharaman Chandramouli {
4807fb5d4327SDasaratharaman Chandramouli 	if (!genuine_intel)
4808fb5d4327SDasaratharaman Chandramouli 		return 0;
4809fb5d4327SDasaratharaman Chandramouli 	switch (model) {
4810869ce69eSLen Brown 	case INTEL_FAM6_XEON_PHI_KNL:	/* KNL */
4811fb5d4327SDasaratharaman Chandramouli 		return 1;
4812fb5d4327SDasaratharaman Chandramouli 	}
4813fb5d4327SDasaratharaman Chandramouli 	return 0;
4814fb5d4327SDasaratharaman Chandramouli }
4815fb5d4327SDasaratharaman Chandramouli 
4816997e5395SSrinivas Pandruvada int is_cnl(unsigned int family, unsigned int model)
4817997e5395SSrinivas Pandruvada {
4818997e5395SSrinivas Pandruvada 	if (!genuine_intel)
4819997e5395SSrinivas Pandruvada 		return 0;
4820997e5395SSrinivas Pandruvada 
4821997e5395SSrinivas Pandruvada 	switch (model) {
4822af239c44SPeter Zijlstra 	case INTEL_FAM6_CANNONLAKE_L: /* CNL */
4823997e5395SSrinivas Pandruvada 		return 1;
4824997e5395SSrinivas Pandruvada 	}
4825997e5395SSrinivas Pandruvada 
4826997e5395SSrinivas Pandruvada 	return 0;
4827997e5395SSrinivas Pandruvada }
4828997e5395SSrinivas Pandruvada 
4829b2b34dfeSHubert Chrzaniuk unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model)
4830b2b34dfeSHubert Chrzaniuk {
4831b2b34dfeSHubert Chrzaniuk 	if (is_knl(family, model))
4832b2b34dfeSHubert Chrzaniuk 		return 1024;
4833b2b34dfeSHubert Chrzaniuk 	return 1;
4834b2b34dfeSHubert Chrzaniuk }
4835b2b34dfeSHubert Chrzaniuk 
4836144b44b1SLen Brown #define SLM_BCLK_FREQS 5
4837144b44b1SLen Brown double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0};
4838144b44b1SLen Brown 
4839144b44b1SLen Brown double slm_bclk(void)
4840144b44b1SLen Brown {
4841144b44b1SLen Brown 	unsigned long long msr = 3;
4842144b44b1SLen Brown 	unsigned int i;
4843144b44b1SLen Brown 	double freq;
4844144b44b1SLen Brown 
48457ce7d5deSPrarit Bhargava 	if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))
4846b7d8c148SLen Brown 		fprintf(outf, "SLM BCLK: unknown\n");
4847144b44b1SLen Brown 
4848144b44b1SLen Brown 	i = msr & 0xf;
4849144b44b1SLen Brown 	if (i >= SLM_BCLK_FREQS) {
4850b7d8c148SLen Brown 		fprintf(outf, "SLM BCLK[%d] invalid\n", i);
48510a91e551SColin Ian King 		i = 3;
4852144b44b1SLen Brown 	}
4853144b44b1SLen Brown 	freq = slm_freq_table[i];
4854144b44b1SLen Brown 
485596e47158SLen Brown 	if (!quiet)
4856b7d8c148SLen Brown 		fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
4857144b44b1SLen Brown 
4858144b44b1SLen Brown 	return freq;
4859144b44b1SLen Brown }
4860144b44b1SLen Brown 
4861103a8feaSLen Brown double discover_bclk(unsigned int family, unsigned int model)
4862103a8feaSLen Brown {
4863121b48bbSChrzaniuk, Hubert 	if (has_snb_msrs(family, model) || is_knl(family, model))
4864103a8feaSLen Brown 		return 100.00;
4865144b44b1SLen Brown 	else if (is_slm(family, model))
4866144b44b1SLen Brown 		return slm_bclk();
4867103a8feaSLen Brown 	else
4868103a8feaSLen Brown 		return 133.33;
4869103a8feaSLen Brown }
4870103a8feaSLen Brown 
4871889facbeSLen Brown /*
4872889facbeSLen Brown  * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where
4873889facbeSLen Brown  * the Thermal Control Circuit (TCC) activates.
4874889facbeSLen Brown  * This is usually equal to tjMax.
4875889facbeSLen Brown  *
4876889facbeSLen Brown  * Older processors do not have this MSR, so there we guess,
4877889facbeSLen Brown  * but also allow cmdline over-ride with -T.
4878889facbeSLen Brown  *
4879889facbeSLen Brown  * Several MSR temperature values are in units of degrees-C
4880889facbeSLen Brown  * below this value, including the Digital Thermal Sensor (DTS),
4881889facbeSLen Brown  * Package Thermal Management Sensor (PTM), and thermal event thresholds.
4882889facbeSLen Brown  */
48836ff7cb37SLen Brown int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
48846ff7cb37SLen Brown {
4885b2b94be7SLen Brown 	unsigned long long msr;
4886b2b94be7SLen Brown 	unsigned int target_c_local;
4887b2b94be7SLen Brown 	int cpu;
4888b2b94be7SLen Brown 
4889889facbeSLen Brown 	/* tcc_activation_temp is used only for dts or ptm */
4890889facbeSLen Brown 	if (!(do_dts || do_ptm))
4891889facbeSLen Brown 		return 0;
4892889facbeSLen Brown 
4893889facbeSLen Brown 	/* this is a per-package concept */
4894889facbeSLen Brown 	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
4895889facbeSLen Brown 		return 0;
4896889facbeSLen Brown 
4897b2b94be7SLen Brown 	cpu = t->cpu_id;
4898b2b94be7SLen Brown 	if (cpu_migrate(cpu)) {
4899b2b94be7SLen Brown 		fprintf(outf, "Could not migrate to CPU %d\n", cpu);
4900b2b94be7SLen Brown 		return -1;
4901b2b94be7SLen Brown 	}
4902b2b94be7SLen Brown 
4903889facbeSLen Brown 	if (tcc_activation_temp_override != 0) {
4904889facbeSLen Brown 		tcc_activation_temp = tcc_activation_temp_override;
4905b2b94be7SLen Brown 		fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n",
4906b2b94be7SLen Brown 			cpu, tcc_activation_temp);
4907889facbeSLen Brown 		return 0;
4908889facbeSLen Brown 	}
4909889facbeSLen Brown 
4910b2b94be7SLen Brown 	/* Temperature Target MSR is Nehalem and newer only */
4911b2b94be7SLen Brown 	if (!do_nhm_platform_info)
4912b2b94be7SLen Brown 		goto guess;
4913b2b94be7SLen Brown 
4914b2b94be7SLen Brown 	if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))
4915b2b94be7SLen Brown 		goto guess;
4916b2b94be7SLen Brown 
4917b2b94be7SLen Brown 	target_c_local = (msr >> 16) & 0xFF;
4918b2b94be7SLen Brown 
4919b2b94be7SLen Brown 	if (!quiet)
4920b2b94be7SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
4921b2b94be7SLen Brown 			cpu, msr, target_c_local);
4922b2b94be7SLen Brown 
4923b2b94be7SLen Brown 	if (!target_c_local)
4924b2b94be7SLen Brown 		goto guess;
4925b2b94be7SLen Brown 
4926b2b94be7SLen Brown 	tcc_activation_temp = target_c_local;
4927b2b94be7SLen Brown 
4928889facbeSLen Brown 	return 0;
4929889facbeSLen Brown 
4930b2b94be7SLen Brown guess:
4931889facbeSLen Brown 	tcc_activation_temp = TJMAX_DEFAULT;
4932b2b94be7SLen Brown 	fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
4933b2b94be7SLen Brown 		cpu, tcc_activation_temp);
4934889facbeSLen Brown 
4935889facbeSLen Brown 	return 0;
4936889facbeSLen Brown }
493769807a63SLen Brown 
4938aa8d8cc7SLen Brown void decode_feature_control_msr(void)
4939aa8d8cc7SLen Brown {
4940aa8d8cc7SLen Brown 	unsigned long long msr;
4941aa8d8cc7SLen Brown 
4942f6505c88SSean Christopherson 	if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr))
4943aa8d8cc7SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
4944aa8d8cc7SLen Brown 			base_cpu, msr,
4945f6505c88SSean Christopherson 			msr & FEAT_CTL_LOCKED ? "" : "UN-",
4946aa8d8cc7SLen Brown 			msr & (1 << 18) ? "SGX" : "");
4947aa8d8cc7SLen Brown }
4948aa8d8cc7SLen Brown 
494969807a63SLen Brown void decode_misc_enable_msr(void)
495069807a63SLen Brown {
495169807a63SLen Brown 	unsigned long long msr;
495269807a63SLen Brown 
4953f26b1519SLen Brown 	if (!genuine_intel)
4954f26b1519SLen Brown 		return;
4955f26b1519SLen Brown 
495669807a63SLen Brown 	if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
4957e6512624SLen Brown 		fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",
495869807a63SLen Brown 			base_cpu, msr,
4959e6512624SLen Brown 			msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",
4960e6512624SLen Brown 			msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",
4961fd3933caSLen Brown 			msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-",
4962e6512624SLen Brown 			msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "",
4963e6512624SLen Brown 			msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");
496469807a63SLen Brown }
496569807a63SLen Brown 
496633148d67SLen Brown void decode_misc_feature_control(void)
496733148d67SLen Brown {
496833148d67SLen Brown 	unsigned long long msr;
496933148d67SLen Brown 
497033148d67SLen Brown 	if (!has_misc_feature_control)
497133148d67SLen Brown 		return;
497233148d67SLen Brown 
497333148d67SLen Brown 	if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))
497433148d67SLen Brown 		fprintf(outf, "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
497533148d67SLen Brown 			base_cpu, msr,
497633148d67SLen Brown 			msr & (0 << 0) ? "No-" : "",
497733148d67SLen Brown 			msr & (1 << 0) ? "No-" : "",
497833148d67SLen Brown 			msr & (2 << 0) ? "No-" : "",
497933148d67SLen Brown 			msr & (3 << 0) ? "No-" : "");
498033148d67SLen Brown }
4981f0057310SLen Brown /*
4982f0057310SLen Brown  * Decode MSR_MISC_PWR_MGMT
4983f0057310SLen Brown  *
4984f0057310SLen Brown  * Decode the bits according to the Nehalem documentation
4985f0057310SLen Brown  * bit[0] seems to continue to have same meaning going forward
4986f0057310SLen Brown  * bit[1] less so...
4987f0057310SLen Brown  */
4988f0057310SLen Brown void decode_misc_pwr_mgmt_msr(void)
4989f0057310SLen Brown {
4990f0057310SLen Brown 	unsigned long long msr;
4991f0057310SLen Brown 
4992f0057310SLen Brown 	if (!do_nhm_platform_info)
4993f0057310SLen Brown 		return;
4994f0057310SLen Brown 
4995cf4cbe53SLen Brown 	if (no_MSR_MISC_PWR_MGMT)
4996cf4cbe53SLen Brown 		return;
4997cf4cbe53SLen Brown 
4998f0057310SLen Brown 	if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
4999ddadb8adSSrinivas Pandruvada 		fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",
5000f0057310SLen Brown 			base_cpu, msr,
5001f0057310SLen Brown 			msr & (1 << 0) ? "DIS" : "EN",
5002ddadb8adSSrinivas Pandruvada 			msr & (1 << 1) ? "EN" : "DIS",
5003ddadb8adSSrinivas Pandruvada 			msr & (1 << 8) ? "EN" : "DIS");
5004f0057310SLen Brown }
500571616c8eSLen Brown /*
500671616c8eSLen Brown  * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
500771616c8eSLen Brown  *
500871616c8eSLen Brown  * This MSRs are present on Silvermont processors,
500971616c8eSLen Brown  * Intel Atom processor E3000 series (Baytrail), and friends.
501071616c8eSLen Brown  */
501171616c8eSLen Brown void decode_c6_demotion_policy_msr(void)
501271616c8eSLen Brown {
501371616c8eSLen Brown 	unsigned long long msr;
501471616c8eSLen Brown 
501571616c8eSLen Brown 	if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))
501671616c8eSLen Brown 		fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",
501771616c8eSLen Brown 			base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
501871616c8eSLen Brown 
501971616c8eSLen Brown 	if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))
502071616c8eSLen Brown 		fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",
502171616c8eSLen Brown 			base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
502271616c8eSLen Brown }
50237f5c258eSLen Brown 
5024f5a4c76aSLen Brown /*
5025f5a4c76aSLen Brown  * When models are the same, for the purpose of turbostat, reuse
5026f5a4c76aSLen Brown  */
5027f5a4c76aSLen Brown unsigned int intel_model_duplicates(unsigned int model)
5028f5a4c76aSLen Brown {
5029f5a4c76aSLen Brown 
5030f5a4c76aSLen Brown 	switch(model) {
5031f5a4c76aSLen Brown 	case INTEL_FAM6_NEHALEM_EP:	/* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
5032f5a4c76aSLen Brown 	case INTEL_FAM6_NEHALEM:	/* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
5033f5a4c76aSLen Brown 	case 0x1F:	/* Core i7 and i5 Processor - Nehalem */
5034f5a4c76aSLen Brown 	case INTEL_FAM6_WESTMERE:	/* Westmere Client - Clarkdale, Arrandale */
5035f5a4c76aSLen Brown 	case INTEL_FAM6_WESTMERE_EP:	/* Westmere EP - Gulftown */
5036f5a4c76aSLen Brown 		return INTEL_FAM6_NEHALEM;
5037f5a4c76aSLen Brown 
5038f5a4c76aSLen Brown 	case INTEL_FAM6_NEHALEM_EX:	/* Nehalem-EX Xeon - Beckton */
5039f5a4c76aSLen Brown 	case INTEL_FAM6_WESTMERE_EX:	/* Westmere-EX Xeon - Eagleton */
5040f5a4c76aSLen Brown 		return INTEL_FAM6_NEHALEM_EX;
5041f5a4c76aSLen Brown 
5042f5a4c76aSLen Brown 	case INTEL_FAM6_XEON_PHI_KNM:
5043f5a4c76aSLen Brown 		return INTEL_FAM6_XEON_PHI_KNL;
5044f5a4c76aSLen Brown 
5045f5a4c76aSLen Brown 	case INTEL_FAM6_BROADWELL_X:
50465ebb34edSPeter Zijlstra 	case INTEL_FAM6_BROADWELL_D:	/* BDX-DE */
5047f5a4c76aSLen Brown 		return INTEL_FAM6_BROADWELL_X;
5048f5a4c76aSLen Brown 
5049af239c44SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE_L:
5050c66f78a6SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE:
5051af239c44SPeter Zijlstra 	case INTEL_FAM6_KABYLAKE_L:
5052c66f78a6SPeter Zijlstra 	case INTEL_FAM6_KABYLAKE:
5053081c5432SChen Yu 	case INTEL_FAM6_COMETLAKE_L:
5054081c5432SChen Yu 	case INTEL_FAM6_COMETLAKE:
5055af239c44SPeter Zijlstra 		return INTEL_FAM6_SKYLAKE_L;
5056937807d3SLen Brown 
5057af239c44SPeter Zijlstra 	case INTEL_FAM6_ICELAKE_L:
5058d93ea567SRajneesh Bhardwaj 	case INTEL_FAM6_ICELAKE_NNPI:
50594bf7132aSChen Yu 	case INTEL_FAM6_TIGERLAKE_L:
50604bf7132aSChen Yu 	case INTEL_FAM6_TIGERLAKE:
5061e7af1ed3SLen Brown 	case INTEL_FAM6_ROCKETLAKE:
5062e7af1ed3SLen Brown 	case INTEL_FAM6_LAKEFIELD:
5063e7af1ed3SLen Brown 	case INTEL_FAM6_ALDERLAKE:
50645683460bSChen Yu 	case INTEL_FAM6_ALDERLAKE_L:
5065af239c44SPeter Zijlstra 		return INTEL_FAM6_CANNONLAKE_L;
5066b62b3184SZhang Rui 
5067d7814c30SChen Yu 	case INTEL_FAM6_ATOM_TREMONT_L:
5068d7814c30SChen Yu 		return INTEL_FAM6_ATOM_TREMONT;
5069d7814c30SChen Yu 
507023274fafSChen Yu 	case INTEL_FAM6_ICELAKE_X:
50716c5c6560SChen Yu 	case INTEL_FAM6_ICELAKE_D:
5072e7af1ed3SLen Brown 	case INTEL_FAM6_SAPPHIRERAPIDS_X:
507323274fafSChen Yu 		return INTEL_FAM6_SKYLAKE_X;
5074f5a4c76aSLen Brown 	}
5075f5a4c76aSLen Brown 	return model;
5076f5a4c76aSLen Brown }
5077d76bb7a0SLen Brown 
5078d76bb7a0SLen Brown void print_dev_latency(void)
5079d76bb7a0SLen Brown {
5080d76bb7a0SLen Brown 	char *path = "/dev/cpu_dma_latency";
5081d76bb7a0SLen Brown 	int fd;
5082d76bb7a0SLen Brown 	int value;
5083d76bb7a0SLen Brown 	int retval;
5084d76bb7a0SLen Brown 
5085d76bb7a0SLen Brown 	fd = open(path, O_RDONLY);
5086d76bb7a0SLen Brown 	if (fd < 0) {
5087d76bb7a0SLen Brown 		warn("fopen %s\n", path);
5088d76bb7a0SLen Brown 		return;
5089d76bb7a0SLen Brown 	}
5090d76bb7a0SLen Brown 
5091d76bb7a0SLen Brown 	retval = read(fd, (void *)&value, sizeof(int));
5092d76bb7a0SLen Brown 	if (retval != sizeof(int)) {
5093d76bb7a0SLen Brown 		warn("read %s\n", path);
5094d76bb7a0SLen Brown 		close(fd);
5095d76bb7a0SLen Brown 		return;
5096d76bb7a0SLen Brown 	}
5097d76bb7a0SLen Brown 	fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n",
5098d76bb7a0SLen Brown 		value, value == 2000000000 ? "default" : "constrained");
5099d76bb7a0SLen Brown 
5100d76bb7a0SLen Brown 	close(fd);
5101d76bb7a0SLen Brown }
5102d76bb7a0SLen Brown 
51032af4f9b8SLen Brown 
51042af4f9b8SLen Brown /*
51052af4f9b8SLen Brown  * Linux-perf manages the the HW instructions-retired counter
51062af4f9b8SLen Brown  * by enabling when requested, and hiding rollover
51072af4f9b8SLen Brown  */
51082af4f9b8SLen Brown void linux_perf_init(void)
51092af4f9b8SLen Brown {
51102af4f9b8SLen Brown 	if (!BIC_IS_ENABLED(BIC_IPC))
51112af4f9b8SLen Brown 		return;
51122af4f9b8SLen Brown 
51132af4f9b8SLen Brown 	if (access("/proc/sys/kernel/perf_event_paranoid", F_OK))
51142af4f9b8SLen Brown 		return;
51152af4f9b8SLen Brown 
51162af4f9b8SLen Brown 	fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
51172af4f9b8SLen Brown 	if (fd_instr_count_percpu == NULL)
51182af4f9b8SLen Brown 		err(-1, "calloc fd_instr_count_percpu");
51192af4f9b8SLen Brown 
51202af4f9b8SLen Brown 	BIC_PRESENT(BIC_IPC);
51212af4f9b8SLen Brown }
51222af4f9b8SLen Brown 
5123fcd17211SLen Brown void process_cpuid()
5124103a8feaSLen Brown {
512534041551SLen Brown 	unsigned int eax, ebx, ecx, edx;
512634041551SLen Brown 	unsigned int fms, family, model, stepping, ecx_flags, edx_flags;
5127b3a34e93SLen Brown 	unsigned int has_turbo;
5128ed0757b8SLen Brown 	unsigned long long ucode_patch = 0;
5129103a8feaSLen Brown 
5130103a8feaSLen Brown 	eax = ebx = ecx = edx = 0;
5131103a8feaSLen Brown 
51325aea2f7fSLen Brown 	__cpuid(0, max_level, ebx, ecx, edx);
5133103a8feaSLen Brown 
513434041551SLen Brown 	if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
5135103a8feaSLen Brown 		genuine_intel = 1;
513634041551SLen Brown 	else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
513734041551SLen Brown 		authentic_amd = 1;
5138c1c10cc7SPu Wen 	else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)
5139c1c10cc7SPu Wen 		hygon_genuine = 1;
5140103a8feaSLen Brown 
514196e47158SLen Brown 	if (!quiet)
5142ed0757b8SLen Brown 		fprintf(outf, "CPUID(0): %.4s%.4s%.4s 0x%x CPUID levels\n",
5143ed0757b8SLen Brown 			(char *)&ebx, (char *)&edx, (char *)&ecx, max_level);
5144103a8feaSLen Brown 
51455aea2f7fSLen Brown 	__cpuid(1, fms, ebx, ecx, edx);
5146103a8feaSLen Brown 	family = (fms >> 8) & 0xf;
5147103a8feaSLen Brown 	model = (fms >> 4) & 0xf;
5148103a8feaSLen Brown 	stepping = fms & 0xf;
51495aa3d1a2SCalvin Walton 	if (family == 0xf)
51505aa3d1a2SCalvin Walton 		family += (fms >> 20) & 0xff;
51515aa3d1a2SCalvin Walton 	if (family >= 6)
5152103a8feaSLen Brown 		model += ((fms >> 16) & 0xf) << 4;
515334041551SLen Brown 	ecx_flags = ecx;
515434041551SLen Brown 	edx_flags = edx;
5155103a8feaSLen Brown 
5156ed0757b8SLen Brown 	if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
5157ed0757b8SLen Brown 		warnx("get_msr(UCODE)\n");
5158ed0757b8SLen Brown 
5159103a8feaSLen Brown 	/*
5160103a8feaSLen Brown 	 * check max extended function levels of CPUID.
5161103a8feaSLen Brown 	 * This is needed to check for invariant TSC.
5162103a8feaSLen Brown 	 * This check is valid for both Intel and AMD.
5163103a8feaSLen Brown 	 */
5164103a8feaSLen Brown 	ebx = ecx = edx = 0;
51655aea2f7fSLen Brown 	__cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
5166103a8feaSLen Brown 
516734041551SLen Brown 	if (!quiet) {
5168ed0757b8SLen Brown 		fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d) microcode 0x%x\n",
5169ed0757b8SLen Brown 			family, model, stepping, family, model, stepping, (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
5170ed0757b8SLen Brown 		fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);
517134041551SLen Brown 		fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",
517234041551SLen Brown 			ecx_flags & (1 << 0) ? "SSE3" : "-",
517334041551SLen Brown 			ecx_flags & (1 << 3) ? "MONITOR" : "-",
517434041551SLen Brown 			ecx_flags & (1 << 6) ? "SMX" : "-",
517534041551SLen Brown 			ecx_flags & (1 << 7) ? "EIST" : "-",
517634041551SLen Brown 			ecx_flags & (1 << 8) ? "TM2" : "-",
517734041551SLen Brown 			edx_flags & (1 << 4) ? "TSC" : "-",
517834041551SLen Brown 			edx_flags & (1 << 5) ? "MSR" : "-",
517934041551SLen Brown 			edx_flags & (1 << 22) ? "ACPI-TM" : "-",
518034041551SLen Brown 			edx_flags & (1 << 28) ? "HT" : "-",
518134041551SLen Brown 			edx_flags & (1 << 29) ? "TM" : "-");
518234041551SLen Brown 	}
5183f5a4c76aSLen Brown 	if (genuine_intel)
5184f5a4c76aSLen Brown 		model = intel_model_duplicates(model);
518534041551SLen Brown 
518634041551SLen Brown 	if (!(edx_flags & (1 << 5)))
518734041551SLen Brown 		errx(1, "CPUID: no MSR");
518834041551SLen Brown 
518961a87ba7SLen Brown 	if (max_extended_level >= 0x80000007) {
5190103a8feaSLen Brown 
5191103a8feaSLen Brown 		/*
5192103a8feaSLen Brown 		 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
5193103a8feaSLen Brown 		 * this check is valid for both Intel and AMD
5194103a8feaSLen Brown 		 */
51955aea2f7fSLen Brown 		__cpuid(0x80000007, eax, ebx, ecx, edx);
51968209e054SThomas Renninger 		has_invariant_tsc = edx & (1 << 8);
5197d7899447SLen Brown 	}
5198103a8feaSLen Brown 
5199103a8feaSLen Brown 	/*
5200103a8feaSLen Brown 	 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
5201103a8feaSLen Brown 	 * this check is valid for both Intel and AMD
5202103a8feaSLen Brown 	 */
5203103a8feaSLen Brown 
52045aea2f7fSLen Brown 	__cpuid(0x6, eax, ebx, ecx, edx);
52058209e054SThomas Renninger 	has_aperf = ecx & (1 << 0);
5206812db3f7SLen Brown 	if (has_aperf) {
5207812db3f7SLen Brown 		BIC_PRESENT(BIC_Avg_MHz);
5208812db3f7SLen Brown 		BIC_PRESENT(BIC_Busy);
5209812db3f7SLen Brown 		BIC_PRESENT(BIC_Bzy_MHz);
5210812db3f7SLen Brown 	}
5211889facbeSLen Brown 	do_dts = eax & (1 << 0);
5212812db3f7SLen Brown 	if (do_dts)
5213812db3f7SLen Brown 		BIC_PRESENT(BIC_CoreTmp);
5214b3a34e93SLen Brown 	has_turbo = eax & (1 << 1);
5215889facbeSLen Brown 	do_ptm = eax & (1 << 6);
5216812db3f7SLen Brown 	if (do_ptm)
5217812db3f7SLen Brown 		BIC_PRESENT(BIC_PkgTmp);
52187f5c258eSLen Brown 	has_hwp = eax & (1 << 7);
52197f5c258eSLen Brown 	has_hwp_notify = eax & (1 << 8);
52207f5c258eSLen Brown 	has_hwp_activity_window = eax & (1 << 9);
52217f5c258eSLen Brown 	has_hwp_epp = eax & (1 << 10);
52227f5c258eSLen Brown 	has_hwp_pkg = eax & (1 << 11);
5223889facbeSLen Brown 	has_epb = ecx & (1 << 3);
5224889facbeSLen Brown 
522596e47158SLen Brown 	if (!quiet)
5226b3a34e93SLen Brown 		fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "
52277f5c258eSLen Brown 			"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
52287f5c258eSLen Brown 			has_aperf ? "" : "No-",
5229b3a34e93SLen Brown 			has_turbo ? "" : "No-",
52307f5c258eSLen Brown 			do_dts ? "" : "No-",
52317f5c258eSLen Brown 			do_ptm ? "" : "No-",
52327f5c258eSLen Brown 			has_hwp ? "" : "No-",
52337f5c258eSLen Brown 			has_hwp_notify ? "" : "No-",
52347f5c258eSLen Brown 			has_hwp_activity_window ? "" : "No-",
52357f5c258eSLen Brown 			has_hwp_epp ? "" : "No-",
52367f5c258eSLen Brown 			has_hwp_pkg ? "" : "No-",
52377f5c258eSLen Brown 			has_epb ? "" : "No-");
5238103a8feaSLen Brown 
523996e47158SLen Brown 	if (!quiet)
524069807a63SLen Brown 		decode_misc_enable_msr();
524169807a63SLen Brown 
524233148d67SLen Brown 
524396e47158SLen Brown 	if (max_level >= 0x7 && !quiet) {
5244aa8d8cc7SLen Brown 		int has_sgx;
5245aa8d8cc7SLen Brown 
5246aa8d8cc7SLen Brown 		ecx = 0;
5247aa8d8cc7SLen Brown 
5248aa8d8cc7SLen Brown 		__cpuid_count(0x7, 0, eax, ebx, ecx, edx);
5249aa8d8cc7SLen Brown 
5250aa8d8cc7SLen Brown 		has_sgx = ebx & (1 << 2);
5251aa8d8cc7SLen Brown 		fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-");
5252aa8d8cc7SLen Brown 
5253aa8d8cc7SLen Brown 		if (has_sgx)
5254aa8d8cc7SLen Brown 			decode_feature_control_msr();
5255aa8d8cc7SLen Brown 	}
5256aa8d8cc7SLen Brown 
525761a87ba7SLen Brown 	if (max_level >= 0x15) {
52588a5bdf41SLen Brown 		unsigned int eax_crystal;
52598a5bdf41SLen Brown 		unsigned int ebx_tsc;
52608a5bdf41SLen Brown 
52618a5bdf41SLen Brown 		/*
52628a5bdf41SLen Brown 		 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz
52638a5bdf41SLen Brown 		 */
52648a5bdf41SLen Brown 		eax_crystal = ebx_tsc = crystal_hz = edx = 0;
52655aea2f7fSLen Brown 		__cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);
52668a5bdf41SLen Brown 
52678a5bdf41SLen Brown 		if (ebx_tsc != 0) {
52688a5bdf41SLen Brown 
526996e47158SLen Brown 			if (!quiet && (ebx != 0))
5270b7d8c148SLen Brown 				fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
52718a5bdf41SLen Brown 					eax_crystal, ebx_tsc, crystal_hz);
52728a5bdf41SLen Brown 
52738a5bdf41SLen Brown 			if (crystal_hz == 0)
52748a5bdf41SLen Brown 				switch(model) {
5275af239c44SPeter Zijlstra 				case INTEL_FAM6_SKYLAKE_L:	/* SKL */
5276e8efbc80SLen Brown 					crystal_hz = 24000000;	/* 24.0 MHz */
5277e8efbc80SLen Brown 					break;
52785ebb34edSPeter Zijlstra 				case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
5279ec53e594SLen Brown 					crystal_hz = 25000000;	/* 25.0 MHz */
5280ec53e594SLen Brown 					break;
5281869ce69eSLen Brown 				case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
5282f2c4db1bSPeter Zijlstra 				case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
5283e8efbc80SLen Brown 					crystal_hz = 19200000;	/* 19.2 MHz */
52848a5bdf41SLen Brown 					break;
52858a5bdf41SLen Brown 				default:
52868a5bdf41SLen Brown 					crystal_hz = 0;
52878a5bdf41SLen Brown 			}
52888a5bdf41SLen Brown 
52898a5bdf41SLen Brown 			if (crystal_hz) {
52908a5bdf41SLen Brown 				tsc_hz =  (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
529196e47158SLen Brown 				if (!quiet)
5292b7d8c148SLen Brown 					fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
52938a5bdf41SLen Brown 						tsc_hz / 1000000, crystal_hz, ebx_tsc,  eax_crystal);
52948a5bdf41SLen Brown 			}
52958a5bdf41SLen Brown 		}
52968a5bdf41SLen Brown 	}
529761a87ba7SLen Brown 	if (max_level >= 0x16) {
529861a87ba7SLen Brown 		unsigned int base_mhz, max_mhz, bus_mhz, edx;
529961a87ba7SLen Brown 
530061a87ba7SLen Brown 		/*
530161a87ba7SLen Brown 		 * CPUID 16H Base MHz, Max MHz, Bus MHz
530261a87ba7SLen Brown 		 */
530361a87ba7SLen Brown 		base_mhz = max_mhz = bus_mhz = edx = 0;
530461a87ba7SLen Brown 
53055aea2f7fSLen Brown 		__cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
530696e47158SLen Brown 		if (!quiet)
5307b7d8c148SLen Brown 			fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
530861a87ba7SLen Brown 				base_mhz, max_mhz, bus_mhz);
530961a87ba7SLen Brown 	}
53108a5bdf41SLen Brown 
5311b2b34dfeSHubert Chrzaniuk 	if (has_aperf)
5312b2b34dfeSHubert Chrzaniuk 		aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model);
5313b2b34dfeSHubert Chrzaniuk 
5314812db3f7SLen Brown 	BIC_PRESENT(BIC_IRQ);
5315812db3f7SLen Brown 	BIC_PRESENT(BIC_TSC_MHz);
5316812db3f7SLen Brown 
5317812db3f7SLen Brown 	if (probe_nhm_msrs(family, model)) {
5318812db3f7SLen Brown 		do_nhm_platform_info = 1;
5319812db3f7SLen Brown 		BIC_PRESENT(BIC_CPU_c1);
5320812db3f7SLen Brown 		BIC_PRESENT(BIC_CPU_c3);
5321812db3f7SLen Brown 		BIC_PRESENT(BIC_CPU_c6);
5322812db3f7SLen Brown 		BIC_PRESENT(BIC_SMI);
5323812db3f7SLen Brown 	}
5324d7899447SLen Brown 	do_snb_cstates = has_snb_msrs(family, model);
5325812db3f7SLen Brown 
5326812db3f7SLen Brown 	if (do_snb_cstates)
5327812db3f7SLen Brown 		BIC_PRESENT(BIC_CPU_c7);
5328812db3f7SLen Brown 
53295a63426eSLen Brown 	do_irtl_snb = has_snb_msrs(family, model);
53300f47c08dSLen Brown 	if (do_snb_cstates && (pkg_cstate_limit >= PCL__2))
53310f47c08dSLen Brown 		BIC_PRESENT(BIC_Pkgpc2);
53320f47c08dSLen Brown 	if (pkg_cstate_limit >= PCL__3)
53330f47c08dSLen Brown 		BIC_PRESENT(BIC_Pkgpc3);
53340f47c08dSLen Brown 	if (pkg_cstate_limit >= PCL__6)
53350f47c08dSLen Brown 		BIC_PRESENT(BIC_Pkgpc6);
53360f47c08dSLen Brown 	if (do_snb_cstates && (pkg_cstate_limit >= PCL__7))
53370f47c08dSLen Brown 		BIC_PRESENT(BIC_Pkgpc7);
53380539ba11SLen Brown 	if (has_slv_msrs(family, model)) {
53390f47c08dSLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc2);
53400f47c08dSLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc3);
53410f47c08dSLen Brown 		BIC_PRESENT(BIC_Pkgpc6);
53420f47c08dSLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc7);
53430539ba11SLen Brown 		BIC_PRESENT(BIC_Mod_c6);
53440539ba11SLen Brown 		use_c1_residency_msr = 1;
53450539ba11SLen Brown 	}
534620de0dabSAntti Laakso 	if (is_jvl(family, model)) {
534720de0dabSAntti Laakso 		BIC_NOT_PRESENT(BIC_CPU_c3);
534820de0dabSAntti Laakso 		BIC_NOT_PRESENT(BIC_CPU_c7);
534920de0dabSAntti Laakso 		BIC_NOT_PRESENT(BIC_Pkgpc2);
535020de0dabSAntti Laakso 		BIC_NOT_PRESENT(BIC_Pkgpc3);
535120de0dabSAntti Laakso 		BIC_NOT_PRESENT(BIC_Pkgpc6);
535220de0dabSAntti Laakso 		BIC_NOT_PRESENT(BIC_Pkgpc7);
535320de0dabSAntti Laakso 	}
53547170a374SLen Brown 	if (is_dnv(family, model)) {
53557170a374SLen Brown 		BIC_PRESENT(BIC_CPU_c1);
53567170a374SLen Brown 		BIC_NOT_PRESENT(BIC_CPU_c3);
53577170a374SLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc3);
53587170a374SLen Brown 		BIC_NOT_PRESENT(BIC_CPU_c7);
53597170a374SLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc7);
53607170a374SLen Brown 		use_c1_residency_msr = 1;
53617170a374SLen Brown 	}
536234c76197SLen Brown 	if (is_skx(family, model)) {
536334c76197SLen Brown 		BIC_NOT_PRESENT(BIC_CPU_c3);
536434c76197SLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc3);
536534c76197SLen Brown 		BIC_NOT_PRESENT(BIC_CPU_c7);
536634c76197SLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc7);
536734c76197SLen Brown 	}
5368ade0ebacSLen Brown 	if (is_bdx(family, model)) {
5369ade0ebacSLen Brown 		BIC_NOT_PRESENT(BIC_CPU_c7);
5370ade0ebacSLen Brown 		BIC_NOT_PRESENT(BIC_Pkgpc7);
5371ade0ebacSLen Brown 	}
5372570992fcSLen Brown 	if (has_c8910_msrs(family, model)) {
5373c315a09bSLen Brown 		if (pkg_cstate_limit >= PCL__8)
53740f47c08dSLen Brown 			BIC_PRESENT(BIC_Pkgpc8);
5375c315a09bSLen Brown 		if (pkg_cstate_limit >= PCL__9)
53760f47c08dSLen Brown 			BIC_PRESENT(BIC_Pkgpc9);
5377c315a09bSLen Brown 		if (pkg_cstate_limit >= PCL_10)
53780f47c08dSLen Brown 			BIC_PRESENT(BIC_Pkgpc10);
53790f47c08dSLen Brown 	}
5380570992fcSLen Brown 	do_irtl_hsw = has_c8910_msrs(family, model);
5381a99d8730SLen Brown 	if (has_skl_msrs(family, model)) {
5382a99d8730SLen Brown 		BIC_PRESENT(BIC_Totl_c0);
5383a99d8730SLen Brown 		BIC_PRESENT(BIC_Any_c0);
5384a99d8730SLen Brown 		BIC_PRESENT(BIC_GFX_c0);
5385a99d8730SLen Brown 		BIC_PRESENT(BIC_CPUGFX);
5386a99d8730SLen Brown 	}
5387144b44b1SLen Brown 	do_slm_cstates = is_slm(family, model);
5388fb5d4327SDasaratharaman Chandramouli 	do_knl_cstates  = is_knl(family, model);
5389103a8feaSLen Brown 
5390f6708400SChen Yu 	if (do_slm_cstates || do_knl_cstates || is_cnl(family, model) ||
5391f6708400SChen Yu 	    is_ehl(family, model))
5392562855eeSLen Brown 		BIC_NOT_PRESENT(BIC_CPU_c3);
5393103a8feaSLen Brown 
539496e47158SLen Brown 	if (!quiet)
5395f0057310SLen Brown 		decode_misc_pwr_mgmt_msr();
5396f0057310SLen Brown 
539796e47158SLen Brown 	if (!quiet && has_slv_msrs(family, model))
539871616c8eSLen Brown 		decode_c6_demotion_policy_msr();
539971616c8eSLen Brown 
5400889facbeSLen Brown 	rapl_probe(family, model);
54013a9a941dSLen Brown 	perf_limit_reasons_probe(family, model);
5402ac980e13SArtem Bityutskiy 	automatic_cstate_conversion_probe(family, model);
5403889facbeSLen Brown 
540496e47158SLen Brown 	if (!quiet)
54051b69317dSColin Ian King 		dump_cstate_pstate_config_info(family, model);
5406fcd17211SLen Brown 
540741618e63SLen Brown 	if (!quiet)
5408d76bb7a0SLen Brown 		print_dev_latency();
5409d76bb7a0SLen Brown 	if (!quiet)
541041618e63SLen Brown 		dump_sysfs_cstate_config();
54117293fccdSLen Brown 	if (!quiet)
54127293fccdSLen Brown 		dump_sysfs_pstate_config();
541341618e63SLen Brown 
5414a2b7b749SLen Brown 	if (has_skl_msrs(family, model))
5415a2b7b749SLen Brown 		calculate_tsc_tweak();
5416a2b7b749SLen Brown 
5417812db3f7SLen Brown 	if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
5418812db3f7SLen Brown 		BIC_PRESENT(BIC_GFX_rc6);
5419fdf676e5SLen Brown 
5420812db3f7SLen Brown 	if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
5421812db3f7SLen Brown 		BIC_PRESENT(BIC_GFXMHz);
542227d47356SLen Brown 
5423b4b91569SRafael Antognolli 	if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
5424b4b91569SRafael Antognolli 		BIC_PRESENT(BIC_GFXACTMHz);
5425b4b91569SRafael Antognolli 
5426be0e54c4SLen Brown 	if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))
5427be0e54c4SLen Brown 		BIC_PRESENT(BIC_CPU_LPI);
5428be0e54c4SLen Brown 	else
5429be0e54c4SLen Brown 		BIC_NOT_PRESENT(BIC_CPU_LPI);
5430be0e54c4SLen Brown 
54311f81c5efSLen Brown 	if (!access(sys_lpi_file_sysfs, R_OK)) {
54321f81c5efSLen Brown 		sys_lpi_file = sys_lpi_file_sysfs;
5433be0e54c4SLen Brown 		BIC_PRESENT(BIC_SYS_LPI);
54341f81c5efSLen Brown 	} else if (!access(sys_lpi_file_debugfs, R_OK)) {
54351f81c5efSLen Brown 		sys_lpi_file = sys_lpi_file_debugfs;
54361f81c5efSLen Brown 		BIC_PRESENT(BIC_SYS_LPI);
54371f81c5efSLen Brown 	} else {
54381f81c5efSLen Brown 		sys_lpi_file_sysfs = NULL;
5439be0e54c4SLen Brown 		BIC_NOT_PRESENT(BIC_SYS_LPI);
54401f81c5efSLen Brown 	}
5441be0e54c4SLen Brown 
544296e47158SLen Brown 	if (!quiet)
544333148d67SLen Brown 		decode_misc_feature_control();
544433148d67SLen Brown 
5445889facbeSLen Brown 	return;
5446103a8feaSLen Brown }
5447103a8feaSLen Brown 
5448103a8feaSLen Brown /*
5449103a8feaSLen Brown  * in /dev/cpu/ return success for names that are numbers
5450103a8feaSLen Brown  * ie. filter out ".", "..", "microcode".
5451103a8feaSLen Brown  */
5452103a8feaSLen Brown int dir_filter(const struct dirent *dirp)
5453103a8feaSLen Brown {
5454103a8feaSLen Brown 	if (isdigit(dirp->d_name[0]))
5455103a8feaSLen Brown 		return 1;
5456103a8feaSLen Brown 	else
5457103a8feaSLen Brown 		return 0;
5458103a8feaSLen Brown }
5459103a8feaSLen Brown 
5460103a8feaSLen Brown int open_dev_cpu_msr(int dummy1)
5461103a8feaSLen Brown {
5462103a8feaSLen Brown 	return 0;
5463103a8feaSLen Brown }
5464103a8feaSLen Brown 
5465c98d5d94SLen Brown void topology_probe()
5466c98d5d94SLen Brown {
5467c98d5d94SLen Brown 	int i;
5468c98d5d94SLen Brown 	int max_core_id = 0;
5469c98d5d94SLen Brown 	int max_package_id = 0;
54706de68fe1SLen Brown 	int max_die_id = 0;
5471c98d5d94SLen Brown 	int max_siblings = 0;
5472c98d5d94SLen Brown 
5473c98d5d94SLen Brown 	/* Initialize num_cpus, max_cpu_num */
5474843c5791SPrarit Bhargava 	set_max_cpu_num();
5475c98d5d94SLen Brown 	topo.num_cpus = 0;
5476c98d5d94SLen Brown 	for_all_proc_cpus(count_cpus);
5477c98d5d94SLen Brown 	if (!summary_only && topo.num_cpus > 1)
5478812db3f7SLen Brown 		BIC_PRESENT(BIC_CPU);
5479c98d5d94SLen Brown 
5480d8af6f5fSLen Brown 	if (debug > 1)
5481b7d8c148SLen Brown 		fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
5482c98d5d94SLen Brown 
5483c98d5d94SLen Brown 	cpus = calloc(1, (topo.max_cpu_num  + 1) * sizeof(struct cpu_topology));
5484b2c95d90SJosh Triplett 	if (cpus == NULL)
5485b2c95d90SJosh Triplett 		err(1, "calloc cpus");
5486c98d5d94SLen Brown 
5487c98d5d94SLen Brown 	/*
5488c98d5d94SLen Brown 	 * Allocate and initialize cpu_present_set
5489c98d5d94SLen Brown 	 */
5490c98d5d94SLen Brown 	cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1));
5491b2c95d90SJosh Triplett 	if (cpu_present_set == NULL)
5492b2c95d90SJosh Triplett 		err(3, "CPU_ALLOC");
5493c98d5d94SLen Brown 	cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
5494c98d5d94SLen Brown 	CPU_ZERO_S(cpu_present_setsize, cpu_present_set);
5495c98d5d94SLen Brown 	for_all_proc_cpus(mark_cpu_present);
5496c98d5d94SLen Brown 
5497c98d5d94SLen Brown 	/*
54981ef7d21aSLen Brown 	 * Validate that all cpus in cpu_subset are also in cpu_present_set
54991ef7d21aSLen Brown 	 */
55001ef7d21aSLen Brown 	for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {
55011ef7d21aSLen Brown 		if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset))
55021ef7d21aSLen Brown 			if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set))
55031ef7d21aSLen Brown 				err(1, "cpu%d not present", i);
55041ef7d21aSLen Brown 	}
55051ef7d21aSLen Brown 
55061ef7d21aSLen Brown 	/*
5507c98d5d94SLen Brown 	 * Allocate and initialize cpu_affinity_set
5508c98d5d94SLen Brown 	 */
5509c98d5d94SLen Brown 	cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));
5510b2c95d90SJosh Triplett 	if (cpu_affinity_set == NULL)
5511b2c95d90SJosh Triplett 		err(3, "CPU_ALLOC");
5512c98d5d94SLen Brown 	cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
5513c98d5d94SLen Brown 	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
5514c98d5d94SLen Brown 
55158cb48b32SPrarit Bhargava 	for_all_proc_cpus(init_thread_id);
5516c98d5d94SLen Brown 
5517c98d5d94SLen Brown 	/*
5518c98d5d94SLen Brown 	 * For online cpus
5519c98d5d94SLen Brown 	 * find max_core_id, max_package_id
5520c98d5d94SLen Brown 	 */
5521c98d5d94SLen Brown 	for (i = 0; i <= topo.max_cpu_num; ++i) {
5522c98d5d94SLen Brown 		int siblings;
5523c98d5d94SLen Brown 
5524c98d5d94SLen Brown 		if (cpu_is_not_present(i)) {
5525d8af6f5fSLen Brown 			if (debug > 1)
5526b7d8c148SLen Brown 				fprintf(outf, "cpu%d NOT PRESENT\n", i);
5527c98d5d94SLen Brown 			continue;
5528c98d5d94SLen Brown 		}
5529c98d5d94SLen Brown 
55300e2d8f05SLen Brown 		cpus[i].logical_cpu_id = i;
55310e2d8f05SLen Brown 
55320e2d8f05SLen Brown 		/* get package information */
5533c98d5d94SLen Brown 		cpus[i].physical_package_id = get_physical_package_id(i);
5534c98d5d94SLen Brown 		if (cpus[i].physical_package_id > max_package_id)
5535c98d5d94SLen Brown 			max_package_id = cpus[i].physical_package_id;
5536c98d5d94SLen Brown 
55376de68fe1SLen Brown 		/* get die information */
55386de68fe1SLen Brown 		cpus[i].die_id = get_die_id(i);
55396de68fe1SLen Brown 		if (cpus[i].die_id > max_die_id)
55406de68fe1SLen Brown 			max_die_id = cpus[i].die_id;
55416de68fe1SLen Brown 
55420e2d8f05SLen Brown 		/* get numa node information */
5543ef605741SPrarit Bhargava 		cpus[i].physical_node_id = get_physical_node_id(&cpus[i]);
5544ef605741SPrarit Bhargava 		if (cpus[i].physical_node_id > topo.max_node_num)
5545ef605741SPrarit Bhargava 			topo.max_node_num = cpus[i].physical_node_id;
55460e2d8f05SLen Brown 
55470e2d8f05SLen Brown 		/* get core information */
55480e2d8f05SLen Brown 		cpus[i].physical_core_id = get_core_id(i);
55490e2d8f05SLen Brown 		if (cpus[i].physical_core_id > max_core_id)
55500e2d8f05SLen Brown 			max_core_id = cpus[i].physical_core_id;
55510e2d8f05SLen Brown 
55520e2d8f05SLen Brown 		/* get thread information */
55530e2d8f05SLen Brown 		siblings = get_thread_siblings(&cpus[i]);
5554c98d5d94SLen Brown 		if (siblings > max_siblings)
5555c98d5d94SLen Brown 			max_siblings = siblings;
55564f206a0fSArtem Bityutskiy 		if (cpus[i].thread_id == 0)
55578cb48b32SPrarit Bhargava 			topo.num_cores++;
5558c98d5d94SLen Brown 	}
5559ef605741SPrarit Bhargava 
556070a9c6e8SPrarit Bhargava 	topo.cores_per_node = max_core_id + 1;
5561d8af6f5fSLen Brown 	if (debug > 1)
5562b7d8c148SLen Brown 		fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
556370a9c6e8SPrarit Bhargava 			max_core_id, topo.cores_per_node);
556470a9c6e8SPrarit Bhargava 	if (!summary_only && topo.cores_per_node > 1)
5565812db3f7SLen Brown 		BIC_PRESENT(BIC_Core);
5566c98d5d94SLen Brown 
55676de68fe1SLen Brown 	topo.num_die = max_die_id + 1;
55686de68fe1SLen Brown 	if (debug > 1)
55696de68fe1SLen Brown 		fprintf(outf, "max_die_id %d, sizing for %d die\n",
55706de68fe1SLen Brown 				max_die_id, topo.num_die);
55716de68fe1SLen Brown 	if (!summary_only && topo.num_die > 1)
55726de68fe1SLen Brown 		BIC_PRESENT(BIC_Die);
55736de68fe1SLen Brown 
5574c98d5d94SLen Brown 	topo.num_packages = max_package_id + 1;
5575d8af6f5fSLen Brown 	if (debug > 1)
5576b7d8c148SLen Brown 		fprintf(outf, "max_package_id %d, sizing for %d packages\n",
5577c98d5d94SLen Brown 			max_package_id, topo.num_packages);
55787da6e3e2SLen Brown 	if (!summary_only && topo.num_packages > 1)
5579812db3f7SLen Brown 		BIC_PRESENT(BIC_Package);
5580c98d5d94SLen Brown 
5581ef605741SPrarit Bhargava 	set_node_data();
5582ef605741SPrarit Bhargava 	if (debug > 1)
558370a9c6e8SPrarit Bhargava 		fprintf(outf, "nodes_per_pkg %d\n", topo.nodes_per_pkg);
558401235041SPrarit Bhargava 	if (!summary_only && topo.nodes_per_pkg > 1)
558501235041SPrarit Bhargava 		BIC_PRESENT(BIC_Node);
5586ef605741SPrarit Bhargava 
558770a9c6e8SPrarit Bhargava 	topo.threads_per_core = max_siblings;
5588d8af6f5fSLen Brown 	if (debug > 1)
5589b7d8c148SLen Brown 		fprintf(outf, "max_siblings %d\n", max_siblings);
55902ffbb224SPrarit Bhargava 
55912ffbb224SPrarit Bhargava 	if (debug < 1)
55922ffbb224SPrarit Bhargava 		return;
55932ffbb224SPrarit Bhargava 
55942ffbb224SPrarit Bhargava 	for (i = 0; i <= topo.max_cpu_num; ++i) {
55950ec712e3SLen Brown 		if (cpu_is_not_present(i))
55960ec712e3SLen Brown 			continue;
55972ffbb224SPrarit Bhargava 		fprintf(outf,
55986de68fe1SLen Brown 			"cpu %d pkg %d die %d node %d lnode %d core %d thread %d\n",
55996de68fe1SLen Brown 			i, cpus[i].physical_package_id, cpus[i].die_id,
56002ffbb224SPrarit Bhargava 			cpus[i].physical_node_id,
56012ffbb224SPrarit Bhargava 			cpus[i].logical_node_id,
56022ffbb224SPrarit Bhargava 			cpus[i].physical_core_id,
56032ffbb224SPrarit Bhargava 			cpus[i].thread_id);
56042ffbb224SPrarit Bhargava 	}
56052ffbb224SPrarit Bhargava 
5606c98d5d94SLen Brown }
5607c98d5d94SLen Brown 
5608c98d5d94SLen Brown void
560940f5cfe7SPrarit Bhargava allocate_counters(struct thread_data **t, struct core_data **c,
561040f5cfe7SPrarit Bhargava 		  struct pkg_data **p)
5611c98d5d94SLen Brown {
5612c98d5d94SLen Brown 	int i;
561340f5cfe7SPrarit Bhargava 	int num_cores = topo.cores_per_node * topo.nodes_per_pkg *
561440f5cfe7SPrarit Bhargava 			topo.num_packages;
561540f5cfe7SPrarit Bhargava 	int num_threads = topo.threads_per_core * num_cores;
5616c98d5d94SLen Brown 
561740f5cfe7SPrarit Bhargava 	*t = calloc(num_threads, sizeof(struct thread_data));
5618c98d5d94SLen Brown 	if (*t == NULL)
5619c98d5d94SLen Brown 		goto error;
5620c98d5d94SLen Brown 
562140f5cfe7SPrarit Bhargava 	for (i = 0; i < num_threads; i++)
5622c98d5d94SLen Brown 		(*t)[i].cpu_id = -1;
5623c98d5d94SLen Brown 
562440f5cfe7SPrarit Bhargava 	*c = calloc(num_cores, sizeof(struct core_data));
5625c98d5d94SLen Brown 	if (*c == NULL)
5626c98d5d94SLen Brown 		goto error;
5627c98d5d94SLen Brown 
562840f5cfe7SPrarit Bhargava 	for (i = 0; i < num_cores; i++)
5629c98d5d94SLen Brown 		(*c)[i].core_id = -1;
5630c98d5d94SLen Brown 
5631678a3bd1SLen Brown 	*p = calloc(topo.num_packages, sizeof(struct pkg_data));
5632c98d5d94SLen Brown 	if (*p == NULL)
5633c98d5d94SLen Brown 		goto error;
5634c98d5d94SLen Brown 
5635c98d5d94SLen Brown 	for (i = 0; i < topo.num_packages; i++)
5636c98d5d94SLen Brown 		(*p)[i].package_id = i;
5637c98d5d94SLen Brown 
5638c98d5d94SLen Brown 	return;
5639c98d5d94SLen Brown error:
5640b2c95d90SJosh Triplett 	err(1, "calloc counters");
5641c98d5d94SLen Brown }
5642c98d5d94SLen Brown /*
5643c98d5d94SLen Brown  * init_counter()
5644c98d5d94SLen Brown  *
5645c98d5d94SLen Brown  * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE
5646c98d5d94SLen Brown  */
5647c98d5d94SLen Brown void init_counter(struct thread_data *thread_base, struct core_data *core_base,
56488cb48b32SPrarit Bhargava 	struct pkg_data *pkg_base, int cpu_id)
5649c98d5d94SLen Brown {
56508cb48b32SPrarit Bhargava 	int pkg_id = cpus[cpu_id].physical_package_id;
565140f5cfe7SPrarit Bhargava 	int node_id = cpus[cpu_id].logical_node_id;
56528cb48b32SPrarit Bhargava 	int core_id = cpus[cpu_id].physical_core_id;
56538cb48b32SPrarit Bhargava 	int thread_id = cpus[cpu_id].thread_id;
5654c98d5d94SLen Brown 	struct thread_data *t;
5655c98d5d94SLen Brown 	struct core_data *c;
5656c98d5d94SLen Brown 	struct pkg_data *p;
5657c98d5d94SLen Brown 
565842dd4520SNathan Ciobanu 
565942dd4520SNathan Ciobanu 	/* Workaround for systems where physical_node_id==-1
566042dd4520SNathan Ciobanu 	 * and logical_node_id==(-1 - topo.num_cpus)
566142dd4520SNathan Ciobanu 	 */
566242dd4520SNathan Ciobanu 	if (node_id < 0)
566342dd4520SNathan Ciobanu 		node_id = 0;
566442dd4520SNathan Ciobanu 
566540f5cfe7SPrarit Bhargava 	t = GET_THREAD(thread_base, thread_id, core_id, node_id, pkg_id);
566640f5cfe7SPrarit Bhargava 	c = GET_CORE(core_base, core_id, node_id, pkg_id);
56678cb48b32SPrarit Bhargava 	p = GET_PKG(pkg_base, pkg_id);
5668c98d5d94SLen Brown 
5669c98d5d94SLen Brown 	t->cpu_id = cpu_id;
56708cb48b32SPrarit Bhargava 	if (thread_id == 0) {
5671c98d5d94SLen Brown 		t->flags |= CPU_IS_FIRST_THREAD_IN_CORE;
5672c98d5d94SLen Brown 		if (cpu_is_first_core_in_package(cpu_id))
5673c98d5d94SLen Brown 			t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE;
5674c98d5d94SLen Brown 	}
5675c98d5d94SLen Brown 
56768cb48b32SPrarit Bhargava 	c->core_id = core_id;
56778cb48b32SPrarit Bhargava 	p->package_id = pkg_id;
5678c98d5d94SLen Brown }
5679c98d5d94SLen Brown 
5680c98d5d94SLen Brown 
5681c98d5d94SLen Brown int initialize_counters(int cpu_id)
5682c98d5d94SLen Brown {
56838cb48b32SPrarit Bhargava 	init_counter(EVEN_COUNTERS, cpu_id);
56848cb48b32SPrarit Bhargava 	init_counter(ODD_COUNTERS, cpu_id);
5685c98d5d94SLen Brown 	return 0;
5686c98d5d94SLen Brown }
5687c98d5d94SLen Brown 
5688c98d5d94SLen Brown void allocate_output_buffer()
5689c98d5d94SLen Brown {
5690eeb71c95SNaoya Horiguchi 	output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);
5691c98d5d94SLen Brown 	outp = output_buffer;
5692b2c95d90SJosh Triplett 	if (outp == NULL)
5693b2c95d90SJosh Triplett 		err(-1, "calloc output buffer");
5694c98d5d94SLen Brown }
569536229897SLen Brown void allocate_fd_percpu(void)
569636229897SLen Brown {
569701a67adfSMika Westerberg 	fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
569836229897SLen Brown 	if (fd_percpu == NULL)
569936229897SLen Brown 		err(-1, "calloc fd_percpu");
570036229897SLen Brown }
5701562a2d37SLen Brown void allocate_irq_buffers(void)
5702562a2d37SLen Brown {
5703562a2d37SLen Brown 	irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
5704562a2d37SLen Brown 	if (irq_column_2_cpu == NULL)
5705562a2d37SLen Brown 		err(-1, "calloc %d", topo.num_cpus);
5706c98d5d94SLen Brown 
570701a67adfSMika Westerberg 	irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int));
5708562a2d37SLen Brown 	if (irqs_per_cpu == NULL)
570901a67adfSMika Westerberg 		err(-1, "calloc %d", topo.max_cpu_num + 1);
5710562a2d37SLen Brown }
5711c98d5d94SLen Brown void setup_all_buffers(void)
5712c98d5d94SLen Brown {
5713c98d5d94SLen Brown 	topology_probe();
5714562a2d37SLen Brown 	allocate_irq_buffers();
571536229897SLen Brown 	allocate_fd_percpu();
5716c98d5d94SLen Brown 	allocate_counters(&thread_even, &core_even, &package_even);
5717c98d5d94SLen Brown 	allocate_counters(&thread_odd, &core_odd, &package_odd);
5718c98d5d94SLen Brown 	allocate_output_buffer();
5719c98d5d94SLen Brown 	for_all_proc_cpus(initialize_counters);
5720c98d5d94SLen Brown }
57213b4d5c7fSAndy Shevchenko 
57227ce7d5deSPrarit Bhargava void set_base_cpu(void)
57237ce7d5deSPrarit Bhargava {
57247ce7d5deSPrarit Bhargava 	base_cpu = sched_getcpu();
57257ce7d5deSPrarit Bhargava 	if (base_cpu < 0)
57267ce7d5deSPrarit Bhargava 		err(-ENODEV, "No valid cpus found");
57277ce7d5deSPrarit Bhargava 
57287ce7d5deSPrarit Bhargava 	if (debug > 1)
5729b7d8c148SLen Brown 		fprintf(outf, "base_cpu = %d\n", base_cpu);
57307ce7d5deSPrarit Bhargava }
57317ce7d5deSPrarit Bhargava 
5732103a8feaSLen Brown void turbostat_init()
5733103a8feaSLen Brown {
57347ce7d5deSPrarit Bhargava 	setup_all_buffers();
57357ce7d5deSPrarit Bhargava 	set_base_cpu();
5736103a8feaSLen Brown 	check_dev_msr();
573798481e79SLen Brown 	check_permissions();
5738fcd17211SLen Brown 	process_cpuid();
57392af4f9b8SLen Brown 	linux_perf_init();
5740103a8feaSLen Brown 
5741103a8feaSLen Brown 
574296e47158SLen Brown 	if (!quiet)
57437f5c258eSLen Brown 		for_all_cpus(print_hwp, ODD_COUNTERS);
57447f5c258eSLen Brown 
574596e47158SLen Brown 	if (!quiet)
5746889facbeSLen Brown 		for_all_cpus(print_epb, ODD_COUNTERS);
5747889facbeSLen Brown 
574896e47158SLen Brown 	if (!quiet)
57493a9a941dSLen Brown 		for_all_cpus(print_perf_limit, ODD_COUNTERS);
57503a9a941dSLen Brown 
575196e47158SLen Brown 	if (!quiet)
5752889facbeSLen Brown 		for_all_cpus(print_rapl, ODD_COUNTERS);
5753889facbeSLen Brown 
5754889facbeSLen Brown 	for_all_cpus(set_temperature_target, ODD_COUNTERS);
5755889facbeSLen Brown 
575696e47158SLen Brown 	if (!quiet)
5757889facbeSLen Brown 		for_all_cpus(print_thermal, ODD_COUNTERS);
57585a63426eSLen Brown 
575996e47158SLen Brown 	if (!quiet && do_irtl_snb)
57605a63426eSLen Brown 		print_irtl();
5761103a8feaSLen Brown }
5762103a8feaSLen Brown 
5763103a8feaSLen Brown int fork_it(char **argv)
5764103a8feaSLen Brown {
5765103a8feaSLen Brown 	pid_t child_pid;
5766d91bb17cSLen Brown 	int status;
5767d15cf7c1SLen Brown 
5768218f0e8dSLen Brown 	snapshot_proc_sysfs_files();
5769d91bb17cSLen Brown 	status = for_all_cpus(get_counters, EVEN_COUNTERS);
57704c2122d4SLen Brown 	first_counter_read = 0;
5771d91bb17cSLen Brown 	if (status)
5772d91bb17cSLen Brown 		exit(status);
5773d15cf7c1SLen Brown 	/* clear affinity side-effect of get_counters() */
5774d15cf7c1SLen Brown 	sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
5775103a8feaSLen Brown 	gettimeofday(&tv_even, (struct timezone *)NULL);
5776103a8feaSLen Brown 
5777103a8feaSLen Brown 	child_pid = fork();
5778103a8feaSLen Brown 	if (!child_pid) {
5779103a8feaSLen Brown 		/* child */
5780103a8feaSLen Brown 		execvp(argv[0], argv);
57810815a3d0SLen Brown 		err(errno, "exec %s", argv[0]);
5782103a8feaSLen Brown 	} else {
5783103a8feaSLen Brown 
5784103a8feaSLen Brown 		/* parent */
5785b2c95d90SJosh Triplett 		if (child_pid == -1)
5786b2c95d90SJosh Triplett 			err(1, "fork");
5787103a8feaSLen Brown 
5788103a8feaSLen Brown 		signal(SIGINT, SIG_IGN);
5789103a8feaSLen Brown 		signal(SIGQUIT, SIG_IGN);
5790b2c95d90SJosh Triplett 		if (waitpid(child_pid, &status, 0) == -1)
5791b2c95d90SJosh Triplett 			err(status, "waitpid");
57922a954966SDavid Arcari 
57932a954966SDavid Arcari 		if (WIFEXITED(status))
57942a954966SDavid Arcari 			status = WEXITSTATUS(status);
5795103a8feaSLen Brown 	}
5796c98d5d94SLen Brown 	/*
5797c98d5d94SLen Brown 	 * n.b. fork_it() does not check for errors from for_all_cpus()
5798c98d5d94SLen Brown 	 * because re-starting is problematic when forking
5799c98d5d94SLen Brown 	 */
5800218f0e8dSLen Brown 	snapshot_proc_sysfs_files();
5801c98d5d94SLen Brown 	for_all_cpus(get_counters, ODD_COUNTERS);
5802103a8feaSLen Brown 	gettimeofday(&tv_odd, (struct timezone *)NULL);
5803103a8feaSLen Brown 	timersub(&tv_odd, &tv_even, &tv_delta);
5804ba3dec99SLen Brown 	if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS))
5805ba3dec99SLen Brown 		fprintf(outf, "%s: Counter reset detected\n", progname);
5806ba3dec99SLen Brown 	else {
5807c98d5d94SLen Brown 		compute_average(EVEN_COUNTERS);
5808c98d5d94SLen Brown 		format_all_counters(EVEN_COUNTERS);
5809ba3dec99SLen Brown 	}
5810103a8feaSLen Brown 
5811b7d8c148SLen Brown 	fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
5812b7d8c148SLen Brown 
5813b7d8c148SLen Brown 	flush_output_stderr();
5814103a8feaSLen Brown 
5815d91bb17cSLen Brown 	return status;
5816103a8feaSLen Brown }
5817103a8feaSLen Brown 
58183b4d5c7fSAndy Shevchenko int get_and_dump_counters(void)
58193b4d5c7fSAndy Shevchenko {
58203b4d5c7fSAndy Shevchenko 	int status;
58213b4d5c7fSAndy Shevchenko 
5822218f0e8dSLen Brown 	snapshot_proc_sysfs_files();
58233b4d5c7fSAndy Shevchenko 	status = for_all_cpus(get_counters, ODD_COUNTERS);
58243b4d5c7fSAndy Shevchenko 	if (status)
58253b4d5c7fSAndy Shevchenko 		return status;
58263b4d5c7fSAndy Shevchenko 
58273b4d5c7fSAndy Shevchenko 	status = for_all_cpus(dump_counters, ODD_COUNTERS);
58283b4d5c7fSAndy Shevchenko 	if (status)
58293b4d5c7fSAndy Shevchenko 		return status;
58303b4d5c7fSAndy Shevchenko 
5831b7d8c148SLen Brown 	flush_output_stdout();
58323b4d5c7fSAndy Shevchenko 
58333b4d5c7fSAndy Shevchenko 	return status;
58343b4d5c7fSAndy Shevchenko }
58353b4d5c7fSAndy Shevchenko 
5836d8af6f5fSLen Brown void print_version() {
58373e9fa998SLen Brown 	fprintf(outf, "turbostat version 20.09.30"
5838d8af6f5fSLen Brown 		" - Len Brown <lenb@kernel.org>\n");
5839d8af6f5fSLen Brown }
5840d8af6f5fSLen Brown 
5841495c7654SLen Brown int add_counter(unsigned int msr_num, char *path, char *name,
5842495c7654SLen Brown 	unsigned int width, enum counter_scope scope,
584341618e63SLen Brown 	enum counter_type type, enum counter_format format, int flags)
5844388e9c81SLen Brown {
5845388e9c81SLen Brown 	struct msr_counter *msrp;
5846388e9c81SLen Brown 
5847388e9c81SLen Brown 	msrp = calloc(1, sizeof(struct msr_counter));
5848388e9c81SLen Brown 	if (msrp == NULL) {
5849388e9c81SLen Brown 		perror("calloc");
5850388e9c81SLen Brown 		exit(1);
5851388e9c81SLen Brown 	}
5852388e9c81SLen Brown 
5853388e9c81SLen Brown 	msrp->msr_num = msr_num;
5854d8d005baSLen Brown 	strncpy(msrp->name, name, NAME_BYTES - 1);
5855495c7654SLen Brown 	if (path)
5856d8d005baSLen Brown 		strncpy(msrp->path, path, PATH_BYTES - 1);
5857388e9c81SLen Brown 	msrp->width = width;
5858388e9c81SLen Brown 	msrp->type = type;
5859388e9c81SLen Brown 	msrp->format = format;
586041618e63SLen Brown 	msrp->flags = flags;
5861388e9c81SLen Brown 
5862388e9c81SLen Brown 	switch (scope) {
5863388e9c81SLen Brown 
5864388e9c81SLen Brown 	case SCOPE_CPU:
5865388e9c81SLen Brown 		msrp->next = sys.tp;
5866388e9c81SLen Brown 		sys.tp = msrp;
5867678a3bd1SLen Brown 		sys.added_thread_counters++;
58680748eaf0SLen Brown 		if (sys.added_thread_counters > MAX_ADDED_THREAD_COUNTERS) {
5869678a3bd1SLen Brown 			fprintf(stderr, "exceeded max %d added thread counters\n",
5870678a3bd1SLen Brown 				MAX_ADDED_COUNTERS);
5871678a3bd1SLen Brown 			exit(-1);
5872678a3bd1SLen Brown 		}
5873388e9c81SLen Brown 		break;
5874388e9c81SLen Brown 
5875388e9c81SLen Brown 	case SCOPE_CORE:
5876388e9c81SLen Brown 		msrp->next = sys.cp;
5877388e9c81SLen Brown 		sys.cp = msrp;
5878678a3bd1SLen Brown 		sys.added_core_counters++;
5879678a3bd1SLen Brown 		if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
5880678a3bd1SLen Brown 			fprintf(stderr, "exceeded max %d added core counters\n",
5881678a3bd1SLen Brown 				MAX_ADDED_COUNTERS);
5882678a3bd1SLen Brown 			exit(-1);
5883678a3bd1SLen Brown 		}
5884388e9c81SLen Brown 		break;
5885388e9c81SLen Brown 
5886388e9c81SLen Brown 	case SCOPE_PACKAGE:
5887388e9c81SLen Brown 		msrp->next = sys.pp;
5888388e9c81SLen Brown 		sys.pp = msrp;
5889678a3bd1SLen Brown 		sys.added_package_counters++;
5890678a3bd1SLen Brown 		if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
5891678a3bd1SLen Brown 			fprintf(stderr, "exceeded max %d added package counters\n",
5892678a3bd1SLen Brown 				MAX_ADDED_COUNTERS);
5893678a3bd1SLen Brown 			exit(-1);
5894678a3bd1SLen Brown 		}
5895388e9c81SLen Brown 		break;
5896388e9c81SLen Brown 	}
5897388e9c81SLen Brown 
5898388e9c81SLen Brown 	return 0;
5899388e9c81SLen Brown }
5900388e9c81SLen Brown 
5901388e9c81SLen Brown void parse_add_command(char *add_command)
5902388e9c81SLen Brown {
5903388e9c81SLen Brown 	int msr_num = 0;
5904495c7654SLen Brown 	char *path = NULL;
59050f47c08dSLen Brown 	char name_buffer[NAME_BYTES] = "";
5906388e9c81SLen Brown 	int width = 64;
5907388e9c81SLen Brown 	int fail = 0;
5908388e9c81SLen Brown 	enum counter_scope scope = SCOPE_CPU;
5909388e9c81SLen Brown 	enum counter_type type = COUNTER_CYCLES;
5910388e9c81SLen Brown 	enum counter_format format = FORMAT_DELTA;
5911388e9c81SLen Brown 
5912388e9c81SLen Brown 	while (add_command) {
5913388e9c81SLen Brown 
5914388e9c81SLen Brown 		if (sscanf(add_command, "msr0x%x", &msr_num) == 1)
5915388e9c81SLen Brown 			goto next;
5916388e9c81SLen Brown 
5917388e9c81SLen Brown 		if (sscanf(add_command, "msr%d", &msr_num) == 1)
5918388e9c81SLen Brown 			goto next;
5919388e9c81SLen Brown 
5920495c7654SLen Brown 		if (*add_command == '/') {
5921495c7654SLen Brown 			path = add_command;
5922495c7654SLen Brown 			goto next;
5923495c7654SLen Brown 		}
5924495c7654SLen Brown 
5925388e9c81SLen Brown 		if (sscanf(add_command, "u%d", &width) == 1) {
5926388e9c81SLen Brown 			if ((width == 32) || (width == 64))
5927388e9c81SLen Brown 				goto next;
5928388e9c81SLen Brown 			width = 64;
5929388e9c81SLen Brown 		}
5930388e9c81SLen Brown 		if (!strncmp(add_command, "cpu", strlen("cpu"))) {
5931388e9c81SLen Brown 			scope = SCOPE_CPU;
5932388e9c81SLen Brown 			goto next;
5933388e9c81SLen Brown 		}
5934388e9c81SLen Brown 		if (!strncmp(add_command, "core", strlen("core"))) {
5935388e9c81SLen Brown 			scope = SCOPE_CORE;
5936388e9c81SLen Brown 			goto next;
5937388e9c81SLen Brown 		}
5938388e9c81SLen Brown 		if (!strncmp(add_command, "package", strlen("package"))) {
5939388e9c81SLen Brown 			scope = SCOPE_PACKAGE;
5940388e9c81SLen Brown 			goto next;
5941388e9c81SLen Brown 		}
5942388e9c81SLen Brown 		if (!strncmp(add_command, "cycles", strlen("cycles"))) {
5943388e9c81SLen Brown 			type = COUNTER_CYCLES;
5944388e9c81SLen Brown 			goto next;
5945388e9c81SLen Brown 		}
5946388e9c81SLen Brown 		if (!strncmp(add_command, "seconds", strlen("seconds"))) {
5947388e9c81SLen Brown 			type = COUNTER_SECONDS;
5948388e9c81SLen Brown 			goto next;
5949388e9c81SLen Brown 		}
595041618e63SLen Brown 		if (!strncmp(add_command, "usec", strlen("usec"))) {
595141618e63SLen Brown 			type = COUNTER_USEC;
595241618e63SLen Brown 			goto next;
595341618e63SLen Brown 		}
5954388e9c81SLen Brown 		if (!strncmp(add_command, "raw", strlen("raw"))) {
5955388e9c81SLen Brown 			format = FORMAT_RAW;
5956388e9c81SLen Brown 			goto next;
5957388e9c81SLen Brown 		}
5958388e9c81SLen Brown 		if (!strncmp(add_command, "delta", strlen("delta"))) {
5959388e9c81SLen Brown 			format = FORMAT_DELTA;
5960388e9c81SLen Brown 			goto next;
5961388e9c81SLen Brown 		}
5962388e9c81SLen Brown 		if (!strncmp(add_command, "percent", strlen("percent"))) {
5963388e9c81SLen Brown 			format = FORMAT_PERCENT;
5964388e9c81SLen Brown 			goto next;
5965388e9c81SLen Brown 		}
5966388e9c81SLen Brown 
5967388e9c81SLen Brown 		if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) {	/* 18 < NAME_BYTES */
5968388e9c81SLen Brown 			char *eos;
5969388e9c81SLen Brown 
5970388e9c81SLen Brown 			eos = strchr(name_buffer, ',');
5971388e9c81SLen Brown 			if (eos)
5972388e9c81SLen Brown 				*eos = '\0';
5973388e9c81SLen Brown 			goto next;
5974388e9c81SLen Brown 		}
5975388e9c81SLen Brown 
5976388e9c81SLen Brown next:
5977388e9c81SLen Brown 		add_command = strchr(add_command, ',');
5978495c7654SLen Brown 		if (add_command) {
5979495c7654SLen Brown 			*add_command = '\0';
5980388e9c81SLen Brown 			add_command++;
5981495c7654SLen Brown 		}
5982388e9c81SLen Brown 
5983388e9c81SLen Brown 	}
5984495c7654SLen Brown 	if ((msr_num == 0) && (path == NULL)) {
5985495c7654SLen Brown 		fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter ) required\n");
5986388e9c81SLen Brown 		fail++;
5987388e9c81SLen Brown 	}
5988388e9c81SLen Brown 
5989388e9c81SLen Brown 	/* generate default column header */
5990388e9c81SLen Brown 	if (*name_buffer == '\0') {
5991388e9c81SLen Brown 		if (width == 32)
59925f3aea57SLen Brown 			sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
5993388e9c81SLen Brown 		else
59945f3aea57SLen Brown 			sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
5995388e9c81SLen Brown 	}
5996388e9c81SLen Brown 
599741618e63SLen Brown 	if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0))
5998388e9c81SLen Brown 		fail++;
5999388e9c81SLen Brown 
6000388e9c81SLen Brown 	if (fail) {
6001388e9c81SLen Brown 		help();
6002388e9c81SLen Brown 		exit(1);
6003388e9c81SLen Brown 	}
6004388e9c81SLen Brown }
600541618e63SLen Brown 
6006dd778a5eSLen Brown int is_deferred_skip(char *name)
6007dd778a5eSLen Brown {
6008dd778a5eSLen Brown 	int i;
6009dd778a5eSLen Brown 
6010dd778a5eSLen Brown 	for (i = 0; i < deferred_skip_index; ++i)
6011dd778a5eSLen Brown 		if (!strcmp(name, deferred_skip_names[i]))
6012dd778a5eSLen Brown 			return 1;
6013dd778a5eSLen Brown 	return 0;
6014dd778a5eSLen Brown }
6015dd778a5eSLen Brown 
601641618e63SLen Brown void probe_sysfs(void)
601741618e63SLen Brown {
601841618e63SLen Brown 	char path[64];
601941618e63SLen Brown 	char name_buf[16];
602041618e63SLen Brown 	FILE *input;
602141618e63SLen Brown 	int state;
602241618e63SLen Brown 	char *sp;
602341618e63SLen Brown 
602441618e63SLen Brown 	if (!DO_BIC(BIC_sysfs))
602541618e63SLen Brown 		return;
602641618e63SLen Brown 
60270748eaf0SLen Brown 	for (state = 10; state >= 0; --state) {
602841618e63SLen Brown 
602941618e63SLen Brown 		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
603041618e63SLen Brown 			base_cpu, state);
603141618e63SLen Brown 		input = fopen(path, "r");
603241618e63SLen Brown 		if (input == NULL)
603341618e63SLen Brown 			continue;
60348173c336SBen Hutchings 		if (!fgets(name_buf, sizeof(name_buf), input))
60358173c336SBen Hutchings 			err(1, "%s: failed to read file", path);
603641618e63SLen Brown 
603741618e63SLen Brown 		 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
603841618e63SLen Brown 		sp = strchr(name_buf, '-');
603941618e63SLen Brown 		if (!sp)
604041618e63SLen Brown 			sp = strchrnul(name_buf, '\n');
604141618e63SLen Brown 		*sp = '%';
604241618e63SLen Brown 		*(sp + 1) = '\0';
604341618e63SLen Brown 
6044fecb3bc8SDavid Arcari 		remove_underbar(name_buf);
6045fecb3bc8SDavid Arcari 
604641618e63SLen Brown 		fclose(input);
604741618e63SLen Brown 
604841618e63SLen Brown 		sprintf(path, "cpuidle/state%d/time", state);
604941618e63SLen Brown 
6050dd778a5eSLen Brown 		if (is_deferred_skip(name_buf))
6051dd778a5eSLen Brown 			continue;
6052dd778a5eSLen Brown 
605341618e63SLen Brown 		add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC,
605441618e63SLen Brown 				FORMAT_PERCENT, SYSFS_PERCPU);
605541618e63SLen Brown 	}
605641618e63SLen Brown 
60570748eaf0SLen Brown 	for (state = 10; state >= 0; --state) {
605841618e63SLen Brown 
605941618e63SLen Brown 		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
606041618e63SLen Brown 			base_cpu, state);
606141618e63SLen Brown 		input = fopen(path, "r");
606241618e63SLen Brown 		if (input == NULL)
606341618e63SLen Brown 			continue;
60648173c336SBen Hutchings 		if (!fgets(name_buf, sizeof(name_buf), input))
60658173c336SBen Hutchings 			err(1, "%s: failed to read file", path);
606641618e63SLen Brown 		 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
606741618e63SLen Brown 		sp = strchr(name_buf, '-');
606841618e63SLen Brown 		if (!sp)
606941618e63SLen Brown 			sp = strchrnul(name_buf, '\n');
607041618e63SLen Brown 		*sp = '\0';
607141618e63SLen Brown 		fclose(input);
607241618e63SLen Brown 
6073fecb3bc8SDavid Arcari 		remove_underbar(name_buf);
6074fecb3bc8SDavid Arcari 
607541618e63SLen Brown 		sprintf(path, "cpuidle/state%d/usage", state);
607641618e63SLen Brown 
6077dd778a5eSLen Brown 		if (is_deferred_skip(name_buf))
6078dd778a5eSLen Brown 			continue;
6079dd778a5eSLen Brown 
608041618e63SLen Brown 		add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS,
608141618e63SLen Brown 				FORMAT_DELTA, SYSFS_PERCPU);
608241618e63SLen Brown 	}
608341618e63SLen Brown 
608441618e63SLen Brown }
608541618e63SLen Brown 
60861ef7d21aSLen Brown 
60871ef7d21aSLen Brown /*
60881ef7d21aSLen Brown  * parse cpuset with following syntax
60891ef7d21aSLen Brown  * 1,2,4..6,8-10 and set bits in cpu_subset
60901ef7d21aSLen Brown  */
60911ef7d21aSLen Brown void parse_cpu_command(char *optarg)
60921ef7d21aSLen Brown {
60931ef7d21aSLen Brown 	unsigned int start, end;
60941ef7d21aSLen Brown 	char *next;
60951ef7d21aSLen Brown 
60964e4e1e7cSLen Brown 	if (!strcmp(optarg, "core")) {
60974e4e1e7cSLen Brown 		if (cpu_subset)
60984e4e1e7cSLen Brown 			goto error;
60994e4e1e7cSLen Brown 		show_core_only++;
61004e4e1e7cSLen Brown 		return;
61014e4e1e7cSLen Brown 	}
61024e4e1e7cSLen Brown 	if (!strcmp(optarg, "package")) {
61034e4e1e7cSLen Brown 		if (cpu_subset)
61044e4e1e7cSLen Brown 			goto error;
61054e4e1e7cSLen Brown 		show_pkg_only++;
61064e4e1e7cSLen Brown 		return;
61074e4e1e7cSLen Brown 	}
61084e4e1e7cSLen Brown 	if (show_core_only || show_pkg_only)
61094e4e1e7cSLen Brown 		goto error;
61104e4e1e7cSLen Brown 
61111ef7d21aSLen Brown 	cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);
61121ef7d21aSLen Brown 	if (cpu_subset == NULL)
61131ef7d21aSLen Brown 		err(3, "CPU_ALLOC");
61141ef7d21aSLen Brown 	cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);
61151ef7d21aSLen Brown 
61161ef7d21aSLen Brown 	CPU_ZERO_S(cpu_subset_size, cpu_subset);
61171ef7d21aSLen Brown 
61181ef7d21aSLen Brown 	next = optarg;
61191ef7d21aSLen Brown 
61201ef7d21aSLen Brown 	while (next && *next) {
61211ef7d21aSLen Brown 
61221ef7d21aSLen Brown 		if (*next == '-')	/* no negative cpu numbers */
61231ef7d21aSLen Brown 			goto error;
61241ef7d21aSLen Brown 
61251ef7d21aSLen Brown 		start = strtoul(next, &next, 10);
61261ef7d21aSLen Brown 
61271ef7d21aSLen Brown 		if (start >= CPU_SUBSET_MAXCPUS)
61281ef7d21aSLen Brown 			goto error;
61291ef7d21aSLen Brown 		CPU_SET_S(start, cpu_subset_size, cpu_subset);
61301ef7d21aSLen Brown 
61311ef7d21aSLen Brown 		if (*next == '\0')
61321ef7d21aSLen Brown 			break;
61331ef7d21aSLen Brown 
61341ef7d21aSLen Brown 		if (*next == ',') {
61351ef7d21aSLen Brown 			next += 1;
61361ef7d21aSLen Brown 			continue;
61371ef7d21aSLen Brown 		}
61381ef7d21aSLen Brown 
61391ef7d21aSLen Brown 		if (*next == '-') {
61401ef7d21aSLen Brown 			next += 1;	/* start range */
61411ef7d21aSLen Brown 		} else if (*next == '.') {
61421ef7d21aSLen Brown 			next += 1;
61431ef7d21aSLen Brown 			if (*next == '.')
61441ef7d21aSLen Brown 				next += 1;	/* start range */
61451ef7d21aSLen Brown 			else
61461ef7d21aSLen Brown 				goto error;
61471ef7d21aSLen Brown 		}
61481ef7d21aSLen Brown 
61491ef7d21aSLen Brown 		end = strtoul(next, &next, 10);
61501ef7d21aSLen Brown 		if (end <= start)
61511ef7d21aSLen Brown 			goto error;
61521ef7d21aSLen Brown 
61531ef7d21aSLen Brown 		while (++start <= end) {
61541ef7d21aSLen Brown 			if (start >= CPU_SUBSET_MAXCPUS)
61551ef7d21aSLen Brown 				goto error;
61561ef7d21aSLen Brown 			CPU_SET_S(start, cpu_subset_size, cpu_subset);
61571ef7d21aSLen Brown 		}
61581ef7d21aSLen Brown 
61591ef7d21aSLen Brown 		if (*next == ',')
61601ef7d21aSLen Brown 			next += 1;
61611ef7d21aSLen Brown 		else if (*next != '\0')
61621ef7d21aSLen Brown 			goto error;
61631ef7d21aSLen Brown 	}
61641ef7d21aSLen Brown 
61651ef7d21aSLen Brown 	return;
61661ef7d21aSLen Brown 
61671ef7d21aSLen Brown error:
61684e4e1e7cSLen Brown 	fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
61694e4e1e7cSLen Brown 	help();
61701ef7d21aSLen Brown 	exit(-1);
61711ef7d21aSLen Brown }
61721ef7d21aSLen Brown 
6173812db3f7SLen Brown 
6174103a8feaSLen Brown void cmdline(int argc, char **argv)
6175103a8feaSLen Brown {
6176103a8feaSLen Brown 	int opt;
6177d8af6f5fSLen Brown 	int option_index = 0;
6178d8af6f5fSLen Brown 	static struct option long_options[] = {
6179388e9c81SLen Brown 		{"add",		required_argument,	0, 'a'},
61801ef7d21aSLen Brown 		{"cpu",		required_argument,	0, 'c'},
6181d8af6f5fSLen Brown 		{"Dump",	no_argument,		0, 'D'},
618296e47158SLen Brown 		{"debug",	no_argument,		0, 'd'},	/* internal, not documented */
61833f44a5c6SLen Brown 		{"enable",	required_argument,	0, 'e'},
6184d8af6f5fSLen Brown 		{"interval",	required_argument,	0, 'i'},
61852af4f9b8SLen Brown 		{"IPC",	no_argument,			0, 'I'},
6186023fe0acSChen Yu 		{"num_iterations",	required_argument,	0, 'n'},
6187d8af6f5fSLen Brown 		{"help",	no_argument,		0, 'h'},
6188812db3f7SLen Brown 		{"hide",	required_argument,	0, 'H'},	// meh, -h taken by --help
6189d8af6f5fSLen Brown 		{"Joules",	no_argument,		0, 'J'},
6190c8ade361SLen Brown 		{"list",	no_argument,		0, 'l'},
6191b7d8c148SLen Brown 		{"out",		required_argument,	0, 'o'},
619296e47158SLen Brown 		{"quiet",	no_argument,		0, 'q'},
6193812db3f7SLen Brown 		{"show",	required_argument,	0, 's'},
6194d8af6f5fSLen Brown 		{"Summary",	no_argument,		0, 'S'},
6195d8af6f5fSLen Brown 		{"TCC",		required_argument,	0, 'T'},
6196d8af6f5fSLen Brown 		{"version",	no_argument,		0, 'v' },
6197d8af6f5fSLen Brown 		{0,		0,			0,  0 }
6198d8af6f5fSLen Brown 	};
6199103a8feaSLen Brown 
6200103a8feaSLen Brown 	progname = argv[0];
6201103a8feaSLen Brown 
6202023fe0acSChen Yu 	while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qST:v",
6203d8af6f5fSLen Brown 				long_options, &option_index)) != -1) {
6204103a8feaSLen Brown 		switch (opt) {
6205388e9c81SLen Brown 		case 'a':
6206388e9c81SLen Brown 			parse_add_command(optarg);
6207388e9c81SLen Brown 			break;
62081ef7d21aSLen Brown 		case 'c':
62091ef7d21aSLen Brown 			parse_cpu_command(optarg);
62101ef7d21aSLen Brown 			break;
6211d8af6f5fSLen Brown 		case 'D':
6212d8af6f5fSLen Brown 			dump_only++;
62138e180f3cSLen Brown 			break;
62143f44a5c6SLen Brown 		case 'e':
62153f44a5c6SLen Brown 			/* --enable specified counter */
62164c2122d4SLen Brown 			bic_enabled = bic_enabled | bic_lookup(optarg, SHOW_LIST);
62173f44a5c6SLen Brown 			break;
6218d8af6f5fSLen Brown 		case 'd':
6219d8af6f5fSLen Brown 			debug++;
62203f44a5c6SLen Brown 			ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);
62212f32edf1SLen Brown 			break;
6222812db3f7SLen Brown 		case 'H':
62233f44a5c6SLen Brown 			/*
62243f44a5c6SLen Brown 			 * --hide: do not show those specified
62253f44a5c6SLen Brown 			 *  multiple invocations simply clear more bits in enabled mask
62263f44a5c6SLen Brown 			 */
62273f44a5c6SLen Brown 			bic_enabled &= ~bic_lookup(optarg, HIDE_LIST);
6228812db3f7SLen Brown 			break;
6229d8af6f5fSLen Brown 		case 'h':
6230d8af6f5fSLen Brown 		default:
6231d8af6f5fSLen Brown 			help();
6232d8af6f5fSLen Brown 			exit(1);
6233d8af6f5fSLen Brown 		case 'i':
62342a0609c0SLen Brown 			{
62352a0609c0SLen Brown 				double interval = strtod(optarg, NULL);
62362a0609c0SLen Brown 
62372a0609c0SLen Brown 				if (interval < 0.001) {
6238b7d8c148SLen Brown 					fprintf(outf, "interval %f seconds is too small\n",
62392a0609c0SLen Brown 						interval);
62402a0609c0SLen Brown 					exit(2);
62412a0609c0SLen Brown 				}
62422a0609c0SLen Brown 
624347936f94SArtem Bityutskiy 				interval_tv.tv_sec = interval_ts.tv_sec = interval;
6244b9ad8ee0SLen Brown 				interval_tv.tv_usec = (interval - interval_tv.tv_sec) * 1000000;
624547936f94SArtem Bityutskiy 				interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000;
62462a0609c0SLen Brown 			}
6247889facbeSLen Brown 			break;
62485c56be9aSDirk Brandewie 		case 'J':
62495c56be9aSDirk Brandewie 			rapl_joules++;
62505c56be9aSDirk Brandewie 			break;
6251c8ade361SLen Brown 		case 'l':
62523f44a5c6SLen Brown 			ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);
6253c8ade361SLen Brown 			list_header_only++;
6254c8ade361SLen Brown 			quiet++;
6255c8ade361SLen Brown 			break;
6256b7d8c148SLen Brown 		case 'o':
6257b7d8c148SLen Brown 			outf = fopen_or_die(optarg, "w");
6258b7d8c148SLen Brown 			break;
625996e47158SLen Brown 		case 'q':
626096e47158SLen Brown 			quiet = 1;
626196e47158SLen Brown 			break;
6262023fe0acSChen Yu 		case 'n':
6263023fe0acSChen Yu 			num_iterations = strtod(optarg, NULL);
6264023fe0acSChen Yu 
6265023fe0acSChen Yu 			if (num_iterations <= 0) {
6266023fe0acSChen Yu 				fprintf(outf, "iterations %d should be positive number\n",
6267023fe0acSChen Yu 					num_iterations);
6268023fe0acSChen Yu 				exit(2);
6269023fe0acSChen Yu 			}
6270023fe0acSChen Yu 			break;
6271812db3f7SLen Brown 		case 's':
62723f44a5c6SLen Brown 			/*
62733f44a5c6SLen Brown 			 * --show: show only those specified
62743f44a5c6SLen Brown 			 *  The 1st invocation will clear and replace the enabled mask
62753f44a5c6SLen Brown 			 *  subsequent invocations can add to it.
62763f44a5c6SLen Brown 			 */
62773f44a5c6SLen Brown 			if (shown == 0)
62783f44a5c6SLen Brown 				bic_enabled = bic_lookup(optarg, SHOW_LIST);
62793f44a5c6SLen Brown 			else
62803f44a5c6SLen Brown 				bic_enabled |= bic_lookup(optarg, SHOW_LIST);
62813f44a5c6SLen Brown 			shown = 1;
6282812db3f7SLen Brown 			break;
6283d8af6f5fSLen Brown 		case 'S':
6284d8af6f5fSLen Brown 			summary_only++;
6285d8af6f5fSLen Brown 			break;
6286d8af6f5fSLen Brown 		case 'T':
6287d8af6f5fSLen Brown 			tcc_activation_temp_override = atoi(optarg);
6288d8af6f5fSLen Brown 			break;
6289d8af6f5fSLen Brown 		case 'v':
6290d8af6f5fSLen Brown 			print_version();
6291d8af6f5fSLen Brown 			exit(0);
6292d8af6f5fSLen Brown 			break;
6293103a8feaSLen Brown 		}
6294103a8feaSLen Brown 	}
6295103a8feaSLen Brown }
6296103a8feaSLen Brown 
6297103a8feaSLen Brown int main(int argc, char **argv)
6298103a8feaSLen Brown {
6299b7d8c148SLen Brown 	outf = stderr;
6300103a8feaSLen Brown 	cmdline(argc, argv);
6301103a8feaSLen Brown 
630296e47158SLen Brown 	if (!quiet)
6303d8af6f5fSLen Brown 		print_version();
6304103a8feaSLen Brown 
630541618e63SLen Brown 	probe_sysfs();
630641618e63SLen Brown 
6307103a8feaSLen Brown 	turbostat_init();
6308103a8feaSLen Brown 
63093b4d5c7fSAndy Shevchenko 	/* dump counters and exit */
63103b4d5c7fSAndy Shevchenko 	if (dump_only)
63113b4d5c7fSAndy Shevchenko 		return get_and_dump_counters();
63123b4d5c7fSAndy Shevchenko 
6313c8ade361SLen Brown 	/* list header and exit */
6314c8ade361SLen Brown 	if (list_header_only) {
6315c8ade361SLen Brown 		print_header(",");
6316c8ade361SLen Brown 		flush_output_stdout();
6317c8ade361SLen Brown 		return 0;
6318c8ade361SLen Brown 	}
6319c8ade361SLen Brown 
63209972d5d8SChen Yu 	msr_sum_record();
6321103a8feaSLen Brown 	/*
6322103a8feaSLen Brown 	 * if any params left, it must be a command to fork
6323103a8feaSLen Brown 	 */
6324103a8feaSLen Brown 	if (argc - optind)
6325103a8feaSLen Brown 		return fork_it(argv + optind);
6326103a8feaSLen Brown 	else
6327103a8feaSLen Brown 		turbostat_loop();
6328103a8feaSLen Brown 
6329103a8feaSLen Brown 	return 0;
6330103a8feaSLen Brown }
6331