brintos

brintos / linux-shallow public Read only

0
0
Text · 262.8 KiB · 089220a Raw
9972 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * turbostat -- show CPU frequency and C-state residency4 * on modern Intel and AMD processors.5 *6 * Copyright (c) 2024 Intel Corporation.7 * Len Brown <len.brown@intel.com>8 */9 10#define _GNU_SOURCE11#include MSRHEADER12 13// copied from arch/x86/include/asm/cpu_device_id.h14#define VFM_MODEL_BIT	015#define VFM_FAMILY_BIT	816#define VFM_VENDOR_BIT	1617#define VFM_RSVD_BIT	2418 19#define	VFM_MODEL_MASK	GENMASK(VFM_FAMILY_BIT - 1, VFM_MODEL_BIT)20#define	VFM_FAMILY_MASK	GENMASK(VFM_VENDOR_BIT - 1, VFM_FAMILY_BIT)21#define	VFM_VENDOR_MASK	GENMASK(VFM_RSVD_BIT - 1, VFM_VENDOR_BIT)22 23#define VFM_MODEL(vfm)	(((vfm) & VFM_MODEL_MASK) >> VFM_MODEL_BIT)24#define VFM_FAMILY(vfm)	(((vfm) & VFM_FAMILY_MASK) >> VFM_FAMILY_BIT)25#define VFM_VENDOR(vfm)	(((vfm) & VFM_VENDOR_MASK) >> VFM_VENDOR_BIT)26 27#define	VFM_MAKE(_vendor, _family, _model) (	\28	((_model) << VFM_MODEL_BIT) |		\29	((_family) << VFM_FAMILY_BIT) |		\30	((_vendor) << VFM_VENDOR_BIT)		\31)32// end copied section33 34#define X86_VENDOR_INTEL	035 36#include INTEL_FAMILY_HEADER37#include BUILD_BUG_HEADER38#include <stdarg.h>39#include <stdio.h>40#include <err.h>41#include <unistd.h>42#include <sys/types.h>43#include <sys/wait.h>44#include <sys/stat.h>45#include <sys/select.h>46#include <sys/resource.h>47#include <sys/mman.h>48#include <fcntl.h>49#include <signal.h>50#include <sys/time.h>51#include <stdlib.h>52#include <getopt.h>53#include <dirent.h>54#include <string.h>55#include <ctype.h>56#include <sched.h>57#include <time.h>58#include <cpuid.h>59#include <sys/capability.h>60#include <errno.h>61#include <math.h>62#include <linux/perf_event.h>63#include <asm/unistd.h>64#include <stdbool.h>65#include <assert.h>66#include <linux/kernel.h>67 68#define UNUSED(x) (void)(x)69 70/*71 * This list matches the column headers, except72 * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time73 * 2. Core and CPU are moved to the end, we can't have strings that contain them74 *    matching on them for --show and --hide.75 */76 77/*78 * buffer size used by sscanf() for added column names79 * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters80 */81#define	NAME_BYTES 2082#define PATH_BYTES 12883#define PERF_NAME_BYTES 12884 85#define MAX_NOFILE 0x800086 87#define COUNTER_KIND_PERF_PREFIX "perf/"88#define COUNTER_KIND_PERF_PREFIX_LEN strlen(COUNTER_KIND_PERF_PREFIX)89#define PERF_DEV_NAME_BYTES 3290#define PERF_EVT_NAME_BYTES 3291 92enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };93enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M };94enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT, FORMAT_AVERAGE };95enum counter_source { COUNTER_SOURCE_NONE, COUNTER_SOURCE_PERF, COUNTER_SOURCE_MSR };96 97struct perf_counter_info {98	struct perf_counter_info *next;99 100	/* How to open the counter / What counter it is. */101	char device[PERF_DEV_NAME_BYTES];102	char event[PERF_EVT_NAME_BYTES];103 104	/* How to show/format the counter. */105	char name[PERF_NAME_BYTES];106	unsigned int width;107	enum counter_scope scope;108	enum counter_type type;109	enum counter_format format;110	double scale;111 112	/* For reading the counter. */113	int *fd_perf_per_domain;114	size_t num_domains;115};116 117struct sysfs_path {118	char path[PATH_BYTES];119	int id;120	struct sysfs_path *next;121};122 123struct msr_counter {124	unsigned int msr_num;125	char name[NAME_BYTES];126	struct sysfs_path *sp;127	unsigned int width;128	enum counter_type type;129	enum counter_format format;130	struct msr_counter *next;131	unsigned int flags;132#define	FLAGS_HIDE	(1 << 0)133#define	FLAGS_SHOW	(1 << 1)134#define	SYSFS_PERCPU	(1 << 1)135};136 137struct msr_counter bic[] = {138	{ 0x0, "usec", NULL, 0, 0, 0, NULL, 0 },139	{ 0x0, "Time_Of_Day_Seconds", NULL, 0, 0, 0, NULL, 0 },140	{ 0x0, "Package", NULL, 0, 0, 0, NULL, 0 },141	{ 0x0, "Node", NULL, 0, 0, 0, NULL, 0 },142	{ 0x0, "Avg_MHz", NULL, 0, 0, 0, NULL, 0 },143	{ 0x0, "Busy%", NULL, 0, 0, 0, NULL, 0 },144	{ 0x0, "Bzy_MHz", NULL, 0, 0, 0, NULL, 0 },145	{ 0x0, "TSC_MHz", NULL, 0, 0, 0, NULL, 0 },146	{ 0x0, "IRQ", NULL, 0, 0, 0, NULL, 0 },147	{ 0x0, "SMI", NULL, 32, 0, FORMAT_DELTA, NULL, 0 },148	{ 0x0, "sysfs", NULL, 0, 0, 0, NULL, 0 },149	{ 0x0, "CPU%c1", NULL, 0, 0, 0, NULL, 0 },150	{ 0x0, "CPU%c3", NULL, 0, 0, 0, NULL, 0 },151	{ 0x0, "CPU%c6", NULL, 0, 0, 0, NULL, 0 },152	{ 0x0, "CPU%c7", NULL, 0, 0, 0, NULL, 0 },153	{ 0x0, "ThreadC", NULL, 0, 0, 0, NULL, 0 },154	{ 0x0, "CoreTmp", NULL, 0, 0, 0, NULL, 0 },155	{ 0x0, "CoreCnt", NULL, 0, 0, 0, NULL, 0 },156	{ 0x0, "PkgTmp", NULL, 0, 0, 0, NULL, 0 },157	{ 0x0, "GFX%rc6", NULL, 0, 0, 0, NULL, 0 },158	{ 0x0, "GFXMHz", NULL, 0, 0, 0, NULL, 0 },159	{ 0x0, "Pkg%pc2", NULL, 0, 0, 0, NULL, 0 },160	{ 0x0, "Pkg%pc3", NULL, 0, 0, 0, NULL, 0 },161	{ 0x0, "Pkg%pc6", NULL, 0, 0, 0, NULL, 0 },162	{ 0x0, "Pkg%pc7", NULL, 0, 0, 0, NULL, 0 },163	{ 0x0, "Pkg%pc8", NULL, 0, 0, 0, NULL, 0 },164	{ 0x0, "Pkg%pc9", NULL, 0, 0, 0, NULL, 0 },165	{ 0x0, "Pk%pc10", NULL, 0, 0, 0, NULL, 0 },166	{ 0x0, "CPU%LPI", NULL, 0, 0, 0, NULL, 0 },167	{ 0x0, "SYS%LPI", NULL, 0, 0, 0, NULL, 0 },168	{ 0x0, "PkgWatt", NULL, 0, 0, 0, NULL, 0 },169	{ 0x0, "CorWatt", NULL, 0, 0, 0, NULL, 0 },170	{ 0x0, "GFXWatt", NULL, 0, 0, 0, NULL, 0 },171	{ 0x0, "PkgCnt", NULL, 0, 0, 0, NULL, 0 },172	{ 0x0, "RAMWatt", NULL, 0, 0, 0, NULL, 0 },173	{ 0x0, "PKG_%", NULL, 0, 0, 0, NULL, 0 },174	{ 0x0, "RAM_%", NULL, 0, 0, 0, NULL, 0 },175	{ 0x0, "Pkg_J", NULL, 0, 0, 0, NULL, 0 },176	{ 0x0, "Cor_J", NULL, 0, 0, 0, NULL, 0 },177	{ 0x0, "GFX_J", NULL, 0, 0, 0, NULL, 0 },178	{ 0x0, "RAM_J", NULL, 0, 0, 0, NULL, 0 },179	{ 0x0, "Mod%c6", NULL, 0, 0, 0, NULL, 0 },180	{ 0x0, "Totl%C0", NULL, 0, 0, 0, NULL, 0 },181	{ 0x0, "Any%C0", NULL, 0, 0, 0, NULL, 0 },182	{ 0x0, "GFX%C0", NULL, 0, 0, 0, NULL, 0 },183	{ 0x0, "CPUGFX%", NULL, 0, 0, 0, NULL, 0 },184	{ 0x0, "Core", NULL, 0, 0, 0, NULL, 0 },185	{ 0x0, "CPU", NULL, 0, 0, 0, NULL, 0 },186	{ 0x0, "APIC", NULL, 0, 0, 0, NULL, 0 },187	{ 0x0, "X2APIC", NULL, 0, 0, 0, NULL, 0 },188	{ 0x0, "Die", NULL, 0, 0, 0, NULL, 0 },189	{ 0x0, "GFXAMHz", NULL, 0, 0, 0, NULL, 0 },190	{ 0x0, "IPC", NULL, 0, 0, 0, NULL, 0 },191	{ 0x0, "CoreThr", NULL, 0, 0, 0, NULL, 0 },192	{ 0x0, "UncMHz", NULL, 0, 0, 0, NULL, 0 },193	{ 0x0, "SAM%mc6", NULL, 0, 0, 0, NULL, 0 },194	{ 0x0, "SAMMHz", NULL, 0, 0, 0, NULL, 0 },195	{ 0x0, "SAMAMHz", NULL, 0, 0, 0, NULL, 0 },196	{ 0x0, "Die%c6", NULL, 0, 0, 0, NULL, 0 },197};198 199#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))200#define	BIC_USEC	(1ULL << 0)201#define	BIC_TOD		(1ULL << 1)202#define	BIC_Package	(1ULL << 2)203#define	BIC_Node	(1ULL << 3)204#define	BIC_Avg_MHz	(1ULL << 4)205#define	BIC_Busy	(1ULL << 5)206#define	BIC_Bzy_MHz	(1ULL << 6)207#define	BIC_TSC_MHz	(1ULL << 7)208#define	BIC_IRQ		(1ULL << 8)209#define	BIC_SMI		(1ULL << 9)210#define	BIC_sysfs	(1ULL << 10)211#define	BIC_CPU_c1	(1ULL << 11)212#define	BIC_CPU_c3	(1ULL << 12)213#define	BIC_CPU_c6	(1ULL << 13)214#define	BIC_CPU_c7	(1ULL << 14)215#define	BIC_ThreadC	(1ULL << 15)216#define	BIC_CoreTmp	(1ULL << 16)217#define	BIC_CoreCnt	(1ULL << 17)218#define	BIC_PkgTmp	(1ULL << 18)219#define	BIC_GFX_rc6	(1ULL << 19)220#define	BIC_GFXMHz	(1ULL << 20)221#define	BIC_Pkgpc2	(1ULL << 21)222#define	BIC_Pkgpc3	(1ULL << 22)223#define	BIC_Pkgpc6	(1ULL << 23)224#define	BIC_Pkgpc7	(1ULL << 24)225#define	BIC_Pkgpc8	(1ULL << 25)226#define	BIC_Pkgpc9	(1ULL << 26)227#define	BIC_Pkgpc10	(1ULL << 27)228#define BIC_CPU_LPI	(1ULL << 28)229#define BIC_SYS_LPI	(1ULL << 29)230#define	BIC_PkgWatt	(1ULL << 30)231#define	BIC_CorWatt	(1ULL << 31)232#define	BIC_GFXWatt	(1ULL << 32)233#define	BIC_PkgCnt	(1ULL << 33)234#define	BIC_RAMWatt	(1ULL << 34)235#define	BIC_PKG__	(1ULL << 35)236#define	BIC_RAM__	(1ULL << 36)237#define	BIC_Pkg_J	(1ULL << 37)238#define	BIC_Cor_J	(1ULL << 38)239#define	BIC_GFX_J	(1ULL << 39)240#define	BIC_RAM_J	(1ULL << 40)241#define	BIC_Mod_c6	(1ULL << 41)242#define	BIC_Totl_c0	(1ULL << 42)243#define	BIC_Any_c0	(1ULL << 43)244#define	BIC_GFX_c0	(1ULL << 44)245#define	BIC_CPUGFX	(1ULL << 45)246#define	BIC_Core	(1ULL << 46)247#define	BIC_CPU		(1ULL << 47)248#define	BIC_APIC	(1ULL << 48)249#define	BIC_X2APIC	(1ULL << 49)250#define	BIC_Die		(1ULL << 50)251#define	BIC_GFXACTMHz	(1ULL << 51)252#define	BIC_IPC		(1ULL << 52)253#define	BIC_CORE_THROT_CNT	(1ULL << 53)254#define	BIC_UNCORE_MHZ		(1ULL << 54)255#define	BIC_SAM_mc6		(1ULL << 55)256#define	BIC_SAMMHz		(1ULL << 56)257#define	BIC_SAMACTMHz		(1ULL << 57)258#define	BIC_Diec6		(1ULL << 58)259 260#define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die )261#define BIC_THERMAL_PWR ( BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__)262#define BIC_FREQUENCY (BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_SAMMHz | BIC_SAMACTMHz | BIC_UNCORE_MHZ)263#define BIC_IDLE (BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6)264#define BIC_OTHER ( BIC_IRQ | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC)265 266#define BIC_DISABLED_BY_DEFAULT	(BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)267 268unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);269unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;270 271#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)272#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)273#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)274#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)275#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)276#define BIC_IS_ENABLED(COUNTER_BIT) (bic_enabled & COUNTER_BIT)277 278/*279 * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:280 * If you change the values, note they are used both in comparisons281 * (>= PCL__7) and to index pkg_cstate_limit_strings[].282 */283#define PCLUKN 0		/* Unknown */284#define PCLRSV 1		/* Reserved */285#define PCL__0 2		/* PC0 */286#define PCL__1 3		/* PC1 */287#define PCL__2 4		/* PC2 */288#define PCL__3 5		/* PC3 */289#define PCL__4 6		/* PC4 */290#define PCL__6 7		/* PC6 */291#define PCL_6N 8		/* PC6 No Retention */292#define PCL_6R 9		/* PC6 Retention */293#define PCL__7 10		/* PC7 */294#define PCL_7S 11		/* PC7 Shrink */295#define PCL__8 12		/* PC8 */296#define PCL__9 13		/* PC9 */297#define PCL_10 14		/* PC10 */298#define PCLUNL 15		/* Unlimited */299 300struct amperf_group_fd;301 302char *proc_stat = "/proc/stat";303FILE *outf;304int *fd_percpu;305int *fd_instr_count_percpu;306struct timeval interval_tv = { 5, 0 };307struct timespec interval_ts = { 5, 0 };308 309unsigned int num_iterations;310unsigned int header_iterations;311unsigned int debug;312unsigned int quiet;313unsigned int shown;314unsigned int sums_need_wide_columns;315unsigned int rapl_joules;316unsigned int summary_only;317unsigned int list_header_only;318unsigned int dump_only;319unsigned int has_aperf;320unsigned int has_aperf_access;321unsigned int has_epb;322unsigned int has_turbo;323unsigned int is_hybrid;324unsigned int units = 1000000;	/* MHz etc */325unsigned int genuine_intel;326unsigned int authentic_amd;327unsigned int hygon_genuine;328unsigned int max_level, max_extended_level;329unsigned int has_invariant_tsc;330unsigned int aperf_mperf_multiplier = 1;331double bclk;332double base_hz;333unsigned int has_base_hz;334double tsc_tweak = 1.0;335unsigned int show_pkg_only;336unsigned int show_core_only;337char *output_buffer, *outp;338unsigned int do_dts;339unsigned int do_ptm;340unsigned int do_ipc;341unsigned long long cpuidle_cur_cpu_lpi_us;342unsigned long long cpuidle_cur_sys_lpi_us;343unsigned int tj_max;344unsigned int tj_max_override;345double rapl_power_units, rapl_time_units;346double rapl_dram_energy_units, rapl_energy_units;347double rapl_joule_counter_range;348unsigned int crystal_hz;349unsigned long long tsc_hz;350int base_cpu;351unsigned int has_hwp;		/* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */352			/* IA32_HWP_REQUEST, IA32_HWP_STATUS */353unsigned int has_hwp_notify;	/* IA32_HWP_INTERRUPT */354unsigned int has_hwp_activity_window;	/* IA32_HWP_REQUEST[bits 41:32] */355unsigned int has_hwp_epp;	/* IA32_HWP_REQUEST[bits 31:24] */356unsigned int has_hwp_pkg;	/* IA32_HWP_REQUEST_PKG */357unsigned int first_counter_read = 1;358int ignore_stdin;359bool no_msr;360bool no_perf;361 362enum gfx_sysfs_idx {363	GFX_rc6,364	GFX_MHz,365	GFX_ACTMHz,366	SAM_mc6,367	SAM_MHz,368	SAM_ACTMHz,369	GFX_MAX370};371 372struct gfx_sysfs_info {373	const char *path;374	FILE *fp;375	unsigned int val;376	unsigned long long val_ull;377};378 379static struct gfx_sysfs_info gfx_info[GFX_MAX];380 381int get_msr(int cpu, off_t offset, unsigned long long *msr);382int add_counter(unsigned int msr_num, char *path, char *name,383		unsigned int width, enum counter_scope scope,384		enum counter_type type, enum counter_format format, int flags, int package_num);385 386/* Model specific support Start */387 388/* List of features that may diverge among different platforms */389struct platform_features {390	bool has_msr_misc_feature_control;	/* MSR_MISC_FEATURE_CONTROL */391	bool has_msr_misc_pwr_mgmt;	/* MSR_MISC_PWR_MGMT */392	bool has_nhm_msrs;	/* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, MSR_IA32_POWER_CTL, TRL MSRs */393	bool has_config_tdp;	/* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */394	int bclk_freq;		/* CPU base clock */395	int crystal_freq;	/* Crystal clock to use when not available from CPUID.15 */396	int supported_cstates;	/* Core cstates and Package cstates supported */397	int cst_limit;		/* MSR_PKG_CST_CONFIG_CONTROL */398	bool has_cst_auto_convension;	/* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */399	bool has_irtl_msrs;	/* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */400	bool has_msr_core_c1_res;	/* MSR_CORE_C1_RES */401	bool has_msr_module_c6_res_ms;	/* MSR_MODULE_C6_RES_MS */402	bool has_msr_c6_demotion_policy_config;	/* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */403	bool has_msr_atom_pkg_c6_residency;	/* MSR_ATOM_PKG_C6_RESIDENCY */404	bool has_msr_knl_core_c6_residency;	/* MSR_KNL_CORE_C6_RESIDENCY */405	bool has_ext_cst_msrs;	/* MSR_PKG_WEIGHTED_CORE_C0_RES/MSR_PKG_ANY_CORE_C0_RES/MSR_PKG_ANY_GFXE_C0_RES/MSR_PKG_BOTH_CORE_GFXE_C0_RES */406	bool has_cst_prewake_bit;	/* Cstate prewake bit in MSR_IA32_POWER_CTL */407	int trl_msrs;		/* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */408	int plr_msrs;		/* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */409	int rapl_msrs;		/* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */410	bool has_per_core_rapl;	/* Indicates cores energy collection is per-core, not per-package. AMD specific for now */411	bool has_rapl_divisor;	/* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */412	bool has_fixed_rapl_unit;	/* Fixed Energy Unit used for DRAM RAPL Domain */413	int rapl_quirk_tdp;	/* Hardcoded TDP value when cannot be retrieved from hardware */414	int tcc_offset_bits;	/* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */415	bool enable_tsc_tweak;	/* Use CPU Base freq instead of TSC freq for aperf/mperf counter */416	bool need_perf_multiplier;	/* mperf/aperf multiplier */417};418 419struct platform_data {420	unsigned int vfm;421	const struct platform_features *features;422};423 424/* For BCLK */425enum bclk_freq {426	BCLK_100MHZ = 1,427	BCLK_133MHZ,428	BCLK_SLV,429};430 431#define SLM_BCLK_FREQS 5432double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 };433 434double slm_bclk(void)435{436	unsigned long long msr = 3;437	unsigned int i;438	double freq;439 440	if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))441		fprintf(outf, "SLM BCLK: unknown\n");442 443	i = msr & 0xf;444	if (i >= SLM_BCLK_FREQS) {445		fprintf(outf, "SLM BCLK[%d] invalid\n", i);446		i = 3;447	}448	freq = slm_freq_table[i];449 450	if (!quiet)451		fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);452 453	return freq;454}455 456/* For Package cstate limit */457enum package_cstate_limit {458	CST_LIMIT_NHM = 1,459	CST_LIMIT_SNB,460	CST_LIMIT_HSW,461	CST_LIMIT_SKX,462	CST_LIMIT_ICX,463	CST_LIMIT_SLV,464	CST_LIMIT_AMT,465	CST_LIMIT_KNL,466	CST_LIMIT_GMT,467};468 469/* For Turbo Ratio Limit MSRs */470enum turbo_ratio_limit_msrs {471	TRL_BASE = BIT(0),472	TRL_LIMIT1 = BIT(1),473	TRL_LIMIT2 = BIT(2),474	TRL_ATOM = BIT(3),475	TRL_KNL = BIT(4),476	TRL_CORECOUNT = BIT(5),477};478 479/* For Perf Limit Reason MSRs */480enum perf_limit_reason_msrs {481	PLR_CORE = BIT(0),482	PLR_GFX = BIT(1),483	PLR_RING = BIT(2),484};485 486/* For RAPL MSRs */487enum rapl_msrs {488	RAPL_PKG_POWER_LIMIT = BIT(0),	/* 0x610 MSR_PKG_POWER_LIMIT */489	RAPL_PKG_ENERGY_STATUS = BIT(1),	/* 0x611 MSR_PKG_ENERGY_STATUS */490	RAPL_PKG_PERF_STATUS = BIT(2),	/* 0x613 MSR_PKG_PERF_STATUS */491	RAPL_PKG_POWER_INFO = BIT(3),	/* 0x614 MSR_PKG_POWER_INFO */492	RAPL_DRAM_POWER_LIMIT = BIT(4),	/* 0x618 MSR_DRAM_POWER_LIMIT */493	RAPL_DRAM_ENERGY_STATUS = BIT(5),	/* 0x619 MSR_DRAM_ENERGY_STATUS */494	RAPL_DRAM_PERF_STATUS = BIT(6),	/* 0x61b MSR_DRAM_PERF_STATUS */495	RAPL_DRAM_POWER_INFO = BIT(7),	/* 0x61c MSR_DRAM_POWER_INFO */496	RAPL_CORE_POWER_LIMIT = BIT(8),	/* 0x638 MSR_PP0_POWER_LIMIT */497	RAPL_CORE_ENERGY_STATUS = BIT(9),	/* 0x639 MSR_PP0_ENERGY_STATUS */498	RAPL_CORE_POLICY = BIT(10),	/* 0x63a MSR_PP0_POLICY */499	RAPL_GFX_POWER_LIMIT = BIT(11),	/* 0x640 MSR_PP1_POWER_LIMIT */500	RAPL_GFX_ENERGY_STATUS = BIT(12),	/* 0x641 MSR_PP1_ENERGY_STATUS */501	RAPL_GFX_POLICY = BIT(13),	/* 0x642 MSR_PP1_POLICY */502	RAPL_AMD_PWR_UNIT = BIT(14),	/* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */503	RAPL_AMD_CORE_ENERGY_STAT = BIT(15),	/* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */504	RAPL_AMD_PKG_ENERGY_STAT = BIT(16),	/* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */505};506 507#define RAPL_PKG	(RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT)508#define RAPL_DRAM	(RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT)509#define RAPL_CORE	(RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT)510#define RAPL_GFX	(RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS)511 512#define RAPL_PKG_ALL	(RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)513#define RAPL_DRAM_ALL	(RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)514#define RAPL_CORE_ALL	(RAPL_CORE | RAPL_CORE_POLICY)515#define RAPL_GFX_ALL	(RAPL_GFX | RAPL_GFX_POLIGY)516 517#define RAPL_AMD_F17H	(RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT)518 519/* For Cstates */520enum cstates {521	CC1 = BIT(0),522	CC3 = BIT(1),523	CC6 = BIT(2),524	CC7 = BIT(3),525	PC2 = BIT(4),526	PC3 = BIT(5),527	PC6 = BIT(6),528	PC7 = BIT(7),529	PC8 = BIT(8),530	PC9 = BIT(9),531	PC10 = BIT(10),532};533 534static const struct platform_features nhm_features = {535	.has_msr_misc_pwr_mgmt = 1,536	.has_nhm_msrs = 1,537	.bclk_freq = BCLK_133MHZ,538	.supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,539	.cst_limit = CST_LIMIT_NHM,540	.trl_msrs = TRL_BASE,541};542 543static const struct platform_features nhx_features = {544	.has_msr_misc_pwr_mgmt = 1,545	.has_nhm_msrs = 1,546	.bclk_freq = BCLK_133MHZ,547	.supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,548	.cst_limit = CST_LIMIT_NHM,549};550 551static const struct platform_features snb_features = {552	.has_msr_misc_feature_control = 1,553	.has_msr_misc_pwr_mgmt = 1,554	.has_nhm_msrs = 1,555	.bclk_freq = BCLK_100MHZ,556	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,557	.cst_limit = CST_LIMIT_SNB,558	.has_irtl_msrs = 1,559	.trl_msrs = TRL_BASE,560	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,561};562 563static const struct platform_features snx_features = {564	.has_msr_misc_feature_control = 1,565	.has_msr_misc_pwr_mgmt = 1,566	.has_nhm_msrs = 1,567	.bclk_freq = BCLK_100MHZ,568	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,569	.cst_limit = CST_LIMIT_SNB,570	.has_irtl_msrs = 1,571	.trl_msrs = TRL_BASE,572	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,573};574 575static const struct platform_features ivb_features = {576	.has_msr_misc_feature_control = 1,577	.has_msr_misc_pwr_mgmt = 1,578	.has_nhm_msrs = 1,579	.has_config_tdp = 1,580	.bclk_freq = BCLK_100MHZ,581	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,582	.cst_limit = CST_LIMIT_SNB,583	.has_irtl_msrs = 1,584	.trl_msrs = TRL_BASE,585	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,586};587 588static const struct platform_features ivx_features = {589	.has_msr_misc_feature_control = 1,590	.has_msr_misc_pwr_mgmt = 1,591	.has_nhm_msrs = 1,592	.bclk_freq = BCLK_100MHZ,593	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,594	.cst_limit = CST_LIMIT_SNB,595	.has_irtl_msrs = 1,596	.trl_msrs = TRL_BASE | TRL_LIMIT1,597	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,598};599 600static const struct platform_features hsw_features = {601	.has_msr_misc_feature_control = 1,602	.has_msr_misc_pwr_mgmt = 1,603	.has_nhm_msrs = 1,604	.has_config_tdp = 1,605	.bclk_freq = BCLK_100MHZ,606	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,607	.cst_limit = CST_LIMIT_HSW,608	.has_irtl_msrs = 1,609	.trl_msrs = TRL_BASE,610	.plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,611	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,612};613 614static const struct platform_features hsx_features = {615	.has_msr_misc_feature_control = 1,616	.has_msr_misc_pwr_mgmt = 1,617	.has_nhm_msrs = 1,618	.has_config_tdp = 1,619	.bclk_freq = BCLK_100MHZ,620	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,621	.cst_limit = CST_LIMIT_HSW,622	.has_irtl_msrs = 1,623	.trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2,624	.plr_msrs = PLR_CORE | PLR_RING,625	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,626	.has_fixed_rapl_unit = 1,627};628 629static const struct platform_features hswl_features = {630	.has_msr_misc_feature_control = 1,631	.has_msr_misc_pwr_mgmt = 1,632	.has_nhm_msrs = 1,633	.has_config_tdp = 1,634	.bclk_freq = BCLK_100MHZ,635	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,636	.cst_limit = CST_LIMIT_HSW,637	.has_irtl_msrs = 1,638	.trl_msrs = TRL_BASE,639	.plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,640	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,641};642 643static const struct platform_features hswg_features = {644	.has_msr_misc_feature_control = 1,645	.has_msr_misc_pwr_mgmt = 1,646	.has_nhm_msrs = 1,647	.has_config_tdp = 1,648	.bclk_freq = BCLK_100MHZ,649	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,650	.cst_limit = CST_LIMIT_HSW,651	.has_irtl_msrs = 1,652	.trl_msrs = TRL_BASE,653	.plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,654	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,655};656 657static const struct platform_features bdw_features = {658	.has_msr_misc_feature_control = 1,659	.has_msr_misc_pwr_mgmt = 1,660	.has_nhm_msrs = 1,661	.has_config_tdp = 1,662	.bclk_freq = BCLK_100MHZ,663	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,664	.cst_limit = CST_LIMIT_HSW,665	.has_irtl_msrs = 1,666	.trl_msrs = TRL_BASE,667	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,668};669 670static const struct platform_features bdwg_features = {671	.has_msr_misc_feature_control = 1,672	.has_msr_misc_pwr_mgmt = 1,673	.has_nhm_msrs = 1,674	.has_config_tdp = 1,675	.bclk_freq = BCLK_100MHZ,676	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,677	.cst_limit = CST_LIMIT_HSW,678	.has_irtl_msrs = 1,679	.trl_msrs = TRL_BASE,680	.rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,681};682 683static const struct platform_features bdx_features = {684	.has_msr_misc_feature_control = 1,685	.has_msr_misc_pwr_mgmt = 1,686	.has_nhm_msrs = 1,687	.has_config_tdp = 1,688	.bclk_freq = BCLK_100MHZ,689	.supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6,690	.cst_limit = CST_LIMIT_HSW,691	.has_irtl_msrs = 1,692	.has_cst_auto_convension = 1,693	.trl_msrs = TRL_BASE,694	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,695	.has_fixed_rapl_unit = 1,696};697 698static const struct platform_features skl_features = {699	.has_msr_misc_feature_control = 1,700	.has_msr_misc_pwr_mgmt = 1,701	.has_nhm_msrs = 1,702	.has_config_tdp = 1,703	.bclk_freq = BCLK_100MHZ,704	.crystal_freq = 24000000,705	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,706	.cst_limit = CST_LIMIT_HSW,707	.has_irtl_msrs = 1,708	.has_ext_cst_msrs = 1,709	.trl_msrs = TRL_BASE,710	.tcc_offset_bits = 6,711	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,712	.enable_tsc_tweak = 1,713};714 715static const struct platform_features cnl_features = {716	.has_msr_misc_feature_control = 1,717	.has_msr_misc_pwr_mgmt = 1,718	.has_nhm_msrs = 1,719	.has_config_tdp = 1,720	.bclk_freq = BCLK_100MHZ,721	.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,722	.cst_limit = CST_LIMIT_HSW,723	.has_irtl_msrs = 1,724	.has_msr_core_c1_res = 1,725	.has_ext_cst_msrs = 1,726	.trl_msrs = TRL_BASE,727	.tcc_offset_bits = 6,728	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,729	.enable_tsc_tweak = 1,730};731 732static const struct platform_features adl_features = {733	.has_msr_misc_feature_control = 1,734	.has_msr_misc_pwr_mgmt = 1,735	.has_nhm_msrs = 1,736	.has_config_tdp = 1,737	.bclk_freq = BCLK_100MHZ,738	.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10,739	.cst_limit = CST_LIMIT_HSW,740	.has_irtl_msrs = 1,741	.has_msr_core_c1_res = 1,742	.has_ext_cst_msrs = 1,743	.trl_msrs = TRL_BASE,744	.tcc_offset_bits = 6,745	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,746	.enable_tsc_tweak = 1,747};748 749static const struct platform_features arl_features = {750	.has_msr_misc_feature_control = 1,751	.has_msr_misc_pwr_mgmt = 1,752	.has_nhm_msrs = 1,753	.has_config_tdp = 1,754	.bclk_freq = BCLK_100MHZ,755	.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC10,756	.cst_limit = CST_LIMIT_HSW,757	.has_irtl_msrs = 1,758	.has_msr_core_c1_res = 1,759	.has_ext_cst_msrs = 1,760	.trl_msrs = TRL_BASE,761	.tcc_offset_bits = 6,762	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,763	.enable_tsc_tweak = 1,764};765 766static const struct platform_features skx_features = {767	.has_msr_misc_feature_control = 1,768	.has_msr_misc_pwr_mgmt = 1,769	.has_nhm_msrs = 1,770	.has_config_tdp = 1,771	.bclk_freq = BCLK_100MHZ,772	.supported_cstates = CC1 | CC6 | PC2 | PC6,773	.cst_limit = CST_LIMIT_SKX,774	.has_irtl_msrs = 1,775	.has_cst_auto_convension = 1,776	.trl_msrs = TRL_BASE | TRL_CORECOUNT,777	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,778	.has_fixed_rapl_unit = 1,779};780 781static const struct platform_features icx_features = {782	.has_msr_misc_feature_control = 1,783	.has_msr_misc_pwr_mgmt = 1,784	.has_nhm_msrs = 1,785	.has_config_tdp = 1,786	.bclk_freq = BCLK_100MHZ,787	.supported_cstates = CC1 | CC6 | PC2 | PC6,788	.cst_limit = CST_LIMIT_ICX,789	.has_msr_core_c1_res = 1,790	.has_irtl_msrs = 1,791	.has_cst_prewake_bit = 1,792	.trl_msrs = TRL_BASE | TRL_CORECOUNT,793	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,794	.has_fixed_rapl_unit = 1,795};796 797static const struct platform_features spr_features = {798	.has_msr_misc_feature_control = 1,799	.has_msr_misc_pwr_mgmt = 1,800	.has_nhm_msrs = 1,801	.has_config_tdp = 1,802	.bclk_freq = BCLK_100MHZ,803	.supported_cstates = CC1 | CC6 | PC2 | PC6,804	.cst_limit = CST_LIMIT_SKX,805	.has_msr_core_c1_res = 1,806	.has_irtl_msrs = 1,807	.has_cst_prewake_bit = 1,808	.trl_msrs = TRL_BASE | TRL_CORECOUNT,809	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,810};811 812static const struct platform_features srf_features = {813	.has_msr_misc_feature_control = 1,814	.has_msr_misc_pwr_mgmt = 1,815	.has_nhm_msrs = 1,816	.has_config_tdp = 1,817	.bclk_freq = BCLK_100MHZ,818	.supported_cstates = CC1 | CC6 | PC2 | PC6,819	.cst_limit = CST_LIMIT_SKX,820	.has_msr_core_c1_res = 1,821	.has_msr_module_c6_res_ms = 1,822	.has_irtl_msrs = 1,823	.has_cst_prewake_bit = 1,824	.trl_msrs = TRL_BASE | TRL_CORECOUNT,825	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,826};827 828static const struct platform_features grr_features = {829	.has_msr_misc_feature_control = 1,830	.has_msr_misc_pwr_mgmt = 1,831	.has_nhm_msrs = 1,832	.has_config_tdp = 1,833	.bclk_freq = BCLK_100MHZ,834	.supported_cstates = CC1 | CC6,835	.cst_limit = CST_LIMIT_SKX,836	.has_msr_core_c1_res = 1,837	.has_msr_module_c6_res_ms = 1,838	.has_irtl_msrs = 1,839	.has_cst_prewake_bit = 1,840	.trl_msrs = TRL_BASE | TRL_CORECOUNT,841	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,842};843 844static const struct platform_features slv_features = {845	.has_nhm_msrs = 1,846	.bclk_freq = BCLK_SLV,847	.supported_cstates = CC1 | CC6 | PC6,848	.cst_limit = CST_LIMIT_SLV,849	.has_msr_core_c1_res = 1,850	.has_msr_module_c6_res_ms = 1,851	.has_msr_c6_demotion_policy_config = 1,852	.has_msr_atom_pkg_c6_residency = 1,853	.trl_msrs = TRL_ATOM,854	.rapl_msrs = RAPL_PKG | RAPL_CORE,855	.has_rapl_divisor = 1,856	.rapl_quirk_tdp = 30,857};858 859static const struct platform_features slvd_features = {860	.has_msr_misc_pwr_mgmt = 1,861	.has_nhm_msrs = 1,862	.bclk_freq = BCLK_SLV,863	.supported_cstates = CC1 | CC6 | PC3 | PC6,864	.cst_limit = CST_LIMIT_SLV,865	.has_msr_atom_pkg_c6_residency = 1,866	.trl_msrs = TRL_BASE,867	.rapl_msrs = RAPL_PKG | RAPL_CORE,868	.rapl_quirk_tdp = 30,869};870 871static const struct platform_features amt_features = {872	.has_nhm_msrs = 1,873	.bclk_freq = BCLK_133MHZ,874	.supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,875	.cst_limit = CST_LIMIT_AMT,876	.trl_msrs = TRL_BASE,877};878 879static const struct platform_features gmt_features = {880	.has_msr_misc_pwr_mgmt = 1,881	.has_nhm_msrs = 1,882	.bclk_freq = BCLK_100MHZ,883	.crystal_freq = 19200000,884	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,885	.cst_limit = CST_LIMIT_GMT,886	.has_irtl_msrs = 1,887	.trl_msrs = TRL_BASE | TRL_CORECOUNT,888	.rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,889};890 891static const struct platform_features gmtd_features = {892	.has_msr_misc_pwr_mgmt = 1,893	.has_nhm_msrs = 1,894	.bclk_freq = BCLK_100MHZ,895	.crystal_freq = 25000000,896	.supported_cstates = CC1 | CC6 | PC2 | PC6,897	.cst_limit = CST_LIMIT_GMT,898	.has_irtl_msrs = 1,899	.has_msr_core_c1_res = 1,900	.trl_msrs = TRL_BASE | TRL_CORECOUNT,901	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS,902};903 904static const struct platform_features gmtp_features = {905	.has_msr_misc_pwr_mgmt = 1,906	.has_nhm_msrs = 1,907	.bclk_freq = BCLK_100MHZ,908	.crystal_freq = 19200000,909	.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,910	.cst_limit = CST_LIMIT_GMT,911	.has_irtl_msrs = 1,912	.trl_msrs = TRL_BASE,913	.rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,914};915 916static const struct platform_features tmt_features = {917	.has_msr_misc_pwr_mgmt = 1,918	.has_nhm_msrs = 1,919	.bclk_freq = BCLK_100MHZ,920	.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,921	.cst_limit = CST_LIMIT_GMT,922	.has_irtl_msrs = 1,923	.trl_msrs = TRL_BASE,924	.rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,925	.enable_tsc_tweak = 1,926};927 928static const struct platform_features tmtd_features = {929	.has_msr_misc_pwr_mgmt = 1,930	.has_nhm_msrs = 1,931	.bclk_freq = BCLK_100MHZ,932	.supported_cstates = CC1 | CC6,933	.cst_limit = CST_LIMIT_GMT,934	.has_irtl_msrs = 1,935	.trl_msrs = TRL_BASE | TRL_CORECOUNT,936	.rapl_msrs = RAPL_PKG_ALL,937};938 939static const struct platform_features knl_features = {940	.has_msr_misc_pwr_mgmt = 1,941	.has_nhm_msrs = 1,942	.has_config_tdp = 1,943	.bclk_freq = BCLK_100MHZ,944	.supported_cstates = CC1 | CC6 | PC3 | PC6,945	.cst_limit = CST_LIMIT_KNL,946	.has_msr_knl_core_c6_residency = 1,947	.trl_msrs = TRL_KNL,948	.rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,949	.has_fixed_rapl_unit = 1,950	.need_perf_multiplier = 1,951};952 953static const struct platform_features default_features = {954};955 956static const struct platform_features amd_features_with_rapl = {957	.rapl_msrs = RAPL_AMD_F17H,958	.has_per_core_rapl = 1,959	.rapl_quirk_tdp = 280,	/* This is the max stock TDP of HEDT/Server Fam17h+ chips */960};961 962static const struct platform_data turbostat_pdata[] = {963	{ INTEL_NEHALEM, &nhm_features },964	{ INTEL_NEHALEM_G, &nhm_features },965	{ INTEL_NEHALEM_EP, &nhm_features },966	{ INTEL_NEHALEM_EX, &nhx_features },967	{ INTEL_WESTMERE, &nhm_features },968	{ INTEL_WESTMERE_EP, &nhm_features },969	{ INTEL_WESTMERE_EX, &nhx_features },970	{ INTEL_SANDYBRIDGE, &snb_features },971	{ INTEL_SANDYBRIDGE_X, &snx_features },972	{ INTEL_IVYBRIDGE, &ivb_features },973	{ INTEL_IVYBRIDGE_X, &ivx_features },974	{ INTEL_HASWELL, &hsw_features },975	{ INTEL_HASWELL_X, &hsx_features },976	{ INTEL_HASWELL_L, &hswl_features },977	{ INTEL_HASWELL_G, &hswg_features },978	{ INTEL_BROADWELL, &bdw_features },979	{ INTEL_BROADWELL_G, &bdwg_features },980	{ INTEL_BROADWELL_X, &bdx_features },981	{ INTEL_BROADWELL_D, &bdx_features },982	{ INTEL_SKYLAKE_L, &skl_features },983	{ INTEL_SKYLAKE, &skl_features },984	{ INTEL_SKYLAKE_X, &skx_features },985	{ INTEL_KABYLAKE_L, &skl_features },986	{ INTEL_KABYLAKE, &skl_features },987	{ INTEL_COMETLAKE, &skl_features },988	{ INTEL_COMETLAKE_L, &skl_features },989	{ INTEL_CANNONLAKE_L, &cnl_features },990	{ INTEL_ICELAKE_X, &icx_features },991	{ INTEL_ICELAKE_D, &icx_features },992	{ INTEL_ICELAKE_L, &cnl_features },993	{ INTEL_ICELAKE_NNPI, &cnl_features },994	{ INTEL_ROCKETLAKE, &cnl_features },995	{ INTEL_TIGERLAKE_L, &cnl_features },996	{ INTEL_TIGERLAKE, &cnl_features },997	{ INTEL_SAPPHIRERAPIDS_X, &spr_features },998	{ INTEL_EMERALDRAPIDS_X, &spr_features },999	{ INTEL_GRANITERAPIDS_X, &spr_features },1000	{ INTEL_LAKEFIELD, &cnl_features },1001	{ INTEL_ALDERLAKE, &adl_features },1002	{ INTEL_ALDERLAKE_L, &adl_features },1003	{ INTEL_RAPTORLAKE, &adl_features },1004	{ INTEL_RAPTORLAKE_P, &adl_features },1005	{ INTEL_RAPTORLAKE_S, &adl_features },1006	{ INTEL_METEORLAKE, &cnl_features },1007	{ INTEL_METEORLAKE_L, &cnl_features },1008	{ INTEL_ARROWLAKE_H, &arl_features },1009	{ INTEL_ARROWLAKE_U, &arl_features },1010	{ INTEL_ARROWLAKE, &arl_features },1011	{ INTEL_LUNARLAKE_M, &arl_features },1012	{ INTEL_ATOM_SILVERMONT, &slv_features },1013	{ INTEL_ATOM_SILVERMONT_D, &slvd_features },1014	{ INTEL_ATOM_AIRMONT, &amt_features },1015	{ INTEL_ATOM_GOLDMONT, &gmt_features },1016	{ INTEL_ATOM_GOLDMONT_D, &gmtd_features },1017	{ INTEL_ATOM_GOLDMONT_PLUS, &gmtp_features },1018	{ INTEL_ATOM_TREMONT_D, &tmtd_features },1019	{ INTEL_ATOM_TREMONT, &tmt_features },1020	{ INTEL_ATOM_TREMONT_L, &tmt_features },1021	{ INTEL_ATOM_GRACEMONT, &adl_features },1022	{ INTEL_ATOM_CRESTMONT_X, &srf_features },1023	{ INTEL_ATOM_CRESTMONT, &grr_features },1024	{ INTEL_XEON_PHI_KNL, &knl_features },1025	{ INTEL_XEON_PHI_KNM, &knl_features },1026	/*1027	 * Missing support for1028	 * INTEL_ICELAKE1029	 * INTEL_ATOM_SILVERMONT_MID1030	 * INTEL_ATOM_AIRMONT_MID1031	 * INTEL_ATOM_AIRMONT_NP1032	 */1033	{ 0, NULL },1034};1035 1036static const struct platform_features *platform;1037 1038void probe_platform_features(unsigned int family, unsigned int model)1039{1040	int i;1041 1042	platform = &default_features;1043 1044	if (authentic_amd || hygon_genuine) {1045		if (max_extended_level >= 0x80000007) {1046			unsigned int eax, ebx, ecx, edx;1047 1048			__cpuid(0x80000007, eax, ebx, ecx, edx);1049			/* RAPL (Fam 17h+) */1050			if ((edx & (1 << 14)) && family >= 0x17)1051				platform = &amd_features_with_rapl;1052		}1053		return;1054	}1055 1056	if (!genuine_intel)1057		return;1058 1059	for (i = 0; turbostat_pdata[i].features; i++) {1060		if (VFM_FAMILY(turbostat_pdata[i].vfm) == family && VFM_MODEL(turbostat_pdata[i].vfm) == model) {1061			platform = turbostat_pdata[i].features;1062			return;1063		}1064	}1065}1066 1067/* Model specific support End */1068 1069#define	TJMAX_DEFAULT	1001070 1071/* MSRs that are not yet in the kernel-provided header. */1072#define MSR_RAPL_PWR_UNIT	0xc00102991073#define MSR_CORE_ENERGY_STAT	0xc001029a1074#define MSR_PKG_ENERGY_STAT	0xc001029b1075 1076#define MAX(a, b) ((a) > (b) ? (a) : (b))1077 1078int backwards_count;1079char *progname;1080 1081#define CPU_SUBSET_MAXCPUS	1024	/* need to use before probe... */1082cpu_set_t *cpu_present_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;1083size_t cpu_present_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size;1084#define MAX_ADDED_THREAD_COUNTERS 241085#define MAX_ADDED_CORE_COUNTERS 81086#define MAX_ADDED_PACKAGE_COUNTERS 161087#define PMT_MAX_ADDED_THREAD_COUNTERS 241088#define PMT_MAX_ADDED_CORE_COUNTERS 81089#define PMT_MAX_ADDED_PACKAGE_COUNTERS 161090#define BITMASK_SIZE 321091 1092#define ZERO_ARRAY(arr) (memset(arr, 0, sizeof(arr)) + __must_be_array(arr))1093 1094/* Indexes used to map data read from perf and MSRs into global variables */1095enum rapl_rci_index {1096	RAPL_RCI_INDEX_ENERGY_PKG = 0,1097	RAPL_RCI_INDEX_ENERGY_CORES = 1,1098	RAPL_RCI_INDEX_DRAM = 2,1099	RAPL_RCI_INDEX_GFX = 3,1100	RAPL_RCI_INDEX_PKG_PERF_STATUS = 4,1101	RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5,1102	RAPL_RCI_INDEX_CORE_ENERGY = 6,1103	NUM_RAPL_COUNTERS,1104};1105 1106enum rapl_unit {1107	RAPL_UNIT_INVALID,1108	RAPL_UNIT_JOULES,1109	RAPL_UNIT_WATTS,1110};1111 1112struct rapl_counter_info_t {1113	unsigned long long data[NUM_RAPL_COUNTERS];1114	enum counter_source source[NUM_RAPL_COUNTERS];1115	unsigned long long flags[NUM_RAPL_COUNTERS];1116	double scale[NUM_RAPL_COUNTERS];1117	enum rapl_unit unit[NUM_RAPL_COUNTERS];1118	unsigned long long msr[NUM_RAPL_COUNTERS];1119	unsigned long long msr_mask[NUM_RAPL_COUNTERS];1120	int msr_shift[NUM_RAPL_COUNTERS];1121 1122	int fd_perf;1123};1124 1125/* struct rapl_counter_info_t for each RAPL domain */1126struct rapl_counter_info_t *rapl_counter_info_perdomain;1127unsigned int rapl_counter_info_perdomain_size;1128 1129#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1)1130 1131struct rapl_counter_arch_info {1132	int feature_mask;	/* Mask for testing if the counter is supported on host */1133	const char *perf_subsys;1134	const char *perf_name;1135	unsigned long long msr;1136	unsigned long long msr_mask;1137	int msr_shift;		/* Positive mean shift right, negative mean shift left */1138	double *platform_rapl_msr_scale;	/* Scale applied to values read by MSR (platform dependent, filled at runtime) */1139	unsigned int rci_index;	/* Maps data from perf counters to global variables */1140	unsigned long long bic;1141	double compat_scale;	/* Some counters require constant scaling to be in the same range as other, similar ones */1142	unsigned long long flags;1143};1144 1145static const struct rapl_counter_arch_info rapl_counter_arch_infos[] = {1146	{1147	 .feature_mask = RAPL_PKG,1148	 .perf_subsys = "power",1149	 .perf_name = "energy-pkg",1150	 .msr = MSR_PKG_ENERGY_STATUS,1151	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1152	 .msr_shift = 0,1153	 .platform_rapl_msr_scale = &rapl_energy_units,1154	 .rci_index = RAPL_RCI_INDEX_ENERGY_PKG,1155	 .bic = BIC_PkgWatt | BIC_Pkg_J,1156	 .compat_scale = 1.0,1157	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1158	  },1159	{1160	 .feature_mask = RAPL_AMD_F17H,1161	 .perf_subsys = "power",1162	 .perf_name = "energy-pkg",1163	 .msr = MSR_PKG_ENERGY_STAT,1164	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1165	 .msr_shift = 0,1166	 .platform_rapl_msr_scale = &rapl_energy_units,1167	 .rci_index = RAPL_RCI_INDEX_ENERGY_PKG,1168	 .bic = BIC_PkgWatt | BIC_Pkg_J,1169	 .compat_scale = 1.0,1170	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1171	  },1172	{1173	 .feature_mask = RAPL_CORE_ENERGY_STATUS,1174	 .perf_subsys = "power",1175	 .perf_name = "energy-cores",1176	 .msr = MSR_PP0_ENERGY_STATUS,1177	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1178	 .msr_shift = 0,1179	 .platform_rapl_msr_scale = &rapl_energy_units,1180	 .rci_index = RAPL_RCI_INDEX_ENERGY_CORES,1181	 .bic = BIC_CorWatt | BIC_Cor_J,1182	 .compat_scale = 1.0,1183	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1184	  },1185	{1186	 .feature_mask = RAPL_DRAM,1187	 .perf_subsys = "power",1188	 .perf_name = "energy-ram",1189	 .msr = MSR_DRAM_ENERGY_STATUS,1190	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1191	 .msr_shift = 0,1192	 .platform_rapl_msr_scale = &rapl_dram_energy_units,1193	 .rci_index = RAPL_RCI_INDEX_DRAM,1194	 .bic = BIC_RAMWatt | BIC_RAM_J,1195	 .compat_scale = 1.0,1196	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1197	  },1198	{1199	 .feature_mask = RAPL_GFX,1200	 .perf_subsys = "power",1201	 .perf_name = "energy-gpu",1202	 .msr = MSR_PP1_ENERGY_STATUS,1203	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1204	 .msr_shift = 0,1205	 .platform_rapl_msr_scale = &rapl_energy_units,1206	 .rci_index = RAPL_RCI_INDEX_GFX,1207	 .bic = BIC_GFXWatt | BIC_GFX_J,1208	 .compat_scale = 1.0,1209	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1210	  },1211	{1212	 .feature_mask = RAPL_PKG_PERF_STATUS,1213	 .perf_subsys = NULL,1214	 .perf_name = NULL,1215	 .msr = MSR_PKG_PERF_STATUS,1216	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1217	 .msr_shift = 0,1218	 .platform_rapl_msr_scale = &rapl_time_units,1219	 .rci_index = RAPL_RCI_INDEX_PKG_PERF_STATUS,1220	 .bic = BIC_PKG__,1221	 .compat_scale = 100.0,1222	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1223	  },1224	{1225	 .feature_mask = RAPL_DRAM_PERF_STATUS,1226	 .perf_subsys = NULL,1227	 .perf_name = NULL,1228	 .msr = MSR_DRAM_PERF_STATUS,1229	 .msr_mask = 0xFFFFFFFFFFFFFFFF,1230	 .msr_shift = 0,1231	 .platform_rapl_msr_scale = &rapl_time_units,1232	 .rci_index = RAPL_RCI_INDEX_DRAM_PERF_STATUS,1233	 .bic = BIC_RAM__,1234	 .compat_scale = 100.0,1235	 .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1236	  },1237	{1238	 .feature_mask = RAPL_AMD_F17H,1239	 .perf_subsys = NULL,1240	 .perf_name = NULL,1241	 .msr = MSR_CORE_ENERGY_STAT,1242	 .msr_mask = 0xFFFFFFFF,1243	 .msr_shift = 0,1244	 .platform_rapl_msr_scale = &rapl_energy_units,1245	 .rci_index = RAPL_RCI_INDEX_CORE_ENERGY,1246	 .bic = BIC_CorWatt | BIC_Cor_J,1247	 .compat_scale = 1.0,1248	 .flags = 0,1249	  },1250};1251 1252struct rapl_counter {1253	unsigned long long raw_value;1254	enum rapl_unit unit;1255	double scale;1256};1257 1258/* Indexes used to map data read from perf and MSRs into global variables */1259enum ccstate_rci_index {1260	CCSTATE_RCI_INDEX_C1_RESIDENCY = 0,1261	CCSTATE_RCI_INDEX_C3_RESIDENCY = 1,1262	CCSTATE_RCI_INDEX_C6_RESIDENCY = 2,1263	CCSTATE_RCI_INDEX_C7_RESIDENCY = 3,1264	PCSTATE_RCI_INDEX_C2_RESIDENCY = 4,1265	PCSTATE_RCI_INDEX_C3_RESIDENCY = 5,1266	PCSTATE_RCI_INDEX_C6_RESIDENCY = 6,1267	PCSTATE_RCI_INDEX_C7_RESIDENCY = 7,1268	PCSTATE_RCI_INDEX_C8_RESIDENCY = 8,1269	PCSTATE_RCI_INDEX_C9_RESIDENCY = 9,1270	PCSTATE_RCI_INDEX_C10_RESIDENCY = 10,1271	NUM_CSTATE_COUNTERS,1272};1273 1274struct cstate_counter_info_t {1275	unsigned long long data[NUM_CSTATE_COUNTERS];1276	enum counter_source source[NUM_CSTATE_COUNTERS];1277	unsigned long long msr[NUM_CSTATE_COUNTERS];1278	int fd_perf_core;1279	int fd_perf_pkg;1280};1281 1282struct cstate_counter_info_t *ccstate_counter_info;1283unsigned int ccstate_counter_info_size;1284 1285#define CSTATE_COUNTER_FLAG_COLLECT_PER_CORE   (1u << 0)1286#define CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD ((1u << 1) | CSTATE_COUNTER_FLAG_COLLECT_PER_CORE)1287#define CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY (1u << 2)1288 1289struct cstate_counter_arch_info {1290	int feature_mask;	/* Mask for testing if the counter is supported on host */1291	const char *perf_subsys;1292	const char *perf_name;1293	unsigned long long msr;1294	unsigned int rci_index;	/* Maps data from perf counters to global variables */1295	unsigned long long bic;1296	unsigned long long flags;1297	int pkg_cstate_limit;1298};1299 1300static struct cstate_counter_arch_info ccstate_counter_arch_infos[] = {1301	{1302	 .feature_mask = CC1,1303	 .perf_subsys = "cstate_core",1304	 .perf_name = "c1-residency",1305	 .msr = MSR_CORE_C1_RES,1306	 .rci_index = CCSTATE_RCI_INDEX_C1_RESIDENCY,1307	 .bic = BIC_CPU_c1,1308	 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD,1309	 .pkg_cstate_limit = 0,1310	  },1311	{1312	 .feature_mask = CC3,1313	 .perf_subsys = "cstate_core",1314	 .perf_name = "c3-residency",1315	 .msr = MSR_CORE_C3_RESIDENCY,1316	 .rci_index = CCSTATE_RCI_INDEX_C3_RESIDENCY,1317	 .bic = BIC_CPU_c3,1318	 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,1319	 .pkg_cstate_limit = 0,1320	  },1321	{1322	 .feature_mask = CC6,1323	 .perf_subsys = "cstate_core",1324	 .perf_name = "c6-residency",1325	 .msr = MSR_CORE_C6_RESIDENCY,1326	 .rci_index = CCSTATE_RCI_INDEX_C6_RESIDENCY,1327	 .bic = BIC_CPU_c6,1328	 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,1329	 .pkg_cstate_limit = 0,1330	  },1331	{1332	 .feature_mask = CC7,1333	 .perf_subsys = "cstate_core",1334	 .perf_name = "c7-residency",1335	 .msr = MSR_CORE_C7_RESIDENCY,1336	 .rci_index = CCSTATE_RCI_INDEX_C7_RESIDENCY,1337	 .bic = BIC_CPU_c7,1338	 .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,1339	 .pkg_cstate_limit = 0,1340	  },1341	{1342	 .feature_mask = PC2,1343	 .perf_subsys = "cstate_pkg",1344	 .perf_name = "c2-residency",1345	 .msr = MSR_PKG_C2_RESIDENCY,1346	 .rci_index = PCSTATE_RCI_INDEX_C2_RESIDENCY,1347	 .bic = BIC_Pkgpc2,1348	 .flags = 0,1349	 .pkg_cstate_limit = PCL__2,1350	  },1351	{1352	 .feature_mask = PC3,1353	 .perf_subsys = "cstate_pkg",1354	 .perf_name = "c3-residency",1355	 .msr = MSR_PKG_C3_RESIDENCY,1356	 .rci_index = PCSTATE_RCI_INDEX_C3_RESIDENCY,1357	 .bic = BIC_Pkgpc3,1358	 .flags = 0,1359	 .pkg_cstate_limit = PCL__3,1360	  },1361	{1362	 .feature_mask = PC6,1363	 .perf_subsys = "cstate_pkg",1364	 .perf_name = "c6-residency",1365	 .msr = MSR_PKG_C6_RESIDENCY,1366	 .rci_index = PCSTATE_RCI_INDEX_C6_RESIDENCY,1367	 .bic = BIC_Pkgpc6,1368	 .flags = 0,1369	 .pkg_cstate_limit = PCL__6,1370	  },1371	{1372	 .feature_mask = PC7,1373	 .perf_subsys = "cstate_pkg",1374	 .perf_name = "c7-residency",1375	 .msr = MSR_PKG_C7_RESIDENCY,1376	 .rci_index = PCSTATE_RCI_INDEX_C7_RESIDENCY,1377	 .bic = BIC_Pkgpc7,1378	 .flags = 0,1379	 .pkg_cstate_limit = PCL__7,1380	  },1381	{1382	 .feature_mask = PC8,1383	 .perf_subsys = "cstate_pkg",1384	 .perf_name = "c8-residency",1385	 .msr = MSR_PKG_C8_RESIDENCY,1386	 .rci_index = PCSTATE_RCI_INDEX_C8_RESIDENCY,1387	 .bic = BIC_Pkgpc8,1388	 .flags = 0,1389	 .pkg_cstate_limit = PCL__8,1390	  },1391	{1392	 .feature_mask = PC9,1393	 .perf_subsys = "cstate_pkg",1394	 .perf_name = "c9-residency",1395	 .msr = MSR_PKG_C9_RESIDENCY,1396	 .rci_index = PCSTATE_RCI_INDEX_C9_RESIDENCY,1397	 .bic = BIC_Pkgpc9,1398	 .flags = 0,1399	 .pkg_cstate_limit = PCL__9,1400	  },1401	{1402	 .feature_mask = PC10,1403	 .perf_subsys = "cstate_pkg",1404	 .perf_name = "c10-residency",1405	 .msr = MSR_PKG_C10_RESIDENCY,1406	 .rci_index = PCSTATE_RCI_INDEX_C10_RESIDENCY,1407	 .bic = BIC_Pkgpc10,1408	 .flags = 0,1409	 .pkg_cstate_limit = PCL_10,1410	  },1411};1412 1413/* Indexes used to map data read from perf and MSRs into global variables */1414enum msr_rci_index {1415	MSR_RCI_INDEX_APERF = 0,1416	MSR_RCI_INDEX_MPERF = 1,1417	MSR_RCI_INDEX_SMI = 2,1418	NUM_MSR_COUNTERS,1419};1420 1421struct msr_counter_info_t {1422	unsigned long long data[NUM_MSR_COUNTERS];1423	enum counter_source source[NUM_MSR_COUNTERS];1424	unsigned long long msr[NUM_MSR_COUNTERS];1425	unsigned long long msr_mask[NUM_MSR_COUNTERS];1426	int fd_perf;1427};1428 1429struct msr_counter_info_t *msr_counter_info;1430unsigned int msr_counter_info_size;1431 1432struct msr_counter_arch_info {1433	const char *perf_subsys;1434	const char *perf_name;1435	unsigned long long msr;1436	unsigned long long msr_mask;1437	unsigned int rci_index;	/* Maps data from perf counters to global variables */1438	bool needed;1439	bool present;1440};1441 1442enum msr_arch_info_index {1443	MSR_ARCH_INFO_APERF_INDEX = 0,1444	MSR_ARCH_INFO_MPERF_INDEX = 1,1445	MSR_ARCH_INFO_SMI_INDEX = 2,1446};1447 1448static struct msr_counter_arch_info msr_counter_arch_infos[] = {1449	[MSR_ARCH_INFO_APERF_INDEX] = {1450				       .perf_subsys = "msr",1451				       .perf_name = "aperf",1452				       .msr = MSR_IA32_APERF,1453				       .msr_mask = 0xFFFFFFFFFFFFFFFF,1454				       .rci_index = MSR_RCI_INDEX_APERF,1455				        },1456 1457	[MSR_ARCH_INFO_MPERF_INDEX] = {1458				       .perf_subsys = "msr",1459				       .perf_name = "mperf",1460				       .msr = MSR_IA32_MPERF,1461				       .msr_mask = 0xFFFFFFFFFFFFFFFF,1462				       .rci_index = MSR_RCI_INDEX_MPERF,1463				        },1464 1465	[MSR_ARCH_INFO_SMI_INDEX] = {1466				     .perf_subsys = "msr",1467				     .perf_name = "smi",1468				     .msr = MSR_SMI_COUNT,1469				     .msr_mask = 0xFFFFFFFF,1470				     .rci_index = MSR_RCI_INDEX_SMI,1471				      },1472};1473 1474/* Can be redefined when compiling, useful for testing. */1475#ifndef SYSFS_TELEM_PATH1476#define SYSFS_TELEM_PATH "/sys/class/intel_pmt"1477#endif1478 1479#define PMT_COUNTER_MTL_DC6_OFFSET 1201480#define PMT_COUNTER_MTL_DC6_LSB    01481#define PMT_COUNTER_MTL_DC6_MSB    631482#define PMT_MTL_DC6_GUID           0x1a0671021483 1484#define PMT_COUNTER_NAME_SIZE_BYTES      161485#define PMT_COUNTER_TYPE_NAME_SIZE_BYTES 321486 1487struct pmt_mmio {1488	struct pmt_mmio *next;1489 1490	unsigned int guid;1491	unsigned int size;1492 1493	/* Base pointer to the mmaped memory. */1494	void *mmio_base;1495 1496	/*1497	 * Offset to be applied to the mmio_base1498	 * to get the beginning of the PMT counters for given GUID.1499	 */1500	unsigned long pmt_offset;1501} *pmt_mmios;1502 1503enum pmt_datatype {1504	PMT_TYPE_RAW,1505	PMT_TYPE_XTAL_TIME,1506};1507 1508struct pmt_domain_info {1509	/*1510	 * Pointer to the MMIO obtained by applying a counter offset1511	 * to the mmio_base of the mmaped region for the given GUID.1512	 *1513	 * This is where to read the raw value of the counter from.1514	 */1515	unsigned long *pcounter;1516};1517 1518struct pmt_counter {1519	struct pmt_counter *next;1520 1521	/* PMT metadata */1522	char name[PMT_COUNTER_NAME_SIZE_BYTES];1523	enum pmt_datatype type;1524	enum counter_scope scope;1525	unsigned int lsb;1526	unsigned int msb;1527 1528	/* BIC-like metadata */1529	enum counter_format format;1530 1531	unsigned int num_domains;1532	struct pmt_domain_info *domains;1533};1534 1535unsigned int pmt_counter_get_width(const struct pmt_counter *p)1536{1537	return (p->msb - p->lsb) + 1;1538}1539 1540void pmt_counter_resize_(struct pmt_counter *pcounter, unsigned int new_size)1541{1542	struct pmt_domain_info *new_mem;1543 1544	new_mem = (struct pmt_domain_info *)reallocarray(pcounter->domains, new_size, sizeof(*pcounter->domains));1545	if (!new_mem) {1546		fprintf(stderr, "%s: failed to allocate memory for PMT counters\n", __func__);1547		exit(1);1548	}1549 1550	/* Zero initialize just allocated memory. */1551	const size_t num_new_domains = new_size - pcounter->num_domains;1552 1553	memset(&new_mem[pcounter->num_domains], 0, num_new_domains * sizeof(*pcounter->domains));1554 1555	pcounter->num_domains = new_size;1556	pcounter->domains = new_mem;1557}1558 1559void pmt_counter_resize(struct pmt_counter *pcounter, unsigned int new_size)1560{1561	/*1562	 * Allocate more memory ahead of time.1563	 *1564	 * Always allocate space for at least 8 elements1565	 * and double the size when growing.1566	 */1567	if (new_size < 8)1568		new_size = 8;1569	new_size = MAX(new_size, pcounter->num_domains * 2);1570 1571	pmt_counter_resize_(pcounter, new_size);1572}1573 1574struct thread_data {1575	struct timeval tv_begin;1576	struct timeval tv_end;1577	struct timeval tv_delta;1578	unsigned long long tsc;1579	unsigned long long aperf;1580	unsigned long long mperf;1581	unsigned long long c1;1582	unsigned long long instr_count;1583	unsigned long long irq_count;1584	unsigned int smi_count;1585	unsigned int cpu_id;1586	unsigned int apic_id;1587	unsigned int x2apic_id;1588	unsigned int flags;1589	bool is_atom;1590	unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];1591	unsigned long long perf_counter[MAX_ADDED_THREAD_COUNTERS];1592	unsigned long long pmt_counter[PMT_MAX_ADDED_THREAD_COUNTERS];1593} *thread_even, *thread_odd;1594 1595struct core_data {1596	int base_cpu;1597	unsigned long long c3;1598	unsigned long long c6;1599	unsigned long long c7;1600	unsigned long long mc6_us;	/* duplicate as per-core for now, even though per module */1601	unsigned int core_temp_c;1602	struct rapl_counter core_energy;	/* MSR_CORE_ENERGY_STAT */1603	unsigned int core_id;1604	unsigned long long core_throt_cnt;1605	unsigned long long counter[MAX_ADDED_CORE_COUNTERS];1606	unsigned long long perf_counter[MAX_ADDED_CORE_COUNTERS];1607	unsigned long long pmt_counter[PMT_MAX_ADDED_CORE_COUNTERS];1608} *core_even, *core_odd;1609 1610struct pkg_data {1611	int base_cpu;1612	unsigned long long pc2;1613	unsigned long long pc3;1614	unsigned long long pc6;1615	unsigned long long pc7;1616	unsigned long long pc8;1617	unsigned long long pc9;1618	unsigned long long pc10;1619	long long cpu_lpi;1620	long long sys_lpi;1621	unsigned long long pkg_wtd_core_c0;1622	unsigned long long pkg_any_core_c0;1623	unsigned long long pkg_any_gfxe_c0;1624	unsigned long long pkg_both_core_gfxe_c0;1625	long long gfx_rc6_ms;1626	unsigned int gfx_mhz;1627	unsigned int gfx_act_mhz;1628	long long sam_mc6_ms;1629	unsigned int sam_mhz;1630	unsigned int sam_act_mhz;1631	unsigned int package_id;1632	struct rapl_counter energy_pkg;	/* MSR_PKG_ENERGY_STATUS */1633	struct rapl_counter energy_dram;	/* MSR_DRAM_ENERGY_STATUS */1634	struct rapl_counter energy_cores;	/* MSR_PP0_ENERGY_STATUS */1635	struct rapl_counter energy_gfx;	/* MSR_PP1_ENERGY_STATUS */1636	struct rapl_counter rapl_pkg_perf_status;	/* MSR_PKG_PERF_STATUS */1637	struct rapl_counter rapl_dram_perf_status;	/* MSR_DRAM_PERF_STATUS */1638	unsigned int pkg_temp_c;1639	unsigned int uncore_mhz;1640	unsigned long long die_c6;1641	unsigned long long counter[MAX_ADDED_PACKAGE_COUNTERS];1642	unsigned long long perf_counter[MAX_ADDED_PACKAGE_COUNTERS];1643	unsigned long long pmt_counter[PMT_MAX_ADDED_PACKAGE_COUNTERS];1644} *package_even, *package_odd;1645 1646#define ODD_COUNTERS thread_odd, core_odd, package_odd1647#define EVEN_COUNTERS thread_even, core_even, package_even1648 1649#define GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no)	      \1650	((thread_base) +						      \1651	 ((pkg_no) *							      \1652	  topo.nodes_per_pkg * topo.cores_per_node * topo.threads_per_core) + \1653	 ((node_no) * topo.cores_per_node * topo.threads_per_core) +	      \1654	 ((core_no) * topo.threads_per_core) +				      \1655	 (thread_no))1656 1657#define GET_CORE(core_base, core_no, node_no, pkg_no)			\1658	((core_base) +							\1659	 ((pkg_no) *  topo.nodes_per_pkg * topo.cores_per_node) +	\1660	 ((node_no) * topo.cores_per_node) +				\1661	 (core_no))1662 1663#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)1664 1665/*1666 * The accumulated sum of MSR is defined as a monotonic1667 * increasing MSR, it will be accumulated periodically,1668 * despite its register's bit width.1669 */1670enum {1671	IDX_PKG_ENERGY,1672	IDX_DRAM_ENERGY,1673	IDX_PP0_ENERGY,1674	IDX_PP1_ENERGY,1675	IDX_PKG_PERF,1676	IDX_DRAM_PERF,1677	IDX_COUNT,1678};1679 1680int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);1681 1682struct msr_sum_array {1683	/* get_msr_sum() = sum + (get_msr() - last) */1684	struct {1685		/*The accumulated MSR value is updated by the timer */1686		unsigned long long sum;1687		/*The MSR footprint recorded in last timer */1688		unsigned long long last;1689	} entries[IDX_COUNT];1690};1691 1692/* The percpu MSR sum array.*/1693struct msr_sum_array *per_cpu_msr_sum;1694 1695off_t idx_to_offset(int idx)1696{1697	off_t offset;1698 1699	switch (idx) {1700	case IDX_PKG_ENERGY:1701		if (platform->rapl_msrs & RAPL_AMD_F17H)1702			offset = MSR_PKG_ENERGY_STAT;1703		else1704			offset = MSR_PKG_ENERGY_STATUS;1705		break;1706	case IDX_DRAM_ENERGY:1707		offset = MSR_DRAM_ENERGY_STATUS;1708		break;1709	case IDX_PP0_ENERGY:1710		offset = MSR_PP0_ENERGY_STATUS;1711		break;1712	case IDX_PP1_ENERGY:1713		offset = MSR_PP1_ENERGY_STATUS;1714		break;1715	case IDX_PKG_PERF:1716		offset = MSR_PKG_PERF_STATUS;1717		break;1718	case IDX_DRAM_PERF:1719		offset = MSR_DRAM_PERF_STATUS;1720		break;1721	default:1722		offset = -1;1723	}1724	return offset;1725}1726 1727int offset_to_idx(off_t offset)1728{1729	int idx;1730 1731	switch (offset) {1732	case MSR_PKG_ENERGY_STATUS:1733	case MSR_PKG_ENERGY_STAT:1734		idx = IDX_PKG_ENERGY;1735		break;1736	case MSR_DRAM_ENERGY_STATUS:1737		idx = IDX_DRAM_ENERGY;1738		break;1739	case MSR_PP0_ENERGY_STATUS:1740		idx = IDX_PP0_ENERGY;1741		break;1742	case MSR_PP1_ENERGY_STATUS:1743		idx = IDX_PP1_ENERGY;1744		break;1745	case MSR_PKG_PERF_STATUS:1746		idx = IDX_PKG_PERF;1747		break;1748	case MSR_DRAM_PERF_STATUS:1749		idx = IDX_DRAM_PERF;1750		break;1751	default:1752		idx = -1;1753	}1754	return idx;1755}1756 1757int idx_valid(int idx)1758{1759	switch (idx) {1760	case IDX_PKG_ENERGY:1761		return platform->rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H);1762	case IDX_DRAM_ENERGY:1763		return platform->rapl_msrs & RAPL_DRAM;1764	case IDX_PP0_ENERGY:1765		return platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS;1766	case IDX_PP1_ENERGY:1767		return platform->rapl_msrs & RAPL_GFX;1768	case IDX_PKG_PERF:1769		return platform->rapl_msrs & RAPL_PKG_PERF_STATUS;1770	case IDX_DRAM_PERF:1771		return platform->rapl_msrs & RAPL_DRAM_PERF_STATUS;1772	default:1773		return 0;1774	}1775}1776 1777struct sys_counters {1778	/* MSR added counters */1779	unsigned int added_thread_counters;1780	unsigned int added_core_counters;1781	unsigned int added_package_counters;1782	struct msr_counter *tp;1783	struct msr_counter *cp;1784	struct msr_counter *pp;1785 1786	/* perf added counters */1787	unsigned int added_thread_perf_counters;1788	unsigned int added_core_perf_counters;1789	unsigned int added_package_perf_counters;1790	struct perf_counter_info *perf_tp;1791	struct perf_counter_info *perf_cp;1792	struct perf_counter_info *perf_pp;1793 1794	struct pmt_counter *pmt_tp;1795	struct pmt_counter *pmt_cp;1796	struct pmt_counter *pmt_pp;1797} sys;1798 1799static size_t free_msr_counters_(struct msr_counter **pp)1800{1801	struct msr_counter *p = NULL;1802	size_t num_freed = 0;1803 1804	while (*pp) {1805		p = *pp;1806 1807		if (p->msr_num != 0) {1808			*pp = p->next;1809 1810			free(p);1811			++num_freed;1812 1813			continue;1814		}1815 1816		pp = &p->next;1817	}1818 1819	return num_freed;1820}1821 1822/*1823 * Free all added counters accessed via msr.1824 */1825static void free_sys_msr_counters(void)1826{1827	/* Thread counters */1828	sys.added_thread_counters -= free_msr_counters_(&sys.tp);1829 1830	/* Core counters */1831	sys.added_core_counters -= free_msr_counters_(&sys.cp);1832 1833	/* Package counters */1834	sys.added_package_counters -= free_msr_counters_(&sys.pp);1835}1836 1837struct system_summary {1838	struct thread_data threads;1839	struct core_data cores;1840	struct pkg_data packages;1841} average;1842 1843struct cpu_topology {1844	int physical_package_id;1845	int die_id;1846	int logical_cpu_id;1847	int physical_node_id;1848	int logical_node_id;	/* 0-based count within the package */1849	int physical_core_id;1850	int thread_id;1851	cpu_set_t *put_ids;	/* Processing Unit/Thread IDs */1852} *cpus;1853 1854struct topo_params {1855	int num_packages;1856	int num_die;1857	int num_cpus;1858	int num_cores;1859	int allowed_packages;1860	int allowed_cpus;1861	int allowed_cores;1862	int max_cpu_num;1863	int max_core_id;1864	int max_package_id;1865	int max_die_id;1866	int max_node_num;1867	int nodes_per_pkg;1868	int cores_per_node;1869	int threads_per_core;1870} topo;1871 1872struct timeval tv_even, tv_odd, tv_delta;1873 1874int *irq_column_2_cpu;		/* /proc/interrupts column numbers */1875int *irqs_per_cpu;		/* indexed by cpu_num */1876 1877void setup_all_buffers(bool startup);1878 1879char *sys_lpi_file;1880char *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us";1881char *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec";1882 1883int cpu_is_not_present(int cpu)1884{1885	return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);1886}1887 1888int cpu_is_not_allowed(int cpu)1889{1890	return !CPU_ISSET_S(cpu, cpu_allowed_setsize, cpu_allowed_set);1891}1892 1893/*1894 * run func(thread, core, package) in topology order1895 * skip non-present cpus1896 */1897 1898int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *),1899		 struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)1900{1901	int retval, pkg_no, core_no, thread_no, node_no;1902 1903	for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {1904		for (node_no = 0; node_no < topo.nodes_per_pkg; node_no++) {1905			for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {1906				for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) {1907					struct thread_data *t;1908					struct core_data *c;1909					struct pkg_data *p;1910					t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no);1911 1912					if (cpu_is_not_allowed(t->cpu_id))1913						continue;1914 1915					c = GET_CORE(core_base, core_no, node_no, pkg_no);1916					p = GET_PKG(pkg_base, pkg_no);1917 1918					retval = func(t, c, p);1919					if (retval)1920						return retval;1921				}1922			}1923		}1924	}1925	return 0;1926}1927 1928int is_cpu_first_thread_in_core(struct thread_data *t, struct core_data *c, struct pkg_data *p)1929{1930	UNUSED(p);1931 1932	return ((int)t->cpu_id == c->base_cpu || c->base_cpu < 0);1933}1934 1935int is_cpu_first_core_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p)1936{1937	UNUSED(c);1938 1939	return ((int)t->cpu_id == p->base_cpu || p->base_cpu < 0);1940}1941 1942int is_cpu_first_thread_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p)1943{1944	return is_cpu_first_thread_in_core(t, c, p) && is_cpu_first_core_in_package(t, c, p);1945}1946 1947int cpu_migrate(int cpu)1948{1949	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);1950	CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);1951	if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)1952		return -1;1953	else1954		return 0;1955}1956 1957int get_msr_fd(int cpu)1958{1959	char pathname[32];1960	int fd;1961 1962	fd = fd_percpu[cpu];1963 1964	if (fd)1965		return fd;1966 1967	sprintf(pathname, "/dev/cpu/%d/msr", cpu);1968	fd = open(pathname, O_RDONLY);1969	if (fd < 0)1970		err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, "1971		    "or run with --no-msr, or run as root", pathname);1972 1973	fd_percpu[cpu] = fd;1974 1975	return fd;1976}1977 1978static void bic_disable_msr_access(void)1979{1980	const unsigned long bic_msrs = BIC_Mod_c6 | BIC_CoreTmp |1981	    BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_PkgTmp;1982 1983	bic_enabled &= ~bic_msrs;1984 1985	free_sys_msr_counters();1986}1987 1988static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)1989{1990	assert(!no_perf);1991 1992	return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);1993}1994 1995static long open_perf_counter(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format)1996{1997	struct perf_event_attr attr;1998	const pid_t pid = -1;1999	const unsigned long flags = 0;2000 2001	assert(!no_perf);2002 2003	memset(&attr, 0, sizeof(struct perf_event_attr));2004 2005	attr.type = type;2006	attr.size = sizeof(struct perf_event_attr);2007	attr.config = config;2008	attr.disabled = 0;2009	attr.sample_type = PERF_SAMPLE_IDENTIFIER;2010	attr.read_format = read_format;2011 2012	const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags);2013 2014	return fd;2015}2016 2017int get_instr_count_fd(int cpu)2018{2019	if (fd_instr_count_percpu[cpu])2020		return fd_instr_count_percpu[cpu];2021 2022	fd_instr_count_percpu[cpu] = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0);2023 2024	return fd_instr_count_percpu[cpu];2025}2026 2027int get_msr(int cpu, off_t offset, unsigned long long *msr)2028{2029	ssize_t retval;2030 2031	assert(!no_msr);2032 2033	retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);2034 2035	if (retval != sizeof *msr)2036		err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);2037 2038	return 0;2039}2040 2041int probe_msr(int cpu, off_t offset)2042{2043	ssize_t retval;2044	unsigned long long dummy;2045 2046	assert(!no_msr);2047 2048	retval = pread(get_msr_fd(cpu), &dummy, sizeof(dummy), offset);2049 2050	if (retval != sizeof(dummy))2051		return 1;2052 2053	return 0;2054}2055 2056/* Convert CPU ID to domain ID for given added perf counter. */2057unsigned int cpu_to_domain(const struct perf_counter_info *pc, int cpu)2058{2059	switch (pc->scope) {2060	case SCOPE_CPU:2061		return cpu;2062 2063	case SCOPE_CORE:2064		return cpus[cpu].physical_core_id;2065 2066	case SCOPE_PACKAGE:2067		return cpus[cpu].physical_package_id;2068	}2069 2070	__builtin_unreachable();2071}2072 2073#define MAX_DEFERRED 162074char *deferred_add_names[MAX_DEFERRED];2075char *deferred_skip_names[MAX_DEFERRED];2076int deferred_add_index;2077int deferred_skip_index;2078 2079/*2080 * HIDE_LIST - hide this list of counters, show the rest [default]2081 * SHOW_LIST - show this list of counters, hide the rest2082 */2083enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;2084 2085void help(void)2086{2087	fprintf(outf,2088		"Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"2089		"\n"2090		"Turbostat forks the specified COMMAND and prints statistics\n"2091		"when COMMAND completes.\n"2092		"If no COMMAND is specified, turbostat wakes every 5-seconds\n"2093		"to print statistics, until interrupted.\n"2094		"  -a, --add	add a counter\n"2095		"		  eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"2096		"		  eg. --add perf/cstate_pkg/c2-residency,package,delta,percent,perfPC2\n"2097		"		  eg. --add pmt,name=XTAL,type=raw,domain=package0,offset=0,lsb=0,msb=63,guid=0x1a067102\n"2098		"  -c, --cpu	cpu-set	limit output to summary plus cpu-set:\n"2099		"		  {core | package | j,k,l..m,n-p }\n"2100		"  -d, --debug	displays usec, Time_Of_Day_Seconds and more debugging\n"2101		"		debug messages are printed to stderr\n"2102		"  -D, --Dump	displays the raw counter values\n"2103		"  -e, --enable	[all | column]\n"2104		"		shows all or the specified disabled column\n"2105		"  -H, --hide [column|column,column,...]\n"2106		"		hide the specified column(s)\n"2107		"  -i, --interval sec.subsec\n"2108		"		Override default 5-second measurement interval\n"2109		"  -J, --Joules	displays energy in Joules instead of Watts\n"2110		"  -l, --list	list column headers only\n"2111		"  -M, --no-msr Disable all uses of the MSR driver\n"2112		"  -P, --no-perf Disable all uses of the perf API\n"2113		"  -n, --num_iterations num\n"2114		"		number of the measurement iterations\n"2115		"  -N, --header_iterations num\n"2116		"		print header every num iterations\n"2117		"  -o, --out file\n"2118		"		create or truncate \"file\" for all output\n"2119		"  -q, --quiet	skip decoding system configuration header\n"2120		"  -s, --show [column|column,column,...]\n"2121		"		show only the specified column(s)\n"2122		"  -S, --Summary\n"2123		"		limits output to 1-line system summary per interval\n"2124		"  -T, --TCC temperature\n"2125		"		sets the Thermal Control Circuit temperature in\n"2126		"		  degrees Celsius\n"2127		"  -h, --help	print this help message\n"2128		"  -v, --version	print version information\n" "\n" "For more help, run \"man turbostat\"\n");2129}2130 2131/*2132 * bic_lookup2133 * for all the strings in comma separate name_list,2134 * set the approprate bit in return value.2135 */2136unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)2137{2138	unsigned int i;2139	unsigned long long retval = 0;2140 2141	while (name_list) {2142		char *comma;2143 2144		comma = strchr(name_list, ',');2145 2146		if (comma)2147			*comma = '\0';2148 2149		for (i = 0; i < MAX_BIC; ++i) {2150			if (!strcmp(name_list, bic[i].name)) {2151				retval |= (1ULL << i);2152				break;2153			}2154			if (!strcmp(name_list, "all")) {2155				retval |= ~0;2156				break;2157			} else if (!strcmp(name_list, "topology")) {2158				retval |= BIC_TOPOLOGY;2159				break;2160			} else if (!strcmp(name_list, "power")) {2161				retval |= BIC_THERMAL_PWR;2162				break;2163			} else if (!strcmp(name_list, "idle")) {2164				retval |= BIC_IDLE;2165				break;2166			} else if (!strcmp(name_list, "frequency")) {2167				retval |= BIC_FREQUENCY;2168				break;2169			} else if (!strcmp(name_list, "other")) {2170				retval |= BIC_OTHER;2171				break;2172			}2173 2174		}2175		if (i == MAX_BIC) {2176			if (mode == SHOW_LIST) {2177				deferred_add_names[deferred_add_index++] = name_list;2178				if (deferred_add_index >= MAX_DEFERRED) {2179					fprintf(stderr, "More than max %d un-recognized --add options '%s'\n",2180						MAX_DEFERRED, name_list);2181					help();2182					exit(1);2183				}2184			} else {2185				deferred_skip_names[deferred_skip_index++] = name_list;2186				if (debug)2187					fprintf(stderr, "deferred \"%s\"\n", name_list);2188				if (deferred_skip_index >= MAX_DEFERRED) {2189					fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",2190						MAX_DEFERRED, name_list);2191					help();2192					exit(1);2193				}2194			}2195		}2196 2197		name_list = comma;2198		if (name_list)2199			name_list++;2200 2201	}2202	return retval;2203}2204 2205void print_header(char *delim)2206{2207	struct msr_counter *mp;2208	struct perf_counter_info *pp;2209	struct pmt_counter *ppmt;2210	int printed = 0;2211 2212	if (DO_BIC(BIC_USEC))2213		outp += sprintf(outp, "%susec", (printed++ ? delim : ""));2214	if (DO_BIC(BIC_TOD))2215		outp += sprintf(outp, "%sTime_Of_Day_Seconds", (printed++ ? delim : ""));2216	if (DO_BIC(BIC_Package))2217		outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));2218	if (DO_BIC(BIC_Die))2219		outp += sprintf(outp, "%sDie", (printed++ ? delim : ""));2220	if (DO_BIC(BIC_Node))2221		outp += sprintf(outp, "%sNode", (printed++ ? delim : ""));2222	if (DO_BIC(BIC_Core))2223		outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));2224	if (DO_BIC(BIC_CPU))2225		outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));2226	if (DO_BIC(BIC_APIC))2227		outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));2228	if (DO_BIC(BIC_X2APIC))2229		outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));2230	if (DO_BIC(BIC_Avg_MHz))2231		outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));2232	if (DO_BIC(BIC_Busy))2233		outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));2234	if (DO_BIC(BIC_Bzy_MHz))2235		outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));2236	if (DO_BIC(BIC_TSC_MHz))2237		outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));2238 2239	if (DO_BIC(BIC_IPC))2240		outp += sprintf(outp, "%sIPC", (printed++ ? delim : ""));2241 2242	if (DO_BIC(BIC_IRQ)) {2243		if (sums_need_wide_columns)2244			outp += sprintf(outp, "%s     IRQ", (printed++ ? delim : ""));2245		else2246			outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));2247	}2248 2249	if (DO_BIC(BIC_SMI))2250		outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));2251 2252	for (mp = sys.tp; mp; mp = mp->next) {2253 2254		if (mp->format == FORMAT_RAW) {2255			if (mp->width == 64)2256				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), mp->name);2257			else2258				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), mp->name);2259		} else {2260			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)2261				outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), mp->name);2262			else2263				outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), mp->name);2264		}2265	}2266 2267	for (pp = sys.perf_tp; pp; pp = pp->next) {2268 2269		if (pp->format == FORMAT_RAW) {2270			if (pp->width == 64)2271				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), pp->name);2272			else2273				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), pp->name);2274		} else {2275			if ((pp->type == COUNTER_ITEMS) && sums_need_wide_columns)2276				outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), pp->name);2277			else2278				outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), pp->name);2279		}2280	}2281 2282	ppmt = sys.pmt_tp;2283	while (ppmt) {2284		switch (ppmt->type) {2285		case PMT_TYPE_RAW:2286			if (pmt_counter_get_width(ppmt) <= 32)2287				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), ppmt->name);2288			else2289				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), ppmt->name);2290 2291			break;2292 2293		case PMT_TYPE_XTAL_TIME:2294			outp += sprintf(outp, "%s%s", delim, ppmt->name);2295			break;2296		}2297 2298		ppmt = ppmt->next;2299	}2300 2301	if (DO_BIC(BIC_CPU_c1))2302		outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));2303	if (DO_BIC(BIC_CPU_c3))2304		outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));2305	if (DO_BIC(BIC_CPU_c6))2306		outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));2307	if (DO_BIC(BIC_CPU_c7))2308		outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));2309 2310	if (DO_BIC(BIC_Mod_c6))2311		outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));2312 2313	if (DO_BIC(BIC_CoreTmp))2314		outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));2315 2316	if (DO_BIC(BIC_CORE_THROT_CNT))2317		outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : ""));2318 2319	if (platform->rapl_msrs && !rapl_joules) {2320		if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl)2321			outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));2322	} else if (platform->rapl_msrs && rapl_joules) {2323		if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl)2324			outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));2325	}2326 2327	for (mp = sys.cp; mp; mp = mp->next) {2328		if (mp->format == FORMAT_RAW) {2329			if (mp->width == 64)2330				outp += sprintf(outp, "%s%18.18s", delim, mp->name);2331			else2332				outp += sprintf(outp, "%s%10.10s", delim, mp->name);2333		} else {2334			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)2335				outp += sprintf(outp, "%s%8s", delim, mp->name);2336			else2337				outp += sprintf(outp, "%s%s", delim, mp->name);2338		}2339	}2340 2341	for (pp = sys.perf_cp; pp; pp = pp->next) {2342 2343		if (pp->format == FORMAT_RAW) {2344			if (pp->width == 64)2345				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), pp->name);2346			else2347				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), pp->name);2348		} else {2349			if ((pp->type == COUNTER_ITEMS) && sums_need_wide_columns)2350				outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), pp->name);2351			else2352				outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), pp->name);2353		}2354	}2355 2356	ppmt = sys.pmt_cp;2357	while (ppmt) {2358		switch (ppmt->type) {2359		case PMT_TYPE_RAW:2360			if (pmt_counter_get_width(ppmt) <= 32)2361				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), ppmt->name);2362			else2363				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), ppmt->name);2364 2365			break;2366 2367		case PMT_TYPE_XTAL_TIME:2368			outp += sprintf(outp, "%s%s", delim, ppmt->name);2369			break;2370		}2371 2372		ppmt = ppmt->next;2373	}2374 2375	if (DO_BIC(BIC_PkgTmp))2376		outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));2377 2378	if (DO_BIC(BIC_GFX_rc6))2379		outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));2380 2381	if (DO_BIC(BIC_GFXMHz))2382		outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));2383 2384	if (DO_BIC(BIC_GFXACTMHz))2385		outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));2386 2387	if (DO_BIC(BIC_SAM_mc6))2388		outp += sprintf(outp, "%sSAM%%mc6", (printed++ ? delim : ""));2389 2390	if (DO_BIC(BIC_SAMMHz))2391		outp += sprintf(outp, "%sSAMMHz", (printed++ ? delim : ""));2392 2393	if (DO_BIC(BIC_SAMACTMHz))2394		outp += sprintf(outp, "%sSAMAMHz", (printed++ ? delim : ""));2395 2396	if (DO_BIC(BIC_Totl_c0))2397		outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));2398	if (DO_BIC(BIC_Any_c0))2399		outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));2400	if (DO_BIC(BIC_GFX_c0))2401		outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));2402	if (DO_BIC(BIC_CPUGFX))2403		outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));2404 2405	if (DO_BIC(BIC_Pkgpc2))2406		outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));2407	if (DO_BIC(BIC_Pkgpc3))2408		outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));2409	if (DO_BIC(BIC_Pkgpc6))2410		outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));2411	if (DO_BIC(BIC_Pkgpc7))2412		outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));2413	if (DO_BIC(BIC_Pkgpc8))2414		outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));2415	if (DO_BIC(BIC_Pkgpc9))2416		outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));2417	if (DO_BIC(BIC_Pkgpc10))2418		outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));2419	if (DO_BIC(BIC_Diec6))2420		outp += sprintf(outp, "%sDie%%c6", (printed++ ? delim : ""));2421	if (DO_BIC(BIC_CPU_LPI))2422		outp += sprintf(outp, "%sCPU%%LPI", (printed++ ? delim : ""));2423	if (DO_BIC(BIC_SYS_LPI))2424		outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));2425 2426	if (platform->rapl_msrs && !rapl_joules) {2427		if (DO_BIC(BIC_PkgWatt))2428			outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));2429		if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)2430			outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));2431		if (DO_BIC(BIC_GFXWatt))2432			outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));2433		if (DO_BIC(BIC_RAMWatt))2434			outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));2435		if (DO_BIC(BIC_PKG__))2436			outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));2437		if (DO_BIC(BIC_RAM__))2438			outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));2439	} else if (platform->rapl_msrs && rapl_joules) {2440		if (DO_BIC(BIC_Pkg_J))2441			outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));2442		if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)2443			outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));2444		if (DO_BIC(BIC_GFX_J))2445			outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));2446		if (DO_BIC(BIC_RAM_J))2447			outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));2448		if (DO_BIC(BIC_PKG__))2449			outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));2450		if (DO_BIC(BIC_RAM__))2451			outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));2452	}2453	if (DO_BIC(BIC_UNCORE_MHZ))2454		outp += sprintf(outp, "%sUncMHz", (printed++ ? delim : ""));2455 2456	for (mp = sys.pp; mp; mp = mp->next) {2457		if (mp->format == FORMAT_RAW) {2458			if (mp->width == 64)2459				outp += sprintf(outp, "%s%18.18s", delim, mp->name);2460			else if (mp->width == 32)2461				outp += sprintf(outp, "%s%10.10s", delim, mp->name);2462			else2463				outp += sprintf(outp, "%s%7.7s", delim, mp->name);2464		} else {2465			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)2466				outp += sprintf(outp, "%s%8s", delim, mp->name);2467			else2468				outp += sprintf(outp, "%s%7.7s", delim, mp->name);2469		}2470	}2471 2472	for (pp = sys.perf_pp; pp; pp = pp->next) {2473 2474		if (pp->format == FORMAT_RAW) {2475			if (pp->width == 64)2476				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), pp->name);2477			else2478				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), pp->name);2479		} else {2480			if ((pp->type == COUNTER_ITEMS) && sums_need_wide_columns)2481				outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), pp->name);2482			else2483				outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), pp->name);2484		}2485	}2486 2487	ppmt = sys.pmt_pp;2488	while (ppmt) {2489		switch (ppmt->type) {2490		case PMT_TYPE_RAW:2491			if (pmt_counter_get_width(ppmt) <= 32)2492				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), ppmt->name);2493			else2494				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), ppmt->name);2495 2496			break;2497 2498		case PMT_TYPE_XTAL_TIME:2499			outp += sprintf(outp, "%s%s", delim, ppmt->name);2500			break;2501		}2502 2503		ppmt = ppmt->next;2504	}2505 2506	outp += sprintf(outp, "\n");2507}2508 2509int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)2510{2511	int i;2512	struct msr_counter *mp;2513 2514	outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);2515 2516	if (t) {2517		outp += sprintf(outp, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags);2518		outp += sprintf(outp, "TSC: %016llX\n", t->tsc);2519		outp += sprintf(outp, "aperf: %016llX\n", t->aperf);2520		outp += sprintf(outp, "mperf: %016llX\n", t->mperf);2521		outp += sprintf(outp, "c1: %016llX\n", t->c1);2522 2523		if (DO_BIC(BIC_IPC))2524			outp += sprintf(outp, "IPC: %lld\n", t->instr_count);2525 2526		if (DO_BIC(BIC_IRQ))2527			outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);2528		if (DO_BIC(BIC_SMI))2529			outp += sprintf(outp, "SMI: %d\n", t->smi_count);2530 2531		for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {2532			outp +=2533			    sprintf(outp, "tADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num,2534				    t->counter[i], mp->sp->path);2535		}2536	}2537 2538	if (c && is_cpu_first_thread_in_core(t, c, p)) {2539		outp += sprintf(outp, "core: %d\n", c->core_id);2540		outp += sprintf(outp, "c3: %016llX\n", c->c3);2541		outp += sprintf(outp, "c6: %016llX\n", c->c6);2542		outp += sprintf(outp, "c7: %016llX\n", c->c7);2543		outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c);2544		outp += sprintf(outp, "cpu_throt_count: %016llX\n", c->core_throt_cnt);2545 2546		const unsigned long long energy_value = c->core_energy.raw_value * c->core_energy.scale;2547		const double energy_scale = c->core_energy.scale;2548 2549		if (c->core_energy.unit == RAPL_UNIT_JOULES)2550			outp += sprintf(outp, "Joules: %0llX (scale: %lf)\n", energy_value, energy_scale);2551 2552		for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {2553			outp +=2554			    sprintf(outp, "cADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num,2555				    c->counter[i], mp->sp->path);2556		}2557		outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);2558	}2559 2560	if (p && is_cpu_first_core_in_package(t, c, p)) {2561		outp += sprintf(outp, "package: %d\n", p->package_id);2562 2563		outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0);2564		outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0);2565		outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0);2566		outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);2567 2568		outp += sprintf(outp, "pc2: %016llX\n", p->pc2);2569		if (DO_BIC(BIC_Pkgpc3))2570			outp += sprintf(outp, "pc3: %016llX\n", p->pc3);2571		if (DO_BIC(BIC_Pkgpc6))2572			outp += sprintf(outp, "pc6: %016llX\n", p->pc6);2573		if (DO_BIC(BIC_Pkgpc7))2574			outp += sprintf(outp, "pc7: %016llX\n", p->pc7);2575		outp += sprintf(outp, "pc8: %016llX\n", p->pc8);2576		outp += sprintf(outp, "pc9: %016llX\n", p->pc9);2577		outp += sprintf(outp, "pc10: %016llX\n", p->pc10);2578		outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);2579		outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);2580		outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg.raw_value);2581		outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores.raw_value);2582		outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx.raw_value);2583		outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram.raw_value);2584		outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status.raw_value);2585		outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status.raw_value);2586		outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);2587 2588		for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {2589			outp +=2590			    sprintf(outp, "pADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num,2591				    p->counter[i], mp->sp->path);2592		}2593	}2594 2595	outp += sprintf(outp, "\n");2596 2597	return 0;2598}2599 2600double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desired_unit, double interval)2601{2602	assert(desired_unit != RAPL_UNIT_INVALID);2603 2604	/*2605	 * For now we don't expect anything other than joules,2606	 * so just simplify the logic.2607	 */2608	assert(c->unit == RAPL_UNIT_JOULES);2609 2610	const double scaled = c->raw_value * c->scale;2611 2612	if (desired_unit == RAPL_UNIT_WATTS)2613		return scaled / interval;2614	return scaled;2615}2616 2617/*2618 * column formatting convention & formats2619 */2620int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)2621{2622	double interval_float, tsc;2623	char *fmt8;2624	int i;2625	struct msr_counter *mp;2626	struct perf_counter_info *pp;2627	struct pmt_counter *ppmt;2628	char *delim = "\t";2629	int printed = 0;2630 2631	/* if showing only 1st thread in core and this isn't one, bail out */2632	if (show_core_only && !is_cpu_first_thread_in_core(t, c, p))2633		return 0;2634 2635	/* if showing only 1st thread in pkg and this isn't one, bail out */2636	if (show_pkg_only && !is_cpu_first_core_in_package(t, c, p))2637		return 0;2638 2639	/*if not summary line and --cpu is used */2640	if ((t != &average.threads) && (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))2641		return 0;2642 2643	if (DO_BIC(BIC_USEC)) {2644		/* on each row, print how many usec each timestamp took to gather */2645		struct timeval tv;2646 2647		timersub(&t->tv_end, &t->tv_begin, &tv);2648		outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec);2649	}2650 2651	/* Time_Of_Day_Seconds: on each row, print sec.usec last timestamp taken */2652	if (DO_BIC(BIC_TOD))2653		outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);2654 2655	interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec / 1000000.0;2656 2657	tsc = t->tsc * tsc_tweak;2658 2659	/* topo columns, print blanks on 1st (average) line */2660	if (t == &average.threads) {2661		if (DO_BIC(BIC_Package))2662			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2663		if (DO_BIC(BIC_Die))2664			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2665		if (DO_BIC(BIC_Node))2666			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2667		if (DO_BIC(BIC_Core))2668			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2669		if (DO_BIC(BIC_CPU))2670			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2671		if (DO_BIC(BIC_APIC))2672			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2673		if (DO_BIC(BIC_X2APIC))2674			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2675	} else {2676		if (DO_BIC(BIC_Package)) {2677			if (p)2678				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id);2679			else2680				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2681		}2682		if (DO_BIC(BIC_Die)) {2683			if (c)2684				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].die_id);2685			else2686				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2687		}2688		if (DO_BIC(BIC_Node)) {2689			if (t)2690				outp += sprintf(outp, "%s%d",2691						(printed++ ? delim : ""), cpus[t->cpu_id].physical_node_id);2692			else2693				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2694		}2695		if (DO_BIC(BIC_Core)) {2696			if (c)2697				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id);2698			else2699				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));2700		}2701		if (DO_BIC(BIC_CPU))2702			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);2703		if (DO_BIC(BIC_APIC))2704			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);2705		if (DO_BIC(BIC_X2APIC))2706			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);2707	}2708 2709	if (DO_BIC(BIC_Avg_MHz))2710		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 / units * t->aperf / interval_float);2711 2712	if (DO_BIC(BIC_Busy))2713		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf / tsc);2714 2715	if (DO_BIC(BIC_Bzy_MHz)) {2716		if (has_base_hz)2717			outp +=2718			    sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);2719		else2720			outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),2721					tsc / units * t->aperf / t->mperf / interval_float);2722	}2723 2724	if (DO_BIC(BIC_TSC_MHz))2725		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc / units / interval_float);2726 2727	if (DO_BIC(BIC_IPC))2728		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 1.0 * t->instr_count / t->aperf);2729 2730	/* IRQ */2731	if (DO_BIC(BIC_IRQ)) {2732		if (sums_need_wide_columns)2733			outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);2734		else2735			outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);2736	}2737 2738	/* SMI */2739	if (DO_BIC(BIC_SMI))2740		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);2741 2742	/* Added counters */2743	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {2744		if (mp->format == FORMAT_RAW) {2745			if (mp->width == 32)2746				outp +=2747				    sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)t->counter[i]);2748			else2749				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);2750		} else if (mp->format == FORMAT_DELTA) {2751			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)2752				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->counter[i]);2753			else2754				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);2755		} else if (mp->format == FORMAT_PERCENT) {2756			if (mp->type == COUNTER_USEC)2757				outp +=2758				    sprintf(outp, "%s%.2f", (printed++ ? delim : ""),2759					    t->counter[i] / interval_float / 10000);2760			else2761				outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i] / tsc);2762		}2763	}2764 2765	/* Added perf counters */2766	for (i = 0, pp = sys.perf_tp; pp; ++i, pp = pp->next) {2767		if (pp->format == FORMAT_RAW) {2768			if (pp->width == 32)2769				outp +=2770				    sprintf(outp, "%s0x%08x", (printed++ ? delim : ""),2771					    (unsigned int)t->perf_counter[i]);2772			else2773				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->perf_counter[i]);2774		} else if (pp->format == FORMAT_DELTA) {2775			if ((pp->type == COUNTER_ITEMS) && sums_need_wide_columns)2776				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->perf_counter[i]);2777			else2778				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->perf_counter[i]);2779		} else if (pp->format == FORMAT_PERCENT) {2780			if (pp->type == COUNTER_USEC)2781				outp +=2782				    sprintf(outp, "%s%.2f", (printed++ ? delim : ""),2783					    t->perf_counter[i] / interval_float / 10000);2784			else2785				outp +=2786				    sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->perf_counter[i] / tsc);2787		}2788	}2789 2790	for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {2791		switch (ppmt->type) {2792		case PMT_TYPE_RAW:2793			if (pmt_counter_get_width(ppmt) <= 32)2794				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""),2795						(unsigned int)t->pmt_counter[i]);2796			else2797				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->pmt_counter[i]);2798 2799			break;2800 2801		case PMT_TYPE_XTAL_TIME:2802			const unsigned long value_raw = t->pmt_counter[i];2803			const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;2804 2805			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);2806			break;2807		}2808	}2809 2810	/* C1 */2811	if (DO_BIC(BIC_CPU_c1))2812		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1 / tsc);2813 2814	/* print per-core data only for 1st thread in core */2815	if (!is_cpu_first_thread_in_core(t, c, p))2816		goto done;2817 2818	if (DO_BIC(BIC_CPU_c3))2819		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3 / tsc);2820	if (DO_BIC(BIC_CPU_c6))2821		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6 / tsc);2822	if (DO_BIC(BIC_CPU_c7))2823		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7 / tsc);2824 2825	/* Mod%c6 */2826	if (DO_BIC(BIC_Mod_c6))2827		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->mc6_us / tsc);2828 2829	if (DO_BIC(BIC_CoreTmp))2830		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);2831 2832	/* Core throttle count */2833	if (DO_BIC(BIC_CORE_THROT_CNT))2834		outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->core_throt_cnt);2835 2836	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {2837		if (mp->format == FORMAT_RAW) {2838			if (mp->width == 32)2839				outp +=2840				    sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)c->counter[i]);2841			else2842				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);2843		} else if (mp->format == FORMAT_DELTA) {2844			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)2845				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->counter[i]);2846			else2847				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);2848		} else if (mp->format == FORMAT_PERCENT) {2849			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i] / tsc);2850		}2851	}2852 2853	for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {2854		if (pp->format == FORMAT_RAW) {2855			if (pp->width == 32)2856				outp +=2857				    sprintf(outp, "%s0x%08x", (printed++ ? delim : ""),2858					    (unsigned int)c->perf_counter[i]);2859			else2860				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->perf_counter[i]);2861		} else if (pp->format == FORMAT_DELTA) {2862			if ((pp->type == COUNTER_ITEMS) && sums_need_wide_columns)2863				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->perf_counter[i]);2864			else2865				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->perf_counter[i]);2866		} else if (pp->format == FORMAT_PERCENT) {2867			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->perf_counter[i] / tsc);2868		}2869	}2870 2871	for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {2872		switch (ppmt->type) {2873		case PMT_TYPE_RAW:2874			if (pmt_counter_get_width(ppmt) <= 32)2875				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""),2876						(unsigned int)c->pmt_counter[i]);2877			else2878				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->pmt_counter[i]);2879 2880			break;2881 2882		case PMT_TYPE_XTAL_TIME:2883			const unsigned long value_raw = c->pmt_counter[i];2884			const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;2885 2886			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);2887			break;2888		}2889	}2890 2891	fmt8 = "%s%.2f";2892 2893	if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl)2894		outp +=2895		    sprintf(outp, fmt8, (printed++ ? delim : ""),2896			    rapl_counter_get_value(&c->core_energy, RAPL_UNIT_WATTS, interval_float));2897	if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl)2898		outp += sprintf(outp, fmt8, (printed++ ? delim : ""),2899				rapl_counter_get_value(&c->core_energy, RAPL_UNIT_JOULES, interval_float));2900 2901	/* print per-package data only for 1st core in package */2902	if (!is_cpu_first_core_in_package(t, c, p))2903		goto done;2904 2905	/* PkgTmp */2906	if (DO_BIC(BIC_PkgTmp))2907		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);2908 2909	/* GFXrc6 */2910	if (DO_BIC(BIC_GFX_rc6)) {2911		if (p->gfx_rc6_ms == -1) {	/* detect GFX counter reset */2912			outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));2913		} else {2914			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),2915					p->gfx_rc6_ms / 10.0 / interval_float);2916		}2917	}2918 2919	/* GFXMHz */2920	if (DO_BIC(BIC_GFXMHz))2921		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);2922 2923	/* GFXACTMHz */2924	if (DO_BIC(BIC_GFXACTMHz))2925		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);2926 2927	/* SAMmc6 */2928	if (DO_BIC(BIC_SAM_mc6)) {2929		if (p->sam_mc6_ms == -1) {	/* detect GFX counter reset */2930			outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));2931		} else {2932			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),2933					p->sam_mc6_ms / 10.0 / interval_float);2934		}2935	}2936 2937	/* SAMMHz */2938	if (DO_BIC(BIC_SAMMHz))2939		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_mhz);2940 2941	/* SAMACTMHz */2942	if (DO_BIC(BIC_SAMACTMHz))2943		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_act_mhz);2944 2945	/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */2946	if (DO_BIC(BIC_Totl_c0))2947		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0 / tsc);2948	if (DO_BIC(BIC_Any_c0))2949		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0 / tsc);2950	if (DO_BIC(BIC_GFX_c0))2951		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0 / tsc);2952	if (DO_BIC(BIC_CPUGFX))2953		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0 / tsc);2954 2955	if (DO_BIC(BIC_Pkgpc2))2956		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2 / tsc);2957	if (DO_BIC(BIC_Pkgpc3))2958		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3 / tsc);2959	if (DO_BIC(BIC_Pkgpc6))2960		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6 / tsc);2961	if (DO_BIC(BIC_Pkgpc7))2962		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7 / tsc);2963	if (DO_BIC(BIC_Pkgpc8))2964		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8 / tsc);2965	if (DO_BIC(BIC_Pkgpc9))2966		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9 / tsc);2967	if (DO_BIC(BIC_Pkgpc10))2968		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10 / tsc);2969 2970	if (DO_BIC(BIC_Diec6))2971		outp +=2972		    sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->die_c6 / crystal_hz / interval_float);2973 2974	if (DO_BIC(BIC_CPU_LPI)) {2975		if (p->cpu_lpi >= 0)2976			outp +=2977			    sprintf(outp, "%s%.2f", (printed++ ? delim : ""),2978				    100.0 * p->cpu_lpi / 1000000.0 / interval_float);2979		else2980			outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));2981	}2982	if (DO_BIC(BIC_SYS_LPI)) {2983		if (p->sys_lpi >= 0)2984			outp +=2985			    sprintf(outp, "%s%.2f", (printed++ ? delim : ""),2986				    100.0 * p->sys_lpi / 1000000.0 / interval_float);2987		else2988			outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));2989	}2990 2991	if (DO_BIC(BIC_PkgWatt))2992		outp +=2993		    sprintf(outp, fmt8, (printed++ ? delim : ""),2994			    rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_WATTS, interval_float));2995	if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)2996		outp +=2997		    sprintf(outp, fmt8, (printed++ ? delim : ""),2998			    rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_WATTS, interval_float));2999	if (DO_BIC(BIC_GFXWatt))3000		outp +=3001		    sprintf(outp, fmt8, (printed++ ? delim : ""),3002			    rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_WATTS, interval_float));3003	if (DO_BIC(BIC_RAMWatt))3004		outp +=3005		    sprintf(outp, fmt8, (printed++ ? delim : ""),3006			    rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_WATTS, interval_float));3007	if (DO_BIC(BIC_Pkg_J))3008		outp += sprintf(outp, fmt8, (printed++ ? delim : ""),3009				rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_JOULES, interval_float));3010	if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)3011		outp += sprintf(outp, fmt8, (printed++ ? delim : ""),3012				rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_JOULES, interval_float));3013	if (DO_BIC(BIC_GFX_J))3014		outp += sprintf(outp, fmt8, (printed++ ? delim : ""),3015				rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_JOULES, interval_float));3016	if (DO_BIC(BIC_RAM_J))3017		outp += sprintf(outp, fmt8, (printed++ ? delim : ""),3018				rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_JOULES, interval_float));3019	if (DO_BIC(BIC_PKG__))3020		outp +=3021		    sprintf(outp, fmt8, (printed++ ? delim : ""),3022			    rapl_counter_get_value(&p->rapl_pkg_perf_status, RAPL_UNIT_WATTS, interval_float));3023	if (DO_BIC(BIC_RAM__))3024		outp +=3025		    sprintf(outp, fmt8, (printed++ ? delim : ""),3026			    rapl_counter_get_value(&p->rapl_dram_perf_status, RAPL_UNIT_WATTS, interval_float));3027	/* UncMHz */3028	if (DO_BIC(BIC_UNCORE_MHZ))3029		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->uncore_mhz);3030 3031	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3032		if (mp->format == FORMAT_RAW) {3033			if (mp->width == 32)3034				outp +=3035				    sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)p->counter[i]);3036			else3037				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);3038		} else if (mp->format == FORMAT_DELTA) {3039			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)3040				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->counter[i]);3041			else3042				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);3043		} else if (mp->format == FORMAT_PERCENT) {3044			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i] / tsc);3045		} else if (mp->type == COUNTER_K2M)3046			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->counter[i] / 1000);3047	}3048 3049	for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {3050		if (pp->format == FORMAT_RAW) {3051			if (pp->width == 32)3052				outp +=3053				    sprintf(outp, "%s0x%08x", (printed++ ? delim : ""),3054					    (unsigned int)p->perf_counter[i]);3055			else3056				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->perf_counter[i]);3057		} else if (pp->format == FORMAT_DELTA) {3058			if ((pp->type == COUNTER_ITEMS) && sums_need_wide_columns)3059				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->perf_counter[i]);3060			else3061				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->perf_counter[i]);3062		} else if (pp->format == FORMAT_PERCENT) {3063			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->perf_counter[i] / tsc);3064		} else if (pp->type == COUNTER_K2M) {3065			outp +=3066			    sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->perf_counter[i] / 1000);3067		}3068	}3069 3070	for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {3071		switch (ppmt->type) {3072		case PMT_TYPE_RAW:3073			if (pmt_counter_get_width(ppmt) <= 32)3074				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""),3075						(unsigned int)p->pmt_counter[i]);3076			else3077				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->pmt_counter[i]);3078 3079			break;3080 3081		case PMT_TYPE_XTAL_TIME:3082			const unsigned long value_raw = p->pmt_counter[i];3083			const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;3084 3085			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);3086			break;3087		}3088	}3089 3090done:3091	if (*(outp - 1) != '\n')3092		outp += sprintf(outp, "\n");3093 3094	return 0;3095}3096 3097void flush_output_stdout(void)3098{3099	FILE *filep;3100 3101	if (outf == stderr)3102		filep = stdout;3103	else3104		filep = outf;3105 3106	fputs(output_buffer, filep);3107	fflush(filep);3108 3109	outp = output_buffer;3110}3111 3112void flush_output_stderr(void)3113{3114	fputs(output_buffer, outf);3115	fflush(outf);3116	outp = output_buffer;3117}3118 3119void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)3120{3121	static int count;3122 3123	if ((!count || (header_iterations && !(count % header_iterations))) || !summary_only)3124		print_header("\t");3125 3126	format_counters(&average.threads, &average.cores, &average.packages);3127 3128	count++;3129 3130	if (summary_only)3131		return;3132 3133	for_all_cpus(format_counters, t, c, p);3134}3135 3136#define DELTA_WRAP32(new, old)			\3137	old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);3138 3139int delta_package(struct pkg_data *new, struct pkg_data *old)3140{3141	int i;3142	struct msr_counter *mp;3143	struct perf_counter_info *pp;3144	struct pmt_counter *ppmt;3145 3146	if (DO_BIC(BIC_Totl_c0))3147		old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;3148	if (DO_BIC(BIC_Any_c0))3149		old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;3150	if (DO_BIC(BIC_GFX_c0))3151		old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;3152	if (DO_BIC(BIC_CPUGFX))3153		old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;3154 3155	old->pc2 = new->pc2 - old->pc2;3156	if (DO_BIC(BIC_Pkgpc3))3157		old->pc3 = new->pc3 - old->pc3;3158	if (DO_BIC(BIC_Pkgpc6))3159		old->pc6 = new->pc6 - old->pc6;3160	if (DO_BIC(BIC_Pkgpc7))3161		old->pc7 = new->pc7 - old->pc7;3162	old->pc8 = new->pc8 - old->pc8;3163	old->pc9 = new->pc9 - old->pc9;3164	old->pc10 = new->pc10 - old->pc10;3165	old->die_c6 = new->die_c6 - old->die_c6;3166	old->cpu_lpi = new->cpu_lpi - old->cpu_lpi;3167	old->sys_lpi = new->sys_lpi - old->sys_lpi;3168	old->pkg_temp_c = new->pkg_temp_c;3169 3170	/* flag an error when rc6 counter resets/wraps */3171	if (old->gfx_rc6_ms > new->gfx_rc6_ms)3172		old->gfx_rc6_ms = -1;3173	else3174		old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;3175 3176	old->uncore_mhz = new->uncore_mhz;3177	old->gfx_mhz = new->gfx_mhz;3178	old->gfx_act_mhz = new->gfx_act_mhz;3179 3180	/* flag an error when mc6 counter resets/wraps */3181	if (old->sam_mc6_ms > new->sam_mc6_ms)3182		old->sam_mc6_ms = -1;3183	else3184		old->sam_mc6_ms = new->sam_mc6_ms - old->sam_mc6_ms;3185 3186	old->sam_mhz = new->sam_mhz;3187	old->sam_act_mhz = new->sam_act_mhz;3188 3189	old->energy_pkg.raw_value = new->energy_pkg.raw_value - old->energy_pkg.raw_value;3190	old->energy_cores.raw_value = new->energy_cores.raw_value - old->energy_cores.raw_value;3191	old->energy_gfx.raw_value = new->energy_gfx.raw_value - old->energy_gfx.raw_value;3192	old->energy_dram.raw_value = new->energy_dram.raw_value - old->energy_dram.raw_value;3193	old->rapl_pkg_perf_status.raw_value = new->rapl_pkg_perf_status.raw_value - old->rapl_pkg_perf_status.raw_value;3194	old->rapl_dram_perf_status.raw_value =3195	    new->rapl_dram_perf_status.raw_value - old->rapl_dram_perf_status.raw_value;3196 3197	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3198		if (mp->format == FORMAT_RAW)3199			old->counter[i] = new->counter[i];3200		else if (mp->format == FORMAT_AVERAGE)3201			old->counter[i] = new->counter[i];3202		else3203			old->counter[i] = new->counter[i] - old->counter[i];3204	}3205 3206	for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {3207		if (pp->format == FORMAT_RAW)3208			old->perf_counter[i] = new->perf_counter[i];3209		else if (pp->format == FORMAT_AVERAGE)3210			old->perf_counter[i] = new->perf_counter[i];3211		else3212			old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i];3213	}3214 3215	for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {3216		if (ppmt->format == FORMAT_RAW)3217			old->pmt_counter[i] = new->pmt_counter[i];3218		else3219			old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i];3220	}3221 3222	return 0;3223}3224 3225void delta_core(struct core_data *new, struct core_data *old)3226{3227	int i;3228	struct msr_counter *mp;3229	struct perf_counter_info *pp;3230	struct pmt_counter *ppmt;3231 3232	old->c3 = new->c3 - old->c3;3233	old->c6 = new->c6 - old->c6;3234	old->c7 = new->c7 - old->c7;3235	old->core_temp_c = new->core_temp_c;3236	old->core_throt_cnt = new->core_throt_cnt;3237	old->mc6_us = new->mc6_us - old->mc6_us;3238 3239	DELTA_WRAP32(new->core_energy.raw_value, old->core_energy.raw_value);3240 3241	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {3242		if (mp->format == FORMAT_RAW)3243			old->counter[i] = new->counter[i];3244		else3245			old->counter[i] = new->counter[i] - old->counter[i];3246	}3247 3248	for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {3249		if (pp->format == FORMAT_RAW)3250			old->perf_counter[i] = new->perf_counter[i];3251		else3252			old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i];3253	}3254 3255	for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {3256		if (ppmt->format == FORMAT_RAW)3257			old->pmt_counter[i] = new->pmt_counter[i];3258		else3259			old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i];3260	}3261}3262 3263int soft_c1_residency_display(int bic)3264{3265	if (!DO_BIC(BIC_CPU_c1) || platform->has_msr_core_c1_res)3266		return 0;3267 3268	return DO_BIC_READ(bic);3269}3270 3271/*3272 * old = new - old3273 */3274int delta_thread(struct thread_data *new, struct thread_data *old, struct core_data *core_delta)3275{3276	int i;3277	struct msr_counter *mp;3278	struct perf_counter_info *pp;3279	struct pmt_counter *ppmt;3280 3281	/* we run cpuid just the 1st time, copy the results */3282	if (DO_BIC(BIC_APIC))3283		new->apic_id = old->apic_id;3284	if (DO_BIC(BIC_X2APIC))3285		new->x2apic_id = old->x2apic_id;3286 3287	/*3288	 * the timestamps from start of measurement interval are in "old"3289	 * the timestamp from end of measurement interval are in "new"3290	 * over-write old w/ new so we can print end of interval values3291	 */3292 3293	timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);3294	old->tv_begin = new->tv_begin;3295	old->tv_end = new->tv_end;3296 3297	old->tsc = new->tsc - old->tsc;3298 3299	/* check for TSC < 1 Mcycles over interval */3300	if (old->tsc < (1000 * 1000))3301		errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n"3302		     "You can disable all c-states by booting with \"idle=poll\"\n"3303		     "or just the deep ones with \"processor.max_cstate=1\"");3304 3305	old->c1 = new->c1 - old->c1;3306 3307	if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || DO_BIC(BIC_IPC)3308	    || soft_c1_residency_display(BIC_Avg_MHz)) {3309		if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {3310			old->aperf = new->aperf - old->aperf;3311			old->mperf = new->mperf - old->mperf;3312		} else {3313			return -1;3314		}3315	}3316 3317	if (platform->has_msr_core_c1_res) {3318		/*3319		 * Some models have a dedicated C1 residency MSR,3320		 * which should be more accurate than the derivation below.3321		 */3322	} else {3323		/*3324		 * As counter collection is not atomic,3325		 * it is possible for mperf's non-halted cycles + idle states3326		 * to exceed TSC's all cycles: show c1 = 0% in that case.3327		 */3328		if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > (old->tsc * tsc_tweak))3329			old->c1 = 0;3330		else {3331			/* normal case, derive c1 */3332			old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c33333			    - core_delta->c6 - core_delta->c7;3334		}3335	}3336 3337	if (old->mperf == 0) {3338		if (debug > 1)3339			fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);3340		old->mperf = 1;	/* divide by 0 protection */3341	}3342 3343	if (DO_BIC(BIC_IPC))3344		old->instr_count = new->instr_count - old->instr_count;3345 3346	if (DO_BIC(BIC_IRQ))3347		old->irq_count = new->irq_count - old->irq_count;3348 3349	if (DO_BIC(BIC_SMI))3350		old->smi_count = new->smi_count - old->smi_count;3351 3352	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {3353		if (mp->format == FORMAT_RAW)3354			old->counter[i] = new->counter[i];3355		else3356			old->counter[i] = new->counter[i] - old->counter[i];3357	}3358 3359	for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) {3360		if (pp->format == FORMAT_RAW)3361			old->perf_counter[i] = new->perf_counter[i];3362		else3363			old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i];3364	}3365 3366	for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {3367		if (ppmt->format == FORMAT_RAW)3368			old->pmt_counter[i] = new->pmt_counter[i];3369		else3370			old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i];3371	}3372 3373	return 0;3374}3375 3376int delta_cpu(struct thread_data *t, struct core_data *c,3377	      struct pkg_data *p, struct thread_data *t2, struct core_data *c2, struct pkg_data *p2)3378{3379	int retval = 0;3380 3381	/* calculate core delta only for 1st thread in core */3382	if (is_cpu_first_thread_in_core(t, c, p))3383		delta_core(c, c2);3384 3385	/* always calculate thread delta */3386	retval = delta_thread(t, t2, c2);	/* c2 is core delta */3387	if (retval)3388		return retval;3389 3390	/* calculate package delta only for 1st core in package */3391	if (is_cpu_first_core_in_package(t, c, p))3392		retval = delta_package(p, p2);3393 3394	return retval;3395}3396 3397void rapl_counter_clear(struct rapl_counter *c)3398{3399	c->raw_value = 0;3400	c->scale = 0.0;3401	c->unit = RAPL_UNIT_INVALID;3402}3403 3404void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)3405{3406	int i;3407	struct msr_counter *mp;3408 3409	t->tv_begin.tv_sec = 0;3410	t->tv_begin.tv_usec = 0;3411	t->tv_end.tv_sec = 0;3412	t->tv_end.tv_usec = 0;3413	t->tv_delta.tv_sec = 0;3414	t->tv_delta.tv_usec = 0;3415 3416	t->tsc = 0;3417	t->aperf = 0;3418	t->mperf = 0;3419	t->c1 = 0;3420 3421	t->instr_count = 0;3422 3423	t->irq_count = 0;3424	t->smi_count = 0;3425 3426	c->c3 = 0;3427	c->c6 = 0;3428	c->c7 = 0;3429	c->mc6_us = 0;3430	c->core_temp_c = 0;3431	rapl_counter_clear(&c->core_energy);3432	c->core_throt_cnt = 0;3433 3434	p->pkg_wtd_core_c0 = 0;3435	p->pkg_any_core_c0 = 0;3436	p->pkg_any_gfxe_c0 = 0;3437	p->pkg_both_core_gfxe_c0 = 0;3438 3439	p->pc2 = 0;3440	if (DO_BIC(BIC_Pkgpc3))3441		p->pc3 = 0;3442	if (DO_BIC(BIC_Pkgpc6))3443		p->pc6 = 0;3444	if (DO_BIC(BIC_Pkgpc7))3445		p->pc7 = 0;3446	p->pc8 = 0;3447	p->pc9 = 0;3448	p->pc10 = 0;3449	p->die_c6 = 0;3450	p->cpu_lpi = 0;3451	p->sys_lpi = 0;3452 3453	rapl_counter_clear(&p->energy_pkg);3454	rapl_counter_clear(&p->energy_dram);3455	rapl_counter_clear(&p->energy_cores);3456	rapl_counter_clear(&p->energy_gfx);3457	rapl_counter_clear(&p->rapl_pkg_perf_status);3458	rapl_counter_clear(&p->rapl_dram_perf_status);3459	p->pkg_temp_c = 0;3460 3461	p->gfx_rc6_ms = 0;3462	p->uncore_mhz = 0;3463	p->gfx_mhz = 0;3464	p->gfx_act_mhz = 0;3465	p->sam_mc6_ms = 0;3466	p->sam_mhz = 0;3467	p->sam_act_mhz = 0;3468	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)3469		t->counter[i] = 0;3470 3471	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next)3472		c->counter[i] = 0;3473 3474	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next)3475		p->counter[i] = 0;3476 3477	memset(&t->perf_counter[0], 0, sizeof(t->perf_counter));3478	memset(&c->perf_counter[0], 0, sizeof(c->perf_counter));3479	memset(&p->perf_counter[0], 0, sizeof(p->perf_counter));3480 3481	memset(&t->pmt_counter[0], 0, ARRAY_SIZE(t->pmt_counter));3482	memset(&c->pmt_counter[0], 0, ARRAY_SIZE(c->pmt_counter));3483	memset(&p->pmt_counter[0], 0, ARRAY_SIZE(p->pmt_counter));3484}3485 3486void rapl_counter_accumulate(struct rapl_counter *dst, const struct rapl_counter *src)3487{3488	/* Copy unit and scale from src if dst is not initialized */3489	if (dst->unit == RAPL_UNIT_INVALID) {3490		dst->unit = src->unit;3491		dst->scale = src->scale;3492	}3493 3494	assert(dst->unit == src->unit);3495	assert(dst->scale == src->scale);3496 3497	dst->raw_value += src->raw_value;3498}3499 3500int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)3501{3502	int i;3503	struct msr_counter *mp;3504	struct perf_counter_info *pp;3505	struct pmt_counter *ppmt;3506 3507	/* copy un-changing apic_id's */3508	if (DO_BIC(BIC_APIC))3509		average.threads.apic_id = t->apic_id;3510	if (DO_BIC(BIC_X2APIC))3511		average.threads.x2apic_id = t->x2apic_id;3512 3513	/* remember first tv_begin */3514	if (average.threads.tv_begin.tv_sec == 0)3515		average.threads.tv_begin = t->tv_begin;3516 3517	/* remember last tv_end */3518	average.threads.tv_end = t->tv_end;3519 3520	average.threads.tsc += t->tsc;3521	average.threads.aperf += t->aperf;3522	average.threads.mperf += t->mperf;3523	average.threads.c1 += t->c1;3524 3525	average.threads.instr_count += t->instr_count;3526 3527	average.threads.irq_count += t->irq_count;3528	average.threads.smi_count += t->smi_count;3529 3530	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {3531		if (mp->format == FORMAT_RAW)3532			continue;3533		average.threads.counter[i] += t->counter[i];3534	}3535 3536	for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) {3537		if (pp->format == FORMAT_RAW)3538			continue;3539		average.threads.perf_counter[i] += t->perf_counter[i];3540	}3541 3542	for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {3543		average.threads.pmt_counter[i] += t->pmt_counter[i];3544	}3545 3546	/* sum per-core values only for 1st thread in core */3547	if (!is_cpu_first_thread_in_core(t, c, p))3548		return 0;3549 3550	average.cores.c3 += c->c3;3551	average.cores.c6 += c->c6;3552	average.cores.c7 += c->c7;3553	average.cores.mc6_us += c->mc6_us;3554 3555	average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);3556	average.cores.core_throt_cnt = MAX(average.cores.core_throt_cnt, c->core_throt_cnt);3557 3558	rapl_counter_accumulate(&average.cores.core_energy, &c->core_energy);3559 3560	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {3561		if (mp->format == FORMAT_RAW)3562			continue;3563		average.cores.counter[i] += c->counter[i];3564	}3565 3566	for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {3567		if (pp->format == FORMAT_RAW)3568			continue;3569		average.cores.perf_counter[i] += c->perf_counter[i];3570	}3571 3572	for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {3573		average.cores.pmt_counter[i] += c->pmt_counter[i];3574	}3575 3576	/* sum per-pkg values only for 1st core in pkg */3577	if (!is_cpu_first_core_in_package(t, c, p))3578		return 0;3579 3580	if (DO_BIC(BIC_Totl_c0))3581		average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0;3582	if (DO_BIC(BIC_Any_c0))3583		average.packages.pkg_any_core_c0 += p->pkg_any_core_c0;3584	if (DO_BIC(BIC_GFX_c0))3585		average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;3586	if (DO_BIC(BIC_CPUGFX))3587		average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;3588 3589	average.packages.pc2 += p->pc2;3590	if (DO_BIC(BIC_Pkgpc3))3591		average.packages.pc3 += p->pc3;3592	if (DO_BIC(BIC_Pkgpc6))3593		average.packages.pc6 += p->pc6;3594	if (DO_BIC(BIC_Pkgpc7))3595		average.packages.pc7 += p->pc7;3596	average.packages.pc8 += p->pc8;3597	average.packages.pc9 += p->pc9;3598	average.packages.pc10 += p->pc10;3599	average.packages.die_c6 += p->die_c6;3600 3601	average.packages.cpu_lpi = p->cpu_lpi;3602	average.packages.sys_lpi = p->sys_lpi;3603 3604	rapl_counter_accumulate(&average.packages.energy_pkg, &p->energy_pkg);3605	rapl_counter_accumulate(&average.packages.energy_dram, &p->energy_dram);3606	rapl_counter_accumulate(&average.packages.energy_cores, &p->energy_cores);3607	rapl_counter_accumulate(&average.packages.energy_gfx, &p->energy_gfx);3608 3609	average.packages.gfx_rc6_ms = p->gfx_rc6_ms;3610	average.packages.uncore_mhz = p->uncore_mhz;3611	average.packages.gfx_mhz = p->gfx_mhz;3612	average.packages.gfx_act_mhz = p->gfx_act_mhz;3613	average.packages.sam_mc6_ms = p->sam_mc6_ms;3614	average.packages.sam_mhz = p->sam_mhz;3615	average.packages.sam_act_mhz = p->sam_act_mhz;3616 3617	average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);3618 3619	rapl_counter_accumulate(&average.packages.rapl_pkg_perf_status, &p->rapl_pkg_perf_status);3620	rapl_counter_accumulate(&average.packages.rapl_dram_perf_status, &p->rapl_dram_perf_status);3621 3622	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3623		if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0))3624			average.packages.counter[i] = p->counter[i];3625		else3626			average.packages.counter[i] += p->counter[i];3627	}3628 3629	for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {3630		if ((pp->format == FORMAT_RAW) && (topo.num_packages == 0))3631			average.packages.perf_counter[i] = p->perf_counter[i];3632		else3633			average.packages.perf_counter[i] += p->perf_counter[i];3634	}3635 3636	for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {3637		average.packages.pmt_counter[i] += p->pmt_counter[i];3638	}3639 3640	return 0;3641}3642 3643/*3644 * sum the counters for all cpus in the system3645 * compute the weighted average3646 */3647void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data *p)3648{3649	int i;3650	struct msr_counter *mp;3651	struct perf_counter_info *pp;3652	struct pmt_counter *ppmt;3653 3654	clear_counters(&average.threads, &average.cores, &average.packages);3655 3656	for_all_cpus(sum_counters, t, c, p);3657 3658	/* Use the global time delta for the average. */3659	average.threads.tv_delta = tv_delta;3660 3661	average.threads.tsc /= topo.allowed_cpus;3662	average.threads.aperf /= topo.allowed_cpus;3663	average.threads.mperf /= topo.allowed_cpus;3664	average.threads.instr_count /= topo.allowed_cpus;3665	average.threads.c1 /= topo.allowed_cpus;3666 3667	if (average.threads.irq_count > 9999999)3668		sums_need_wide_columns = 1;3669 3670	average.cores.c3 /= topo.allowed_cores;3671	average.cores.c6 /= topo.allowed_cores;3672	average.cores.c7 /= topo.allowed_cores;3673	average.cores.mc6_us /= topo.allowed_cores;3674 3675	if (DO_BIC(BIC_Totl_c0))3676		average.packages.pkg_wtd_core_c0 /= topo.allowed_packages;3677	if (DO_BIC(BIC_Any_c0))3678		average.packages.pkg_any_core_c0 /= topo.allowed_packages;3679	if (DO_BIC(BIC_GFX_c0))3680		average.packages.pkg_any_gfxe_c0 /= topo.allowed_packages;3681	if (DO_BIC(BIC_CPUGFX))3682		average.packages.pkg_both_core_gfxe_c0 /= topo.allowed_packages;3683 3684	average.packages.pc2 /= topo.allowed_packages;3685	if (DO_BIC(BIC_Pkgpc3))3686		average.packages.pc3 /= topo.allowed_packages;3687	if (DO_BIC(BIC_Pkgpc6))3688		average.packages.pc6 /= topo.allowed_packages;3689	if (DO_BIC(BIC_Pkgpc7))3690		average.packages.pc7 /= topo.allowed_packages;3691 3692	average.packages.pc8 /= topo.allowed_packages;3693	average.packages.pc9 /= topo.allowed_packages;3694	average.packages.pc10 /= topo.allowed_packages;3695	average.packages.die_c6 /= topo.allowed_packages;3696 3697	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {3698		if (mp->format == FORMAT_RAW)3699			continue;3700		if (mp->type == COUNTER_ITEMS) {3701			if (average.threads.counter[i] > 9999999)3702				sums_need_wide_columns = 1;3703			continue;3704		}3705		average.threads.counter[i] /= topo.allowed_cpus;3706	}3707	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {3708		if (mp->format == FORMAT_RAW)3709			continue;3710		if (mp->type == COUNTER_ITEMS) {3711			if (average.cores.counter[i] > 9999999)3712				sums_need_wide_columns = 1;3713		}3714		average.cores.counter[i] /= topo.allowed_cores;3715	}3716	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3717		if (mp->format == FORMAT_RAW)3718			continue;3719		if (mp->type == COUNTER_ITEMS) {3720			if (average.packages.counter[i] > 9999999)3721				sums_need_wide_columns = 1;3722		}3723		average.packages.counter[i] /= topo.allowed_packages;3724	}3725 3726	for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) {3727		if (pp->format == FORMAT_RAW)3728			continue;3729		if (pp->type == COUNTER_ITEMS) {3730			if (average.threads.perf_counter[i] > 9999999)3731				sums_need_wide_columns = 1;3732			continue;3733		}3734		average.threads.perf_counter[i] /= topo.allowed_cpus;3735	}3736	for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {3737		if (pp->format == FORMAT_RAW)3738			continue;3739		if (pp->type == COUNTER_ITEMS) {3740			if (average.cores.perf_counter[i] > 9999999)3741				sums_need_wide_columns = 1;3742		}3743		average.cores.perf_counter[i] /= topo.allowed_cores;3744	}3745	for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {3746		if (pp->format == FORMAT_RAW)3747			continue;3748		if (pp->type == COUNTER_ITEMS) {3749			if (average.packages.perf_counter[i] > 9999999)3750				sums_need_wide_columns = 1;3751		}3752		average.packages.perf_counter[i] /= topo.allowed_packages;3753	}3754 3755	for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {3756		average.threads.pmt_counter[i] /= topo.allowed_cpus;3757	}3758	for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {3759		average.cores.pmt_counter[i] /= topo.allowed_cores;3760	}3761	for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {3762		average.packages.pmt_counter[i] /= topo.allowed_packages;3763	}3764}3765 3766static unsigned long long rdtsc(void)3767{3768	unsigned int low, high;3769 3770	asm volatile ("rdtsc":"=a" (low), "=d"(high));3771 3772	return low | ((unsigned long long)high) << 32;3773}3774 3775/*3776 * Open a file, and exit on failure3777 */3778FILE *fopen_or_die(const char *path, const char *mode)3779{3780	FILE *filep = fopen(path, mode);3781 3782	if (!filep)3783		err(1, "%s: open failed", path);3784	return filep;3785}3786 3787/*3788 * snapshot_sysfs_counter()3789 *3790 * return snapshot of given counter3791 */3792unsigned long long snapshot_sysfs_counter(char *path)3793{3794	FILE *fp;3795	int retval;3796	unsigned long long counter;3797 3798	fp = fopen_or_die(path, "r");3799 3800	retval = fscanf(fp, "%lld", &counter);3801	if (retval != 1)3802		err(1, "snapshot_sysfs_counter(%s)", path);3803 3804	fclose(fp);3805 3806	return counter;3807}3808 3809int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp, char *counter_path)3810{3811	if (mp->msr_num != 0) {3812		assert(!no_msr);3813		if (get_msr(cpu, mp->msr_num, counterp))3814			return -1;3815	} else {3816		char path[128 + PATH_BYTES];3817 3818		if (mp->flags & SYSFS_PERCPU) {3819			sprintf(path, "/sys/devices/system/cpu/cpu%d/%s", cpu, mp->sp->path);3820 3821			*counterp = snapshot_sysfs_counter(path);3822		} else {3823			*counterp = snapshot_sysfs_counter(counter_path);3824		}3825	}3826 3827	return 0;3828}3829 3830unsigned long long get_legacy_uncore_mhz(int package)3831{3832	char path[128];3833	int die;3834	static int warn_once;3835 3836	/*3837	 * for this package, use the first die_id that exists3838	 */3839	for (die = 0; die <= topo.max_die_id; ++die) {3840 3841		sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/current_freq_khz",3842			package, die);3843 3844		if (access(path, R_OK) == 0)3845			return (snapshot_sysfs_counter(path) / 1000);3846	}3847	if (!warn_once) {3848		warnx("BUG: %s: No %s", __func__, path);3849		warn_once = 1;3850	}3851 3852	return 0;3853}3854 3855int get_epb(int cpu)3856{3857	char path[128 + PATH_BYTES];3858	unsigned long long msr;3859	int ret, epb = -1;3860	FILE *fp;3861 3862	sprintf(path, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", cpu);3863 3864	fp = fopen(path, "r");3865	if (!fp)3866		goto msr_fallback;3867 3868	ret = fscanf(fp, "%d", &epb);3869	if (ret != 1)3870		err(1, "%s(%s)", __func__, path);3871 3872	fclose(fp);3873 3874	return epb;3875 3876msr_fallback:3877	if (no_msr)3878		return -1;3879 3880	get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);3881 3882	return msr & 0xf;3883}3884 3885void get_apic_id(struct thread_data *t)3886{3887	unsigned int eax, ebx, ecx, edx;3888 3889	if (DO_BIC(BIC_APIC)) {3890		eax = ebx = ecx = edx = 0;3891		__cpuid(1, eax, ebx, ecx, edx);3892 3893		t->apic_id = (ebx >> 24) & 0xff;3894	}3895 3896	if (!DO_BIC(BIC_X2APIC))3897		return;3898 3899	if (authentic_amd || hygon_genuine) {3900		unsigned int topology_extensions;3901 3902		if (max_extended_level < 0x8000001e)3903			return;3904 3905		eax = ebx = ecx = edx = 0;3906		__cpuid(0x80000001, eax, ebx, ecx, edx);3907		topology_extensions = ecx & (1 << 22);3908 3909		if (topology_extensions == 0)3910			return;3911 3912		eax = ebx = ecx = edx = 0;3913		__cpuid(0x8000001e, eax, ebx, ecx, edx);3914 3915		t->x2apic_id = eax;3916		return;3917	}3918 3919	if (!genuine_intel)3920		return;3921 3922	if (max_level < 0xb)3923		return;3924 3925	ecx = 0;3926	__cpuid(0xb, eax, ebx, ecx, edx);3927	t->x2apic_id = edx;3928 3929	if (debug && (t->apic_id != (t->x2apic_id & 0xff)))3930		fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id);3931}3932 3933int get_core_throt_cnt(int cpu, unsigned long long *cnt)3934{3935	char path[128 + PATH_BYTES];3936	unsigned long long tmp;3937	FILE *fp;3938	int ret;3939 3940	sprintf(path, "/sys/devices/system/cpu/cpu%d/thermal_throttle/core_throttle_count", cpu);3941	fp = fopen(path, "r");3942	if (!fp)3943		return -1;3944	ret = fscanf(fp, "%lld", &tmp);3945	fclose(fp);3946	if (ret != 1)3947		return -1;3948	*cnt = tmp;3949 3950	return 0;3951}3952 3953struct amperf_group_fd {3954	int aperf;		/* Also the group descriptor */3955	int mperf;3956};3957 3958static int read_perf_counter_info(const char *const path, const char *const parse_format, void *value_ptr)3959{3960	int fdmt;3961	int bytes_read;3962	char buf[64];3963	int ret = -1;3964 3965	fdmt = open(path, O_RDONLY, 0);3966	if (fdmt == -1) {3967		if (debug)3968			fprintf(stderr, "Failed to parse perf counter info %s\n", path);3969		ret = -1;3970		goto cleanup_and_exit;3971	}3972 3973	bytes_read = read(fdmt, buf, sizeof(buf) - 1);3974	if (bytes_read <= 0 || bytes_read >= (int)sizeof(buf)) {3975		if (debug)3976			fprintf(stderr, "Failed to parse perf counter info %s\n", path);3977		ret = -1;3978		goto cleanup_and_exit;3979	}3980 3981	buf[bytes_read] = '\0';3982 3983	if (sscanf(buf, parse_format, value_ptr) != 1) {3984		if (debug)3985			fprintf(stderr, "Failed to parse perf counter info %s\n", path);3986		ret = -1;3987		goto cleanup_and_exit;3988	}3989 3990	ret = 0;3991 3992cleanup_and_exit:3993	close(fdmt);3994	return ret;3995}3996 3997static unsigned int read_perf_counter_info_n(const char *const path, const char *const parse_format)3998{3999	unsigned int v;4000	int status;4001 4002	status = read_perf_counter_info(path, parse_format, &v);4003	if (status)4004		v = -1;4005 4006	return v;4007}4008 4009static unsigned int read_perf_type(const char *subsys)4010{4011	const char *const path_format = "/sys/bus/event_source/devices/%s/type";4012	const char *const format = "%u";4013	char path[128];4014 4015	snprintf(path, sizeof(path), path_format, subsys);4016 4017	return read_perf_counter_info_n(path, format);4018}4019 4020static unsigned int read_perf_config(const char *subsys, const char *event_name)4021{4022	const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s";4023	FILE *fconfig = NULL;4024	char path[128];4025	char config_str[64];4026	unsigned int config;4027	unsigned int umask;4028	bool has_config = false;4029	bool has_umask = false;4030	unsigned int ret = -1;4031 4032	snprintf(path, sizeof(path), path_format, subsys, event_name);4033 4034	fconfig = fopen(path, "r");4035	if (!fconfig)4036		return -1;4037 4038	if (fgets(config_str, ARRAY_SIZE(config_str), fconfig) != config_str)4039		goto cleanup_and_exit;4040 4041	for (char *pconfig_str = &config_str[0]; pconfig_str;) {4042		if (sscanf(pconfig_str, "event=%x", &config) == 1) {4043			has_config = true;4044			goto next;4045		}4046 4047		if (sscanf(pconfig_str, "umask=%x", &umask) == 1) {4048			has_umask = true;4049			goto next;4050		}4051 4052next:4053		pconfig_str = strchr(pconfig_str, ',');4054		if (pconfig_str) {4055			*pconfig_str = '\0';4056			++pconfig_str;4057		}4058	}4059 4060	if (!has_umask)4061		umask = 0;4062 4063	if (has_config)4064		ret = (umask << 8) | config;4065 4066cleanup_and_exit:4067	fclose(fconfig);4068	return ret;4069}4070 4071static unsigned int read_perf_rapl_unit(const char *subsys, const char *event_name)4072{4073	const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.unit";4074	const char *const format = "%s";4075	char path[128];4076	char unit_buffer[16];4077 4078	snprintf(path, sizeof(path), path_format, subsys, event_name);4079 4080	read_perf_counter_info(path, format, &unit_buffer);4081	if (strcmp("Joules", unit_buffer) == 0)4082		return RAPL_UNIT_JOULES;4083 4084	return RAPL_UNIT_INVALID;4085}4086 4087static double read_perf_scale(const char *subsys, const char *event_name)4088{4089	const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.scale";4090	const char *const format = "%lf";4091	char path[128];4092	double scale;4093 4094	snprintf(path, sizeof(path), path_format, subsys, event_name);4095 4096	if (read_perf_counter_info(path, format, &scale))4097		return 0.0;4098 4099	return scale;4100}4101 4102size_t rapl_counter_info_count_perf(const struct rapl_counter_info_t *rci)4103{4104	size_t ret = 0;4105 4106	for (int i = 0; i < NUM_RAPL_COUNTERS; ++i)4107		if (rci->source[i] == COUNTER_SOURCE_PERF)4108			++ret;4109 4110	return ret;4111}4112 4113static size_t cstate_counter_info_count_perf(const struct cstate_counter_info_t *cci)4114{4115	size_t ret = 0;4116 4117	for (int i = 0; i < NUM_CSTATE_COUNTERS; ++i)4118		if (cci->source[i] == COUNTER_SOURCE_PERF)4119			++ret;4120 4121	return ret;4122}4123 4124void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx)4125{4126	rc->raw_value = rci->data[idx];4127	rc->unit = rci->unit[idx];4128	rc->scale = rci->scale[idx];4129}4130 4131int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p)4132{4133	unsigned long long perf_data[NUM_RAPL_COUNTERS + 1];4134	struct rapl_counter_info_t *rci;4135 4136	if (debug >= 2)4137		fprintf(stderr, "%s: cpu%d domain%d\n", __func__, cpu, domain);4138 4139	assert(rapl_counter_info_perdomain);4140	assert(domain < rapl_counter_info_perdomain_size);4141 4142	rci = &rapl_counter_info_perdomain[domain];4143 4144	/*4145	 * If we have any perf counters to read, read them all now, in bulk4146	 */4147	if (rci->fd_perf != -1) {4148		size_t num_perf_counters = rapl_counter_info_count_perf(rci);4149		const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long);4150		const ssize_t actual_read_size = read(rci->fd_perf, &perf_data[0], sizeof(perf_data));4151 4152		if (actual_read_size != expected_read_size)4153			err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size,4154			    actual_read_size);4155	}4156 4157	for (unsigned int i = 0, pi = 1; i < NUM_RAPL_COUNTERS; ++i) {4158		switch (rci->source[i]) {4159		case COUNTER_SOURCE_NONE:4160			break;4161 4162		case COUNTER_SOURCE_PERF:4163			assert(pi < ARRAY_SIZE(perf_data));4164			assert(rci->fd_perf != -1);4165 4166			if (debug >= 2)4167				fprintf(stderr, "Reading rapl counter via perf at %u (%llu %e %lf)\n",4168					i, perf_data[pi], rci->scale[i], perf_data[pi] * rci->scale[i]);4169 4170			rci->data[i] = perf_data[pi];4171 4172			++pi;4173			break;4174 4175		case COUNTER_SOURCE_MSR:4176			if (debug >= 2)4177				fprintf(stderr, "Reading rapl counter via msr at %u\n", i);4178 4179			assert(!no_msr);4180			if (rci->flags[i] & RAPL_COUNTER_FLAG_USE_MSR_SUM) {4181				if (get_msr_sum(cpu, rci->msr[i], &rci->data[i]))4182					return -13 - i;4183			} else {4184				if (get_msr(cpu, rci->msr[i], &rci->data[i]))4185					return -13 - i;4186			}4187 4188			rci->data[i] &= rci->msr_mask[i];4189			if (rci->msr_shift[i] >= 0)4190				rci->data[i] >>= abs(rci->msr_shift[i]);4191			else4192				rci->data[i] <<= abs(rci->msr_shift[i]);4193 4194			break;4195		}4196	}4197 4198	BUILD_BUG_ON(NUM_RAPL_COUNTERS != 7);4199	write_rapl_counter(&p->energy_pkg, rci, RAPL_RCI_INDEX_ENERGY_PKG);4200	write_rapl_counter(&p->energy_cores, rci, RAPL_RCI_INDEX_ENERGY_CORES);4201	write_rapl_counter(&p->energy_dram, rci, RAPL_RCI_INDEX_DRAM);4202	write_rapl_counter(&p->energy_gfx, rci, RAPL_RCI_INDEX_GFX);4203	write_rapl_counter(&p->rapl_pkg_perf_status, rci, RAPL_RCI_INDEX_PKG_PERF_STATUS);4204	write_rapl_counter(&p->rapl_dram_perf_status, rci, RAPL_RCI_INDEX_DRAM_PERF_STATUS);4205	write_rapl_counter(&c->core_energy, rci, RAPL_RCI_INDEX_CORE_ENERGY);4206 4207	return 0;4208}4209 4210char *find_sysfs_path_by_id(struct sysfs_path *sp, int id)4211{4212	while (sp) {4213		if (sp->id == id)4214			return (sp->path);4215		sp = sp->next;4216	}4217	if (debug)4218		warnx("%s: id%d not found", __func__, id);4219	return NULL;4220}4221 4222int get_cstate_counters(unsigned int cpu, struct thread_data *t, struct core_data *c, struct pkg_data *p)4223{4224	/*4225	 * Overcommit memory a little bit here,4226	 * but skip calculating exact sizes for the buffers.4227	 */4228	unsigned long long perf_data[NUM_CSTATE_COUNTERS];4229	unsigned long long perf_data_core[NUM_CSTATE_COUNTERS + 1];4230	unsigned long long perf_data_pkg[NUM_CSTATE_COUNTERS + 1];4231 4232	struct cstate_counter_info_t *cci;4233 4234	if (debug >= 2)4235		fprintf(stderr, "%s: cpu%d\n", __func__, cpu);4236 4237	assert(ccstate_counter_info);4238	assert(cpu <= ccstate_counter_info_size);4239 4240	ZERO_ARRAY(perf_data);4241	ZERO_ARRAY(perf_data_core);4242	ZERO_ARRAY(perf_data_pkg);4243 4244	cci = &ccstate_counter_info[cpu];4245 4246	/*4247	 * If we have any perf counters to read, read them all now, in bulk4248	 */4249	const size_t num_perf_counters = cstate_counter_info_count_perf(cci);4250	ssize_t expected_read_size = num_perf_counters * sizeof(unsigned long long);4251	ssize_t actual_read_size_core = 0, actual_read_size_pkg = 0;4252 4253	if (cci->fd_perf_core != -1) {4254		/* Each descriptor read begins with number of counters read. */4255		expected_read_size += sizeof(unsigned long long);4256 4257		actual_read_size_core = read(cci->fd_perf_core, &perf_data_core[0], sizeof(perf_data_core));4258 4259		if (actual_read_size_core <= 0)4260			err(-1, "%s: read perf %s: %ld", __func__, "core", actual_read_size_core);4261	}4262 4263	if (cci->fd_perf_pkg != -1) {4264		/* Each descriptor read begins with number of counters read. */4265		expected_read_size += sizeof(unsigned long long);4266 4267		actual_read_size_pkg = read(cci->fd_perf_pkg, &perf_data_pkg[0], sizeof(perf_data_pkg));4268 4269		if (actual_read_size_pkg <= 0)4270			err(-1, "%s: read perf %s: %ld", __func__, "pkg", actual_read_size_pkg);4271	}4272 4273	const ssize_t actual_read_size_total = actual_read_size_core + actual_read_size_pkg;4274 4275	if (actual_read_size_total != expected_read_size)4276		err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size_total);4277 4278	/*4279	 * Copy ccstate and pcstate data into unified buffer.4280	 *4281	 * Skip first element from core and pkg buffers.4282	 * Kernel puts there how many counters were read.4283	 */4284	const size_t num_core_counters = perf_data_core[0];4285	const size_t num_pkg_counters = perf_data_pkg[0];4286 4287	assert(num_perf_counters == num_core_counters + num_pkg_counters);4288 4289	/* Copy ccstate perf data */4290	memcpy(&perf_data[0], &perf_data_core[1], num_core_counters * sizeof(unsigned long long));4291 4292	/* Copy pcstate perf data */4293	memcpy(&perf_data[num_core_counters], &perf_data_pkg[1], num_pkg_counters * sizeof(unsigned long long));4294 4295	for (unsigned int i = 0, pi = 0; i < NUM_CSTATE_COUNTERS; ++i) {4296		switch (cci->source[i]) {4297		case COUNTER_SOURCE_NONE:4298			break;4299 4300		case COUNTER_SOURCE_PERF:4301			assert(pi < ARRAY_SIZE(perf_data));4302			assert(cci->fd_perf_core != -1 || cci->fd_perf_pkg != -1);4303 4304			if (debug >= 2)4305				fprintf(stderr, "cstate via %s %u: %llu\n", "perf", i, perf_data[pi]);4306 4307			cci->data[i] = perf_data[pi];4308 4309			++pi;4310			break;4311 4312		case COUNTER_SOURCE_MSR:4313			assert(!no_msr);4314			if (get_msr(cpu, cci->msr[i], &cci->data[i]))4315				return -13 - i;4316 4317			if (debug >= 2)4318				fprintf(stderr, "cstate via %s0x%llx %u: %llu\n", "msr", cci->msr[i], i, cci->data[i]);4319 4320			break;4321		}4322	}4323 4324	/*4325	 * Helper to write the data only if the source of4326	 * the counter for the current cpu is not none.4327	 *4328	 * Otherwise we would overwrite core data with 0 (default value),4329	 * when invoked for the thread sibling.4330	 */4331#define PERF_COUNTER_WRITE_DATA(out_counter, index) do {	\4332	if (cci->source[index] != COUNTER_SOURCE_NONE)		\4333		out_counter = cci->data[index];			\4334} while (0)4335 4336	BUILD_BUG_ON(NUM_CSTATE_COUNTERS != 11);4337 4338	PERF_COUNTER_WRITE_DATA(t->c1, CCSTATE_RCI_INDEX_C1_RESIDENCY);4339	PERF_COUNTER_WRITE_DATA(c->c3, CCSTATE_RCI_INDEX_C3_RESIDENCY);4340	PERF_COUNTER_WRITE_DATA(c->c6, CCSTATE_RCI_INDEX_C6_RESIDENCY);4341	PERF_COUNTER_WRITE_DATA(c->c7, CCSTATE_RCI_INDEX_C7_RESIDENCY);4342 4343	PERF_COUNTER_WRITE_DATA(p->pc2, PCSTATE_RCI_INDEX_C2_RESIDENCY);4344	PERF_COUNTER_WRITE_DATA(p->pc3, PCSTATE_RCI_INDEX_C3_RESIDENCY);4345	PERF_COUNTER_WRITE_DATA(p->pc6, PCSTATE_RCI_INDEX_C6_RESIDENCY);4346	PERF_COUNTER_WRITE_DATA(p->pc7, PCSTATE_RCI_INDEX_C7_RESIDENCY);4347	PERF_COUNTER_WRITE_DATA(p->pc8, PCSTATE_RCI_INDEX_C8_RESIDENCY);4348	PERF_COUNTER_WRITE_DATA(p->pc9, PCSTATE_RCI_INDEX_C9_RESIDENCY);4349	PERF_COUNTER_WRITE_DATA(p->pc10, PCSTATE_RCI_INDEX_C10_RESIDENCY);4350 4351#undef PERF_COUNTER_WRITE_DATA4352 4353	return 0;4354}4355 4356size_t msr_counter_info_count_perf(const struct msr_counter_info_t *mci)4357{4358	size_t ret = 0;4359 4360	for (int i = 0; i < NUM_MSR_COUNTERS; ++i)4361		if (mci->source[i] == COUNTER_SOURCE_PERF)4362			++ret;4363 4364	return ret;4365}4366 4367int get_smi_aperf_mperf(unsigned int cpu, struct thread_data *t)4368{4369	unsigned long long perf_data[NUM_MSR_COUNTERS + 1];4370 4371	struct msr_counter_info_t *mci;4372 4373	if (debug >= 2)4374		fprintf(stderr, "%s: cpu%d\n", __func__, cpu);4375 4376	assert(msr_counter_info);4377	assert(cpu <= msr_counter_info_size);4378 4379	mci = &msr_counter_info[cpu];4380 4381	ZERO_ARRAY(perf_data);4382	ZERO_ARRAY(mci->data);4383 4384	if (mci->fd_perf != -1) {4385		const size_t num_perf_counters = msr_counter_info_count_perf(mci);4386		const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long);4387		const ssize_t actual_read_size = read(mci->fd_perf, &perf_data[0], sizeof(perf_data));4388 4389		if (actual_read_size != expected_read_size)4390			err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size,4391			    actual_read_size);4392	}4393 4394	for (unsigned int i = 0, pi = 1; i < NUM_MSR_COUNTERS; ++i) {4395		switch (mci->source[i]) {4396		case COUNTER_SOURCE_NONE:4397			break;4398 4399		case COUNTER_SOURCE_PERF:4400			assert(pi < ARRAY_SIZE(perf_data));4401			assert(mci->fd_perf != -1);4402 4403			if (debug >= 2)4404				fprintf(stderr, "Reading msr counter via perf at %u: %llu\n", i, perf_data[pi]);4405 4406			mci->data[i] = perf_data[pi];4407 4408			++pi;4409			break;4410 4411		case COUNTER_SOURCE_MSR:4412			assert(!no_msr);4413 4414			if (get_msr(cpu, mci->msr[i], &mci->data[i]))4415				return -2 - i;4416 4417			mci->data[i] &= mci->msr_mask[i];4418 4419			if (debug >= 2)4420				fprintf(stderr, "Reading msr counter via msr at %u: %llu\n", i, mci->data[i]);4421 4422			break;4423		}4424	}4425 4426	BUILD_BUG_ON(NUM_MSR_COUNTERS != 3);4427	t->aperf = mci->data[MSR_RCI_INDEX_APERF];4428	t->mperf = mci->data[MSR_RCI_INDEX_MPERF];4429	t->smi_count = mci->data[MSR_RCI_INDEX_SMI];4430 4431	return 0;4432}4433 4434int perf_counter_info_read_values(struct perf_counter_info *pp, int cpu, unsigned long long *out, size_t out_size)4435{4436	unsigned int domain;4437	unsigned long long value;4438	int fd_counter;4439 4440	for (size_t i = 0; pp; ++i, pp = pp->next) {4441		domain = cpu_to_domain(pp, cpu);4442		assert(domain < pp->num_domains);4443 4444		fd_counter = pp->fd_perf_per_domain[domain];4445 4446		if (fd_counter == -1)4447			continue;4448 4449		if (read(fd_counter, &value, sizeof(value)) != sizeof(value))4450			return 1;4451 4452		assert(i < out_size);4453		out[i] = value * pp->scale;4454	}4455 4456	return 0;4457}4458 4459unsigned long pmt_gen_value_mask(unsigned int lsb, unsigned int msb)4460{4461	unsigned long mask;4462 4463	if (msb == 63)4464		mask = 0xffffffffffffffff;4465	else4466		mask = ((1 << (msb + 1)) - 1);4467 4468	mask -= (1 << lsb) - 1;4469 4470	return mask;4471}4472 4473unsigned long pmt_read_counter(struct pmt_counter *ppmt, unsigned int domain_id)4474{4475	assert(domain_id < ppmt->num_domains);4476 4477	const unsigned long *pmmio = ppmt->domains[domain_id].pcounter;4478	const unsigned long value = pmmio ? *pmmio : 0;4479	const unsigned long value_mask = pmt_gen_value_mask(ppmt->lsb, ppmt->msb);4480	const unsigned long value_shift = ppmt->lsb;4481 4482	return (value & value_mask) >> value_shift;4483}4484 4485/*4486 * get_counters(...)4487 * migrate to cpu4488 * acquire and record local counters for that cpu4489 */4490int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)4491{4492	int cpu = t->cpu_id;4493	unsigned long long msr;4494	struct msr_counter *mp;4495	struct pmt_counter *pp;4496	int i;4497	int status;4498 4499	if (cpu_migrate(cpu)) {4500		fprintf(outf, "%s: Could not migrate to CPU %d\n", __func__, cpu);4501		return -1;4502	}4503 4504	gettimeofday(&t->tv_begin, (struct timezone *)NULL);4505 4506	if (first_counter_read)4507		get_apic_id(t);4508 4509	t->tsc = rdtsc();	/* we are running on local CPU of interest */4510 4511	get_smi_aperf_mperf(cpu, t);4512 4513	if (DO_BIC(BIC_IPC))4514		if (read(get_instr_count_fd(cpu), &t->instr_count, sizeof(long long)) != sizeof(long long))4515			return -4;4516 4517	if (DO_BIC(BIC_IRQ))4518		t->irq_count = irqs_per_cpu[cpu];4519 4520	get_cstate_counters(cpu, t, c, p);4521 4522	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {4523		if (get_mp(cpu, mp, &t->counter[i], mp->sp->path))4524			return -10;4525	}4526 4527	if (perf_counter_info_read_values(sys.perf_tp, cpu, t->perf_counter, MAX_ADDED_THREAD_COUNTERS))4528		return -10;4529 4530	for (i = 0, pp = sys.pmt_tp; pp; i++, pp = pp->next)4531		t->pmt_counter[i] = pmt_read_counter(pp, t->cpu_id);4532 4533	/* collect core counters only for 1st thread in core */4534	if (!is_cpu_first_thread_in_core(t, c, p))4535		goto done;4536 4537	if (platform->has_per_core_rapl) {4538		status = get_rapl_counters(cpu, c->core_id, c, p);4539		if (status != 0)4540			return status;4541	}4542 4543	if (DO_BIC(BIC_CPU_c7) && t->is_atom) {4544		/*4545		 * For Atom CPUs that has core cstate deeper than c6,4546		 * MSR_CORE_C6_RESIDENCY returns residency of cc6 and deeper.4547		 * Minus CC7 (and deeper cstates) residency to get4548		 * accturate cc6 residency.4549		 */4550		c->c6 -= c->c7;4551	}4552 4553	if (DO_BIC(BIC_Mod_c6))4554		if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))4555			return -8;4556 4557	if (DO_BIC(BIC_CoreTmp)) {4558		if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))4559			return -9;4560		c->core_temp_c = tj_max - ((msr >> 16) & 0x7F);4561	}4562 4563	if (DO_BIC(BIC_CORE_THROT_CNT))4564		get_core_throt_cnt(cpu, &c->core_throt_cnt);4565 4566	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {4567		if (get_mp(cpu, mp, &c->counter[i], mp->sp->path))4568			return -10;4569	}4570 4571	if (perf_counter_info_read_values(sys.perf_cp, cpu, c->perf_counter, MAX_ADDED_CORE_COUNTERS))4572		return -10;4573 4574	for (i = 0, pp = sys.pmt_cp; pp; i++, pp = pp->next)4575		c->pmt_counter[i] = pmt_read_counter(pp, c->core_id);4576 4577	/* collect package counters only for 1st core in package */4578	if (!is_cpu_first_core_in_package(t, c, p))4579		goto done;4580 4581	if (DO_BIC(BIC_Totl_c0)) {4582		if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))4583			return -10;4584	}4585	if (DO_BIC(BIC_Any_c0)) {4586		if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))4587			return -11;4588	}4589	if (DO_BIC(BIC_GFX_c0)) {4590		if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))4591			return -12;4592	}4593	if (DO_BIC(BIC_CPUGFX)) {4594		if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))4595			return -13;4596	}4597 4598	if (DO_BIC(BIC_CPU_LPI))4599		p->cpu_lpi = cpuidle_cur_cpu_lpi_us;4600	if (DO_BIC(BIC_SYS_LPI))4601		p->sys_lpi = cpuidle_cur_sys_lpi_us;4602 4603	if (!platform->has_per_core_rapl) {4604		status = get_rapl_counters(cpu, p->package_id, c, p);4605		if (status != 0)4606			return status;4607	}4608 4609	if (DO_BIC(BIC_PkgTmp)) {4610		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))4611			return -17;4612		p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F);4613	}4614 4615	if (DO_BIC(BIC_UNCORE_MHZ))4616		p->uncore_mhz = get_legacy_uncore_mhz(p->package_id);4617 4618	if (DO_BIC(BIC_GFX_rc6))4619		p->gfx_rc6_ms = gfx_info[GFX_rc6].val_ull;4620 4621	if (DO_BIC(BIC_GFXMHz))4622		p->gfx_mhz = gfx_info[GFX_MHz].val;4623 4624	if (DO_BIC(BIC_GFXACTMHz))4625		p->gfx_act_mhz = gfx_info[GFX_ACTMHz].val;4626 4627	if (DO_BIC(BIC_SAM_mc6))4628		p->sam_mc6_ms = gfx_info[SAM_mc6].val_ull;4629 4630	if (DO_BIC(BIC_SAMMHz))4631		p->sam_mhz = gfx_info[SAM_MHz].val;4632 4633	if (DO_BIC(BIC_SAMACTMHz))4634		p->sam_act_mhz = gfx_info[SAM_ACTMHz].val;4635 4636	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {4637		char *path = NULL;4638 4639		if (mp->msr_num == 0) {4640			path = find_sysfs_path_by_id(mp->sp, p->package_id);4641			if (path == NULL) {4642				warnx("%s: package_id %d not found", __func__, p->package_id);4643				return -10;4644			}4645		}4646		if (get_mp(cpu, mp, &p->counter[i], path))4647			return -10;4648	}4649 4650	if (perf_counter_info_read_values(sys.perf_pp, cpu, p->perf_counter, MAX_ADDED_PACKAGE_COUNTERS))4651		return -10;4652 4653	for (i = 0, pp = sys.pmt_pp; pp; i++, pp = pp->next)4654		p->pmt_counter[i] = pmt_read_counter(pp, p->package_id);4655 4656done:4657	gettimeofday(&t->tv_end, (struct timezone *)NULL);4658 4659	return 0;4660}4661 4662int pkg_cstate_limit = PCLUKN;4663char *pkg_cstate_limit_strings[] = { "unknown", "reserved", "pc0", "pc1", "pc2",4664	"pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"4665};4666 4667int nhm_pkg_cstate_limits[16] =4668    { PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4669	PCLRSV, PCLRSV4670};4671 4672int snb_pkg_cstate_limits[16] =4673    { PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4674	PCLRSV, PCLRSV4675};4676 4677int hsw_pkg_cstate_limits[16] =4678    { PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4679	PCLRSV, PCLRSV4680};4681 4682int slv_pkg_cstate_limits[16] =4683    { PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4684	PCL__6, PCL__74685};4686 4687int amt_pkg_cstate_limits[16] =4688    { PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4689	PCLRSV, PCLRSV4690};4691 4692int phi_pkg_cstate_limits[16] =4693    { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4694	PCLRSV, PCLRSV4695};4696 4697int glm_pkg_cstate_limits[16] =4698    { PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4699	PCLRSV, PCLRSV4700};4701 4702int skx_pkg_cstate_limits[16] =4703    { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4704	PCLRSV, PCLRSV4705};4706 4707int icx_pkg_cstate_limits[16] =4708    { PCL__0, PCL__2, PCL__6, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,4709	PCLRSV, PCLRSV4710};4711 4712void probe_cst_limit(void)4713{4714	unsigned long long msr;4715	int *pkg_cstate_limits;4716 4717	if (!platform->has_nhm_msrs || no_msr)4718		return;4719 4720	switch (platform->cst_limit) {4721	case CST_LIMIT_NHM:4722		pkg_cstate_limits = nhm_pkg_cstate_limits;4723		break;4724	case CST_LIMIT_SNB:4725		pkg_cstate_limits = snb_pkg_cstate_limits;4726		break;4727	case CST_LIMIT_HSW:4728		pkg_cstate_limits = hsw_pkg_cstate_limits;4729		break;4730	case CST_LIMIT_SKX:4731		pkg_cstate_limits = skx_pkg_cstate_limits;4732		break;4733	case CST_LIMIT_ICX:4734		pkg_cstate_limits = icx_pkg_cstate_limits;4735		break;4736	case CST_LIMIT_SLV:4737		pkg_cstate_limits = slv_pkg_cstate_limits;4738		break;4739	case CST_LIMIT_AMT:4740		pkg_cstate_limits = amt_pkg_cstate_limits;4741		break;4742	case CST_LIMIT_KNL:4743		pkg_cstate_limits = phi_pkg_cstate_limits;4744		break;4745	case CST_LIMIT_GMT:4746		pkg_cstate_limits = glm_pkg_cstate_limits;4747		break;4748	default:4749		return;4750	}4751 4752	get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);4753	pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];4754}4755 4756static void dump_platform_info(void)4757{4758	unsigned long long msr;4759	unsigned int ratio;4760 4761	if (!platform->has_nhm_msrs || no_msr)4762		return;4763 4764	get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);4765 4766	fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);4767 4768	ratio = (msr >> 40) & 0xFF;4769	fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n", ratio, bclk, ratio * bclk);4770 4771	ratio = (msr >> 8) & 0xFF;4772	fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);4773}4774 4775static void dump_power_ctl(void)4776{4777	unsigned long long msr;4778 4779	if (!platform->has_nhm_msrs || no_msr)4780		return;4781 4782	get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);4783	fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",4784		base_cpu, msr, msr & 0x2 ? "EN" : "DIS");4785 4786	/* C-state Pre-wake Disable (CSTATE_PREWAKE_DISABLE) */4787	if (platform->has_cst_prewake_bit)4788		fprintf(outf, "C-state Pre-wake: %sabled\n", msr & 0x40000000 ? "DIS" : "EN");4789 4790	return;4791}4792 4793static void dump_turbo_ratio_limit2(void)4794{4795	unsigned long long msr;4796	unsigned int ratio;4797 4798	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);4799 4800	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);4801 4802	ratio = (msr >> 8) & 0xFF;4803	if (ratio)4804		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n", ratio, bclk, ratio * bclk);4805 4806	ratio = (msr >> 0) & 0xFF;4807	if (ratio)4808		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n", ratio, bclk, ratio * bclk);4809	return;4810}4811 4812static void dump_turbo_ratio_limit1(void)4813{4814	unsigned long long msr;4815	unsigned int ratio;4816 4817	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);4818 4819	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);4820 4821	ratio = (msr >> 56) & 0xFF;4822	if (ratio)4823		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n", ratio, bclk, ratio * bclk);4824 4825	ratio = (msr >> 48) & 0xFF;4826	if (ratio)4827		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n", ratio, bclk, ratio * bclk);4828 4829	ratio = (msr >> 40) & 0xFF;4830	if (ratio)4831		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n", ratio, bclk, ratio * bclk);4832 4833	ratio = (msr >> 32) & 0xFF;4834	if (ratio)4835		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n", ratio, bclk, ratio * bclk);4836 4837	ratio = (msr >> 24) & 0xFF;4838	if (ratio)4839		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n", ratio, bclk, ratio * bclk);4840 4841	ratio = (msr >> 16) & 0xFF;4842	if (ratio)4843		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n", ratio, bclk, ratio * bclk);4844 4845	ratio = (msr >> 8) & 0xFF;4846	if (ratio)4847		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n", ratio, bclk, ratio * bclk);4848 4849	ratio = (msr >> 0) & 0xFF;4850	if (ratio)4851		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n", ratio, bclk, ratio * bclk);4852	return;4853}4854 4855static void dump_turbo_ratio_limits(int trl_msr_offset)4856{4857	unsigned long long msr, core_counts;4858	int shift;4859 4860	get_msr(base_cpu, trl_msr_offset, &msr);4861	fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n",4862		base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr);4863 4864	if (platform->trl_msrs & TRL_CORECOUNT) {4865		get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);4866		fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts);4867	} else {4868		core_counts = 0x0807060504030201;4869	}4870 4871	for (shift = 56; shift >= 0; shift -= 8) {4872		unsigned int ratio, group_size;4873 4874		ratio = (msr >> shift) & 0xFF;4875		group_size = (core_counts >> shift) & 0xFF;4876		if (ratio)4877			fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",4878				ratio, bclk, ratio * bclk, group_size);4879	}4880 4881	return;4882}4883 4884static void dump_atom_turbo_ratio_limits(void)4885{4886	unsigned long long msr;4887	unsigned int ratio;4888 4889	get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);4890	fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);4891 4892	ratio = (msr >> 0) & 0x3F;4893	if (ratio)4894		fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n", ratio, bclk, ratio * bclk);4895 4896	ratio = (msr >> 8) & 0x3F;4897	if (ratio)4898		fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n", ratio, bclk, ratio * bclk);4899 4900	ratio = (msr >> 16) & 0x3F;4901	if (ratio)4902		fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);4903 4904	get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);4905	fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);4906 4907	ratio = (msr >> 24) & 0x3F;4908	if (ratio)4909		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n", ratio, bclk, ratio * bclk);4910 4911	ratio = (msr >> 16) & 0x3F;4912	if (ratio)4913		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n", ratio, bclk, ratio * bclk);4914 4915	ratio = (msr >> 8) & 0x3F;4916	if (ratio)4917		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n", ratio, bclk, ratio * bclk);4918 4919	ratio = (msr >> 0) & 0x3F;4920	if (ratio)4921		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n", ratio, bclk, ratio * bclk);4922}4923 4924static void dump_knl_turbo_ratio_limits(void)4925{4926	const unsigned int buckets_no = 7;4927 4928	unsigned long long msr;4929	int delta_cores, delta_ratio;4930	int i, b_nr;4931	unsigned int cores[buckets_no];4932	unsigned int ratio[buckets_no];4933 4934	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);4935 4936	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);4937 4938	/*4939	 * Turbo encoding in KNL is as follows:4940	 * [0] -- Reserved4941	 * [7:1] -- Base value of number of active cores of bucket 1.4942	 * [15:8] -- Base value of freq ratio of bucket 1.4943	 * [20:16] -- +ve delta of number of active cores of bucket 2.4944	 * i.e. active cores of bucket 2 =4945	 * active cores of bucket 1 + delta4946	 * [23:21] -- Negative delta of freq ratio of bucket 2.4947	 * i.e. freq ratio of bucket 2 =4948	 * freq ratio of bucket 1 - delta4949	 * [28:24]-- +ve delta of number of active cores of bucket 3.4950	 * [31:29]-- -ve delta of freq ratio of bucket 3.4951	 * [36:32]-- +ve delta of number of active cores of bucket 4.4952	 * [39:37]-- -ve delta of freq ratio of bucket 4.4953	 * [44:40]-- +ve delta of number of active cores of bucket 5.4954	 * [47:45]-- -ve delta of freq ratio of bucket 5.4955	 * [52:48]-- +ve delta of number of active cores of bucket 6.4956	 * [55:53]-- -ve delta of freq ratio of bucket 6.4957	 * [60:56]-- +ve delta of number of active cores of bucket 7.4958	 * [63:61]-- -ve delta of freq ratio of bucket 7.4959	 */4960 4961	b_nr = 0;4962	cores[b_nr] = (msr & 0xFF) >> 1;4963	ratio[b_nr] = (msr >> 8) & 0xFF;4964 4965	for (i = 16; i < 64; i += 8) {4966		delta_cores = (msr >> i) & 0x1F;4967		delta_ratio = (msr >> (i + 5)) & 0x7;4968 4969		cores[b_nr + 1] = cores[b_nr] + delta_cores;4970		ratio[b_nr + 1] = ratio[b_nr] - delta_ratio;4971		b_nr++;4972	}4973 4974	for (i = buckets_no - 1; i >= 0; i--)4975		if (i > 0 ? ratio[i] != ratio[i - 1] : 1)4976			fprintf(outf,4977				"%d * %.1f = %.1f MHz max turbo %d active cores\n",4978				ratio[i], bclk, ratio[i] * bclk, cores[i]);4979}4980 4981static void dump_cst_cfg(void)4982{4983	unsigned long long msr;4984 4985	if (!platform->has_nhm_msrs || no_msr)4986		return;4987 4988	get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);4989 4990	fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr);4991 4992	fprintf(outf, " (%s%s%s%s%slocked, pkg-cstate-limit=%d (%s)",4993		(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",4994		(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",4995		(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",4996		(msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",4997		(msr & (1 << 15)) ? "" : "UN", (unsigned int)msr & 0xF, pkg_cstate_limit_strings[pkg_cstate_limit]);4998 4999#define AUTOMATIC_CSTATE_CONVERSION		(1UL << 16)5000	if (platform->has_cst_auto_convension) {5001		fprintf(outf, ", automatic c-state conversion=%s", (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");5002	}5003 5004	fprintf(outf, ")\n");5005 5006	return;5007}5008 5009static void dump_config_tdp(void)5010{5011	unsigned long long msr;5012 5013	get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);5014	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);5015	fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);5016 5017	get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);5018	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);5019	if (msr) {5020		fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);5021		fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);5022		fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);5023		fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);5024	}5025	fprintf(outf, ")\n");5026 5027	get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);5028	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);5029	if (msr) {5030		fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);5031		fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);5032		fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);5033		fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);5034	}5035	fprintf(outf, ")\n");5036 5037	get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr);5038	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);5039	if ((msr) & 0x3)5040		fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);5041	fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);5042	fprintf(outf, ")\n");5043 5044	get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);5045	fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);5046	fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);5047	fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);5048	fprintf(outf, ")\n");5049}5050 5051unsigned int irtl_time_units[] = { 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };5052 5053void print_irtl(void)5054{5055	unsigned long long msr;5056 5057	if (!platform->has_irtl_msrs || no_msr)5058		return;5059 5060	if (platform->supported_cstates & PC3) {5061		get_msr(base_cpu, MSR_PKGC3_IRTL, &msr);5062		fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr);5063		fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",5064			(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5065	}5066 5067	if (platform->supported_cstates & PC6) {5068		get_msr(base_cpu, MSR_PKGC6_IRTL, &msr);5069		fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr);5070		fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",5071			(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5072	}5073 5074	if (platform->supported_cstates & PC7) {5075		get_msr(base_cpu, MSR_PKGC7_IRTL, &msr);5076		fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr);5077		fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",5078			(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5079	}5080 5081	if (platform->supported_cstates & PC8) {5082		get_msr(base_cpu, MSR_PKGC8_IRTL, &msr);5083		fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr);5084		fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",5085			(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5086	}5087 5088	if (platform->supported_cstates & PC9) {5089		get_msr(base_cpu, MSR_PKGC9_IRTL, &msr);5090		fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr);5091		fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",5092			(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5093	}5094 5095	if (platform->supported_cstates & PC10) {5096		get_msr(base_cpu, MSR_PKGC10_IRTL, &msr);5097		fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr);5098		fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",5099			(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5100	}5101}5102 5103void free_fd_percpu(void)5104{5105	int i;5106 5107	if (!fd_percpu)5108		return;5109 5110	for (i = 0; i < topo.max_cpu_num + 1; ++i) {5111		if (fd_percpu[i] != 0)5112			close(fd_percpu[i]);5113	}5114 5115	free(fd_percpu);5116	fd_percpu = NULL;5117}5118 5119void free_fd_instr_count_percpu(void)5120{5121	if (!fd_instr_count_percpu)5122		return;5123 5124	for (int i = 0; i < topo.max_cpu_num + 1; ++i) {5125		if (fd_instr_count_percpu[i] != 0)5126			close(fd_instr_count_percpu[i]);5127	}5128 5129	free(fd_instr_count_percpu);5130	fd_instr_count_percpu = NULL;5131}5132 5133void free_fd_cstate(void)5134{5135	if (!ccstate_counter_info)5136		return;5137 5138	const int counter_info_num = ccstate_counter_info_size;5139 5140	for (int counter_id = 0; counter_id < counter_info_num; ++counter_id) {5141		if (ccstate_counter_info[counter_id].fd_perf_core != -1)5142			close(ccstate_counter_info[counter_id].fd_perf_core);5143 5144		if (ccstate_counter_info[counter_id].fd_perf_pkg != -1)5145			close(ccstate_counter_info[counter_id].fd_perf_pkg);5146	}5147 5148	free(ccstate_counter_info);5149	ccstate_counter_info = NULL;5150	ccstate_counter_info_size = 0;5151}5152 5153void free_fd_msr(void)5154{5155	if (!msr_counter_info)5156		return;5157 5158	for (int cpu = 0; cpu < topo.max_cpu_num; ++cpu) {5159		if (msr_counter_info[cpu].fd_perf != -1)5160			close(msr_counter_info[cpu].fd_perf);5161	}5162 5163	free(msr_counter_info);5164	msr_counter_info = NULL;5165	msr_counter_info_size = 0;5166}5167 5168void free_fd_rapl_percpu(void)5169{5170	if (!rapl_counter_info_perdomain)5171		return;5172 5173	const int num_domains = rapl_counter_info_perdomain_size;5174 5175	for (int domain_id = 0; domain_id < num_domains; ++domain_id) {5176		if (rapl_counter_info_perdomain[domain_id].fd_perf != -1)5177			close(rapl_counter_info_perdomain[domain_id].fd_perf);5178	}5179 5180	free(rapl_counter_info_perdomain);5181	rapl_counter_info_perdomain = NULL;5182	rapl_counter_info_perdomain_size = 0;5183}5184 5185void free_fd_added_perf_counters_(struct perf_counter_info *pp)5186{5187	if (!pp)5188		return;5189 5190	if (!pp->fd_perf_per_domain)5191		return;5192 5193	while (pp) {5194		for (size_t domain = 0; domain < pp->num_domains; ++domain) {5195			if (pp->fd_perf_per_domain[domain] != -1) {5196				close(pp->fd_perf_per_domain[domain]);5197				pp->fd_perf_per_domain[domain] = -1;5198			}5199		}5200 5201		free(pp->fd_perf_per_domain);5202		pp->fd_perf_per_domain = NULL;5203 5204		pp = pp->next;5205	}5206}5207 5208void free_fd_added_perf_counters(void)5209{5210	free_fd_added_perf_counters_(sys.perf_tp);5211	free_fd_added_perf_counters_(sys.perf_cp);5212	free_fd_added_perf_counters_(sys.perf_pp);5213}5214 5215void free_all_buffers(void)5216{5217	int i;5218 5219	CPU_FREE(cpu_present_set);5220	cpu_present_set = NULL;5221	cpu_present_setsize = 0;5222 5223	CPU_FREE(cpu_effective_set);5224	cpu_effective_set = NULL;5225	cpu_effective_setsize = 0;5226 5227	CPU_FREE(cpu_allowed_set);5228	cpu_allowed_set = NULL;5229	cpu_allowed_setsize = 0;5230 5231	CPU_FREE(cpu_affinity_set);5232	cpu_affinity_set = NULL;5233	cpu_affinity_setsize = 0;5234 5235	free(thread_even);5236	free(core_even);5237	free(package_even);5238 5239	thread_even = NULL;5240	core_even = NULL;5241	package_even = NULL;5242 5243	free(thread_odd);5244	free(core_odd);5245	free(package_odd);5246 5247	thread_odd = NULL;5248	core_odd = NULL;5249	package_odd = NULL;5250 5251	free(output_buffer);5252	output_buffer = NULL;5253	outp = NULL;5254 5255	free_fd_percpu();5256	free_fd_instr_count_percpu();5257	free_fd_msr();5258	free_fd_rapl_percpu();5259	free_fd_cstate();5260	free_fd_added_perf_counters();5261 5262	free(irq_column_2_cpu);5263	free(irqs_per_cpu);5264 5265	for (i = 0; i <= topo.max_cpu_num; ++i) {5266		if (cpus[i].put_ids)5267			CPU_FREE(cpus[i].put_ids);5268	}5269	free(cpus);5270}5271 5272/*5273 * Parse a file containing a single int.5274 * Return 0 if file can not be opened5275 * Exit if file can be opened, but can not be parsed5276 */5277int parse_int_file(const char *fmt, ...)5278{5279	va_list args;5280	char path[PATH_MAX];5281	FILE *filep;5282	int value;5283 5284	va_start(args, fmt);5285	vsnprintf(path, sizeof(path), fmt, args);5286	va_end(args);5287	filep = fopen(path, "r");5288	if (!filep)5289		return 0;5290	if (fscanf(filep, "%d", &value) != 1)5291		err(1, "%s: failed to parse number from file", path);5292	fclose(filep);5293	return value;5294}5295 5296/*5297 * cpu_is_first_core_in_package(cpu)5298 * return 1 if given CPU is 1st core in package5299 */5300int cpu_is_first_core_in_package(int cpu)5301{5302	return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu);5303}5304 5305int get_physical_package_id(int cpu)5306{5307	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);5308}5309 5310int get_die_id(int cpu)5311{5312	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/die_id", cpu);5313}5314 5315int get_core_id(int cpu)5316{5317	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);5318}5319 5320void set_node_data(void)5321{5322	int pkg, node, lnode, cpu, cpux;5323	int cpu_count;5324 5325	/* initialize logical_node_id */5326	for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu)5327		cpus[cpu].logical_node_id = -1;5328 5329	cpu_count = 0;5330	for (pkg = 0; pkg < topo.num_packages; pkg++) {5331		lnode = 0;5332		for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {5333			if (cpus[cpu].physical_package_id != pkg)5334				continue;5335			/* find a cpu with an unset logical_node_id */5336			if (cpus[cpu].logical_node_id != -1)5337				continue;5338			cpus[cpu].logical_node_id = lnode;5339			node = cpus[cpu].physical_node_id;5340			cpu_count++;5341			/*5342			 * find all matching cpus on this pkg and set5343			 * the logical_node_id5344			 */5345			for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) {5346				if ((cpus[cpux].physical_package_id == pkg) && (cpus[cpux].physical_node_id == node)) {5347					cpus[cpux].logical_node_id = lnode;5348					cpu_count++;5349				}5350			}5351			lnode++;5352			if (lnode > topo.nodes_per_pkg)5353				topo.nodes_per_pkg = lnode;5354		}5355		if (cpu_count >= topo.max_cpu_num)5356			break;5357	}5358}5359 5360int get_physical_node_id(struct cpu_topology *thiscpu)5361{5362	char path[80];5363	FILE *filep;5364	int i;5365	int cpu = thiscpu->logical_cpu_id;5366 5367	for (i = 0; i <= topo.max_cpu_num; i++) {5368		sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist", cpu, i);5369		filep = fopen(path, "r");5370		if (!filep)5371			continue;5372		fclose(filep);5373		return i;5374	}5375	return -1;5376}5377 5378static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size)5379{5380	unsigned int start, end;5381	char *next = cpu_str;5382 5383	while (next && *next) {5384 5385		if (*next == '-')	/* no negative cpu numbers */5386			return 1;5387 5388		start = strtoul(next, &next, 10);5389 5390		if (start >= CPU_SUBSET_MAXCPUS)5391			return 1;5392		CPU_SET_S(start, cpu_set_size, cpu_set);5393 5394		if (*next == '\0' || *next == '\n')5395			break;5396 5397		if (*next == ',') {5398			next += 1;5399			continue;5400		}5401 5402		if (*next == '-') {5403			next += 1;	/* start range */5404		} else if (*next == '.') {5405			next += 1;5406			if (*next == '.')5407				next += 1;	/* start range */5408			else5409				return 1;5410		}5411 5412		end = strtoul(next, &next, 10);5413		if (end <= start)5414			return 1;5415 5416		while (++start <= end) {5417			if (start >= CPU_SUBSET_MAXCPUS)5418				return 1;5419			CPU_SET_S(start, cpu_set_size, cpu_set);5420		}5421 5422		if (*next == ',')5423			next += 1;5424		else if (*next != '\0' && *next != '\n')5425			return 1;5426	}5427 5428	return 0;5429}5430 5431int get_thread_siblings(struct cpu_topology *thiscpu)5432{5433	char path[80], character;5434	FILE *filep;5435	unsigned long map;5436	int so, shift, sib_core;5437	int cpu = thiscpu->logical_cpu_id;5438	int offset = topo.max_cpu_num + 1;5439	size_t size;5440	int thread_id = 0;5441 5442	thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1));5443	if (thiscpu->thread_id < 0)5444		thiscpu->thread_id = thread_id++;5445	if (!thiscpu->put_ids)5446		return -1;5447 5448	size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));5449	CPU_ZERO_S(size, thiscpu->put_ids);5450 5451	sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);5452	filep = fopen(path, "r");5453 5454	if (!filep) {5455		warnx("%s: open failed", path);5456		return -1;5457	}5458	do {5459		offset -= BITMASK_SIZE;5460		if (fscanf(filep, "%lx%c", &map, &character) != 2)5461			err(1, "%s: failed to parse file", path);5462		for (shift = 0; shift < BITMASK_SIZE; shift++) {5463			if ((map >> shift) & 0x1) {5464				so = shift + offset;5465				sib_core = get_core_id(so);5466				if (sib_core == thiscpu->physical_core_id) {5467					CPU_SET_S(so, size, thiscpu->put_ids);5468					if ((so != cpu) && (cpus[so].thread_id < 0))5469						cpus[so].thread_id = thread_id++;5470				}5471			}5472		}5473	} while (character == ',');5474	fclose(filep);5475 5476	return CPU_COUNT_S(size, thiscpu->put_ids);5477}5478 5479/*5480 * run func(thread, core, package) in topology order5481 * skip non-present cpus5482 */5483 5484int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *,5485			       struct pkg_data *, struct thread_data *, struct core_data *,5486			       struct pkg_data *), struct thread_data *thread_base,5487		   struct core_data *core_base, struct pkg_data *pkg_base,5488		   struct thread_data *thread_base2, struct core_data *core_base2, struct pkg_data *pkg_base2)5489{5490	int retval, pkg_no, node_no, core_no, thread_no;5491 5492	for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {5493		for (node_no = 0; node_no < topo.nodes_per_pkg; ++node_no) {5494			for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {5495				for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) {5496					struct thread_data *t, *t2;5497					struct core_data *c, *c2;5498					struct pkg_data *p, *p2;5499 5500					t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no);5501 5502					if (cpu_is_not_allowed(t->cpu_id))5503						continue;5504 5505					t2 = GET_THREAD(thread_base2, thread_no, core_no, node_no, pkg_no);5506 5507					c = GET_CORE(core_base, core_no, node_no, pkg_no);5508					c2 = GET_CORE(core_base2, core_no, node_no, pkg_no);5509 5510					p = GET_PKG(pkg_base, pkg_no);5511					p2 = GET_PKG(pkg_base2, pkg_no);5512 5513					retval = func(t, c, p, t2, c2, p2);5514					if (retval)5515						return retval;5516				}5517			}5518		}5519	}5520	return 0;5521}5522 5523/*5524 * run func(cpu) on every cpu in /proc/stat5525 * return max_cpu number5526 */5527int for_all_proc_cpus(int (func) (int))5528{5529	FILE *fp;5530	int cpu_num;5531	int retval;5532 5533	fp = fopen_or_die(proc_stat, "r");5534 5535	retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");5536	if (retval != 0)5537		err(1, "%s: failed to parse format", proc_stat);5538 5539	while (1) {5540		retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);5541		if (retval != 1)5542			break;5543 5544		retval = func(cpu_num);5545		if (retval) {5546			fclose(fp);5547			return (retval);5548		}5549	}5550	fclose(fp);5551	return 0;5552}5553 5554#define PATH_EFFECTIVE_CPUS	"/sys/fs/cgroup/cpuset.cpus.effective"5555 5556static char cpu_effective_str[1024];5557 5558static int update_effective_str(bool startup)5559{5560	FILE *fp;5561	char *pos;5562	char buf[1024];5563	int ret;5564 5565	if (cpu_effective_str[0] == '\0' && !startup)5566		return 0;5567 5568	fp = fopen(PATH_EFFECTIVE_CPUS, "r");5569	if (!fp)5570		return 0;5571 5572	pos = fgets(buf, 1024, fp);5573	if (!pos)5574		err(1, "%s: file read failed\n", PATH_EFFECTIVE_CPUS);5575 5576	fclose(fp);5577 5578	ret = strncmp(cpu_effective_str, buf, 1024);5579	if (!ret)5580		return 0;5581 5582	strncpy(cpu_effective_str, buf, 1024);5583	return 1;5584}5585 5586static void update_effective_set(bool startup)5587{5588	update_effective_str(startup);5589 5590	if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_effective_setsize))5591		err(1, "%s: cpu str malformat %s\n", PATH_EFFECTIVE_CPUS, cpu_effective_str);5592}5593 5594void linux_perf_init(void);5595void msr_perf_init(void);5596void rapl_perf_init(void);5597void cstate_perf_init(void);5598void added_perf_counters_init(void);5599void pmt_init(void);5600 5601void re_initialize(void)5602{5603	free_all_buffers();5604	setup_all_buffers(false);5605	linux_perf_init();5606	msr_perf_init();5607	rapl_perf_init();5608	cstate_perf_init();5609	added_perf_counters_init();5610	pmt_init();5611	fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus,5612		topo.allowed_cpus);5613}5614 5615void set_max_cpu_num(void)5616{5617	FILE *filep;5618	int base_cpu;5619	unsigned long dummy;5620	char pathname[64];5621 5622	base_cpu = sched_getcpu();5623	if (base_cpu < 0)5624		err(1, "cannot find calling cpu ID");5625	sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", base_cpu);5626 5627	filep = fopen_or_die(pathname, "r");5628	topo.max_cpu_num = 0;5629	while (fscanf(filep, "%lx,", &dummy) == 1)5630		topo.max_cpu_num += BITMASK_SIZE;5631	fclose(filep);5632	topo.max_cpu_num--;	/* 0 based */5633}5634 5635/*5636 * count_cpus()5637 * remember the last one seen, it will be the max5638 */5639int count_cpus(int cpu)5640{5641	UNUSED(cpu);5642 5643	topo.num_cpus++;5644	return 0;5645}5646 5647int mark_cpu_present(int cpu)5648{5649	CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);5650	return 0;5651}5652 5653int init_thread_id(int cpu)5654{5655	cpus[cpu].thread_id = -1;5656	return 0;5657}5658 5659/*5660 * snapshot_proc_interrupts()5661 *5662 * read and record summary of /proc/interrupts5663 *5664 * return 1 if config change requires a restart, else return 05665 */5666int snapshot_proc_interrupts(void)5667{5668	static FILE *fp;5669	int column, retval;5670 5671	if (fp == NULL)5672		fp = fopen_or_die("/proc/interrupts", "r");5673	else5674		rewind(fp);5675 5676	/* read 1st line of /proc/interrupts to get cpu* name for each column */5677	for (column = 0; column < topo.num_cpus; ++column) {5678		int cpu_number;5679 5680		retval = fscanf(fp, " CPU%d", &cpu_number);5681		if (retval != 1)5682			break;5683 5684		if (cpu_number > topo.max_cpu_num) {5685			warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);5686			return 1;5687		}5688 5689		irq_column_2_cpu[column] = cpu_number;5690		irqs_per_cpu[cpu_number] = 0;5691	}5692 5693	/* read /proc/interrupt count lines and sum up irqs per cpu */5694	while (1) {5695		int column;5696		char buf[64];5697 5698		retval = fscanf(fp, " %s:", buf);	/* flush irq# "N:" */5699		if (retval != 1)5700			break;5701 5702		/* read the count per cpu */5703		for (column = 0; column < topo.num_cpus; ++column) {5704 5705			int cpu_number, irq_count;5706 5707			retval = fscanf(fp, " %d", &irq_count);5708			if (retval != 1)5709				break;5710 5711			cpu_number = irq_column_2_cpu[column];5712			irqs_per_cpu[cpu_number] += irq_count;5713 5714		}5715 5716		while (getc(fp) != '\n') ;	/* flush interrupt description */5717 5718	}5719	return 0;5720}5721 5722/*5723 * snapshot_graphics()5724 *5725 * record snapshot of specified graphics sysfs knob5726 *5727 * return 1 if config change requires a restart, else return 05728 */5729int snapshot_graphics(int idx)5730{5731	FILE *fp;5732	int retval;5733 5734	switch (idx) {5735	case GFX_rc6:5736	case SAM_mc6:5737		fp = fopen_or_die(gfx_info[idx].path, "r");5738		retval = fscanf(fp, "%lld", &gfx_info[idx].val_ull);5739		if (retval != 1)5740			err(1, "rc6");5741		fclose(fp);5742		return 0;5743	case GFX_MHz:5744	case GFX_ACTMHz:5745	case SAM_MHz:5746	case SAM_ACTMHz:5747		if (gfx_info[idx].fp == NULL) {5748			gfx_info[idx].fp = fopen_or_die(gfx_info[idx].path, "r");5749		} else {5750			rewind(gfx_info[idx].fp);5751			fflush(gfx_info[idx].fp);5752		}5753		retval = fscanf(gfx_info[idx].fp, "%d", &gfx_info[idx].val);5754		if (retval != 1)5755			err(1, "MHz");5756		return 0;5757	default:5758		return -EINVAL;5759	}5760}5761 5762/*5763 * snapshot_cpu_lpi()5764 *5765 * record snapshot of5766 * /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us5767 */5768int snapshot_cpu_lpi_us(void)5769{5770	FILE *fp;5771	int retval;5772 5773	fp = fopen_or_die("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", "r");5774 5775	retval = fscanf(fp, "%lld", &cpuidle_cur_cpu_lpi_us);5776	if (retval != 1) {5777		fprintf(stderr, "Disabling Low Power Idle CPU output\n");5778		BIC_NOT_PRESENT(BIC_CPU_LPI);5779		fclose(fp);5780		return -1;5781	}5782 5783	fclose(fp);5784 5785	return 0;5786}5787 5788/*5789 * snapshot_sys_lpi()5790 *5791 * record snapshot of sys_lpi_file5792 */5793int snapshot_sys_lpi_us(void)5794{5795	FILE *fp;5796	int retval;5797 5798	fp = fopen_or_die(sys_lpi_file, "r");5799 5800	retval = fscanf(fp, "%lld", &cpuidle_cur_sys_lpi_us);5801	if (retval != 1) {5802		fprintf(stderr, "Disabling Low Power Idle System output\n");5803		BIC_NOT_PRESENT(BIC_SYS_LPI);5804		fclose(fp);5805		return -1;5806	}5807	fclose(fp);5808 5809	return 0;5810}5811 5812/*5813 * snapshot /proc and /sys files5814 *5815 * return 1 if configuration restart needed, else return 05816 */5817int snapshot_proc_sysfs_files(void)5818{5819	if (DO_BIC(BIC_IRQ))5820		if (snapshot_proc_interrupts())5821			return 1;5822 5823	if (DO_BIC(BIC_GFX_rc6))5824		snapshot_graphics(GFX_rc6);5825 5826	if (DO_BIC(BIC_GFXMHz))5827		snapshot_graphics(GFX_MHz);5828 5829	if (DO_BIC(BIC_GFXACTMHz))5830		snapshot_graphics(GFX_ACTMHz);5831 5832	if (DO_BIC(BIC_SAM_mc6))5833		snapshot_graphics(SAM_mc6);5834 5835	if (DO_BIC(BIC_SAMMHz))5836		snapshot_graphics(SAM_MHz);5837 5838	if (DO_BIC(BIC_SAMACTMHz))5839		snapshot_graphics(SAM_ACTMHz);5840 5841	if (DO_BIC(BIC_CPU_LPI))5842		snapshot_cpu_lpi_us();5843 5844	if (DO_BIC(BIC_SYS_LPI))5845		snapshot_sys_lpi_us();5846 5847	return 0;5848}5849 5850int exit_requested;5851 5852static void signal_handler(int signal)5853{5854	switch (signal) {5855	case SIGINT:5856		exit_requested = 1;5857		if (debug)5858			fprintf(stderr, " SIGINT\n");5859		break;5860	case SIGUSR1:5861		if (debug > 1)5862			fprintf(stderr, "SIGUSR1\n");5863		break;5864	}5865}5866 5867void setup_signal_handler(void)5868{5869	struct sigaction sa;5870 5871	memset(&sa, 0, sizeof(sa));5872 5873	sa.sa_handler = &signal_handler;5874 5875	if (sigaction(SIGINT, &sa, NULL) < 0)5876		err(1, "sigaction SIGINT");5877	if (sigaction(SIGUSR1, &sa, NULL) < 0)5878		err(1, "sigaction SIGUSR1");5879}5880 5881void do_sleep(void)5882{5883	struct timeval tout;5884	struct timespec rest;5885	fd_set readfds;5886	int retval;5887 5888	FD_ZERO(&readfds);5889	FD_SET(0, &readfds);5890 5891	if (ignore_stdin) {5892		nanosleep(&interval_ts, NULL);5893		return;5894	}5895 5896	tout = interval_tv;5897	retval = select(1, &readfds, NULL, NULL, &tout);5898 5899	if (retval == 1) {5900		switch (getc(stdin)) {5901		case 'q':5902			exit_requested = 1;5903			break;5904		case EOF:5905			/*5906			 * 'stdin' is a pipe closed on the other end. There5907			 * won't be any further input.5908			 */5909			ignore_stdin = 1;5910			/* Sleep the rest of the time */5911			rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);5912			rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;5913			nanosleep(&rest, NULL);5914		}5915	}5916}5917 5918int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)5919{5920	int ret, idx;5921	unsigned long long msr_cur, msr_last;5922 5923	assert(!no_msr);5924 5925	if (!per_cpu_msr_sum)5926		return 1;5927 5928	idx = offset_to_idx(offset);5929	if (idx < 0)5930		return idx;5931	/* get_msr_sum() = sum + (get_msr() - last) */5932	ret = get_msr(cpu, offset, &msr_cur);5933	if (ret)5934		return ret;5935	msr_last = per_cpu_msr_sum[cpu].entries[idx].last;5936	DELTA_WRAP32(msr_cur, msr_last);5937	*msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;5938 5939	return 0;5940}5941 5942timer_t timerid;5943 5944/* Timer callback, update the sum of MSRs periodically. */5945static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)5946{5947	int i, ret;5948	int cpu = t->cpu_id;5949 5950	UNUSED(c);5951	UNUSED(p);5952 5953	assert(!no_msr);5954 5955	for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {5956		unsigned long long msr_cur, msr_last;5957		off_t offset;5958 5959		if (!idx_valid(i))5960			continue;5961		offset = idx_to_offset(i);5962		if (offset < 0)5963			continue;5964		ret = get_msr(cpu, offset, &msr_cur);5965		if (ret) {5966			fprintf(outf, "Can not update msr(0x%llx)\n", (unsigned long long)offset);5967			continue;5968		}5969 5970		msr_last = per_cpu_msr_sum[cpu].entries[i].last;5971		per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;5972 5973		DELTA_WRAP32(msr_cur, msr_last);5974		per_cpu_msr_sum[cpu].entries[i].sum += msr_last;5975	}5976	return 0;5977}5978 5979static void msr_record_handler(union sigval v)5980{5981	UNUSED(v);5982 5983	for_all_cpus(update_msr_sum, EVEN_COUNTERS);5984}5985 5986void msr_sum_record(void)5987{5988	struct itimerspec its;5989	struct sigevent sev;5990 5991	per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));5992	if (!per_cpu_msr_sum) {5993		fprintf(outf, "Can not allocate memory for long time MSR.\n");5994		return;5995	}5996	/*5997	 * Signal handler might be restricted, so use thread notifier instead.5998	 */5999	memset(&sev, 0, sizeof(struct sigevent));6000	sev.sigev_notify = SIGEV_THREAD;6001	sev.sigev_notify_function = msr_record_handler;6002 6003	sev.sigev_value.sival_ptr = &timerid;6004	if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {6005		fprintf(outf, "Can not create timer.\n");6006		goto release_msr;6007	}6008 6009	its.it_value.tv_sec = 0;6010	its.it_value.tv_nsec = 1;6011	/*6012	 * A wraparound time has been calculated early.6013	 * Some sources state that the peak power for a6014	 * microprocessor is usually 1.5 times the TDP rating,6015	 * use 2 * TDP for safety.6016	 */6017	its.it_interval.tv_sec = rapl_joule_counter_range / 2;6018	its.it_interval.tv_nsec = 0;6019 6020	if (timer_settime(timerid, 0, &its, NULL) == -1) {6021		fprintf(outf, "Can not set timer.\n");6022		goto release_timer;6023	}6024	return;6025 6026release_timer:6027	timer_delete(timerid);6028release_msr:6029	free(per_cpu_msr_sum);6030}6031 6032/*6033 * set_my_sched_priority(pri)6034 * return previous priority on success6035 * return value < -20 on failure6036 */6037int set_my_sched_priority(int priority)6038{6039	int retval;6040	int original_priority;6041 6042	errno = 0;6043	original_priority = getpriority(PRIO_PROCESS, 0);6044	if (errno && (original_priority == -1))6045		return -21;6046 6047	retval = setpriority(PRIO_PROCESS, 0, priority);6048	if (retval)6049		return -21;6050 6051	errno = 0;6052	retval = getpriority(PRIO_PROCESS, 0);6053	if (retval != priority)6054		return -21;6055 6056	return original_priority;6057}6058 6059void turbostat_loop()6060{6061	int retval;6062	int restarted = 0;6063	unsigned int done_iters = 0;6064 6065	setup_signal_handler();6066 6067	/*6068	 * elevate own priority for interval mode6069	 *6070	 * ignore on error - we probably don't have permission to set it, but6071	 * it's not a big deal6072	 */6073	set_my_sched_priority(-20);6074 6075restart:6076	restarted++;6077 6078	snapshot_proc_sysfs_files();6079	retval = for_all_cpus(get_counters, EVEN_COUNTERS);6080	first_counter_read = 0;6081	if (retval < -1) {6082		exit(retval);6083	} else if (retval == -1) {6084		if (restarted > 10) {6085			exit(retval);6086		}6087		re_initialize();6088		goto restart;6089	}6090	restarted = 0;6091	done_iters = 0;6092	gettimeofday(&tv_even, (struct timezone *)NULL);6093 6094	while (1) {6095		if (for_all_proc_cpus(cpu_is_not_present)) {6096			re_initialize();6097			goto restart;6098		}6099		if (update_effective_str(false)) {6100			re_initialize();6101			goto restart;6102		}6103		do_sleep();6104		if (snapshot_proc_sysfs_files())6105			goto restart;6106		retval = for_all_cpus(get_counters, ODD_COUNTERS);6107		if (retval < -1) {6108			exit(retval);6109		} else if (retval == -1) {6110			re_initialize();6111			goto restart;6112		}6113		gettimeofday(&tv_odd, (struct timezone *)NULL);6114		timersub(&tv_odd, &tv_even, &tv_delta);6115		if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) {6116			re_initialize();6117			goto restart;6118		}6119		compute_average(EVEN_COUNTERS);6120		format_all_counters(EVEN_COUNTERS);6121		flush_output_stdout();6122		if (exit_requested)6123			break;6124		if (num_iterations && ++done_iters >= num_iterations)6125			break;6126		do_sleep();6127		if (snapshot_proc_sysfs_files())6128			goto restart;6129		retval = for_all_cpus(get_counters, EVEN_COUNTERS);6130		if (retval < -1) {6131			exit(retval);6132		} else if (retval == -1) {6133			re_initialize();6134			goto restart;6135		}6136		gettimeofday(&tv_even, (struct timezone *)NULL);6137		timersub(&tv_even, &tv_odd, &tv_delta);6138		if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) {6139			re_initialize();6140			goto restart;6141		}6142		compute_average(ODD_COUNTERS);6143		format_all_counters(ODD_COUNTERS);6144		flush_output_stdout();6145		if (exit_requested)6146			break;6147		if (num_iterations && ++done_iters >= num_iterations)6148			break;6149	}6150}6151 6152void check_dev_msr()6153{6154	struct stat sb;6155	char pathname[32];6156 6157	if (no_msr)6158		return;6159 6160	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);6161	if (stat(pathname, &sb))6162		if (system("/sbin/modprobe msr > /dev/null 2>&1"))6163			no_msr = 1;6164}6165 6166/*6167 * check for CAP_SYS_RAWIO6168 * return 0 on success6169 * return 1 on fail6170 */6171int check_for_cap_sys_rawio(void)6172{6173	cap_t caps;6174	cap_flag_value_t cap_flag_value;6175	int ret = 0;6176 6177	caps = cap_get_proc();6178	if (caps == NULL)6179		return 1;6180 6181	if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value)) {6182		ret = 1;6183		goto free_and_exit;6184	}6185 6186	if (cap_flag_value != CAP_SET) {6187		ret = 1;6188		goto free_and_exit;6189	}6190 6191free_and_exit:6192	if (cap_free(caps) == -1)6193		err(-6, "cap_free\n");6194 6195	return ret;6196}6197 6198void check_msr_permission(void)6199{6200	int failed = 0;6201	char pathname[32];6202 6203	if (no_msr)6204		return;6205 6206	/* check for CAP_SYS_RAWIO */6207	failed += check_for_cap_sys_rawio();6208 6209	/* test file permissions */6210	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);6211	if (euidaccess(pathname, R_OK)) {6212		failed++;6213	}6214 6215	if (failed) {6216		warnx("Failed to access %s. Some of the counters may not be available\n"6217		      "\tRun as root to enable them or use %s to disable the access explicitly", pathname, "--no-msr");6218		no_msr = 1;6219	}6220}6221 6222void probe_bclk(void)6223{6224	unsigned long long msr;6225	unsigned int base_ratio;6226 6227	if (!platform->has_nhm_msrs || no_msr)6228		return;6229 6230	if (platform->bclk_freq == BCLK_100MHZ)6231		bclk = 100.00;6232	else if (platform->bclk_freq == BCLK_133MHZ)6233		bclk = 133.33;6234	else if (platform->bclk_freq == BCLK_SLV)6235		bclk = slm_bclk();6236	else6237		return;6238 6239	get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);6240	base_ratio = (msr >> 8) & 0xFF;6241 6242	base_hz = base_ratio * bclk * 1000000;6243	has_base_hz = 1;6244 6245	if (platform->enable_tsc_tweak)6246		tsc_tweak = base_hz / tsc_hz;6247}6248 6249static void remove_underbar(char *s)6250{6251	char *to = s;6252 6253	while (*s) {6254		if (*s != '_')6255			*to++ = *s;6256		s++;6257	}6258 6259	*to = 0;6260}6261 6262static void dump_turbo_ratio_info(void)6263{6264	if (!has_turbo)6265		return;6266 6267	if (!platform->has_nhm_msrs || no_msr)6268		return;6269 6270	if (platform->trl_msrs & TRL_LIMIT2)6271		dump_turbo_ratio_limit2();6272 6273	if (platform->trl_msrs & TRL_LIMIT1)6274		dump_turbo_ratio_limit1();6275 6276	if (platform->trl_msrs & TRL_BASE) {6277		dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT);6278 6279		if (is_hybrid)6280			dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT);6281	}6282 6283	if (platform->trl_msrs & TRL_ATOM)6284		dump_atom_turbo_ratio_limits();6285 6286	if (platform->trl_msrs & TRL_KNL)6287		dump_knl_turbo_ratio_limits();6288 6289	if (platform->has_config_tdp)6290		dump_config_tdp();6291}6292 6293static int read_sysfs_int(char *path)6294{6295	FILE *input;6296	int retval = -1;6297 6298	input = fopen(path, "r");6299	if (input == NULL) {6300		if (debug)6301			fprintf(outf, "NSFOD %s\n", path);6302		return (-1);6303	}6304	if (fscanf(input, "%d", &retval) != 1)6305		err(1, "%s: failed to read int from file", path);6306	fclose(input);6307 6308	return (retval);6309}6310 6311static void dump_sysfs_file(char *path)6312{6313	FILE *input;6314	char cpuidle_buf[64];6315 6316	input = fopen(path, "r");6317	if (input == NULL) {6318		if (debug)6319			fprintf(outf, "NSFOD %s\n", path);6320		return;6321	}6322	if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input))6323		err(1, "%s: failed to read file", path);6324	fclose(input);6325 6326	fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);6327}6328 6329static void probe_intel_uncore_frequency_legacy(void)6330{6331	int i, j;6332	char path[256];6333 6334	for (i = 0; i < topo.num_packages; ++i) {6335		for (j = 0; j <= topo.max_die_id; ++j) {6336			int k, l;6337			char path_base[128];6338 6339			sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d", i,6340				j);6341 6342			if (access(path_base, R_OK))6343				continue;6344 6345			BIC_PRESENT(BIC_UNCORE_MHZ);6346 6347			if (quiet)6348				return;6349 6350			sprintf(path, "%s/min_freq_khz", path_base);6351			k = read_sysfs_int(path);6352			sprintf(path, "%s/max_freq_khz", path_base);6353			l = read_sysfs_int(path);6354			fprintf(outf, "Uncore Frequency package%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000);6355 6356			sprintf(path, "%s/initial_min_freq_khz", path_base);6357			k = read_sysfs_int(path);6358			sprintf(path, "%s/initial_max_freq_khz", path_base);6359			l = read_sysfs_int(path);6360			fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000);6361 6362			sprintf(path, "%s/current_freq_khz", path_base);6363			k = read_sysfs_int(path);6364			fprintf(outf, " %d MHz\n", k / 1000);6365		}6366	}6367}6368 6369static void probe_intel_uncore_frequency_cluster(void)6370{6371	int i, uncore_max_id;6372	char path[256];6373	char path_base[128];6374 6375	if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00/current_freq_khz", R_OK))6376		return;6377 6378	for (uncore_max_id = 0;; ++uncore_max_id) {6379 6380		sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", uncore_max_id);6381 6382		/* uncore## start at 00 and skips no numbers, so stop upon first missing */6383		if (access(path_base, R_OK)) {6384			uncore_max_id -= 1;6385			break;6386		}6387	}6388	for (i = uncore_max_id; i >= 0; --i) {6389		int k, l;6390		int package_id, domain_id, cluster_id;6391		char name_buf[16];6392 6393		sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", i);6394 6395		if (access(path_base, R_OK))6396			err(1, "%s: %s\n", __func__, path_base);6397 6398		sprintf(path, "%s/package_id", path_base);6399		package_id = read_sysfs_int(path);6400 6401		sprintf(path, "%s/domain_id", path_base);6402		domain_id = read_sysfs_int(path);6403 6404		sprintf(path, "%s/fabric_cluster_id", path_base);6405		cluster_id = read_sysfs_int(path);6406 6407		sprintf(path, "%s/current_freq_khz", path_base);6408		sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id);6409 6410		add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id);6411 6412		if (quiet)6413			continue;6414 6415		sprintf(path, "%s/min_freq_khz", path_base);6416		k = read_sysfs_int(path);6417		sprintf(path, "%s/max_freq_khz", path_base);6418		l = read_sysfs_int(path);6419		fprintf(outf, "Uncore Frequency package%d domain%d cluster%d: %d - %d MHz ", package_id, domain_id,6420			cluster_id, k / 1000, l / 1000);6421 6422		sprintf(path, "%s/initial_min_freq_khz", path_base);6423		k = read_sysfs_int(path);6424		sprintf(path, "%s/initial_max_freq_khz", path_base);6425		l = read_sysfs_int(path);6426		fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000);6427 6428		sprintf(path, "%s/current_freq_khz", path_base);6429		k = read_sysfs_int(path);6430		fprintf(outf, " %d MHz\n", k / 1000);6431	}6432}6433 6434static void probe_intel_uncore_frequency(void)6435{6436	if (!genuine_intel)6437		return;6438 6439	if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK) == 0)6440		probe_intel_uncore_frequency_cluster();6441	else6442		probe_intel_uncore_frequency_legacy();6443}6444 6445static void probe_graphics(void)6446{6447	/* Xe graphics sysfs knobs */6448	if (!access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) {6449		FILE *fp;6450		char buf[8];6451		bool gt0_is_gt;6452		int idx;6453 6454		fp = fopen("/sys/class/drm/card0/device/tile0/gt0/gtidle/name", "r");6455		if (!fp)6456			goto next;6457 6458		if (!fread(buf, sizeof(char), 7, fp)) {6459			fclose(fp);6460			goto next;6461		}6462		fclose(fp);6463 6464		if (!strncmp(buf, "gt0-rc", strlen("gt0-rc")))6465			gt0_is_gt = true;6466		else if (!strncmp(buf, "gt0-mc", strlen("gt0-mc")))6467			gt0_is_gt = false;6468		else6469			goto next;6470 6471		idx = gt0_is_gt ? GFX_rc6 : SAM_mc6;6472		gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms";6473 6474		idx = gt0_is_gt ? GFX_MHz : SAM_MHz;6475		if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", R_OK))6476			gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq";6477 6478		idx = gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz;6479		if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", R_OK))6480			gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq";6481 6482		idx = gt0_is_gt ? SAM_mc6 : GFX_rc6;6483		if (!access("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", R_OK))6484			gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms";6485 6486		idx = gt0_is_gt ? SAM_MHz : GFX_MHz;6487		if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", R_OK))6488			gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq";6489 6490		idx = gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz;6491		if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", R_OK))6492			gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq";6493 6494		goto end;6495	}6496 6497next:6498	/* New i915 graphics sysfs knobs */6499	if (!access("/sys/class/drm/card0/gt/gt0/rc6_residency_ms", R_OK)) {6500		gfx_info[GFX_rc6].path = "/sys/class/drm/card0/gt/gt0/rc6_residency_ms";6501 6502		if (!access("/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz", R_OK))6503			gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz";6504 6505		if (!access("/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz", R_OK))6506			gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz";6507 6508		if (!access("/sys/class/drm/card0/gt/gt1/rc6_residency_ms", R_OK))6509			gfx_info[SAM_mc6].path = "/sys/class/drm/card0/gt/gt1/rc6_residency_ms";6510 6511		if (!access("/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz", R_OK))6512			gfx_info[SAM_MHz].path = "/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz";6513 6514		if (!access("/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz", R_OK))6515			gfx_info[SAM_ACTMHz].path = "/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz";6516 6517		goto end;6518	}6519 6520	/* Fall back to traditional i915 graphics sysfs knobs */6521	if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))6522		gfx_info[GFX_rc6].path = "/sys/class/drm/card0/power/rc6_residency_ms";6523 6524	if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK))6525		gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt_cur_freq_mhz";6526	else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))6527		gfx_info[GFX_MHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz";6528 6529	if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK))6530		gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt_act_freq_mhz";6531	else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))6532		gfx_info[GFX_ACTMHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz";6533 6534end:6535	if (gfx_info[GFX_rc6].path)6536		BIC_PRESENT(BIC_GFX_rc6);6537	if (gfx_info[GFX_MHz].path)6538		BIC_PRESENT(BIC_GFXMHz);6539	if (gfx_info[GFX_ACTMHz].path)6540		BIC_PRESENT(BIC_GFXACTMHz);6541	if (gfx_info[SAM_mc6].path)6542		BIC_PRESENT(BIC_SAM_mc6);6543	if (gfx_info[SAM_MHz].path)6544		BIC_PRESENT(BIC_SAMMHz);6545	if (gfx_info[SAM_ACTMHz].path)6546		BIC_PRESENT(BIC_SAMACTMHz);6547}6548 6549static void dump_sysfs_cstate_config(void)6550{6551	char path[64];6552	char name_buf[16];6553	char desc[64];6554	FILE *input;6555	int state;6556	char *sp;6557 6558	if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {6559		fprintf(outf, "cpuidle not loaded\n");6560		return;6561	}6562 6563	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver");6564	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor");6565	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro");6566 6567	for (state = 0; state < 10; ++state) {6568 6569		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);6570		input = fopen(path, "r");6571		if (input == NULL)6572			continue;6573		if (!fgets(name_buf, sizeof(name_buf), input))6574			err(1, "%s: failed to read file", path);6575 6576		/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */6577		sp = strchr(name_buf, '-');6578		if (!sp)6579			sp = strchrnul(name_buf, '\n');6580		*sp = '\0';6581		fclose(input);6582 6583		remove_underbar(name_buf);6584 6585		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc", base_cpu, state);6586		input = fopen(path, "r");6587		if (input == NULL)6588			continue;6589		if (!fgets(desc, sizeof(desc), input))6590			err(1, "%s: failed to read file", path);6591 6592		fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc);6593		fclose(input);6594	}6595}6596 6597static void dump_sysfs_pstate_config(void)6598{6599	char path[64];6600	char driver_buf[64];6601	char governor_buf[64];6602	FILE *input;6603	int turbo;6604 6605	sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", base_cpu);6606	input = fopen(path, "r");6607	if (input == NULL) {6608		fprintf(outf, "NSFOD %s\n", path);6609		return;6610	}6611	if (!fgets(driver_buf, sizeof(driver_buf), input))6612		err(1, "%s: failed to read file", path);6613	fclose(input);6614 6615	sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", base_cpu);6616	input = fopen(path, "r");6617	if (input == NULL) {6618		fprintf(outf, "NSFOD %s\n", path);6619		return;6620	}6621	if (!fgets(governor_buf, sizeof(governor_buf), input))6622		err(1, "%s: failed to read file", path);6623	fclose(input);6624 6625	fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf);6626	fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf);6627 6628	sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");6629	input = fopen(path, "r");6630	if (input != NULL) {6631		if (fscanf(input, "%d", &turbo) != 1)6632			err(1, "%s: failed to parse number from file", path);6633		fprintf(outf, "cpufreq boost: %d\n", turbo);6634		fclose(input);6635	}6636 6637	sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");6638	input = fopen(path, "r");6639	if (input != NULL) {6640		if (fscanf(input, "%d", &turbo) != 1)6641			err(1, "%s: failed to parse number from file", path);6642		fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);6643		fclose(input);6644	}6645}6646 6647/*6648 * print_epb()6649 * Decode the ENERGY_PERF_BIAS MSR6650 */6651int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)6652{6653	char *epb_string;6654	int cpu, epb;6655 6656	UNUSED(c);6657	UNUSED(p);6658 6659	if (!has_epb)6660		return 0;6661 6662	cpu = t->cpu_id;6663 6664	/* EPB is per-package */6665	if (!is_cpu_first_thread_in_package(t, c, p))6666		return 0;6667 6668	if (cpu_migrate(cpu)) {6669		fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);6670		return -1;6671	}6672 6673	epb = get_epb(cpu);6674	if (epb < 0)6675		return 0;6676 6677	switch (epb) {6678	case ENERGY_PERF_BIAS_PERFORMANCE:6679		epb_string = "performance";6680		break;6681	case ENERGY_PERF_BIAS_NORMAL:6682		epb_string = "balanced";6683		break;6684	case ENERGY_PERF_BIAS_POWERSAVE:6685		epb_string = "powersave";6686		break;6687	default:6688		epb_string = "custom";6689		break;6690	}6691	fprintf(outf, "cpu%d: EPB: %d (%s)\n", cpu, epb, epb_string);6692 6693	return 0;6694}6695 6696/*6697 * print_hwp()6698 * Decode the MSR_HWP_CAPABILITIES6699 */6700int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)6701{6702	unsigned long long msr;6703	int cpu;6704 6705	UNUSED(c);6706	UNUSED(p);6707 6708	if (no_msr)6709		return 0;6710 6711	if (!has_hwp)6712		return 0;6713 6714	cpu = t->cpu_id;6715 6716	/* MSR_HWP_CAPABILITIES is per-package */6717	if (!is_cpu_first_thread_in_package(t, c, p))6718		return 0;6719 6720	if (cpu_migrate(cpu)) {6721		fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);6722		return -1;6723	}6724 6725	if (get_msr(cpu, MSR_PM_ENABLE, &msr))6726		return 0;6727 6728	fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", cpu, msr, (msr & (1 << 0)) ? "" : "No-");6729 6730	/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */6731	if ((msr & (1 << 0)) == 0)6732		return 0;6733 6734	if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))6735		return 0;6736 6737	fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "6738		"(high %d guar %d eff %d low %d)\n",6739		cpu, msr,6740		(unsigned int)HWP_HIGHEST_PERF(msr),6741		(unsigned int)HWP_GUARANTEED_PERF(msr),6742		(unsigned int)HWP_MOSTEFFICIENT_PERF(msr), (unsigned int)HWP_LOWEST_PERF(msr));6743 6744	if (get_msr(cpu, MSR_HWP_REQUEST, &msr))6745		return 0;6746 6747	fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "6748		"(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",6749		cpu, msr,6750		(unsigned int)(((msr) >> 0) & 0xff),6751		(unsigned int)(((msr) >> 8) & 0xff),6752		(unsigned int)(((msr) >> 16) & 0xff),6753		(unsigned int)(((msr) >> 24) & 0xff),6754		(unsigned int)(((msr) >> 32) & 0xff3), (unsigned int)(((msr) >> 42) & 0x1));6755 6756	if (has_hwp_pkg) {6757		if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))6758			return 0;6759 6760		fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "6761			"(min %d max %d des %d epp 0x%x window 0x%x)\n",6762			cpu, msr,6763			(unsigned int)(((msr) >> 0) & 0xff),6764			(unsigned int)(((msr) >> 8) & 0xff),6765			(unsigned int)(((msr) >> 16) & 0xff),6766			(unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3));6767	}6768	if (has_hwp_notify) {6769		if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))6770			return 0;6771 6772		fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "6773			"(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",6774			cpu, msr, ((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x2) ? "EN" : "Dis");6775	}6776	if (get_msr(cpu, MSR_HWP_STATUS, &msr))6777		return 0;6778 6779	fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "6780		"(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",6781		cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-");6782 6783	return 0;6784}6785 6786/*6787 * print_perf_limit()6788 */6789int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p)6790{6791	unsigned long long msr;6792	int cpu;6793 6794	UNUSED(c);6795	UNUSED(p);6796 6797	if (no_msr)6798		return 0;6799 6800	cpu = t->cpu_id;6801 6802	/* per-package */6803	if (!is_cpu_first_thread_in_package(t, c, p))6804		return 0;6805 6806	if (cpu_migrate(cpu)) {6807		fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);6808		return -1;6809	}6810 6811	if (platform->plr_msrs & PLR_CORE) {6812		get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);6813		fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);6814		fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",6815			(msr & 1 << 15) ? "bit15, " : "",6816			(msr & 1 << 14) ? "bit14, " : "",6817			(msr & 1 << 13) ? "Transitions, " : "",6818			(msr & 1 << 12) ? "MultiCoreTurbo, " : "",6819			(msr & 1 << 11) ? "PkgPwrL2, " : "",6820			(msr & 1 << 10) ? "PkgPwrL1, " : "",6821			(msr & 1 << 9) ? "CorePwr, " : "",6822			(msr & 1 << 8) ? "Amps, " : "",6823			(msr & 1 << 6) ? "VR-Therm, " : "",6824			(msr & 1 << 5) ? "Auto-HWP, " : "",6825			(msr & 1 << 4) ? "Graphics, " : "",6826			(msr & 1 << 2) ? "bit2, " : "",6827			(msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 0) ? "PROCHOT, " : "");6828		fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",6829			(msr & 1 << 31) ? "bit31, " : "",6830			(msr & 1 << 30) ? "bit30, " : "",6831			(msr & 1 << 29) ? "Transitions, " : "",6832			(msr & 1 << 28) ? "MultiCoreTurbo, " : "",6833			(msr & 1 << 27) ? "PkgPwrL2, " : "",6834			(msr & 1 << 26) ? "PkgPwrL1, " : "",6835			(msr & 1 << 25) ? "CorePwr, " : "",6836			(msr & 1 << 24) ? "Amps, " : "",6837			(msr & 1 << 22) ? "VR-Therm, " : "",6838			(msr & 1 << 21) ? "Auto-HWP, " : "",6839			(msr & 1 << 20) ? "Graphics, " : "",6840			(msr & 1 << 18) ? "bit18, " : "",6841			(msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 16) ? "PROCHOT, " : "");6842 6843	}6844	if (platform->plr_msrs & PLR_GFX) {6845		get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);6846		fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);6847		fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",6848			(msr & 1 << 0) ? "PROCHOT, " : "",6849			(msr & 1 << 1) ? "ThermStatus, " : "",6850			(msr & 1 << 4) ? "Graphics, " : "",6851			(msr & 1 << 6) ? "VR-Therm, " : "",6852			(msr & 1 << 8) ? "Amps, " : "",6853			(msr & 1 << 9) ? "GFXPwr, " : "",6854			(msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");6855		fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",6856			(msr & 1 << 16) ? "PROCHOT, " : "",6857			(msr & 1 << 17) ? "ThermStatus, " : "",6858			(msr & 1 << 20) ? "Graphics, " : "",6859			(msr & 1 << 22) ? "VR-Therm, " : "",6860			(msr & 1 << 24) ? "Amps, " : "",6861			(msr & 1 << 25) ? "GFXPwr, " : "",6862			(msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");6863	}6864	if (platform->plr_msrs & PLR_RING) {6865		get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);6866		fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);6867		fprintf(outf, " (Active: %s%s%s%s%s%s)",6868			(msr & 1 << 0) ? "PROCHOT, " : "",6869			(msr & 1 << 1) ? "ThermStatus, " : "",6870			(msr & 1 << 6) ? "VR-Therm, " : "",6871			(msr & 1 << 8) ? "Amps, " : "",6872			(msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");6873		fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",6874			(msr & 1 << 16) ? "PROCHOT, " : "",6875			(msr & 1 << 17) ? "ThermStatus, " : "",6876			(msr & 1 << 22) ? "VR-Therm, " : "",6877			(msr & 1 << 24) ? "Amps, " : "",6878			(msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");6879	}6880	return 0;6881}6882 6883#define	RAPL_POWER_GRANULARITY	0x7FFF	/* 15 bit power granularity */6884#define	RAPL_TIME_GRANULARITY	0x3F	/* 6 bit time granularity */6885 6886double get_quirk_tdp(void)6887{6888	if (platform->rapl_quirk_tdp)6889		return platform->rapl_quirk_tdp;6890 6891	return 135.0;6892}6893 6894double get_tdp_intel(void)6895{6896	unsigned long long msr;6897 6898	if (platform->rapl_msrs & RAPL_PKG_POWER_INFO)6899		if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr))6900			return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;6901	return get_quirk_tdp();6902}6903 6904double get_tdp_amd(void)6905{6906	return get_quirk_tdp();6907}6908 6909void rapl_probe_intel(void)6910{6911	unsigned long long msr;6912	unsigned int time_unit;6913	double tdp;6914	const unsigned long long bic_watt_bits = BIC_PkgWatt | BIC_CorWatt | BIC_RAMWatt | BIC_GFXWatt;6915	const unsigned long long bic_joules_bits = BIC_Pkg_J | BIC_Cor_J | BIC_RAM_J | BIC_GFX_J;6916 6917	if (rapl_joules)6918		bic_enabled &= ~bic_watt_bits;6919	else6920		bic_enabled &= ~bic_joules_bits;6921 6922	if (!(platform->rapl_msrs & RAPL_PKG_PERF_STATUS))6923		bic_enabled &= ~BIC_PKG__;6924	if (!(platform->rapl_msrs & RAPL_DRAM_PERF_STATUS))6925		bic_enabled &= ~BIC_RAM__;6926 6927	/* units on package 0, verify later other packages match */6928	if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr))6929		return;6930 6931	rapl_power_units = 1.0 / (1 << (msr & 0xF));6932	if (platform->has_rapl_divisor)6933		rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;6934	else6935		rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));6936 6937	if (platform->has_fixed_rapl_unit)6938		rapl_dram_energy_units = (15.3 / 1000000);6939	else6940		rapl_dram_energy_units = rapl_energy_units;6941 6942	time_unit = msr >> 16 & 0xF;6943	if (time_unit == 0)6944		time_unit = 0xA;6945 6946	rapl_time_units = 1.0 / (1 << (time_unit));6947 6948	tdp = get_tdp_intel();6949 6950	rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;6951	if (!quiet)6952		fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);6953}6954 6955void rapl_probe_amd(void)6956{6957	unsigned long long msr;6958	double tdp;6959	const unsigned long long bic_watt_bits = BIC_PkgWatt | BIC_CorWatt;6960	const unsigned long long bic_joules_bits = BIC_Pkg_J | BIC_Cor_J;6961 6962	if (rapl_joules)6963		bic_enabled &= ~bic_watt_bits;6964	else6965		bic_enabled &= ~bic_joules_bits;6966 6967	if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))6968		return;6969 6970	rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf));6971	rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));6972	rapl_power_units = ldexp(1.0, -(msr & 0xf));6973 6974	tdp = get_tdp_amd();6975 6976	rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;6977	if (!quiet)6978		fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);6979}6980 6981void print_power_limit_msr(int cpu, unsigned long long msr, char *label)6982{6983	fprintf(outf, "cpu%d: %s: %sabled (%0.3f Watts, %f sec, clamp %sabled)\n",6984		cpu, label,6985		((msr >> 15) & 1) ? "EN" : "DIS",6986		((msr >> 0) & 0x7FFF) * rapl_power_units,6987		(1.0 + (((msr >> 22) & 0x3) / 4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units,6988		(((msr >> 16) & 1) ? "EN" : "DIS"));6989 6990	return;6991}6992 6993int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)6994{6995	unsigned long long msr;6996	const char *msr_name;6997	int cpu;6998 6999	UNUSED(c);7000	UNUSED(p);7001 7002	if (!platform->rapl_msrs)7003		return 0;7004 7005	/* RAPL counters are per package, so print only for 1st thread/package */7006	if (!is_cpu_first_thread_in_package(t, c, p))7007		return 0;7008 7009	cpu = t->cpu_id;7010	if (cpu_migrate(cpu)) {7011		fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);7012		return -1;7013	}7014 7015	if (platform->rapl_msrs & RAPL_AMD_F17H) {7016		msr_name = "MSR_RAPL_PWR_UNIT";7017		if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr))7018			return -1;7019	} else {7020		msr_name = "MSR_RAPL_POWER_UNIT";7021		if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))7022			return -1;7023	}7024 7025	fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr,7026		rapl_power_units, rapl_energy_units, rapl_time_units);7027 7028	if (platform->rapl_msrs & RAPL_PKG_POWER_INFO) {7029 7030		if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))7031			return -5;7032 7033		fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",7034			cpu, msr,7035			((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,7036			((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,7037			((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,7038			((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);7039 7040	}7041	if (platform->rapl_msrs & RAPL_PKG) {7042 7043		if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))7044			return -9;7045 7046		fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",7047			cpu, msr, (msr >> 63) & 1 ? "" : "UN");7048 7049		print_power_limit_msr(cpu, msr, "PKG Limit #1");7050		fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%0.3f Watts, %f* sec, clamp %sabled)\n",7051			cpu,7052			((msr >> 47) & 1) ? "EN" : "DIS",7053			((msr >> 32) & 0x7FFF) * rapl_power_units,7054			(1.0 + (((msr >> 54) & 0x3) / 4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units,7055			((msr >> 48) & 1) ? "EN" : "DIS");7056 7057		if (get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr))7058			return -9;7059 7060		fprintf(outf, "cpu%d: MSR_VR_CURRENT_CONFIG: 0x%08llx\n", cpu, msr);7061		fprintf(outf, "cpu%d: PKG Limit #4: %f Watts (%slocked)\n",7062			cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN");7063	}7064 7065	if (platform->rapl_msrs & RAPL_DRAM_POWER_INFO) {7066		if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))7067			return -6;7068 7069		fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",7070			cpu, msr,7071			((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,7072			((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,7073			((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,7074			((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);7075	}7076	if (platform->rapl_msrs & RAPL_DRAM) {7077		if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))7078			return -9;7079		fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",7080			cpu, msr, (msr >> 31) & 1 ? "" : "UN");7081 7082		print_power_limit_msr(cpu, msr, "DRAM Limit");7083	}7084	if (platform->rapl_msrs & RAPL_CORE_POLICY) {7085		if (get_msr(cpu, MSR_PP0_POLICY, &msr))7086			return -7;7087 7088		fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);7089	}7090	if (platform->rapl_msrs & RAPL_CORE_POWER_LIMIT) {7091		if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))7092			return -9;7093		fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",7094			cpu, msr, (msr >> 31) & 1 ? "" : "UN");7095		print_power_limit_msr(cpu, msr, "Cores Limit");7096	}7097	if (platform->rapl_msrs & RAPL_GFX) {7098		if (get_msr(cpu, MSR_PP1_POLICY, &msr))7099			return -8;7100 7101		fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);7102 7103		if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))7104			return -9;7105		fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",7106			cpu, msr, (msr >> 31) & 1 ? "" : "UN");7107		print_power_limit_msr(cpu, msr, "GFX Limit");7108	}7109	return 0;7110}7111 7112/*7113 * probe_rapl()7114 *7115 * sets rapl_power_units, rapl_energy_units, rapl_time_units7116 */7117void probe_rapl(void)7118{7119	if (!platform->rapl_msrs || no_msr)7120		return;7121 7122	if (genuine_intel)7123		rapl_probe_intel();7124	if (authentic_amd || hygon_genuine)7125		rapl_probe_amd();7126 7127	if (quiet)7128		return;7129 7130	for_all_cpus(print_rapl, ODD_COUNTERS);7131}7132 7133/*7134 * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where7135 * the Thermal Control Circuit (TCC) activates.7136 * This is usually equal to tjMax.7137 *7138 * Older processors do not have this MSR, so there we guess,7139 * but also allow cmdline over-ride with -T.7140 *7141 * Several MSR temperature values are in units of degrees-C7142 * below this value, including the Digital Thermal Sensor (DTS),7143 * Package Thermal Management Sensor (PTM), and thermal event thresholds.7144 */7145int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)7146{7147	unsigned long long msr;7148	unsigned int tcc_default, tcc_offset;7149	int cpu;7150 7151	UNUSED(c);7152	UNUSED(p);7153 7154	/* tj_max is used only for dts or ptm */7155	if (!(do_dts || do_ptm))7156		return 0;7157 7158	/* this is a per-package concept */7159	if (!is_cpu_first_thread_in_package(t, c, p))7160		return 0;7161 7162	cpu = t->cpu_id;7163	if (cpu_migrate(cpu)) {7164		fprintf(outf, "Could not migrate to CPU %d\n", cpu);7165		return -1;7166	}7167 7168	if (tj_max_override != 0) {7169		tj_max = tj_max_override;7170		fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", cpu, tj_max);7171		return 0;7172	}7173 7174	/* Temperature Target MSR is Nehalem and newer only */7175	if (!platform->has_nhm_msrs || no_msr)7176		goto guess;7177 7178	if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))7179		goto guess;7180 7181	tcc_default = (msr >> 16) & 0xFF;7182 7183	if (!quiet) {7184		int bits = platform->tcc_offset_bits;7185		unsigned long long enabled = 0;7186 7187		if (bits && !get_msr(base_cpu, MSR_PLATFORM_INFO, &enabled))7188			enabled = (enabled >> 30) & 1;7189 7190		if (bits && enabled) {7191			tcc_offset = (msr >> 24) & GENMASK(bits - 1, 0);7192			fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n",7193				cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset);7194		} else {7195			fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, tcc_default);7196		}7197	}7198 7199	if (!tcc_default)7200		goto guess;7201 7202	tj_max = tcc_default;7203 7204	return 0;7205 7206guess:7207	tj_max = TJMAX_DEFAULT;7208	fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", cpu, tj_max);7209 7210	return 0;7211}7212 7213int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p)7214{7215	unsigned long long msr;7216	unsigned int dts, dts2;7217	int cpu;7218 7219	UNUSED(c);7220	UNUSED(p);7221 7222	if (no_msr)7223		return 0;7224 7225	if (!(do_dts || do_ptm))7226		return 0;7227 7228	cpu = t->cpu_id;7229 7230	/* DTS is per-core, no need to print for each thread */7231	if (!is_cpu_first_thread_in_core(t, c, p))7232		return 0;7233 7234	if (cpu_migrate(cpu)) {7235		fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);7236		return -1;7237	}7238 7239	if (do_ptm && is_cpu_first_core_in_package(t, c, p)) {7240		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))7241			return 0;7242 7243		dts = (msr >> 16) & 0x7F;7244		fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts);7245 7246		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr))7247			return 0;7248 7249		dts = (msr >> 16) & 0x7F;7250		dts2 = (msr >> 8) & 0x7F;7251		fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",7252			cpu, msr, tj_max - dts, tj_max - dts2);7253	}7254 7255	if (do_dts && debug) {7256		unsigned int resolution;7257 7258		if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))7259			return 0;7260 7261		dts = (msr >> 16) & 0x7F;7262		resolution = (msr >> 27) & 0xF;7263		fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",7264			cpu, msr, tj_max - dts, resolution);7265 7266		if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr))7267			return 0;7268 7269		dts = (msr >> 16) & 0x7F;7270		dts2 = (msr >> 8) & 0x7F;7271		fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",7272			cpu, msr, tj_max - dts, tj_max - dts2);7273	}7274 7275	return 0;7276}7277 7278void probe_thermal(void)7279{7280	if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK))7281		BIC_PRESENT(BIC_CORE_THROT_CNT);7282	else7283		BIC_NOT_PRESENT(BIC_CORE_THROT_CNT);7284 7285	for_all_cpus(set_temperature_target, ODD_COUNTERS);7286 7287	if (quiet)7288		return;7289 7290	for_all_cpus(print_thermal, ODD_COUNTERS);7291}7292 7293int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p)7294{7295	unsigned int eax, ebx, ecx, edx;7296 7297	UNUSED(c);7298	UNUSED(p);7299 7300	if (!genuine_intel)7301		return 0;7302 7303	if (cpu_migrate(t->cpu_id)) {7304		fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id);7305		return -1;7306	}7307 7308	if (max_level < 0x1a)7309		return 0;7310 7311	__cpuid(0x1a, eax, ebx, ecx, edx);7312	eax = (eax >> 24) & 0xFF;7313	if (eax == 0x20)7314		t->is_atom = true;7315	return 0;7316}7317 7318void decode_feature_control_msr(void)7319{7320	unsigned long long msr;7321 7322	if (no_msr)7323		return;7324 7325	if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr))7326		fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",7327			base_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : "");7328}7329 7330void decode_misc_enable_msr(void)7331{7332	unsigned long long msr;7333 7334	if (no_msr)7335		return;7336 7337	if (!genuine_intel)7338		return;7339 7340	if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))7341		fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",7342			base_cpu, msr,7343			msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",7344			msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",7345			msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-",7346			msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "",7347			msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");7348}7349 7350void decode_misc_feature_control(void)7351{7352	unsigned long long msr;7353 7354	if (no_msr)7355		return;7356 7357	if (!platform->has_msr_misc_feature_control)7358		return;7359 7360	if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))7361		fprintf(outf,7362			"cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",7363			base_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "",7364			msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : "");7365}7366 7367/*7368 * Decode MSR_MISC_PWR_MGMT7369 *7370 * Decode the bits according to the Nehalem documentation7371 * bit[0] seems to continue to have same meaning going forward7372 * bit[1] less so...7373 */7374void decode_misc_pwr_mgmt_msr(void)7375{7376	unsigned long long msr;7377 7378	if (no_msr)7379		return;7380 7381	if (!platform->has_msr_misc_pwr_mgmt)7382		return;7383 7384	if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))7385		fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",7386			base_cpu, msr,7387			msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS");7388}7389 7390/*7391 * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG7392 *7393 * This MSRs are present on Silvermont processors,7394 * Intel Atom processor E3000 series (Baytrail), and friends.7395 */7396void decode_c6_demotion_policy_msr(void)7397{7398	unsigned long long msr;7399 7400	if (no_msr)7401		return;7402 7403	if (!platform->has_msr_c6_demotion_policy_config)7404		return;7405 7406	if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))7407		fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",7408			base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");7409 7410	if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))7411		fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",7412			base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");7413}7414 7415void print_dev_latency(void)7416{7417	char *path = "/dev/cpu_dma_latency";7418	int fd;7419	int value;7420	int retval;7421 7422	fd = open(path, O_RDONLY);7423	if (fd < 0) {7424		if (debug)7425			warnx("Read %s failed", path);7426		return;7427	}7428 7429	retval = read(fd, (void *)&value, sizeof(int));7430	if (retval != sizeof(int)) {7431		warn("read failed %s", path);7432		close(fd);7433		return;7434	}7435	fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n", value, value == 2000000000 ? "default" : "constrained");7436 7437	close(fd);7438}7439 7440static int has_instr_count_access(void)7441{7442	int fd;7443	int has_access;7444 7445	if (no_perf)7446		return 0;7447 7448	fd = open_perf_counter(base_cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0);7449	has_access = fd != -1;7450 7451	if (fd != -1)7452		close(fd);7453 7454	if (!has_access)7455		warnx("Failed to access %s. Some of the counters may not be available\n"7456		      "\tRun as root to enable them or use %s to disable the access explicitly",7457		      "instructions retired perf counter", "--no-perf");7458 7459	return has_access;7460}7461 7462int add_rapl_perf_counter_(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai,7463			   double *scale_, enum rapl_unit *unit_)7464{7465	if (no_perf)7466		return -1;7467 7468	const double scale = read_perf_scale(cai->perf_subsys, cai->perf_name);7469 7470	if (scale == 0.0)7471		return -1;7472 7473	const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name);7474 7475	if (unit == RAPL_UNIT_INVALID)7476		return -1;7477 7478	const unsigned int rapl_type = read_perf_type(cai->perf_subsys);7479	const unsigned int rapl_energy_pkg_config = read_perf_config(cai->perf_subsys, cai->perf_name);7480 7481	const int fd_counter =7482	    open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP);7483	if (fd_counter == -1)7484		return -1;7485 7486	/* If it's the first counter opened, make it a group descriptor */7487	if (rci->fd_perf == -1)7488		rci->fd_perf = fd_counter;7489 7490	*scale_ = scale;7491	*unit_ = unit;7492	return fd_counter;7493}7494 7495int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai,7496			  double *scale, enum rapl_unit *unit)7497{7498	int ret = add_rapl_perf_counter_(cpu, rci, cai, scale, unit);7499 7500	if (debug >= 2)7501		fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);7502 7503	return ret;7504}7505 7506/*7507 * Linux-perf manages the HW instructions-retired counter7508 * by enabling when requested, and hiding rollover7509 */7510void linux_perf_init(void)7511{7512	if (access("/proc/sys/kernel/perf_event_paranoid", F_OK))7513		return;7514 7515	if (BIC_IS_ENABLED(BIC_IPC) && has_aperf) {7516		fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));7517		if (fd_instr_count_percpu == NULL)7518			err(-1, "calloc fd_instr_count_percpu");7519	}7520}7521 7522void rapl_perf_init(void)7523{7524	const unsigned int num_domains = (platform->has_per_core_rapl ? topo.max_core_id : topo.max_package_id) + 1;7525	bool *domain_visited = calloc(num_domains, sizeof(bool));7526 7527	rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain));7528	if (rapl_counter_info_perdomain == NULL)7529		err(-1, "calloc rapl_counter_info_percpu");7530	rapl_counter_info_perdomain_size = num_domains;7531 7532	/*7533	 * Initialize rapl_counter_info_percpu7534	 */7535	for (unsigned int domain_id = 0; domain_id < num_domains; ++domain_id) {7536		struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id];7537 7538		rci->fd_perf = -1;7539		for (size_t i = 0; i < NUM_RAPL_COUNTERS; ++i) {7540			rci->data[i] = 0;7541			rci->source[i] = COUNTER_SOURCE_NONE;7542		}7543	}7544 7545	/*7546	 * Open/probe the counters7547	 * If can't get it via perf, fallback to MSR7548	 */7549	for (size_t i = 0; i < ARRAY_SIZE(rapl_counter_arch_infos); ++i) {7550 7551		const struct rapl_counter_arch_info *const cai = &rapl_counter_arch_infos[i];7552		bool has_counter = 0;7553		double scale;7554		enum rapl_unit unit;7555		unsigned int next_domain;7556 7557		memset(domain_visited, 0, num_domains * sizeof(*domain_visited));7558 7559		for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) {7560 7561			if (cpu_is_not_allowed(cpu))7562				continue;7563 7564			/* Skip already seen and handled RAPL domains */7565			next_domain =7566			    platform->has_per_core_rapl ? cpus[cpu].physical_core_id : cpus[cpu].physical_package_id;7567 7568			assert(next_domain < num_domains);7569 7570			if (domain_visited[next_domain])7571				continue;7572 7573			domain_visited[next_domain] = 1;7574 7575			struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain];7576 7577			/* Check if the counter is enabled and accessible */7578			if (BIC_IS_ENABLED(cai->bic) && (platform->rapl_msrs & cai->feature_mask)) {7579 7580				/* Use perf API for this counter */7581				if (!no_perf && cai->perf_name7582				    && add_rapl_perf_counter(cpu, rci, cai, &scale, &unit) != -1) {7583					rci->source[cai->rci_index] = COUNTER_SOURCE_PERF;7584					rci->scale[cai->rci_index] = scale * cai->compat_scale;7585					rci->unit[cai->rci_index] = unit;7586					rci->flags[cai->rci_index] = cai->flags;7587 7588					/* Use MSR for this counter */7589				} else if (!no_msr && cai->msr && probe_msr(cpu, cai->msr) == 0) {7590					rci->source[cai->rci_index] = COUNTER_SOURCE_MSR;7591					rci->msr[cai->rci_index] = cai->msr;7592					rci->msr_mask[cai->rci_index] = cai->msr_mask;7593					rci->msr_shift[cai->rci_index] = cai->msr_shift;7594					rci->unit[cai->rci_index] = RAPL_UNIT_JOULES;7595					rci->scale[cai->rci_index] = *cai->platform_rapl_msr_scale * cai->compat_scale;7596					rci->flags[cai->rci_index] = cai->flags;7597				}7598			}7599 7600			if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE)7601				has_counter = 1;7602		}7603 7604		/* If any CPU has access to the counter, make it present */7605		if (has_counter)7606			BIC_PRESENT(cai->bic);7607	}7608 7609	free(domain_visited);7610}7611 7612/* Assumes msr_counter_info is populated */7613static int has_amperf_access(void)7614{7615	return msr_counter_arch_infos[MSR_ARCH_INFO_APERF_INDEX].present &&7616	    msr_counter_arch_infos[MSR_ARCH_INFO_MPERF_INDEX].present;7617}7618 7619int *get_cstate_perf_group_fd(struct cstate_counter_info_t *cci, const char *group_name)7620{7621	if (strcmp(group_name, "cstate_core") == 0)7622		return &cci->fd_perf_core;7623 7624	if (strcmp(group_name, "cstate_pkg") == 0)7625		return &cci->fd_perf_pkg;7626 7627	return NULL;7628}7629 7630int add_cstate_perf_counter_(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai)7631{7632	if (no_perf)7633		return -1;7634 7635	int *pfd_group = get_cstate_perf_group_fd(cci, cai->perf_subsys);7636 7637	if (pfd_group == NULL)7638		return -1;7639 7640	const unsigned int type = read_perf_type(cai->perf_subsys);7641	const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);7642 7643	const int fd_counter = open_perf_counter(cpu, type, config, *pfd_group, PERF_FORMAT_GROUP);7644 7645	if (fd_counter == -1)7646		return -1;7647 7648	/* If it's the first counter opened, make it a group descriptor */7649	if (*pfd_group == -1)7650		*pfd_group = fd_counter;7651 7652	return fd_counter;7653}7654 7655int add_cstate_perf_counter(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai)7656{7657	int ret = add_cstate_perf_counter_(cpu, cci, cai);7658 7659	if (debug >= 2)7660		fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);7661 7662	return ret;7663}7664 7665int add_msr_perf_counter_(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai)7666{7667	if (no_perf)7668		return -1;7669 7670	const unsigned int type = read_perf_type(cai->perf_subsys);7671	const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);7672 7673	const int fd_counter = open_perf_counter(cpu, type, config, cci->fd_perf, PERF_FORMAT_GROUP);7674 7675	if (fd_counter == -1)7676		return -1;7677 7678	/* If it's the first counter opened, make it a group descriptor */7679	if (cci->fd_perf == -1)7680		cci->fd_perf = fd_counter;7681 7682	return fd_counter;7683}7684 7685int add_msr_perf_counter(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai)7686{7687	int ret = add_msr_perf_counter_(cpu, cci, cai);7688 7689	if (debug)7690		fprintf(stderr, "%s: %s/%s: %d (cpu: %d)\n", __func__, cai->perf_subsys, cai->perf_name, ret, cpu);7691 7692	return ret;7693}7694 7695void msr_perf_init_(void)7696{7697	const int mci_num = topo.max_cpu_num + 1;7698 7699	msr_counter_info = calloc(mci_num, sizeof(*msr_counter_info));7700	if (!msr_counter_info)7701		err(1, "calloc msr_counter_info");7702	msr_counter_info_size = mci_num;7703 7704	for (int cpu = 0; cpu < mci_num; ++cpu)7705		msr_counter_info[cpu].fd_perf = -1;7706 7707	for (int cidx = 0; cidx < NUM_MSR_COUNTERS; ++cidx) {7708 7709		struct msr_counter_arch_info *cai = &msr_counter_arch_infos[cidx];7710 7711		cai->present = false;7712 7713		for (int cpu = 0; cpu < mci_num; ++cpu) {7714 7715			struct msr_counter_info_t *const cci = &msr_counter_info[cpu];7716 7717			if (cpu_is_not_allowed(cpu))7718				continue;7719 7720			if (cai->needed) {7721				/* Use perf API for this counter */7722				if (!no_perf && cai->perf_name && add_msr_perf_counter(cpu, cci, cai) != -1) {7723					cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;7724					cai->present = true;7725 7726					/* User MSR for this counter */7727				} else if (!no_msr && cai->msr && probe_msr(cpu, cai->msr) == 0) {7728					cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;7729					cci->msr[cai->rci_index] = cai->msr;7730					cci->msr_mask[cai->rci_index] = cai->msr_mask;7731					cai->present = true;7732				}7733			}7734		}7735	}7736}7737 7738/* Initialize data for reading perf counters from the MSR group. */7739void msr_perf_init(void)7740{7741	bool need_amperf = false, need_smi = false;7742	const bool need_soft_c1 = (!platform->has_msr_core_c1_res) && (platform->supported_cstates & CC1);7743 7744	need_amperf = BIC_IS_ENABLED(BIC_Avg_MHz) || BIC_IS_ENABLED(BIC_Busy) || BIC_IS_ENABLED(BIC_Bzy_MHz)7745	    || BIC_IS_ENABLED(BIC_IPC) || need_soft_c1;7746 7747	if (BIC_IS_ENABLED(BIC_SMI))7748		need_smi = true;7749 7750	/* Enable needed counters */7751	msr_counter_arch_infos[MSR_ARCH_INFO_APERF_INDEX].needed = need_amperf;7752	msr_counter_arch_infos[MSR_ARCH_INFO_MPERF_INDEX].needed = need_amperf;7753	msr_counter_arch_infos[MSR_ARCH_INFO_SMI_INDEX].needed = need_smi;7754 7755	msr_perf_init_();7756 7757	const bool has_amperf = has_amperf_access();7758	const bool has_smi = msr_counter_arch_infos[MSR_ARCH_INFO_SMI_INDEX].present;7759 7760	has_aperf_access = has_amperf;7761 7762	if (has_amperf) {7763		BIC_PRESENT(BIC_Avg_MHz);7764		BIC_PRESENT(BIC_Busy);7765		BIC_PRESENT(BIC_Bzy_MHz);7766		BIC_PRESENT(BIC_SMI);7767	}7768 7769	if (has_smi)7770		BIC_PRESENT(BIC_SMI);7771}7772 7773void cstate_perf_init_(bool soft_c1)7774{7775	bool has_counter;7776	bool *cores_visited = NULL, *pkg_visited = NULL;7777	const int cores_visited_elems = topo.max_core_id + 1;7778	const int pkg_visited_elems = topo.max_package_id + 1;7779	const int cci_num = topo.max_cpu_num + 1;7780 7781	ccstate_counter_info = calloc(cci_num, sizeof(*ccstate_counter_info));7782	if (!ccstate_counter_info)7783		err(1, "calloc ccstate_counter_arch_info");7784	ccstate_counter_info_size = cci_num;7785 7786	cores_visited = calloc(cores_visited_elems, sizeof(*cores_visited));7787	if (!cores_visited)7788		err(1, "calloc cores_visited");7789 7790	pkg_visited = calloc(pkg_visited_elems, sizeof(*pkg_visited));7791	if (!pkg_visited)7792		err(1, "calloc pkg_visited");7793 7794	/* Initialize cstate_counter_info_percpu */7795	for (int cpu = 0; cpu < cci_num; ++cpu) {7796		ccstate_counter_info[cpu].fd_perf_core = -1;7797		ccstate_counter_info[cpu].fd_perf_pkg = -1;7798	}7799 7800	for (int cidx = 0; cidx < NUM_CSTATE_COUNTERS; ++cidx) {7801		has_counter = false;7802		memset(cores_visited, 0, cores_visited_elems * sizeof(*cores_visited));7803		memset(pkg_visited, 0, pkg_visited_elems * sizeof(*pkg_visited));7804 7805		const struct cstate_counter_arch_info *cai = &ccstate_counter_arch_infos[cidx];7806 7807		for (int cpu = 0; cpu < cci_num; ++cpu) {7808 7809			struct cstate_counter_info_t *const cci = &ccstate_counter_info[cpu];7810 7811			if (cpu_is_not_allowed(cpu))7812				continue;7813 7814			const int core_id = cpus[cpu].physical_core_id;7815			const int pkg_id = cpus[cpu].physical_package_id;7816 7817			assert(core_id < cores_visited_elems);7818			assert(pkg_id < pkg_visited_elems);7819 7820			const bool per_thread = cai->flags & CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD;7821			const bool per_core = cai->flags & CSTATE_COUNTER_FLAG_COLLECT_PER_CORE;7822 7823			if (!per_thread && cores_visited[core_id])7824				continue;7825 7826			if (!per_core && pkg_visited[pkg_id])7827				continue;7828 7829			const bool counter_needed = BIC_IS_ENABLED(cai->bic) ||7830			    (soft_c1 && (cai->flags & CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY));7831			const bool counter_supported = (platform->supported_cstates & cai->feature_mask);7832 7833			if (counter_needed && counter_supported) {7834				/* Use perf API for this counter */7835				if (!no_perf && cai->perf_name && add_cstate_perf_counter(cpu, cci, cai) != -1) {7836 7837					cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;7838 7839					/* User MSR for this counter */7840				} else if (!no_msr && cai->msr && pkg_cstate_limit >= cai->pkg_cstate_limit7841					   && probe_msr(cpu, cai->msr) == 0) {7842					cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;7843					cci->msr[cai->rci_index] = cai->msr;7844				}7845			}7846 7847			if (cci->source[cai->rci_index] != COUNTER_SOURCE_NONE) {7848				has_counter = true;7849				cores_visited[core_id] = true;7850				pkg_visited[pkg_id] = true;7851			}7852		}7853 7854		/* If any CPU has access to the counter, make it present */7855		if (has_counter)7856			BIC_PRESENT(cai->bic);7857	}7858 7859	free(cores_visited);7860	free(pkg_visited);7861}7862 7863void cstate_perf_init(void)7864{7865	/*7866	 * If we don't have a C1 residency MSR, we calculate it "in software",7867	 * but we need APERF, MPERF too.7868	 */7869	const bool soft_c1 = !platform->has_msr_core_c1_res && has_amperf_access()7870	    && platform->supported_cstates & CC1;7871 7872	if (soft_c1)7873		BIC_PRESENT(BIC_CPU_c1);7874 7875	cstate_perf_init_(soft_c1);7876}7877 7878void probe_cstates(void)7879{7880	probe_cst_limit();7881 7882	if (platform->has_msr_module_c6_res_ms)7883		BIC_PRESENT(BIC_Mod_c6);7884 7885	if (platform->has_ext_cst_msrs && !no_msr) {7886		BIC_PRESENT(BIC_Totl_c0);7887		BIC_PRESENT(BIC_Any_c0);7888		BIC_PRESENT(BIC_GFX_c0);7889		BIC_PRESENT(BIC_CPUGFX);7890	}7891 7892	if (quiet)7893		return;7894 7895	dump_power_ctl();7896	dump_cst_cfg();7897	decode_c6_demotion_policy_msr();7898	print_dev_latency();7899	dump_sysfs_cstate_config();7900	print_irtl();7901}7902 7903void probe_lpi(void)7904{7905	if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))7906		BIC_PRESENT(BIC_CPU_LPI);7907	else7908		BIC_NOT_PRESENT(BIC_CPU_LPI);7909 7910	if (!access(sys_lpi_file_sysfs, R_OK)) {7911		sys_lpi_file = sys_lpi_file_sysfs;7912		BIC_PRESENT(BIC_SYS_LPI);7913	} else if (!access(sys_lpi_file_debugfs, R_OK)) {7914		sys_lpi_file = sys_lpi_file_debugfs;7915		BIC_PRESENT(BIC_SYS_LPI);7916	} else {7917		sys_lpi_file_sysfs = NULL;7918		BIC_NOT_PRESENT(BIC_SYS_LPI);7919	}7920 7921}7922 7923void probe_pstates(void)7924{7925	probe_bclk();7926 7927	if (quiet)7928		return;7929 7930	dump_platform_info();7931	dump_turbo_ratio_info();7932	dump_sysfs_pstate_config();7933	decode_misc_pwr_mgmt_msr();7934 7935	for_all_cpus(print_hwp, ODD_COUNTERS);7936	for_all_cpus(print_epb, ODD_COUNTERS);7937	for_all_cpus(print_perf_limit, ODD_COUNTERS);7938}7939 7940void process_cpuid()7941{7942	unsigned int eax, ebx, ecx, edx;7943	unsigned int fms, family, model, stepping, ecx_flags, edx_flags;7944	unsigned long long ucode_patch = 0;7945	bool ucode_patch_valid = false;7946 7947	eax = ebx = ecx = edx = 0;7948 7949	__cpuid(0, max_level, ebx, ecx, edx);7950 7951	if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)7952		genuine_intel = 1;7953	else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)7954		authentic_amd = 1;7955	else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)7956		hygon_genuine = 1;7957 7958	if (!quiet)7959		fprintf(outf, "CPUID(0): %.4s%.4s%.4s 0x%x CPUID levels\n",7960			(char *)&ebx, (char *)&edx, (char *)&ecx, max_level);7961 7962	__cpuid(1, fms, ebx, ecx, edx);7963	family = (fms >> 8) & 0xf;7964	model = (fms >> 4) & 0xf;7965	stepping = fms & 0xf;7966	if (family == 0xf)7967		family += (fms >> 20) & 0xff;7968	if (family >= 6)7969		model += ((fms >> 16) & 0xf) << 4;7970	ecx_flags = ecx;7971	edx_flags = edx;7972 7973	if (!no_msr) {7974		if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))7975			warnx("get_msr(UCODE)");7976		else7977			ucode_patch_valid = true;7978	}7979 7980	/*7981	 * check max extended function levels of CPUID.7982	 * This is needed to check for invariant TSC.7983	 * This check is valid for both Intel and AMD.7984	 */7985	ebx = ecx = edx = 0;7986	__cpuid(0x80000000, max_extended_level, ebx, ecx, edx);7987 7988	if (!quiet) {7989		fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)",7990			family, model, stepping, family, model, stepping);7991		if (ucode_patch_valid)7992			fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));7993		fputc('\n', outf);7994 7995		fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);7996		fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",7997			ecx_flags & (1 << 0) ? "SSE3" : "-",7998			ecx_flags & (1 << 3) ? "MONITOR" : "-",7999			ecx_flags & (1 << 6) ? "SMX" : "-",8000			ecx_flags & (1 << 7) ? "EIST" : "-",8001			ecx_flags & (1 << 8) ? "TM2" : "-",8002			edx_flags & (1 << 4) ? "TSC" : "-",8003			edx_flags & (1 << 5) ? "MSR" : "-",8004			edx_flags & (1 << 22) ? "ACPI-TM" : "-",8005			edx_flags & (1 << 28) ? "HT" : "-", edx_flags & (1 << 29) ? "TM" : "-");8006	}8007 8008	probe_platform_features(family, model);8009 8010	if (!(edx_flags & (1 << 5)))8011		errx(1, "CPUID: no MSR");8012 8013	if (max_extended_level >= 0x80000007) {8014 8015		/*8016		 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit88017		 * this check is valid for both Intel and AMD8018		 */8019		__cpuid(0x80000007, eax, ebx, ecx, edx);8020		has_invariant_tsc = edx & (1 << 8);8021	}8022 8023	/*8024	 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit08025	 * this check is valid for both Intel and AMD8026	 */8027 8028	__cpuid(0x6, eax, ebx, ecx, edx);8029	has_aperf = ecx & (1 << 0);8030	do_dts = eax & (1 << 0);8031	if (do_dts)8032		BIC_PRESENT(BIC_CoreTmp);8033	has_turbo = eax & (1 << 1);8034	do_ptm = eax & (1 << 6);8035	if (do_ptm)8036		BIC_PRESENT(BIC_PkgTmp);8037	has_hwp = eax & (1 << 7);8038	has_hwp_notify = eax & (1 << 8);8039	has_hwp_activity_window = eax & (1 << 9);8040	has_hwp_epp = eax & (1 << 10);8041	has_hwp_pkg = eax & (1 << 11);8042	has_epb = ecx & (1 << 3);8043 8044	if (!quiet)8045		fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "8046			"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",8047			has_aperf ? "" : "No-",8048			has_turbo ? "" : "No-",8049			do_dts ? "" : "No-",8050			do_ptm ? "" : "No-",8051			has_hwp ? "" : "No-",8052			has_hwp_notify ? "" : "No-",8053			has_hwp_activity_window ? "" : "No-",8054			has_hwp_epp ? "" : "No-", has_hwp_pkg ? "" : "No-", has_epb ? "" : "No-");8055 8056	if (!quiet)8057		decode_misc_enable_msr();8058 8059	if (max_level >= 0x7 && !quiet) {8060		int has_sgx;8061 8062		ecx = 0;8063 8064		__cpuid_count(0x7, 0, eax, ebx, ecx, edx);8065 8066		has_sgx = ebx & (1 << 2);8067 8068		is_hybrid = edx & (1 << 15);8069 8070		fprintf(outf, "CPUID(7): %sSGX %sHybrid\n", has_sgx ? "" : "No-", is_hybrid ? "" : "No-");8071 8072		if (has_sgx)8073			decode_feature_control_msr();8074	}8075 8076	if (max_level >= 0x15) {8077		unsigned int eax_crystal;8078		unsigned int ebx_tsc;8079 8080		/*8081		 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz8082		 */8083		eax_crystal = ebx_tsc = crystal_hz = edx = 0;8084		__cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);8085 8086		if (ebx_tsc != 0) {8087			if (!quiet && (ebx != 0))8088				fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",8089					eax_crystal, ebx_tsc, crystal_hz);8090 8091			if (crystal_hz == 0)8092				crystal_hz = platform->crystal_freq;8093 8094			if (crystal_hz) {8095				tsc_hz = (unsigned long long)crystal_hz *ebx_tsc / eax_crystal;8096				if (!quiet)8097					fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",8098						tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);8099			}8100		}8101	}8102	if (max_level >= 0x16) {8103		unsigned int base_mhz, max_mhz, bus_mhz, edx;8104 8105		/*8106		 * CPUID 16H Base MHz, Max MHz, Bus MHz8107		 */8108		base_mhz = max_mhz = bus_mhz = edx = 0;8109 8110		__cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);8111 8112		bclk = bus_mhz;8113 8114		base_hz = base_mhz * 1000000;8115		has_base_hz = 1;8116 8117		if (platform->enable_tsc_tweak)8118			tsc_tweak = base_hz / tsc_hz;8119 8120		if (!quiet)8121			fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",8122				base_mhz, max_mhz, bus_mhz);8123	}8124 8125	if (has_aperf)8126		aperf_mperf_multiplier = platform->need_perf_multiplier ? 1024 : 1;8127 8128	BIC_PRESENT(BIC_IRQ);8129	BIC_PRESENT(BIC_TSC_MHz);8130}8131 8132static void counter_info_init(void)8133{8134	for (int i = 0; i < NUM_CSTATE_COUNTERS; ++i) {8135		struct cstate_counter_arch_info *const cai = &ccstate_counter_arch_infos[i];8136 8137		if (platform->has_msr_knl_core_c6_residency && cai->msr == MSR_CORE_C6_RESIDENCY)8138			cai->msr = MSR_KNL_CORE_C6_RESIDENCY;8139 8140		if (!platform->has_msr_core_c1_res && cai->msr == MSR_CORE_C1_RES)8141			cai->msr = 0;8142 8143		if (platform->has_msr_atom_pkg_c6_residency && cai->msr == MSR_PKG_C6_RESIDENCY)8144			cai->msr = MSR_ATOM_PKG_C6_RESIDENCY;8145	}8146 8147	for (int i = 0; i < NUM_MSR_COUNTERS; ++i) {8148		msr_counter_arch_infos[i].present = false;8149		msr_counter_arch_infos[i].needed = false;8150	}8151}8152 8153void probe_pm_features(void)8154{8155	probe_pstates();8156 8157	probe_cstates();8158 8159	probe_lpi();8160 8161	probe_intel_uncore_frequency();8162 8163	probe_graphics();8164 8165	probe_rapl();8166 8167	probe_thermal();8168 8169	if (platform->has_nhm_msrs && !no_msr)8170		BIC_PRESENT(BIC_SMI);8171 8172	if (!quiet)8173		decode_misc_feature_control();8174}8175 8176/*8177 * in /dev/cpu/ return success for names that are numbers8178 * ie. filter out ".", "..", "microcode".8179 */8180int dir_filter(const struct dirent *dirp)8181{8182	if (isdigit(dirp->d_name[0]))8183		return 1;8184	else8185		return 0;8186}8187 8188void topology_probe(bool startup)8189{8190	int i;8191	int max_core_id = 0;8192	int max_package_id = 0;8193	int max_siblings = 0;8194 8195	/* Initialize num_cpus, max_cpu_num */8196	set_max_cpu_num();8197	topo.num_cpus = 0;8198	for_all_proc_cpus(count_cpus);8199	if (!summary_only && topo.num_cpus > 1)8200		BIC_PRESENT(BIC_CPU);8201 8202	if (debug > 1)8203		fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);8204 8205	cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));8206	if (cpus == NULL)8207		err(1, "calloc cpus");8208 8209	/*8210	 * Allocate and initialize cpu_present_set8211	 */8212	cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1));8213	if (cpu_present_set == NULL)8214		err(3, "CPU_ALLOC");8215	cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));8216	CPU_ZERO_S(cpu_present_setsize, cpu_present_set);8217	for_all_proc_cpus(mark_cpu_present);8218 8219	/*8220	 * Allocate and initialize cpu_effective_set8221	 */8222	cpu_effective_set = CPU_ALLOC((topo.max_cpu_num + 1));8223	if (cpu_effective_set == NULL)8224		err(3, "CPU_ALLOC");8225	cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));8226	CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set);8227	update_effective_set(startup);8228 8229	/*8230	 * Allocate and initialize cpu_allowed_set8231	 */8232	cpu_allowed_set = CPU_ALLOC((topo.max_cpu_num + 1));8233	if (cpu_allowed_set == NULL)8234		err(3, "CPU_ALLOC");8235	cpu_allowed_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));8236	CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set);8237 8238	/*8239	 * Validate and update cpu_allowed_set.8240	 *8241	 * Make sure all cpus in cpu_subset are also in cpu_present_set during startup.8242	 * Give a warning when cpus in cpu_subset become unavailable at runtime.8243	 * Give a warning when cpus are not effective because of cgroup setting.8244	 *8245	 * cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpu_subset.8246	 */8247	for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {8248		if (cpu_subset && !CPU_ISSET_S(i, cpu_subset_size, cpu_subset))8249			continue;8250 8251		if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) {8252			if (cpu_subset) {8253				/* cpus in cpu_subset must be in cpu_present_set during startup */8254				if (startup)8255					err(1, "cpu%d not present", i);8256				else8257					fprintf(stderr, "cpu%d not present\n", i);8258			}8259			continue;8260		}8261 8262		if (CPU_COUNT_S(cpu_effective_setsize, cpu_effective_set)) {8263			if (!CPU_ISSET_S(i, cpu_effective_setsize, cpu_effective_set)) {8264				fprintf(stderr, "cpu%d not effective\n", i);8265				continue;8266			}8267		}8268 8269		CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set);8270	}8271 8272	if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set))8273		err(-ENODEV, "No valid cpus found");8274	sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set);8275 8276	/*8277	 * Allocate and initialize cpu_affinity_set8278	 */8279	cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));8280	if (cpu_affinity_set == NULL)8281		err(3, "CPU_ALLOC");8282	cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));8283	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);8284 8285	for_all_proc_cpus(init_thread_id);8286 8287	/*8288	 * For online cpus8289	 * find max_core_id, max_package_id8290	 */8291	for (i = 0; i <= topo.max_cpu_num; ++i) {8292		int siblings;8293 8294		if (cpu_is_not_present(i)) {8295			if (debug > 1)8296				fprintf(outf, "cpu%d NOT PRESENT\n", i);8297			continue;8298		}8299 8300		cpus[i].logical_cpu_id = i;8301 8302		/* get package information */8303		cpus[i].physical_package_id = get_physical_package_id(i);8304		if (cpus[i].physical_package_id > max_package_id)8305			max_package_id = cpus[i].physical_package_id;8306 8307		/* get die information */8308		cpus[i].die_id = get_die_id(i);8309		if (cpus[i].die_id > topo.max_die_id)8310			topo.max_die_id = cpus[i].die_id;8311 8312		/* get numa node information */8313		cpus[i].physical_node_id = get_physical_node_id(&cpus[i]);8314		if (cpus[i].physical_node_id > topo.max_node_num)8315			topo.max_node_num = cpus[i].physical_node_id;8316 8317		/* get core information */8318		cpus[i].physical_core_id = get_core_id(i);8319		if (cpus[i].physical_core_id > max_core_id)8320			max_core_id = cpus[i].physical_core_id;8321 8322		/* get thread information */8323		siblings = get_thread_siblings(&cpus[i]);8324		if (siblings > max_siblings)8325			max_siblings = siblings;8326		if (cpus[i].thread_id == 0)8327			topo.num_cores++;8328	}8329	topo.max_core_id = max_core_id;8330	topo.max_package_id = max_package_id;8331 8332	topo.cores_per_node = max_core_id + 1;8333	if (debug > 1)8334		fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node);8335	if (!summary_only && topo.cores_per_node > 1)8336		BIC_PRESENT(BIC_Core);8337 8338	topo.num_die = topo.max_die_id + 1;8339	if (debug > 1)8340		fprintf(outf, "max_die_id %d, sizing for %d die\n", topo.max_die_id, topo.num_die);8341	if (!summary_only && topo.num_die > 1)8342		BIC_PRESENT(BIC_Die);8343 8344	topo.num_packages = max_package_id + 1;8345	if (debug > 1)8346		fprintf(outf, "max_package_id %d, sizing for %d packages\n", max_package_id, topo.num_packages);8347	if (!summary_only && topo.num_packages > 1)8348		BIC_PRESENT(BIC_Package);8349 8350	set_node_data();8351	if (debug > 1)8352		fprintf(outf, "nodes_per_pkg %d\n", topo.nodes_per_pkg);8353	if (!summary_only && topo.nodes_per_pkg > 1)8354		BIC_PRESENT(BIC_Node);8355 8356	topo.threads_per_core = max_siblings;8357	if (debug > 1)8358		fprintf(outf, "max_siblings %d\n", max_siblings);8359 8360	if (debug < 1)8361		return;8362 8363	for (i = 0; i <= topo.max_cpu_num; ++i) {8364		if (cpu_is_not_present(i))8365			continue;8366		fprintf(outf,8367			"cpu %d pkg %d die %d node %d lnode %d core %d thread %d\n",8368			i, cpus[i].physical_package_id, cpus[i].die_id,8369			cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].physical_core_id, cpus[i].thread_id);8370	}8371 8372}8373 8374void allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p)8375{8376	int i;8377	int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages;8378	int num_threads = topo.threads_per_core * num_cores;8379 8380	*t = calloc(num_threads, sizeof(struct thread_data));8381	if (*t == NULL)8382		goto error;8383 8384	for (i = 0; i < num_threads; i++)8385		(*t)[i].cpu_id = -1;8386 8387	*c = calloc(num_cores, sizeof(struct core_data));8388	if (*c == NULL)8389		goto error;8390 8391	for (i = 0; i < num_cores; i++) {8392		(*c)[i].core_id = -1;8393		(*c)[i].base_cpu = -1;8394	}8395 8396	*p = calloc(topo.num_packages, sizeof(struct pkg_data));8397	if (*p == NULL)8398		goto error;8399 8400	for (i = 0; i < topo.num_packages; i++) {8401		(*p)[i].package_id = i;8402		(*p)[i].base_cpu = -1;8403	}8404 8405	return;8406error:8407	err(1, "calloc counters");8408}8409 8410/*8411 * init_counter()8412 *8413 * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE8414 */8415void init_counter(struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base, int cpu_id)8416{8417	int pkg_id = cpus[cpu_id].physical_package_id;8418	int node_id = cpus[cpu_id].logical_node_id;8419	int core_id = cpus[cpu_id].physical_core_id;8420	int thread_id = cpus[cpu_id].thread_id;8421	struct thread_data *t;8422	struct core_data *c;8423	struct pkg_data *p;8424 8425	/* Workaround for systems where physical_node_id==-18426	 * and logical_node_id==(-1 - topo.num_cpus)8427	 */8428	if (node_id < 0)8429		node_id = 0;8430 8431	t = GET_THREAD(thread_base, thread_id, core_id, node_id, pkg_id);8432	c = GET_CORE(core_base, core_id, node_id, pkg_id);8433	p = GET_PKG(pkg_base, pkg_id);8434 8435	t->cpu_id = cpu_id;8436	if (!cpu_is_not_allowed(cpu_id)) {8437		if (c->base_cpu < 0)8438			c->base_cpu = t->cpu_id;8439		if (p->base_cpu < 0)8440			p->base_cpu = t->cpu_id;8441	}8442 8443	c->core_id = core_id;8444	p->package_id = pkg_id;8445}8446 8447int initialize_counters(int cpu_id)8448{8449	init_counter(EVEN_COUNTERS, cpu_id);8450	init_counter(ODD_COUNTERS, cpu_id);8451	return 0;8452}8453 8454void allocate_output_buffer()8455{8456	output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);8457	outp = output_buffer;8458	if (outp == NULL)8459		err(-1, "calloc output buffer");8460}8461 8462void allocate_fd_percpu(void)8463{8464	fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));8465	if (fd_percpu == NULL)8466		err(-1, "calloc fd_percpu");8467}8468 8469void allocate_irq_buffers(void)8470{8471	irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));8472	if (irq_column_2_cpu == NULL)8473		err(-1, "calloc %d", topo.num_cpus);8474 8475	irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int));8476	if (irqs_per_cpu == NULL)8477		err(-1, "calloc %d", topo.max_cpu_num + 1);8478}8479 8480int update_topo(struct thread_data *t, struct core_data *c, struct pkg_data *p)8481{8482	topo.allowed_cpus++;8483	if ((int)t->cpu_id == c->base_cpu)8484		topo.allowed_cores++;8485	if ((int)t->cpu_id == p->base_cpu)8486		topo.allowed_packages++;8487 8488	return 0;8489}8490 8491void topology_update(void)8492{8493	topo.allowed_cpus = 0;8494	topo.allowed_cores = 0;8495	topo.allowed_packages = 0;8496	for_all_cpus(update_topo, ODD_COUNTERS);8497}8498 8499void setup_all_buffers(bool startup)8500{8501	topology_probe(startup);8502	allocate_irq_buffers();8503	allocate_fd_percpu();8504	allocate_counters(&thread_even, &core_even, &package_even);8505	allocate_counters(&thread_odd, &core_odd, &package_odd);8506	allocate_output_buffer();8507	for_all_proc_cpus(initialize_counters);8508	topology_update();8509}8510 8511void set_base_cpu(void)8512{8513	int i;8514 8515	for (i = 0; i < topo.max_cpu_num + 1; ++i) {8516		if (cpu_is_not_allowed(i))8517			continue;8518		base_cpu = i;8519		if (debug > 1)8520			fprintf(outf, "base_cpu = %d\n", base_cpu);8521		return;8522	}8523	err(-ENODEV, "No valid cpus found");8524}8525 8526bool has_added_counters(void)8527{8528	/*8529	 * It only makes sense to call this after the command line is parsed,8530	 * otherwise sys structure is not populated.8531	 */8532 8533	return sys.added_core_counters | sys.added_thread_counters | sys.added_package_counters;8534}8535 8536void check_msr_access(void)8537{8538	check_dev_msr();8539	check_msr_permission();8540 8541	if (no_msr)8542		bic_disable_msr_access();8543}8544 8545void check_perf_access(void)8546{8547	if (no_perf || !BIC_IS_ENABLED(BIC_IPC) || !has_instr_count_access())8548		bic_enabled &= ~BIC_IPC;8549}8550 8551int added_perf_counters_init_(struct perf_counter_info *pinfo)8552{8553	size_t num_domains = 0;8554	unsigned int next_domain;8555	bool *domain_visited;8556	unsigned int perf_type, perf_config;8557	double perf_scale;8558	int fd_perf;8559 8560	if (!pinfo)8561		return 0;8562 8563	const size_t max_num_domains = MAX(topo.max_cpu_num + 1, MAX(topo.max_core_id + 1, topo.max_package_id + 1));8564 8565	domain_visited = calloc(max_num_domains, sizeof(*domain_visited));8566 8567	while (pinfo) {8568		switch (pinfo->scope) {8569		case SCOPE_CPU:8570			num_domains = topo.max_cpu_num + 1;8571			break;8572 8573		case SCOPE_CORE:8574			num_domains = topo.max_core_id + 1;8575			break;8576 8577		case SCOPE_PACKAGE:8578			num_domains = topo.max_package_id + 1;8579			break;8580		}8581 8582		/* Allocate buffer for file descriptor for each domain. */8583		pinfo->fd_perf_per_domain = calloc(num_domains, sizeof(*pinfo->fd_perf_per_domain));8584		if (!pinfo->fd_perf_per_domain)8585			errx(1, "%s: alloc %s", __func__, "fd_perf_per_domain");8586 8587		for (size_t i = 0; i < num_domains; ++i)8588			pinfo->fd_perf_per_domain[i] = -1;8589 8590		pinfo->num_domains = num_domains;8591		pinfo->scale = 1.0;8592 8593		memset(domain_visited, 0, max_num_domains * sizeof(*domain_visited));8594 8595		for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) {8596 8597			next_domain = cpu_to_domain(pinfo, cpu);8598 8599			assert(next_domain < num_domains);8600 8601			if (cpu_is_not_allowed(cpu))8602				continue;8603 8604			if (domain_visited[next_domain])8605				continue;8606 8607			perf_type = read_perf_type(pinfo->device);8608			if (perf_type == (unsigned int)-1) {8609				warnx("%s: perf/%s/%s: failed to read %s",8610				      __func__, pinfo->device, pinfo->event, "type");8611				continue;8612			}8613 8614			perf_config = read_perf_config(pinfo->device, pinfo->event);8615			if (perf_config == (unsigned int)-1) {8616				warnx("%s: perf/%s/%s: failed to read %s",8617				      __func__, pinfo->device, pinfo->event, "config");8618				continue;8619			}8620 8621			/* Scale is not required, some counters just don't have it. */8622			perf_scale = read_perf_scale(pinfo->device, pinfo->event);8623			if (perf_scale == 0.0)8624				perf_scale = 1.0;8625 8626			fd_perf = open_perf_counter(cpu, perf_type, perf_config, -1, 0);8627			if (fd_perf == -1) {8628				warnx("%s: perf/%s/%s: failed to open counter on cpu%d",8629				      __func__, pinfo->device, pinfo->event, cpu);8630				continue;8631			}8632 8633			domain_visited[next_domain] = 1;8634			pinfo->fd_perf_per_domain[next_domain] = fd_perf;8635			pinfo->scale = perf_scale;8636 8637			if (debug)8638				fprintf(stderr, "Add perf/%s/%s cpu%d: %d\n",8639					pinfo->device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]);8640		}8641 8642		pinfo = pinfo->next;8643	}8644 8645	free(domain_visited);8646 8647	return 0;8648}8649 8650void added_perf_counters_init(void)8651{8652	if (added_perf_counters_init_(sys.perf_tp))8653		errx(1, "%s: %s", __func__, "thread");8654 8655	if (added_perf_counters_init_(sys.perf_cp))8656		errx(1, "%s: %s", __func__, "core");8657 8658	if (added_perf_counters_init_(sys.perf_pp))8659		errx(1, "%s: %s", __func__, "package");8660}8661 8662int parse_telem_info_file(int fd_dir, const char *info_filename, const char *format, unsigned long *output)8663{8664	int fd_telem_info;8665	FILE *file_telem_info;8666	unsigned long value;8667 8668	fd_telem_info = openat(fd_dir, info_filename, O_RDONLY);8669	if (fd_telem_info == -1)8670		return -1;8671 8672	file_telem_info = fdopen(fd_telem_info, "r");8673	if (file_telem_info == NULL) {8674		close(fd_telem_info);8675		return -1;8676	}8677 8678	if (fscanf(file_telem_info, format, &value) != 1) {8679		fclose(file_telem_info);8680		return -1;8681	}8682 8683	fclose(file_telem_info);8684 8685	*output = value;8686 8687	return 0;8688}8689 8690struct pmt_mmio *pmt_mmio_open(unsigned int target_guid)8691{8692	DIR *dirp;8693	struct dirent *entry;8694	struct stat st;8695	unsigned int telem_idx;8696	int fd_telem_dir, fd_pmt;8697	unsigned long guid, size, offset;8698	size_t mmap_size;8699	void *mmio;8700	struct pmt_mmio *ret = NULL;8701 8702	if (stat(SYSFS_TELEM_PATH, &st) == -1)8703		return NULL;8704 8705	dirp = opendir(SYSFS_TELEM_PATH);8706	if (dirp == NULL)8707		return NULL;8708 8709	for (;;) {8710		entry = readdir(dirp);8711 8712		if (entry == NULL)8713			break;8714 8715		if (strcmp(entry->d_name, ".") == 0)8716			continue;8717 8718		if (strcmp(entry->d_name, "..") == 0)8719			continue;8720 8721		if (sscanf(entry->d_name, "telem%u", &telem_idx) != 1)8722			continue;8723 8724		if (fstatat(dirfd(dirp), entry->d_name, &st, 0) == -1) {8725			break;8726		}8727 8728		if (!S_ISDIR(st.st_mode))8729			continue;8730 8731		fd_telem_dir = openat(dirfd(dirp), entry->d_name, O_RDONLY);8732		if (fd_telem_dir == -1) {8733			break;8734		}8735 8736		if (parse_telem_info_file(fd_telem_dir, "guid", "%lx", &guid)) {8737			close(fd_telem_dir);8738			break;8739		}8740 8741		if (parse_telem_info_file(fd_telem_dir, "size", "%lu", &size)) {8742			close(fd_telem_dir);8743			break;8744		}8745 8746		if (guid != target_guid) {8747			close(fd_telem_dir);8748			continue;8749		}8750 8751		if (parse_telem_info_file(fd_telem_dir, "offset", "%lu", &offset)) {8752			close(fd_telem_dir);8753			break;8754		}8755 8756		assert(offset == 0);8757 8758		fd_pmt = openat(fd_telem_dir, "telem", O_RDONLY);8759		if (fd_pmt == -1)8760			goto loop_cleanup_and_break;8761 8762		mmap_size = (size + 0x1000UL) & (~0x1000UL);8763		mmio = mmap(0, mmap_size, PROT_READ, MAP_SHARED, fd_pmt, 0);8764		if (mmio != MAP_FAILED) {8765 8766			if (debug)8767				fprintf(stderr, "%s: 0x%lx mmaped at: %p\n", __func__, guid, mmio);8768 8769			ret = calloc(1, sizeof(*ret));8770 8771			if (!ret) {8772				fprintf(stderr, "%s: Failed to allocate pmt_mmio\n", __func__);8773				exit(1);8774			}8775 8776			ret->guid = guid;8777			ret->mmio_base = mmio;8778			ret->pmt_offset = offset;8779			ret->size = size;8780 8781			ret->next = pmt_mmios;8782			pmt_mmios = ret;8783		}8784 8785loop_cleanup_and_break:8786		close(fd_pmt);8787		close(fd_telem_dir);8788		break;8789	}8790 8791	closedir(dirp);8792 8793	return ret;8794}8795 8796struct pmt_mmio *pmt_mmio_find(unsigned int guid)8797{8798	struct pmt_mmio *pmmio = pmt_mmios;8799 8800	while (pmmio) {8801		if (pmmio->guid == guid)8802			return pmmio;8803 8804		pmmio = pmmio->next;8805	}8806 8807	return NULL;8808}8809 8810void *pmt_get_counter_pointer(struct pmt_mmio *pmmio, unsigned long counter_offset)8811{8812	char *ret;8813 8814	/* Get base of mmaped PMT file. */8815	ret = (char *)pmmio->mmio_base;8816 8817	/*8818	 * Apply PMT MMIO offset to obtain beginning of the mmaped telemetry data.8819	 * It's not guaranteed that the mmaped memory begins with the telemetry data8820	 *      - we might have to apply the offset first.8821	 */8822	ret += pmmio->pmt_offset;8823 8824	/* Apply the counter offset to get the address to the mmaped counter. */8825	ret += counter_offset;8826 8827	return ret;8828}8829 8830struct pmt_mmio *pmt_add_guid(unsigned int guid)8831{8832	struct pmt_mmio *ret;8833 8834	ret = pmt_mmio_find(guid);8835	if (!ret)8836		ret = pmt_mmio_open(guid);8837 8838	return ret;8839}8840 8841enum pmt_open_mode {8842	PMT_OPEN_TRY,		/* Open failure is not an error. */8843	PMT_OPEN_REQUIRED,	/* Open failure is a fatal error. */8844};8845 8846struct pmt_counter *pmt_find_counter(struct pmt_counter *pcounter, const char *name)8847{8848	while (pcounter) {8849		if (strcmp(pcounter->name, name) == 0)8850			break;8851 8852		pcounter = pcounter->next;8853	}8854 8855	return pcounter;8856}8857 8858struct pmt_counter **pmt_get_scope_root(enum counter_scope scope)8859{8860	switch (scope) {8861	case SCOPE_CPU:8862		return &sys.pmt_tp;8863	case SCOPE_CORE:8864		return &sys.pmt_cp;8865	case SCOPE_PACKAGE:8866		return &sys.pmt_pp;8867	}8868 8869	__builtin_unreachable();8870}8871 8872void pmt_counter_add_domain(struct pmt_counter *pcounter, unsigned long *pmmio, unsigned int domain_id)8873{8874	/* Make sure the new domain fits. */8875	if (domain_id >= pcounter->num_domains)8876		pmt_counter_resize(pcounter, domain_id + 1);8877 8878	assert(pcounter->domains);8879	assert(domain_id < pcounter->num_domains);8880 8881	pcounter->domains[domain_id].pcounter = pmmio;8882}8883 8884int pmt_add_counter(unsigned int guid, const char *name, enum pmt_datatype type,8885		    unsigned int lsb, unsigned int msb, unsigned int offset, enum counter_scope scope,8886		    enum counter_format format, unsigned int domain_id, enum pmt_open_mode mode)8887{8888	struct pmt_mmio *mmio;8889	struct pmt_counter *pcounter;8890	struct pmt_counter **const pmt_root = pmt_get_scope_root(scope);8891	bool new_counter = false;8892	int conflict = 0;8893 8894	if (lsb > msb) {8895		fprintf(stderr, "%s: %s: `%s` must be satisfied\n", __func__, "lsb <= msb", name);8896		exit(1);8897	}8898 8899	if (msb >= 64) {8900		fprintf(stderr, "%s: %s: `%s` must be satisfied\n", __func__, "msb < 64", name);8901		exit(1);8902	}8903 8904	mmio = pmt_add_guid(guid);8905	if (!mmio) {8906		if (mode != PMT_OPEN_TRY) {8907			fprintf(stderr, "%s: failed to map PMT MMIO for guid %x\n", __func__, guid);8908			exit(1);8909		}8910 8911		return 1;8912	}8913 8914	if (offset >= mmio->size) {8915		if (mode != PMT_OPEN_TRY) {8916			fprintf(stderr, "%s: offset %u outside of PMT MMIO size %u\n", __func__, offset, mmio->size);8917			exit(1);8918		}8919 8920		return 1;8921	}8922 8923	pcounter = pmt_find_counter(*pmt_root, name);8924	if (!pcounter) {8925		pcounter = calloc(1, sizeof(*pcounter));8926		new_counter = true;8927	}8928 8929	if (new_counter) {8930		strncpy(pcounter->name, name, ARRAY_SIZE(pcounter->name) - 1);8931		pcounter->type = type;8932		pcounter->scope = scope;8933		pcounter->lsb = lsb;8934		pcounter->msb = msb;8935		pcounter->format = format;8936	} else {8937		conflict += pcounter->type != type;8938		conflict += pcounter->scope != scope;8939		conflict += pcounter->lsb != lsb;8940		conflict += pcounter->msb != msb;8941		conflict += pcounter->format != format;8942	}8943 8944	if (conflict) {8945		fprintf(stderr, "%s: conflicting parameters for the PMT counter with the same name %s\n",8946			__func__, name);8947		exit(1);8948	}8949 8950	pmt_counter_add_domain(pcounter, pmt_get_counter_pointer(mmio, offset), domain_id);8951 8952	if (new_counter) {8953		pcounter->next = *pmt_root;8954		*pmt_root = pcounter;8955	}8956 8957	return 0;8958}8959 8960void pmt_init(void)8961{8962	if (BIC_IS_ENABLED(BIC_Diec6)) {8963		pmt_add_counter(PMT_MTL_DC6_GUID, "Die%c6", PMT_TYPE_XTAL_TIME, PMT_COUNTER_MTL_DC6_LSB,8964				PMT_COUNTER_MTL_DC6_MSB, PMT_COUNTER_MTL_DC6_OFFSET, SCOPE_PACKAGE, FORMAT_DELTA,8965				0, PMT_OPEN_TRY);8966	}8967}8968 8969void turbostat_init()8970{8971	setup_all_buffers(true);8972	set_base_cpu();8973	check_msr_access();8974	check_perf_access();8975	process_cpuid();8976	counter_info_init();8977	probe_pm_features();8978	msr_perf_init();8979	linux_perf_init();8980	rapl_perf_init();8981	cstate_perf_init();8982	added_perf_counters_init();8983	pmt_init();8984 8985	for_all_cpus(get_cpu_type, ODD_COUNTERS);8986	for_all_cpus(get_cpu_type, EVEN_COUNTERS);8987 8988	if (BIC_IS_ENABLED(BIC_IPC) && has_aperf_access && get_instr_count_fd(base_cpu) != -1)8989		BIC_PRESENT(BIC_IPC);8990 8991	/*8992	 * If TSC tweak is needed, but couldn't get it,8993	 * disable more BICs, since it can't be reported accurately.8994	 */8995	if (platform->enable_tsc_tweak && !has_base_hz) {8996		bic_enabled &= ~BIC_Busy;8997		bic_enabled &= ~BIC_Bzy_MHz;8998	}8999}9000 9001int fork_it(char **argv)9002{9003	pid_t child_pid;9004	int status;9005 9006	snapshot_proc_sysfs_files();9007	status = for_all_cpus(get_counters, EVEN_COUNTERS);9008	first_counter_read = 0;9009	if (status)9010		exit(status);9011	gettimeofday(&tv_even, (struct timezone *)NULL);9012 9013	child_pid = fork();9014	if (!child_pid) {9015		/* child */9016		execvp(argv[0], argv);9017		err(errno, "exec %s", argv[0]);9018	} else {9019 9020		/* parent */9021		if (child_pid == -1)9022			err(1, "fork");9023 9024		signal(SIGINT, SIG_IGN);9025		signal(SIGQUIT, SIG_IGN);9026		if (waitpid(child_pid, &status, 0) == -1)9027			err(status, "waitpid");9028 9029		if (WIFEXITED(status))9030			status = WEXITSTATUS(status);9031	}9032	/*9033	 * n.b. fork_it() does not check for errors from for_all_cpus()9034	 * because re-starting is problematic when forking9035	 */9036	snapshot_proc_sysfs_files();9037	for_all_cpus(get_counters, ODD_COUNTERS);9038	gettimeofday(&tv_odd, (struct timezone *)NULL);9039	timersub(&tv_odd, &tv_even, &tv_delta);9040	if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS))9041		fprintf(outf, "%s: Counter reset detected\n", progname);9042	else {9043		compute_average(EVEN_COUNTERS);9044		format_all_counters(EVEN_COUNTERS);9045	}9046 9047	fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec / 1000000.0);9048 9049	flush_output_stderr();9050 9051	return status;9052}9053 9054int get_and_dump_counters(void)9055{9056	int status;9057 9058	snapshot_proc_sysfs_files();9059	status = for_all_cpus(get_counters, ODD_COUNTERS);9060	if (status)9061		return status;9062 9063	status = for_all_cpus(dump_counters, ODD_COUNTERS);9064	if (status)9065		return status;9066 9067	flush_output_stdout();9068 9069	return status;9070}9071 9072void print_version()9073{9074	fprintf(outf, "turbostat version 2024.07.26 - Len Brown <lenb@kernel.org>\n");9075}9076 9077#define COMMAND_LINE_SIZE 20489078 9079void print_bootcmd(void)9080{9081	char bootcmd[COMMAND_LINE_SIZE];9082	FILE *fp;9083	int ret;9084 9085	memset(bootcmd, 0, COMMAND_LINE_SIZE);9086	fp = fopen("/proc/cmdline", "r");9087	if (!fp)9088		return;9089 9090	ret = fread(bootcmd, sizeof(char), COMMAND_LINE_SIZE - 1, fp);9091	if (ret) {9092		bootcmd[ret] = '\0';9093		/* the last character is already '\n' */9094		fprintf(outf, "Kernel command line: %s", bootcmd);9095	}9096 9097	fclose(fp);9098}9099 9100struct msr_counter *find_msrp_by_name(struct msr_counter *head, char *name)9101{9102	struct msr_counter *mp;9103 9104	for (mp = head; mp; mp = mp->next) {9105		if (debug)9106			fprintf(stderr, "%s: %s %s\n", __func__, name, mp->name);9107		if (!strncmp(name, mp->name, strlen(mp->name)))9108			return mp;9109	}9110	return NULL;9111}9112 9113int add_counter(unsigned int msr_num, char *path, char *name,9114		unsigned int width, enum counter_scope scope,9115		enum counter_type type, enum counter_format format, int flags, int id)9116{9117	struct msr_counter *msrp;9118 9119	if (no_msr && msr_num)9120		errx(1, "Requested MSR counter 0x%x, but in --no-msr mode", msr_num);9121 9122	if (debug)9123		fprintf(stderr, "%s(msr%d, %s, %s, width%d, scope%d, type%d, format%d, flags%x, id%d)\n",9124			__func__, msr_num, path, name, width, scope, type, format, flags, id);9125 9126	switch (scope) {9127 9128	case SCOPE_CPU:9129		msrp = find_msrp_by_name(sys.tp, name);9130		if (msrp) {9131			if (debug)9132				fprintf(stderr, "%s: %s FOUND\n", __func__, name);9133			break;9134		}9135		if (sys.added_thread_counters++ >= MAX_ADDED_THREAD_COUNTERS) {9136			warnx("ignoring thread counter %s", name);9137			return -1;9138		}9139		break;9140	case SCOPE_CORE:9141		msrp = find_msrp_by_name(sys.cp, name);9142		if (msrp) {9143			if (debug)9144				fprintf(stderr, "%s: %s FOUND\n", __func__, name);9145			break;9146		}9147		if (sys.added_core_counters++ >= MAX_ADDED_CORE_COUNTERS) {9148			warnx("ignoring core counter %s", name);9149			return -1;9150		}9151		break;9152	case SCOPE_PACKAGE:9153		msrp = find_msrp_by_name(sys.pp, name);9154		if (msrp) {9155			if (debug)9156				fprintf(stderr, "%s: %s FOUND\n", __func__, name);9157			break;9158		}9159		if (sys.added_package_counters++ >= MAX_ADDED_PACKAGE_COUNTERS) {9160			warnx("ignoring package counter %s", name);9161			return -1;9162		}9163		break;9164	default:9165		warnx("ignoring counter %s with unknown scope", name);9166		return -1;9167	}9168 9169	if (msrp == NULL) {9170		msrp = calloc(1, sizeof(struct msr_counter));9171		if (msrp == NULL)9172			err(-1, "calloc msr_counter");9173 9174		msrp->msr_num = msr_num;9175		strncpy(msrp->name, name, NAME_BYTES - 1);9176		msrp->width = width;9177		msrp->type = type;9178		msrp->format = format;9179		msrp->flags = flags;9180 9181		switch (scope) {9182		case SCOPE_CPU:9183			msrp->next = sys.tp;9184			sys.tp = msrp;9185			break;9186		case SCOPE_CORE:9187			msrp->next = sys.cp;9188			sys.cp = msrp;9189			break;9190		case SCOPE_PACKAGE:9191			msrp->next = sys.pp;9192			sys.pp = msrp;9193			break;9194		}9195	}9196 9197	if (path) {9198		struct sysfs_path *sp;9199 9200		sp = calloc(1, sizeof(struct sysfs_path));9201		if (sp == NULL) {9202			perror("calloc");9203			exit(1);9204		}9205		strncpy(sp->path, path, PATH_BYTES - 1);9206		sp->id = id;9207		sp->next = msrp->sp;9208		msrp->sp = sp;9209	}9210 9211	return 0;9212}9213 9214/*9215 * Initialize the fields used for identifying and opening the counter.9216 *9217 * Defer the initialization of any runtime buffers for actually reading9218 * the counters for when we initialize all perf counters, so we can later9219 * easily call re_initialize().9220 */9221struct perf_counter_info *make_perf_counter_info(const char *perf_device,9222						 const char *perf_event,9223						 const char *name,9224						 unsigned int width,9225						 enum counter_scope scope,9226						 enum counter_type type, enum counter_format format)9227{9228	struct perf_counter_info *pinfo;9229 9230	pinfo = calloc(1, sizeof(*pinfo));9231	if (!pinfo)9232		errx(1, "%s: Failed to allocate %s/%s\n", __func__, perf_device, perf_event);9233 9234	strncpy(pinfo->device, perf_device, ARRAY_SIZE(pinfo->device) - 1);9235	strncpy(pinfo->event, perf_event, ARRAY_SIZE(pinfo->event) - 1);9236 9237	strncpy(pinfo->name, name, ARRAY_SIZE(pinfo->name) - 1);9238	pinfo->width = width;9239	pinfo->scope = scope;9240	pinfo->type = type;9241	pinfo->format = format;9242 9243	return pinfo;9244}9245 9246int add_perf_counter(const char *perf_device, const char *perf_event, const char *name_buffer, unsigned int width,9247		     enum counter_scope scope, enum counter_type type, enum counter_format format)9248{9249	struct perf_counter_info *pinfo;9250 9251	switch (scope) {9252	case SCOPE_CPU:9253		if (sys.added_thread_perf_counters >= MAX_ADDED_THREAD_COUNTERS) {9254			warnx("ignoring thread counter perf/%s/%s", perf_device, perf_event);9255			return -1;9256		}9257		break;9258 9259	case SCOPE_CORE:9260		if (sys.added_core_perf_counters >= MAX_ADDED_CORE_COUNTERS) {9261			warnx("ignoring core counter perf/%s/%s", perf_device, perf_event);9262			return -1;9263		}9264		break;9265 9266	case SCOPE_PACKAGE:9267		if (sys.added_package_perf_counters >= MAX_ADDED_PACKAGE_COUNTERS) {9268			warnx("ignoring package counter perf/%s/%s", perf_device, perf_event);9269			return -1;9270		}9271		break;9272	}9273 9274	pinfo = make_perf_counter_info(perf_device, perf_event, name_buffer, width, scope, type, format);9275 9276	if (!pinfo)9277		return -1;9278 9279	switch (scope) {9280	case SCOPE_CPU:9281		pinfo->next = sys.perf_tp;9282		sys.perf_tp = pinfo;9283		++sys.added_thread_perf_counters;9284		break;9285 9286	case SCOPE_CORE:9287		pinfo->next = sys.perf_cp;9288		sys.perf_cp = pinfo;9289		++sys.added_core_perf_counters;9290		break;9291 9292	case SCOPE_PACKAGE:9293		pinfo->next = sys.perf_pp;9294		sys.perf_pp = pinfo;9295		++sys.added_package_perf_counters;9296		break;9297	}9298 9299	// FIXME: we might not have debug here yet9300	if (debug)9301		fprintf(stderr, "%s: %s/%s, name: %s, scope%d\n",9302			__func__, pinfo->device, pinfo->event, pinfo->name, pinfo->scope);9303 9304	return 0;9305}9306 9307void parse_add_command_msr(char *add_command)9308{9309	int msr_num = 0;9310	char *path = NULL;9311	char perf_device[PERF_DEV_NAME_BYTES] = "";9312	char perf_event[PERF_EVT_NAME_BYTES] = "";9313	char name_buffer[PERF_NAME_BYTES] = "";9314	int width = 64;9315	int fail = 0;9316	enum counter_scope scope = SCOPE_CPU;9317	enum counter_type type = COUNTER_CYCLES;9318	enum counter_format format = FORMAT_DELTA;9319 9320	while (add_command) {9321 9322		if (sscanf(add_command, "msr0x%x", &msr_num) == 1)9323			goto next;9324 9325		if (sscanf(add_command, "msr%d", &msr_num) == 1)9326			goto next;9327 9328		BUILD_BUG_ON(ARRAY_SIZE(perf_device) <= 31);9329		BUILD_BUG_ON(ARRAY_SIZE(perf_event) <= 31);9330		if (sscanf(add_command, "perf/%31[^/]/%31[^,]", &perf_device[0], &perf_event[0]) == 2)9331			goto next;9332 9333		if (*add_command == '/') {9334			path = add_command;9335			goto next;9336		}9337 9338		if (sscanf(add_command, "u%d", &width) == 1) {9339			if ((width == 32) || (width == 64))9340				goto next;9341			width = 64;9342		}9343		if (!strncmp(add_command, "cpu", strlen("cpu"))) {9344			scope = SCOPE_CPU;9345			goto next;9346		}9347		if (!strncmp(add_command, "core", strlen("core"))) {9348			scope = SCOPE_CORE;9349			goto next;9350		}9351		if (!strncmp(add_command, "package", strlen("package"))) {9352			scope = SCOPE_PACKAGE;9353			goto next;9354		}9355		if (!strncmp(add_command, "cycles", strlen("cycles"))) {9356			type = COUNTER_CYCLES;9357			goto next;9358		}9359		if (!strncmp(add_command, "seconds", strlen("seconds"))) {9360			type = COUNTER_SECONDS;9361			goto next;9362		}9363		if (!strncmp(add_command, "usec", strlen("usec"))) {9364			type = COUNTER_USEC;9365			goto next;9366		}9367		if (!strncmp(add_command, "raw", strlen("raw"))) {9368			format = FORMAT_RAW;9369			goto next;9370		}9371		if (!strncmp(add_command, "delta", strlen("delta"))) {9372			format = FORMAT_DELTA;9373			goto next;9374		}9375		if (!strncmp(add_command, "percent", strlen("percent"))) {9376			format = FORMAT_PERCENT;9377			goto next;9378		}9379 9380		BUILD_BUG_ON(ARRAY_SIZE(name_buffer) <= 18);9381		if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) {9382			char *eos;9383 9384			eos = strchr(name_buffer, ',');9385			if (eos)9386				*eos = '\0';9387			goto next;9388		}9389 9390next:9391		add_command = strchr(add_command, ',');9392		if (add_command) {9393			*add_command = '\0';9394			add_command++;9395		}9396 9397	}9398	if ((msr_num == 0) && (path == NULL) && (perf_device[0] == '\0' || perf_event[0] == '\0')) {9399		fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter | perf/device/event ) required\n");9400		fail++;9401	}9402 9403	/* Test for non-empty perf_device and perf_event */9404	const bool is_perf_counter = perf_device[0] && perf_event[0];9405 9406	/* generate default column header */9407	if (*name_buffer == '\0') {9408		if (is_perf_counter) {9409			snprintf(name_buffer, ARRAY_SIZE(name_buffer), "perf/%s", perf_event);9410		} else {9411			if (width == 32)9412				sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");9413			else9414				sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");9415		}9416	}9417 9418	if (is_perf_counter) {9419		if (add_perf_counter(perf_device, perf_event, name_buffer, width, scope, type, format))9420			fail++;9421	} else {9422		if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0, 0))9423			fail++;9424	}9425 9426	if (fail) {9427		help();9428		exit(1);9429	}9430}9431 9432bool starts_with(const char *str, const char *prefix)9433{9434	return strncmp(prefix, str, strlen(prefix)) == 0;9435}9436 9437void parse_add_command_pmt(char *add_command)9438{9439	char *name = NULL;9440	char *type_name = NULL;9441	char *format_name = NULL;9442	unsigned int offset;9443	unsigned int lsb;9444	unsigned int msb;9445	unsigned int guid;9446	unsigned int domain_id;9447	enum counter_scope scope = 0;9448	enum pmt_datatype type = PMT_TYPE_RAW;9449	enum counter_format format = FORMAT_RAW;9450	bool has_offset = false;9451	bool has_lsb = false;9452	bool has_msb = false;9453	bool has_format = true;	/* Format has a default value. */9454	bool has_guid = false;9455	bool has_scope = false;9456	bool has_type = true;	/* Type has a default value. */9457 9458	/* Consume the "pmt," prefix. */9459	add_command = strchr(add_command, ',');9460	if (!add_command) {9461		help();9462		exit(1);9463	}9464	++add_command;9465 9466	while (add_command) {9467		if (starts_with(add_command, "name=")) {9468			name = add_command + strlen("name=");9469			goto next;9470		}9471 9472		if (starts_with(add_command, "type=")) {9473			type_name = add_command + strlen("type=");9474			goto next;9475		}9476 9477		if (starts_with(add_command, "domain=")) {9478			const size_t prefix_len = strlen("domain=");9479 9480			if (sscanf(add_command + prefix_len, "cpu%u", &domain_id) == 1) {9481				scope = SCOPE_CPU;9482				has_scope = true;9483			} else if (sscanf(add_command + prefix_len, "core%u", &domain_id) == 1) {9484				scope = SCOPE_CORE;9485				has_scope = true;9486			} else if (sscanf(add_command + prefix_len, "package%u", &domain_id) == 1) {9487				scope = SCOPE_PACKAGE;9488				has_scope = true;9489			}9490 9491			if (!has_scope) {9492				printf("%s: invalid value for scope. Expected cpu%%u, core%%u or package%%u.\n",9493				       __func__);9494				exit(1);9495			}9496 9497			goto next;9498		}9499 9500		if (starts_with(add_command, "format=")) {9501			format_name = add_command + strlen("format=");9502			goto next;9503		}9504 9505		if (sscanf(add_command, "offset=%u", &offset) == 1) {9506			has_offset = true;9507			goto next;9508		}9509 9510		if (sscanf(add_command, "lsb=%u", &lsb) == 1) {9511			has_lsb = true;9512			goto next;9513		}9514 9515		if (sscanf(add_command, "msb=%u", &msb) == 1) {9516			has_msb = true;9517			goto next;9518		}9519 9520		if (sscanf(add_command, "guid=%x", &guid) == 1) {9521			has_guid = true;9522			goto next;9523		}9524 9525next:9526		add_command = strchr(add_command, ',');9527		if (add_command) {9528			*add_command = '\0';9529			add_command++;9530		}9531	}9532 9533	if (!name) {9534		printf("%s: missing %s\n", __func__, "name");9535		exit(1);9536	}9537 9538	if (strlen(name) >= PMT_COUNTER_NAME_SIZE_BYTES) {9539		printf("%s: name has to be at most %d characters long\n", __func__, PMT_COUNTER_NAME_SIZE_BYTES);9540		exit(1);9541	}9542 9543	if (format_name) {9544		has_format = false;9545 9546		if (strcmp("raw", format_name) == 0) {9547			format = FORMAT_RAW;9548			has_format = true;9549		}9550 9551		if (strcmp("delta", format_name) == 0) {9552			format = FORMAT_DELTA;9553			has_format = true;9554		}9555 9556		if (!has_format) {9557			fprintf(stderr, "%s: Invalid format %s. Expected raw or delta\n", __func__, format_name);9558			exit(1);9559		}9560	}9561 9562	if (type_name) {9563		has_type = false;9564 9565		if (strcmp("raw", type_name) == 0) {9566			type = PMT_TYPE_RAW;9567			has_type = true;9568		}9569 9570		if (strcmp("txtal_time", type_name) == 0) {9571			type = PMT_TYPE_XTAL_TIME;9572			has_type = true;9573		}9574 9575		if (!has_type) {9576			printf("%s: invalid %s: %s\n", __func__, "type", type_name);9577			exit(1);9578		}9579	}9580 9581	if (!has_offset) {9582		printf("%s : missing %s\n", __func__, "offset");9583		exit(1);9584	}9585 9586	if (!has_lsb) {9587		printf("%s: missing %s\n", __func__, "lsb");9588		exit(1);9589	}9590 9591	if (!has_msb) {9592		printf("%s: missing %s\n", __func__, "msb");9593		exit(1);9594	}9595 9596	if (!has_guid) {9597		printf("%s: missing %s\n", __func__, "guid");9598		exit(1);9599	}9600 9601	if (!has_scope) {9602		printf("%s: missing %s\n", __func__, "scope");9603		exit(1);9604	}9605 9606	if (lsb > msb) {9607		printf("%s: lsb > msb doesn't make sense\n", __func__);9608		exit(1);9609	}9610 9611	pmt_add_counter(guid, name, type, lsb, msb, offset, scope, format, domain_id, PMT_OPEN_REQUIRED);9612}9613 9614void parse_add_command(char *add_command)9615{9616	if (strncmp(add_command, "pmt", strlen("pmt")) == 0)9617		return parse_add_command_pmt(add_command);9618	return parse_add_command_msr(add_command);9619}9620 9621int is_deferred_add(char *name)9622{9623	int i;9624 9625	for (i = 0; i < deferred_add_index; ++i)9626		if (!strcmp(name, deferred_add_names[i]))9627			return 1;9628	return 0;9629}9630 9631int is_deferred_skip(char *name)9632{9633	int i;9634 9635	for (i = 0; i < deferred_skip_index; ++i)9636		if (!strcmp(name, deferred_skip_names[i]))9637			return 1;9638	return 0;9639}9640 9641void probe_sysfs(void)9642{9643	char path[64];9644	char name_buf[16];9645	FILE *input;9646	int state;9647	char *sp;9648 9649	for (state = 10; state >= 0; --state) {9650 9651		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);9652		input = fopen(path, "r");9653		if (input == NULL)9654			continue;9655		if (!fgets(name_buf, sizeof(name_buf), input))9656			err(1, "%s: failed to read file", path);9657 9658		/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */9659		sp = strchr(name_buf, '-');9660		if (!sp)9661			sp = strchrnul(name_buf, '\n');9662		*sp = '%';9663		*(sp + 1) = '\0';9664 9665		remove_underbar(name_buf);9666 9667		fclose(input);9668 9669		sprintf(path, "cpuidle/state%d/time", state);9670 9671		if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf))9672			continue;9673 9674		if (is_deferred_skip(name_buf))9675			continue;9676 9677		add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC, FORMAT_PERCENT, SYSFS_PERCPU, 0);9678	}9679 9680	for (state = 10; state >= 0; --state) {9681 9682		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);9683		input = fopen(path, "r");9684		if (input == NULL)9685			continue;9686		if (!fgets(name_buf, sizeof(name_buf), input))9687			err(1, "%s: failed to read file", path);9688		/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */9689		sp = strchr(name_buf, '-');9690		if (!sp)9691			sp = strchrnul(name_buf, '\n');9692		*sp = '\0';9693		fclose(input);9694 9695		remove_underbar(name_buf);9696 9697		sprintf(path, "cpuidle/state%d/usage", state);9698 9699		if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf))9700			continue;9701 9702		if (is_deferred_skip(name_buf))9703			continue;9704 9705		add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);9706	}9707 9708}9709 9710/*9711 * parse cpuset with following syntax9712 * 1,2,4..6,8-10 and set bits in cpu_subset9713 */9714void parse_cpu_command(char *optarg)9715{9716	if (!strcmp(optarg, "core")) {9717		if (cpu_subset)9718			goto error;9719		show_core_only++;9720		return;9721	}9722	if (!strcmp(optarg, "package")) {9723		if (cpu_subset)9724			goto error;9725		show_pkg_only++;9726		return;9727	}9728	if (show_core_only || show_pkg_only)9729		goto error;9730 9731	cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);9732	if (cpu_subset == NULL)9733		err(3, "CPU_ALLOC");9734	cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);9735 9736	CPU_ZERO_S(cpu_subset_size, cpu_subset);9737 9738	if (parse_cpu_str(optarg, cpu_subset, cpu_subset_size))9739		goto error;9740 9741	return;9742 9743error:9744	fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);9745	help();9746	exit(-1);9747}9748 9749void cmdline(int argc, char **argv)9750{9751	int opt;9752	int option_index = 0;9753	static struct option long_options[] = {9754		{ "add", required_argument, 0, 'a' },9755		{ "cpu", required_argument, 0, 'c' },9756		{ "Dump", no_argument, 0, 'D' },9757		{ "debug", no_argument, 0, 'd' },	/* internal, not documented */9758		{ "enable", required_argument, 0, 'e' },9759		{ "interval", required_argument, 0, 'i' },9760		{ "IPC", no_argument, 0, 'I' },9761		{ "num_iterations", required_argument, 0, 'n' },9762		{ "header_iterations", required_argument, 0, 'N' },9763		{ "help", no_argument, 0, 'h' },9764		{ "hide", required_argument, 0, 'H' },	// meh, -h taken by --help9765		{ "Joules", no_argument, 0, 'J' },9766		{ "list", no_argument, 0, 'l' },9767		{ "out", required_argument, 0, 'o' },9768		{ "quiet", no_argument, 0, 'q' },9769		{ "no-msr", no_argument, 0, 'M' },9770		{ "no-perf", no_argument, 0, 'P' },9771		{ "show", required_argument, 0, 's' },9772		{ "Summary", no_argument, 0, 'S' },9773		{ "TCC", required_argument, 0, 'T' },9774		{ "version", no_argument, 0, 'v' },9775		{ 0, 0, 0, 0 }9776	};9777 9778	progname = argv[0];9779 9780	/*9781	 * Parse some options early, because they may make other options invalid,9782	 * like adding the MSR counter with --add and at the same time using --no-msr.9783	 */9784	while ((opt = getopt_long_only(argc, argv, "MPn:", long_options, &option_index)) != -1) {9785		switch (opt) {9786		case 'M':9787			no_msr = 1;9788			break;9789		case 'P':9790			no_perf = 1;9791			break;9792		default:9793			break;9794		}9795	}9796	optind = 0;9797 9798	while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qMST:v", long_options, &option_index)) != -1) {9799		switch (opt) {9800		case 'a':9801			parse_add_command(optarg);9802			break;9803		case 'c':9804			parse_cpu_command(optarg);9805			break;9806		case 'D':9807			dump_only++;9808			break;9809		case 'e':9810			/* --enable specified counter */9811			bic_enabled = bic_enabled | bic_lookup(optarg, SHOW_LIST);9812			break;9813		case 'd':9814			debug++;9815			ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);9816			break;9817		case 'H':9818			/*9819			 * --hide: do not show those specified9820			 *  multiple invocations simply clear more bits in enabled mask9821			 */9822			bic_enabled &= ~bic_lookup(optarg, HIDE_LIST);9823			break;9824		case 'h':9825		default:9826			help();9827			exit(1);9828		case 'i':9829			{9830				double interval = strtod(optarg, NULL);9831 9832				if (interval < 0.001) {9833					fprintf(outf, "interval %f seconds is too small\n", interval);9834					exit(2);9835				}9836 9837				interval_tv.tv_sec = interval_ts.tv_sec = interval;9838				interval_tv.tv_usec = (interval - interval_tv.tv_sec) * 1000000;9839				interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000;9840			}9841			break;9842		case 'J':9843			rapl_joules++;9844			break;9845		case 'l':9846			ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);9847			list_header_only++;9848			quiet++;9849			break;9850		case 'o':9851			outf = fopen_or_die(optarg, "w");9852			break;9853		case 'q':9854			quiet = 1;9855			break;9856		case 'M':9857		case 'P':9858			/* Parsed earlier */9859			break;9860		case 'n':9861			num_iterations = strtod(optarg, NULL);9862 9863			if (num_iterations <= 0) {9864				fprintf(outf, "iterations %d should be positive number\n", num_iterations);9865				exit(2);9866			}9867			break;9868		case 'N':9869			header_iterations = strtod(optarg, NULL);9870 9871			if (header_iterations <= 0) {9872				fprintf(outf, "iterations %d should be positive number\n", header_iterations);9873				exit(2);9874			}9875			break;9876		case 's':9877			/*9878			 * --show: show only those specified9879			 *  The 1st invocation will clear and replace the enabled mask9880			 *  subsequent invocations can add to it.9881			 */9882			if (shown == 0)9883				bic_enabled = bic_lookup(optarg, SHOW_LIST);9884			else9885				bic_enabled |= bic_lookup(optarg, SHOW_LIST);9886			shown = 1;9887			break;9888		case 'S':9889			summary_only++;9890			break;9891		case 'T':9892			tj_max_override = atoi(optarg);9893			break;9894		case 'v':9895			print_version();9896			exit(0);9897			break;9898		}9899	}9900}9901 9902void set_rlimit(void)9903{9904	struct rlimit limit;9905 9906	if (getrlimit(RLIMIT_NOFILE, &limit) < 0)9907		err(1, "Failed to get rlimit");9908 9909	if (limit.rlim_max < MAX_NOFILE)9910		limit.rlim_max = MAX_NOFILE;9911	if (limit.rlim_cur < MAX_NOFILE)9912		limit.rlim_cur = MAX_NOFILE;9913 9914	if (setrlimit(RLIMIT_NOFILE, &limit) < 0)9915		err(1, "Failed to set rlimit");9916}9917 9918int main(int argc, char **argv)9919{9920	int fd, ret;9921 9922	fd = open("/sys/fs/cgroup/cgroup.procs", O_WRONLY);9923	if (fd < 0)9924		goto skip_cgroup_setting;9925 9926	ret = write(fd, "0\n", 2);9927	if (ret == -1)9928		perror("Can't update cgroup\n");9929 9930	close(fd);9931 9932skip_cgroup_setting:9933	outf = stderr;9934	cmdline(argc, argv);9935 9936	if (!quiet) {9937		print_version();9938		print_bootcmd();9939	}9940 9941	probe_sysfs();9942 9943	if (!getuid())9944		set_rlimit();9945 9946	turbostat_init();9947 9948	if (!no_msr)9949		msr_sum_record();9950 9951	/* dump counters and exit */9952	if (dump_only)9953		return get_and_dump_counters();9954 9955	/* list header and exit */9956	if (list_header_only) {9957		print_header(",");9958		flush_output_stdout();9959		return 0;9960	}9961 9962	/*9963	 * if any params left, it must be a command to fork9964	 */9965	if (argc - optind)9966		return fork_it(argv + optind);9967	else9968		turbostat_loop();9969 9970	return 0;9971}9972