18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * turbostat -- show CPU frequency and C-state residency
48c2ecf20Sopenharmony_ci * on modern Intel and AMD processors.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (c) 2013 Intel Corporation.
78c2ecf20Sopenharmony_ci * Len Brown <len.brown@intel.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define _GNU_SOURCE
118c2ecf20Sopenharmony_ci#include MSRHEADER
128c2ecf20Sopenharmony_ci#include INTEL_FAMILY_HEADER
138c2ecf20Sopenharmony_ci#include <stdarg.h>
148c2ecf20Sopenharmony_ci#include <stdio.h>
158c2ecf20Sopenharmony_ci#include <err.h>
168c2ecf20Sopenharmony_ci#include <unistd.h>
178c2ecf20Sopenharmony_ci#include <sys/types.h>
188c2ecf20Sopenharmony_ci#include <sys/wait.h>
198c2ecf20Sopenharmony_ci#include <sys/stat.h>
208c2ecf20Sopenharmony_ci#include <sys/select.h>
218c2ecf20Sopenharmony_ci#include <sys/resource.h>
228c2ecf20Sopenharmony_ci#include <fcntl.h>
238c2ecf20Sopenharmony_ci#include <signal.h>
248c2ecf20Sopenharmony_ci#include <sys/time.h>
258c2ecf20Sopenharmony_ci#include <stdlib.h>
268c2ecf20Sopenharmony_ci#include <getopt.h>
278c2ecf20Sopenharmony_ci#include <dirent.h>
288c2ecf20Sopenharmony_ci#include <string.h>
298c2ecf20Sopenharmony_ci#include <ctype.h>
308c2ecf20Sopenharmony_ci#include <sched.h>
318c2ecf20Sopenharmony_ci#include <time.h>
328c2ecf20Sopenharmony_ci#include <cpuid.h>
338c2ecf20Sopenharmony_ci#include <sys/capability.h>
348c2ecf20Sopenharmony_ci#include <errno.h>
358c2ecf20Sopenharmony_ci#include <math.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cichar *proc_stat = "/proc/stat";
388c2ecf20Sopenharmony_ciFILE *outf;
398c2ecf20Sopenharmony_ciint *fd_percpu;
408c2ecf20Sopenharmony_cistruct timeval interval_tv = {5, 0};
418c2ecf20Sopenharmony_cistruct timespec interval_ts = {5, 0};
428c2ecf20Sopenharmony_ciunsigned int num_iterations;
438c2ecf20Sopenharmony_ciunsigned int debug;
448c2ecf20Sopenharmony_ciunsigned int quiet;
458c2ecf20Sopenharmony_ciunsigned int shown;
468c2ecf20Sopenharmony_ciunsigned int sums_need_wide_columns;
478c2ecf20Sopenharmony_ciunsigned int rapl_joules;
488c2ecf20Sopenharmony_ciunsigned int summary_only;
498c2ecf20Sopenharmony_ciunsigned int list_header_only;
508c2ecf20Sopenharmony_ciunsigned int dump_only;
518c2ecf20Sopenharmony_ciunsigned int do_snb_cstates;
528c2ecf20Sopenharmony_ciunsigned int do_knl_cstates;
538c2ecf20Sopenharmony_ciunsigned int do_slm_cstates;
548c2ecf20Sopenharmony_ciunsigned int use_c1_residency_msr;
558c2ecf20Sopenharmony_ciunsigned int has_aperf;
568c2ecf20Sopenharmony_ciunsigned int has_epb;
578c2ecf20Sopenharmony_ciunsigned int do_irtl_snb;
588c2ecf20Sopenharmony_ciunsigned int do_irtl_hsw;
598c2ecf20Sopenharmony_ciunsigned int units = 1000000;	/* MHz etc */
608c2ecf20Sopenharmony_ciunsigned int genuine_intel;
618c2ecf20Sopenharmony_ciunsigned int authentic_amd;
628c2ecf20Sopenharmony_ciunsigned int hygon_genuine;
638c2ecf20Sopenharmony_ciunsigned int max_level, max_extended_level;
648c2ecf20Sopenharmony_ciunsigned int has_invariant_tsc;
658c2ecf20Sopenharmony_ciunsigned int do_nhm_platform_info;
668c2ecf20Sopenharmony_ciunsigned int no_MSR_MISC_PWR_MGMT;
678c2ecf20Sopenharmony_ciunsigned int aperf_mperf_multiplier = 1;
688c2ecf20Sopenharmony_cidouble bclk;
698c2ecf20Sopenharmony_cidouble base_hz;
708c2ecf20Sopenharmony_ciunsigned int has_base_hz;
718c2ecf20Sopenharmony_cidouble tsc_tweak = 1.0;
728c2ecf20Sopenharmony_ciunsigned int show_pkg_only;
738c2ecf20Sopenharmony_ciunsigned int show_core_only;
748c2ecf20Sopenharmony_cichar *output_buffer, *outp;
758c2ecf20Sopenharmony_ciunsigned int do_rapl;
768c2ecf20Sopenharmony_ciunsigned int do_dts;
778c2ecf20Sopenharmony_ciunsigned int do_ptm;
788c2ecf20Sopenharmony_ciunsigned long long  gfx_cur_rc6_ms;
798c2ecf20Sopenharmony_ciunsigned long long cpuidle_cur_cpu_lpi_us;
808c2ecf20Sopenharmony_ciunsigned long long cpuidle_cur_sys_lpi_us;
818c2ecf20Sopenharmony_ciunsigned int gfx_cur_mhz;
828c2ecf20Sopenharmony_ciunsigned int gfx_act_mhz;
838c2ecf20Sopenharmony_ciunsigned int tcc_activation_temp;
848c2ecf20Sopenharmony_ciunsigned int tcc_activation_temp_override;
858c2ecf20Sopenharmony_cidouble rapl_power_units, rapl_time_units;
868c2ecf20Sopenharmony_cidouble rapl_dram_energy_units, rapl_energy_units;
878c2ecf20Sopenharmony_cidouble rapl_joule_counter_range;
888c2ecf20Sopenharmony_ciunsigned int do_core_perf_limit_reasons;
898c2ecf20Sopenharmony_ciunsigned int has_automatic_cstate_conversion;
908c2ecf20Sopenharmony_ciunsigned int do_gfx_perf_limit_reasons;
918c2ecf20Sopenharmony_ciunsigned int do_ring_perf_limit_reasons;
928c2ecf20Sopenharmony_ciunsigned int crystal_hz;
938c2ecf20Sopenharmony_ciunsigned long long tsc_hz;
948c2ecf20Sopenharmony_ciint base_cpu;
958c2ecf20Sopenharmony_cidouble discover_bclk(unsigned int family, unsigned int model);
968c2ecf20Sopenharmony_ciunsigned int has_hwp;	/* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
978c2ecf20Sopenharmony_ci			/* IA32_HWP_REQUEST, IA32_HWP_STATUS */
988c2ecf20Sopenharmony_ciunsigned int has_hwp_notify;		/* IA32_HWP_INTERRUPT */
998c2ecf20Sopenharmony_ciunsigned int has_hwp_activity_window;	/* IA32_HWP_REQUEST[bits 41:32] */
1008c2ecf20Sopenharmony_ciunsigned int has_hwp_epp;		/* IA32_HWP_REQUEST[bits 31:24] */
1018c2ecf20Sopenharmony_ciunsigned int has_hwp_pkg;		/* IA32_HWP_REQUEST_PKG */
1028c2ecf20Sopenharmony_ciunsigned int has_misc_feature_control;
1038c2ecf20Sopenharmony_ciunsigned int first_counter_read = 1;
1048c2ecf20Sopenharmony_ciint ignore_stdin;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci#define RAPL_PKG		(1 << 0)
1078c2ecf20Sopenharmony_ci					/* 0x610 MSR_PKG_POWER_LIMIT */
1088c2ecf20Sopenharmony_ci					/* 0x611 MSR_PKG_ENERGY_STATUS */
1098c2ecf20Sopenharmony_ci#define RAPL_PKG_PERF_STATUS	(1 << 1)
1108c2ecf20Sopenharmony_ci					/* 0x613 MSR_PKG_PERF_STATUS */
1118c2ecf20Sopenharmony_ci#define RAPL_PKG_POWER_INFO	(1 << 2)
1128c2ecf20Sopenharmony_ci					/* 0x614 MSR_PKG_POWER_INFO */
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci#define RAPL_DRAM		(1 << 3)
1158c2ecf20Sopenharmony_ci					/* 0x618 MSR_DRAM_POWER_LIMIT */
1168c2ecf20Sopenharmony_ci					/* 0x619 MSR_DRAM_ENERGY_STATUS */
1178c2ecf20Sopenharmony_ci#define RAPL_DRAM_PERF_STATUS	(1 << 4)
1188c2ecf20Sopenharmony_ci					/* 0x61b MSR_DRAM_PERF_STATUS */
1198c2ecf20Sopenharmony_ci#define RAPL_DRAM_POWER_INFO	(1 << 5)
1208c2ecf20Sopenharmony_ci					/* 0x61c MSR_DRAM_POWER_INFO */
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define RAPL_CORES_POWER_LIMIT	(1 << 6)
1238c2ecf20Sopenharmony_ci					/* 0x638 MSR_PP0_POWER_LIMIT */
1248c2ecf20Sopenharmony_ci#define RAPL_CORE_POLICY	(1 << 7)
1258c2ecf20Sopenharmony_ci					/* 0x63a MSR_PP0_POLICY */
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci#define RAPL_GFX		(1 << 8)
1288c2ecf20Sopenharmony_ci					/* 0x640 MSR_PP1_POWER_LIMIT */
1298c2ecf20Sopenharmony_ci					/* 0x641 MSR_PP1_ENERGY_STATUS */
1308c2ecf20Sopenharmony_ci					/* 0x642 MSR_PP1_POLICY */
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci#define RAPL_CORES_ENERGY_STATUS	(1 << 9)
1338c2ecf20Sopenharmony_ci					/* 0x639 MSR_PP0_ENERGY_STATUS */
1348c2ecf20Sopenharmony_ci#define RAPL_PER_CORE_ENERGY	(1 << 10)
1358c2ecf20Sopenharmony_ci					/* Indicates cores energy collection is per-core,
1368c2ecf20Sopenharmony_ci					 * not per-package. */
1378c2ecf20Sopenharmony_ci#define RAPL_AMD_F17H		(1 << 11)
1388c2ecf20Sopenharmony_ci					/* 0xc0010299 MSR_RAPL_PWR_UNIT */
1398c2ecf20Sopenharmony_ci					/* 0xc001029a MSR_CORE_ENERGY_STAT */
1408c2ecf20Sopenharmony_ci					/* 0xc001029b MSR_PKG_ENERGY_STAT */
1418c2ecf20Sopenharmony_ci#define RAPL_CORES (RAPL_CORES_ENERGY_STATUS | RAPL_CORES_POWER_LIMIT)
1428c2ecf20Sopenharmony_ci#define	TJMAX_DEFAULT	100
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/* MSRs that are not yet in the kernel-provided header. */
1458c2ecf20Sopenharmony_ci#define MSR_RAPL_PWR_UNIT	0xc0010299
1468c2ecf20Sopenharmony_ci#define MSR_CORE_ENERGY_STAT	0xc001029a
1478c2ecf20Sopenharmony_ci#define MSR_PKG_ENERGY_STAT	0xc001029b
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci#define MAX(a, b) ((a) > (b) ? (a) : (b))
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci/*
1528c2ecf20Sopenharmony_ci * buffer size used by sscanf() for added column names
1538c2ecf20Sopenharmony_ci * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_ci#define	NAME_BYTES 20
1568c2ecf20Sopenharmony_ci#define PATH_BYTES 128
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ciint backwards_count;
1598c2ecf20Sopenharmony_cichar *progname;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci#define CPU_SUBSET_MAXCPUS	1024	/* need to use before probe... */
1628c2ecf20Sopenharmony_cicpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset;
1638c2ecf20Sopenharmony_cisize_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
1648c2ecf20Sopenharmony_ci#define MAX_ADDED_COUNTERS 8
1658c2ecf20Sopenharmony_ci#define MAX_ADDED_THREAD_COUNTERS 24
1668c2ecf20Sopenharmony_ci#define BITMASK_SIZE 32
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistruct thread_data {
1698c2ecf20Sopenharmony_ci	struct timeval tv_begin;
1708c2ecf20Sopenharmony_ci	struct timeval tv_end;
1718c2ecf20Sopenharmony_ci	struct timeval tv_delta;
1728c2ecf20Sopenharmony_ci	unsigned long long tsc;
1738c2ecf20Sopenharmony_ci	unsigned long long aperf;
1748c2ecf20Sopenharmony_ci	unsigned long long mperf;
1758c2ecf20Sopenharmony_ci	unsigned long long c1;
1768c2ecf20Sopenharmony_ci	unsigned long long  irq_count;
1778c2ecf20Sopenharmony_ci	unsigned int smi_count;
1788c2ecf20Sopenharmony_ci	unsigned int cpu_id;
1798c2ecf20Sopenharmony_ci	unsigned int apic_id;
1808c2ecf20Sopenharmony_ci	unsigned int x2apic_id;
1818c2ecf20Sopenharmony_ci	unsigned int flags;
1828c2ecf20Sopenharmony_ci#define CPU_IS_FIRST_THREAD_IN_CORE	0x2
1838c2ecf20Sopenharmony_ci#define CPU_IS_FIRST_CORE_IN_PACKAGE	0x4
1848c2ecf20Sopenharmony_ci	unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];
1858c2ecf20Sopenharmony_ci} *thread_even, *thread_odd;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistruct core_data {
1888c2ecf20Sopenharmony_ci	unsigned long long c3;
1898c2ecf20Sopenharmony_ci	unsigned long long c6;
1908c2ecf20Sopenharmony_ci	unsigned long long c7;
1918c2ecf20Sopenharmony_ci	unsigned long long mc6_us;	/* duplicate as per-core for now, even though per module */
1928c2ecf20Sopenharmony_ci	unsigned int core_temp_c;
1938c2ecf20Sopenharmony_ci	unsigned int core_energy;	/* MSR_CORE_ENERGY_STAT */
1948c2ecf20Sopenharmony_ci	unsigned int core_id;
1958c2ecf20Sopenharmony_ci	unsigned long long counter[MAX_ADDED_COUNTERS];
1968c2ecf20Sopenharmony_ci} *core_even, *core_odd;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistruct pkg_data {
1998c2ecf20Sopenharmony_ci	unsigned long long pc2;
2008c2ecf20Sopenharmony_ci	unsigned long long pc3;
2018c2ecf20Sopenharmony_ci	unsigned long long pc6;
2028c2ecf20Sopenharmony_ci	unsigned long long pc7;
2038c2ecf20Sopenharmony_ci	unsigned long long pc8;
2048c2ecf20Sopenharmony_ci	unsigned long long pc9;
2058c2ecf20Sopenharmony_ci	unsigned long long pc10;
2068c2ecf20Sopenharmony_ci	unsigned long long cpu_lpi;
2078c2ecf20Sopenharmony_ci	unsigned long long sys_lpi;
2088c2ecf20Sopenharmony_ci	unsigned long long pkg_wtd_core_c0;
2098c2ecf20Sopenharmony_ci	unsigned long long pkg_any_core_c0;
2108c2ecf20Sopenharmony_ci	unsigned long long pkg_any_gfxe_c0;
2118c2ecf20Sopenharmony_ci	unsigned long long pkg_both_core_gfxe_c0;
2128c2ecf20Sopenharmony_ci	long long gfx_rc6_ms;
2138c2ecf20Sopenharmony_ci	unsigned int gfx_mhz;
2148c2ecf20Sopenharmony_ci	unsigned int gfx_act_mhz;
2158c2ecf20Sopenharmony_ci	unsigned int package_id;
2168c2ecf20Sopenharmony_ci	unsigned long long energy_pkg;	/* MSR_PKG_ENERGY_STATUS */
2178c2ecf20Sopenharmony_ci	unsigned long long energy_dram;	/* MSR_DRAM_ENERGY_STATUS */
2188c2ecf20Sopenharmony_ci	unsigned long long energy_cores;	/* MSR_PP0_ENERGY_STATUS */
2198c2ecf20Sopenharmony_ci	unsigned long long energy_gfx;	/* MSR_PP1_ENERGY_STATUS */
2208c2ecf20Sopenharmony_ci	unsigned long long rapl_pkg_perf_status;	/* MSR_PKG_PERF_STATUS */
2218c2ecf20Sopenharmony_ci	unsigned long long rapl_dram_perf_status;	/* MSR_DRAM_PERF_STATUS */
2228c2ecf20Sopenharmony_ci	unsigned int pkg_temp_c;
2238c2ecf20Sopenharmony_ci	unsigned long long counter[MAX_ADDED_COUNTERS];
2248c2ecf20Sopenharmony_ci} *package_even, *package_odd;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci#define ODD_COUNTERS thread_odd, core_odd, package_odd
2278c2ecf20Sopenharmony_ci#define EVEN_COUNTERS thread_even, core_even, package_even
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci#define GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no)	      \
2308c2ecf20Sopenharmony_ci	((thread_base) +						      \
2318c2ecf20Sopenharmony_ci	 ((pkg_no) *							      \
2328c2ecf20Sopenharmony_ci	  topo.nodes_per_pkg * topo.cores_per_node * topo.threads_per_core) + \
2338c2ecf20Sopenharmony_ci	 ((node_no) * topo.cores_per_node * topo.threads_per_core) +	      \
2348c2ecf20Sopenharmony_ci	 ((core_no) * topo.threads_per_core) +				      \
2358c2ecf20Sopenharmony_ci	 (thread_no))
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci#define GET_CORE(core_base, core_no, node_no, pkg_no)			\
2388c2ecf20Sopenharmony_ci	((core_base) +							\
2398c2ecf20Sopenharmony_ci	 ((pkg_no) *  topo.nodes_per_pkg * topo.cores_per_node) +	\
2408c2ecf20Sopenharmony_ci	 ((node_no) * topo.cores_per_node) +				\
2418c2ecf20Sopenharmony_ci	 (core_no))
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cienum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE};
2478c2ecf20Sopenharmony_cienum counter_type {COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC};
2488c2ecf20Sopenharmony_cienum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT};
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistruct msr_counter {
2518c2ecf20Sopenharmony_ci	unsigned int msr_num;
2528c2ecf20Sopenharmony_ci	char name[NAME_BYTES];
2538c2ecf20Sopenharmony_ci	char path[PATH_BYTES];
2548c2ecf20Sopenharmony_ci	unsigned int width;
2558c2ecf20Sopenharmony_ci	enum counter_type type;
2568c2ecf20Sopenharmony_ci	enum counter_format format;
2578c2ecf20Sopenharmony_ci	struct msr_counter *next;
2588c2ecf20Sopenharmony_ci	unsigned int flags;
2598c2ecf20Sopenharmony_ci#define	FLAGS_HIDE	(1 << 0)
2608c2ecf20Sopenharmony_ci#define	FLAGS_SHOW	(1 << 1)
2618c2ecf20Sopenharmony_ci#define	SYSFS_PERCPU	(1 << 1)
2628c2ecf20Sopenharmony_ci};
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci/*
2658c2ecf20Sopenharmony_ci * The accumulated sum of MSR is defined as a monotonic
2668c2ecf20Sopenharmony_ci * increasing MSR, it will be accumulated periodically,
2678c2ecf20Sopenharmony_ci * despite its register's bit width.
2688c2ecf20Sopenharmony_ci */
2698c2ecf20Sopenharmony_cienum {
2708c2ecf20Sopenharmony_ci	IDX_PKG_ENERGY,
2718c2ecf20Sopenharmony_ci	IDX_DRAM_ENERGY,
2728c2ecf20Sopenharmony_ci	IDX_PP0_ENERGY,
2738c2ecf20Sopenharmony_ci	IDX_PP1_ENERGY,
2748c2ecf20Sopenharmony_ci	IDX_PKG_PERF,
2758c2ecf20Sopenharmony_ci	IDX_DRAM_PERF,
2768c2ecf20Sopenharmony_ci	IDX_COUNT,
2778c2ecf20Sopenharmony_ci};
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ciint get_msr_sum(int cpu, off_t offset, unsigned long long *msr);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_cistruct msr_sum_array {
2828c2ecf20Sopenharmony_ci	/* get_msr_sum() = sum + (get_msr() - last) */
2838c2ecf20Sopenharmony_ci	struct {
2848c2ecf20Sopenharmony_ci		/*The accumulated MSR value is updated by the timer*/
2858c2ecf20Sopenharmony_ci		unsigned long long sum;
2868c2ecf20Sopenharmony_ci		/*The MSR footprint recorded in last timer*/
2878c2ecf20Sopenharmony_ci		unsigned long long last;
2888c2ecf20Sopenharmony_ci	} entries[IDX_COUNT];
2898c2ecf20Sopenharmony_ci};
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci/* The percpu MSR sum array.*/
2928c2ecf20Sopenharmony_cistruct msr_sum_array *per_cpu_msr_sum;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cioff_t idx_to_offset(int idx)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	off_t offset;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	switch (idx) {
2998c2ecf20Sopenharmony_ci	case IDX_PKG_ENERGY:
3008c2ecf20Sopenharmony_ci		if (do_rapl & RAPL_AMD_F17H)
3018c2ecf20Sopenharmony_ci			offset = MSR_PKG_ENERGY_STAT;
3028c2ecf20Sopenharmony_ci		else
3038c2ecf20Sopenharmony_ci			offset = MSR_PKG_ENERGY_STATUS;
3048c2ecf20Sopenharmony_ci		break;
3058c2ecf20Sopenharmony_ci	case IDX_DRAM_ENERGY:
3068c2ecf20Sopenharmony_ci		offset = MSR_DRAM_ENERGY_STATUS;
3078c2ecf20Sopenharmony_ci		break;
3088c2ecf20Sopenharmony_ci	case IDX_PP0_ENERGY:
3098c2ecf20Sopenharmony_ci		offset = MSR_PP0_ENERGY_STATUS;
3108c2ecf20Sopenharmony_ci		break;
3118c2ecf20Sopenharmony_ci	case IDX_PP1_ENERGY:
3128c2ecf20Sopenharmony_ci		offset = MSR_PP1_ENERGY_STATUS;
3138c2ecf20Sopenharmony_ci		break;
3148c2ecf20Sopenharmony_ci	case IDX_PKG_PERF:
3158c2ecf20Sopenharmony_ci		offset = MSR_PKG_PERF_STATUS;
3168c2ecf20Sopenharmony_ci		break;
3178c2ecf20Sopenharmony_ci	case IDX_DRAM_PERF:
3188c2ecf20Sopenharmony_ci		offset = MSR_DRAM_PERF_STATUS;
3198c2ecf20Sopenharmony_ci		break;
3208c2ecf20Sopenharmony_ci	default:
3218c2ecf20Sopenharmony_ci		offset = -1;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci	return offset;
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ciint offset_to_idx(off_t offset)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	int idx;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	switch (offset) {
3318c2ecf20Sopenharmony_ci	case MSR_PKG_ENERGY_STATUS:
3328c2ecf20Sopenharmony_ci	case MSR_PKG_ENERGY_STAT:
3338c2ecf20Sopenharmony_ci		idx = IDX_PKG_ENERGY;
3348c2ecf20Sopenharmony_ci		break;
3358c2ecf20Sopenharmony_ci	case MSR_DRAM_ENERGY_STATUS:
3368c2ecf20Sopenharmony_ci		idx = IDX_DRAM_ENERGY;
3378c2ecf20Sopenharmony_ci		break;
3388c2ecf20Sopenharmony_ci	case MSR_PP0_ENERGY_STATUS:
3398c2ecf20Sopenharmony_ci		idx = IDX_PP0_ENERGY;
3408c2ecf20Sopenharmony_ci		break;
3418c2ecf20Sopenharmony_ci	case MSR_PP1_ENERGY_STATUS:
3428c2ecf20Sopenharmony_ci		idx = IDX_PP1_ENERGY;
3438c2ecf20Sopenharmony_ci		break;
3448c2ecf20Sopenharmony_ci	case MSR_PKG_PERF_STATUS:
3458c2ecf20Sopenharmony_ci		idx = IDX_PKG_PERF;
3468c2ecf20Sopenharmony_ci		break;
3478c2ecf20Sopenharmony_ci	case MSR_DRAM_PERF_STATUS:
3488c2ecf20Sopenharmony_ci		idx = IDX_DRAM_PERF;
3498c2ecf20Sopenharmony_ci		break;
3508c2ecf20Sopenharmony_ci	default:
3518c2ecf20Sopenharmony_ci		idx = -1;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci	return idx;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ciint idx_valid(int idx)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	switch (idx) {
3598c2ecf20Sopenharmony_ci	case IDX_PKG_ENERGY:
3608c2ecf20Sopenharmony_ci		return do_rapl & (RAPL_PKG | RAPL_AMD_F17H);
3618c2ecf20Sopenharmony_ci	case IDX_DRAM_ENERGY:
3628c2ecf20Sopenharmony_ci		return do_rapl & RAPL_DRAM;
3638c2ecf20Sopenharmony_ci	case IDX_PP0_ENERGY:
3648c2ecf20Sopenharmony_ci		return do_rapl & RAPL_CORES_ENERGY_STATUS;
3658c2ecf20Sopenharmony_ci	case IDX_PP1_ENERGY:
3668c2ecf20Sopenharmony_ci		return do_rapl & RAPL_GFX;
3678c2ecf20Sopenharmony_ci	case IDX_PKG_PERF:
3688c2ecf20Sopenharmony_ci		return do_rapl & RAPL_PKG_PERF_STATUS;
3698c2ecf20Sopenharmony_ci	case IDX_DRAM_PERF:
3708c2ecf20Sopenharmony_ci		return do_rapl & RAPL_DRAM_PERF_STATUS;
3718c2ecf20Sopenharmony_ci	default:
3728c2ecf20Sopenharmony_ci		return 0;
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_cistruct sys_counters {
3768c2ecf20Sopenharmony_ci	unsigned int added_thread_counters;
3778c2ecf20Sopenharmony_ci	unsigned int added_core_counters;
3788c2ecf20Sopenharmony_ci	unsigned int added_package_counters;
3798c2ecf20Sopenharmony_ci	struct msr_counter *tp;
3808c2ecf20Sopenharmony_ci	struct msr_counter *cp;
3818c2ecf20Sopenharmony_ci	struct msr_counter *pp;
3828c2ecf20Sopenharmony_ci} sys;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistruct system_summary {
3858c2ecf20Sopenharmony_ci	struct thread_data threads;
3868c2ecf20Sopenharmony_ci	struct core_data cores;
3878c2ecf20Sopenharmony_ci	struct pkg_data packages;
3888c2ecf20Sopenharmony_ci} average;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistruct cpu_topology {
3918c2ecf20Sopenharmony_ci	int physical_package_id;
3928c2ecf20Sopenharmony_ci	int die_id;
3938c2ecf20Sopenharmony_ci	int logical_cpu_id;
3948c2ecf20Sopenharmony_ci	int physical_node_id;
3958c2ecf20Sopenharmony_ci	int logical_node_id;	/* 0-based count within the package */
3968c2ecf20Sopenharmony_ci	int physical_core_id;
3978c2ecf20Sopenharmony_ci	int thread_id;
3988c2ecf20Sopenharmony_ci	cpu_set_t *put_ids; /* Processing Unit/Thread IDs */
3998c2ecf20Sopenharmony_ci} *cpus;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistruct topo_params {
4028c2ecf20Sopenharmony_ci	int num_packages;
4038c2ecf20Sopenharmony_ci	int num_die;
4048c2ecf20Sopenharmony_ci	int num_cpus;
4058c2ecf20Sopenharmony_ci	int num_cores;
4068c2ecf20Sopenharmony_ci	int max_cpu_num;
4078c2ecf20Sopenharmony_ci	int max_node_num;
4088c2ecf20Sopenharmony_ci	int nodes_per_pkg;
4098c2ecf20Sopenharmony_ci	int cores_per_node;
4108c2ecf20Sopenharmony_ci	int threads_per_core;
4118c2ecf20Sopenharmony_ci} topo;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistruct timeval tv_even, tv_odd, tv_delta;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ciint *irq_column_2_cpu;	/* /proc/interrupts column numbers */
4168c2ecf20Sopenharmony_ciint *irqs_per_cpu;		/* indexed by cpu_num */
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_civoid setup_all_buffers(void);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cichar *sys_lpi_file;
4218c2ecf20Sopenharmony_cichar *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us";
4228c2ecf20Sopenharmony_cichar *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec";
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ciint cpu_is_not_present(int cpu)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci/*
4298c2ecf20Sopenharmony_ci * run func(thread, core, package) in topology order
4308c2ecf20Sopenharmony_ci * skip non-present cpus
4318c2ecf20Sopenharmony_ci */
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ciint for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *),
4348c2ecf20Sopenharmony_ci	struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	int retval, pkg_no, core_no, thread_no, node_no;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
4398c2ecf20Sopenharmony_ci		for (node_no = 0; node_no < topo.nodes_per_pkg; node_no++) {
4408c2ecf20Sopenharmony_ci			for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {
4418c2ecf20Sopenharmony_ci				for (thread_no = 0; thread_no <
4428c2ecf20Sopenharmony_ci					topo.threads_per_core; ++thread_no) {
4438c2ecf20Sopenharmony_ci					struct thread_data *t;
4448c2ecf20Sopenharmony_ci					struct core_data *c;
4458c2ecf20Sopenharmony_ci					struct pkg_data *p;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci					t = GET_THREAD(thread_base, thread_no,
4488c2ecf20Sopenharmony_ci						       core_no, node_no,
4498c2ecf20Sopenharmony_ci						       pkg_no);
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci					if (cpu_is_not_present(t->cpu_id))
4528c2ecf20Sopenharmony_ci						continue;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci					c = GET_CORE(core_base, core_no,
4558c2ecf20Sopenharmony_ci						     node_no, pkg_no);
4568c2ecf20Sopenharmony_ci					p = GET_PKG(pkg_base, pkg_no);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci					retval = func(t, c, p);
4598c2ecf20Sopenharmony_ci					if (retval)
4608c2ecf20Sopenharmony_ci						return retval;
4618c2ecf20Sopenharmony_ci				}
4628c2ecf20Sopenharmony_ci			}
4638c2ecf20Sopenharmony_ci		}
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci	return 0;
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ciint cpu_migrate(int cpu)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
4718c2ecf20Sopenharmony_ci	CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
4728c2ecf20Sopenharmony_ci	if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)
4738c2ecf20Sopenharmony_ci		return -1;
4748c2ecf20Sopenharmony_ci	else
4758c2ecf20Sopenharmony_ci		return 0;
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ciint get_msr_fd(int cpu)
4788c2ecf20Sopenharmony_ci{
4798c2ecf20Sopenharmony_ci	char pathname[32];
4808c2ecf20Sopenharmony_ci	int fd;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	fd = fd_percpu[cpu];
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	if (fd)
4858c2ecf20Sopenharmony_ci		return fd;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	sprintf(pathname, "/dev/cpu/%d/msr", cpu);
4888c2ecf20Sopenharmony_ci	fd = open(pathname, O_RDONLY);
4898c2ecf20Sopenharmony_ci	if (fd < 0)
4908c2ecf20Sopenharmony_ci		err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	fd_percpu[cpu] = fd;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	return fd;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ciint get_msr(int cpu, off_t offset, unsigned long long *msr)
4988c2ecf20Sopenharmony_ci{
4998c2ecf20Sopenharmony_ci	ssize_t retval;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	if (retval != sizeof *msr)
5048c2ecf20Sopenharmony_ci		err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	return 0;
5078c2ecf20Sopenharmony_ci}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci/*
5108c2ecf20Sopenharmony_ci * This list matches the column headers, except
5118c2ecf20Sopenharmony_ci * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
5128c2ecf20Sopenharmony_ci * 2. Core and CPU are moved to the end, we can't have strings that contain them
5138c2ecf20Sopenharmony_ci *    matching on them for --show and --hide.
5148c2ecf20Sopenharmony_ci */
5158c2ecf20Sopenharmony_cistruct msr_counter bic[] = {
5168c2ecf20Sopenharmony_ci	{ 0x0, "usec" },
5178c2ecf20Sopenharmony_ci	{ 0x0, "Time_Of_Day_Seconds" },
5188c2ecf20Sopenharmony_ci	{ 0x0, "Package" },
5198c2ecf20Sopenharmony_ci	{ 0x0, "Node" },
5208c2ecf20Sopenharmony_ci	{ 0x0, "Avg_MHz" },
5218c2ecf20Sopenharmony_ci	{ 0x0, "Busy%" },
5228c2ecf20Sopenharmony_ci	{ 0x0, "Bzy_MHz" },
5238c2ecf20Sopenharmony_ci	{ 0x0, "TSC_MHz" },
5248c2ecf20Sopenharmony_ci	{ 0x0, "IRQ" },
5258c2ecf20Sopenharmony_ci	{ 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL},
5268c2ecf20Sopenharmony_ci	{ 0x0, "sysfs" },
5278c2ecf20Sopenharmony_ci	{ 0x0, "CPU%c1" },
5288c2ecf20Sopenharmony_ci	{ 0x0, "CPU%c3" },
5298c2ecf20Sopenharmony_ci	{ 0x0, "CPU%c6" },
5308c2ecf20Sopenharmony_ci	{ 0x0, "CPU%c7" },
5318c2ecf20Sopenharmony_ci	{ 0x0, "ThreadC" },
5328c2ecf20Sopenharmony_ci	{ 0x0, "CoreTmp" },
5338c2ecf20Sopenharmony_ci	{ 0x0, "CoreCnt" },
5348c2ecf20Sopenharmony_ci	{ 0x0, "PkgTmp" },
5358c2ecf20Sopenharmony_ci	{ 0x0, "GFX%rc6" },
5368c2ecf20Sopenharmony_ci	{ 0x0, "GFXMHz" },
5378c2ecf20Sopenharmony_ci	{ 0x0, "Pkg%pc2" },
5388c2ecf20Sopenharmony_ci	{ 0x0, "Pkg%pc3" },
5398c2ecf20Sopenharmony_ci	{ 0x0, "Pkg%pc6" },
5408c2ecf20Sopenharmony_ci	{ 0x0, "Pkg%pc7" },
5418c2ecf20Sopenharmony_ci	{ 0x0, "Pkg%pc8" },
5428c2ecf20Sopenharmony_ci	{ 0x0, "Pkg%pc9" },
5438c2ecf20Sopenharmony_ci	{ 0x0, "Pk%pc10" },
5448c2ecf20Sopenharmony_ci	{ 0x0, "CPU%LPI" },
5458c2ecf20Sopenharmony_ci	{ 0x0, "SYS%LPI" },
5468c2ecf20Sopenharmony_ci	{ 0x0, "PkgWatt" },
5478c2ecf20Sopenharmony_ci	{ 0x0, "CorWatt" },
5488c2ecf20Sopenharmony_ci	{ 0x0, "GFXWatt" },
5498c2ecf20Sopenharmony_ci	{ 0x0, "PkgCnt" },
5508c2ecf20Sopenharmony_ci	{ 0x0, "RAMWatt" },
5518c2ecf20Sopenharmony_ci	{ 0x0, "PKG_%" },
5528c2ecf20Sopenharmony_ci	{ 0x0, "RAM_%" },
5538c2ecf20Sopenharmony_ci	{ 0x0, "Pkg_J" },
5548c2ecf20Sopenharmony_ci	{ 0x0, "Cor_J" },
5558c2ecf20Sopenharmony_ci	{ 0x0, "GFX_J" },
5568c2ecf20Sopenharmony_ci	{ 0x0, "RAM_J" },
5578c2ecf20Sopenharmony_ci	{ 0x0, "Mod%c6" },
5588c2ecf20Sopenharmony_ci	{ 0x0, "Totl%C0" },
5598c2ecf20Sopenharmony_ci	{ 0x0, "Any%C0" },
5608c2ecf20Sopenharmony_ci	{ 0x0, "GFX%C0" },
5618c2ecf20Sopenharmony_ci	{ 0x0, "CPUGFX%" },
5628c2ecf20Sopenharmony_ci	{ 0x0, "Core" },
5638c2ecf20Sopenharmony_ci	{ 0x0, "CPU" },
5648c2ecf20Sopenharmony_ci	{ 0x0, "APIC" },
5658c2ecf20Sopenharmony_ci	{ 0x0, "X2APIC" },
5668c2ecf20Sopenharmony_ci	{ 0x0, "Die" },
5678c2ecf20Sopenharmony_ci	{ 0x0, "GFXAMHz" },
5688c2ecf20Sopenharmony_ci};
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
5718c2ecf20Sopenharmony_ci#define	BIC_USEC	(1ULL << 0)
5728c2ecf20Sopenharmony_ci#define	BIC_TOD		(1ULL << 1)
5738c2ecf20Sopenharmony_ci#define	BIC_Package	(1ULL << 2)
5748c2ecf20Sopenharmony_ci#define	BIC_Node	(1ULL << 3)
5758c2ecf20Sopenharmony_ci#define	BIC_Avg_MHz	(1ULL << 4)
5768c2ecf20Sopenharmony_ci#define	BIC_Busy	(1ULL << 5)
5778c2ecf20Sopenharmony_ci#define	BIC_Bzy_MHz	(1ULL << 6)
5788c2ecf20Sopenharmony_ci#define	BIC_TSC_MHz	(1ULL << 7)
5798c2ecf20Sopenharmony_ci#define	BIC_IRQ		(1ULL << 8)
5808c2ecf20Sopenharmony_ci#define	BIC_SMI		(1ULL << 9)
5818c2ecf20Sopenharmony_ci#define	BIC_sysfs	(1ULL << 10)
5828c2ecf20Sopenharmony_ci#define	BIC_CPU_c1	(1ULL << 11)
5838c2ecf20Sopenharmony_ci#define	BIC_CPU_c3	(1ULL << 12)
5848c2ecf20Sopenharmony_ci#define	BIC_CPU_c6	(1ULL << 13)
5858c2ecf20Sopenharmony_ci#define	BIC_CPU_c7	(1ULL << 14)
5868c2ecf20Sopenharmony_ci#define	BIC_ThreadC	(1ULL << 15)
5878c2ecf20Sopenharmony_ci#define	BIC_CoreTmp	(1ULL << 16)
5888c2ecf20Sopenharmony_ci#define	BIC_CoreCnt	(1ULL << 17)
5898c2ecf20Sopenharmony_ci#define	BIC_PkgTmp	(1ULL << 18)
5908c2ecf20Sopenharmony_ci#define	BIC_GFX_rc6	(1ULL << 19)
5918c2ecf20Sopenharmony_ci#define	BIC_GFXMHz	(1ULL << 20)
5928c2ecf20Sopenharmony_ci#define	BIC_Pkgpc2	(1ULL << 21)
5938c2ecf20Sopenharmony_ci#define	BIC_Pkgpc3	(1ULL << 22)
5948c2ecf20Sopenharmony_ci#define	BIC_Pkgpc6	(1ULL << 23)
5958c2ecf20Sopenharmony_ci#define	BIC_Pkgpc7	(1ULL << 24)
5968c2ecf20Sopenharmony_ci#define	BIC_Pkgpc8	(1ULL << 25)
5978c2ecf20Sopenharmony_ci#define	BIC_Pkgpc9	(1ULL << 26)
5988c2ecf20Sopenharmony_ci#define	BIC_Pkgpc10	(1ULL << 27)
5998c2ecf20Sopenharmony_ci#define BIC_CPU_LPI	(1ULL << 28)
6008c2ecf20Sopenharmony_ci#define BIC_SYS_LPI	(1ULL << 29)
6018c2ecf20Sopenharmony_ci#define	BIC_PkgWatt	(1ULL << 30)
6028c2ecf20Sopenharmony_ci#define	BIC_CorWatt	(1ULL << 31)
6038c2ecf20Sopenharmony_ci#define	BIC_GFXWatt	(1ULL << 32)
6048c2ecf20Sopenharmony_ci#define	BIC_PkgCnt	(1ULL << 33)
6058c2ecf20Sopenharmony_ci#define	BIC_RAMWatt	(1ULL << 34)
6068c2ecf20Sopenharmony_ci#define	BIC_PKG__	(1ULL << 35)
6078c2ecf20Sopenharmony_ci#define	BIC_RAM__	(1ULL << 36)
6088c2ecf20Sopenharmony_ci#define	BIC_Pkg_J	(1ULL << 37)
6098c2ecf20Sopenharmony_ci#define	BIC_Cor_J	(1ULL << 38)
6108c2ecf20Sopenharmony_ci#define	BIC_GFX_J	(1ULL << 39)
6118c2ecf20Sopenharmony_ci#define	BIC_RAM_J	(1ULL << 40)
6128c2ecf20Sopenharmony_ci#define	BIC_Mod_c6	(1ULL << 41)
6138c2ecf20Sopenharmony_ci#define	BIC_Totl_c0	(1ULL << 42)
6148c2ecf20Sopenharmony_ci#define	BIC_Any_c0	(1ULL << 43)
6158c2ecf20Sopenharmony_ci#define	BIC_GFX_c0	(1ULL << 44)
6168c2ecf20Sopenharmony_ci#define	BIC_CPUGFX	(1ULL << 45)
6178c2ecf20Sopenharmony_ci#define	BIC_Core	(1ULL << 46)
6188c2ecf20Sopenharmony_ci#define	BIC_CPU		(1ULL << 47)
6198c2ecf20Sopenharmony_ci#define	BIC_APIC	(1ULL << 48)
6208c2ecf20Sopenharmony_ci#define	BIC_X2APIC	(1ULL << 49)
6218c2ecf20Sopenharmony_ci#define	BIC_Die		(1ULL << 50)
6228c2ecf20Sopenharmony_ci#define	BIC_GFXACTMHz	(1ULL << 51)
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci#define BIC_DISABLED_BY_DEFAULT	(BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ciunsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
6278c2ecf20Sopenharmony_ciunsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
6308c2ecf20Sopenharmony_ci#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
6318c2ecf20Sopenharmony_ci#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
6328c2ecf20Sopenharmony_ci#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
6338c2ecf20Sopenharmony_ci#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci#define MAX_DEFERRED 16
6378c2ecf20Sopenharmony_cichar *deferred_skip_names[MAX_DEFERRED];
6388c2ecf20Sopenharmony_ciint deferred_skip_index;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci/*
6418c2ecf20Sopenharmony_ci * HIDE_LIST - hide this list of counters, show the rest [default]
6428c2ecf20Sopenharmony_ci * SHOW_LIST - show this list of counters, hide the rest
6438c2ecf20Sopenharmony_ci */
6448c2ecf20Sopenharmony_cienum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_civoid help(void)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	fprintf(outf,
6498c2ecf20Sopenharmony_ci	"Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
6508c2ecf20Sopenharmony_ci	"\n"
6518c2ecf20Sopenharmony_ci	"Turbostat forks the specified COMMAND and prints statistics\n"
6528c2ecf20Sopenharmony_ci	"when COMMAND completes.\n"
6538c2ecf20Sopenharmony_ci	"If no COMMAND is specified, turbostat wakes every 5-seconds\n"
6548c2ecf20Sopenharmony_ci	"to print statistics, until interrupted.\n"
6558c2ecf20Sopenharmony_ci	"  -a, --add	add a counter\n"
6568c2ecf20Sopenharmony_ci	"		  eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
6578c2ecf20Sopenharmony_ci	"  -c, --cpu	cpu-set	limit output to summary plus cpu-set:\n"
6588c2ecf20Sopenharmony_ci	"		  {core | package | j,k,l..m,n-p }\n"
6598c2ecf20Sopenharmony_ci	"  -d, --debug	displays usec, Time_Of_Day_Seconds and more debugging\n"
6608c2ecf20Sopenharmony_ci	"  -D, --Dump	displays the raw counter values\n"
6618c2ecf20Sopenharmony_ci	"  -e, --enable	[all | column]\n"
6628c2ecf20Sopenharmony_ci	"		shows all or the specified disabled column\n"
6638c2ecf20Sopenharmony_ci	"  -H, --hide [column|column,column,...]\n"
6648c2ecf20Sopenharmony_ci	"		hide the specified column(s)\n"
6658c2ecf20Sopenharmony_ci	"  -i, --interval sec.subsec\n"
6668c2ecf20Sopenharmony_ci	"		Override default 5-second measurement interval\n"
6678c2ecf20Sopenharmony_ci	"  -J, --Joules	displays energy in Joules instead of Watts\n"
6688c2ecf20Sopenharmony_ci	"  -l, --list	list column headers only\n"
6698c2ecf20Sopenharmony_ci	"  -n, --num_iterations num\n"
6708c2ecf20Sopenharmony_ci	"		number of the measurement iterations\n"
6718c2ecf20Sopenharmony_ci	"  -o, --out file\n"
6728c2ecf20Sopenharmony_ci	"		create or truncate \"file\" for all output\n"
6738c2ecf20Sopenharmony_ci	"  -q, --quiet	skip decoding system configuration header\n"
6748c2ecf20Sopenharmony_ci	"  -s, --show [column|column,column,...]\n"
6758c2ecf20Sopenharmony_ci	"		show only the specified column(s)\n"
6768c2ecf20Sopenharmony_ci	"  -S, --Summary\n"
6778c2ecf20Sopenharmony_ci	"		limits output to 1-line system summary per interval\n"
6788c2ecf20Sopenharmony_ci	"  -T, --TCC temperature\n"
6798c2ecf20Sopenharmony_ci	"		sets the Thermal Control Circuit temperature in\n"
6808c2ecf20Sopenharmony_ci	"		  degrees Celsius\n"
6818c2ecf20Sopenharmony_ci	"  -h, --help	print this help message\n"
6828c2ecf20Sopenharmony_ci	"  -v, --version	print version information\n"
6838c2ecf20Sopenharmony_ci	"\n"
6848c2ecf20Sopenharmony_ci	"For more help, run \"man turbostat\"\n");
6858c2ecf20Sopenharmony_ci}
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci/*
6888c2ecf20Sopenharmony_ci * bic_lookup
6898c2ecf20Sopenharmony_ci * for all the strings in comma separate name_list,
6908c2ecf20Sopenharmony_ci * set the approprate bit in return value.
6918c2ecf20Sopenharmony_ci */
6928c2ecf20Sopenharmony_ciunsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	int i;
6958c2ecf20Sopenharmony_ci	unsigned long long retval = 0;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	while (name_list) {
6988c2ecf20Sopenharmony_ci		char *comma;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci		comma = strchr(name_list, ',');
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci		if (comma)
7038c2ecf20Sopenharmony_ci			*comma = '\0';
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci		if (!strcmp(name_list, "all"))
7068c2ecf20Sopenharmony_ci			return ~0;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci		for (i = 0; i < MAX_BIC; ++i) {
7098c2ecf20Sopenharmony_ci			if (!strcmp(name_list, bic[i].name)) {
7108c2ecf20Sopenharmony_ci				retval |= (1ULL << i);
7118c2ecf20Sopenharmony_ci				break;
7128c2ecf20Sopenharmony_ci			}
7138c2ecf20Sopenharmony_ci		}
7148c2ecf20Sopenharmony_ci		if (i == MAX_BIC) {
7158c2ecf20Sopenharmony_ci			if (mode == SHOW_LIST) {
7168c2ecf20Sopenharmony_ci				fprintf(stderr, "Invalid counter name: %s\n", name_list);
7178c2ecf20Sopenharmony_ci				exit(-1);
7188c2ecf20Sopenharmony_ci			}
7198c2ecf20Sopenharmony_ci			deferred_skip_names[deferred_skip_index++] = name_list;
7208c2ecf20Sopenharmony_ci			if (debug)
7218c2ecf20Sopenharmony_ci				fprintf(stderr, "deferred \"%s\"\n", name_list);
7228c2ecf20Sopenharmony_ci			if (deferred_skip_index >= MAX_DEFERRED) {
7238c2ecf20Sopenharmony_ci				fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
7248c2ecf20Sopenharmony_ci					MAX_DEFERRED, name_list);
7258c2ecf20Sopenharmony_ci				help();
7268c2ecf20Sopenharmony_ci				exit(1);
7278c2ecf20Sopenharmony_ci			}
7288c2ecf20Sopenharmony_ci		}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci		name_list = comma;
7318c2ecf20Sopenharmony_ci		if (name_list)
7328c2ecf20Sopenharmony_ci			name_list++;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	}
7358c2ecf20Sopenharmony_ci	return retval;
7368c2ecf20Sopenharmony_ci}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_civoid print_header(char *delim)
7408c2ecf20Sopenharmony_ci{
7418c2ecf20Sopenharmony_ci	struct msr_counter *mp;
7428c2ecf20Sopenharmony_ci	int printed = 0;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_USEC))
7458c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%susec", (printed++ ? delim : ""));
7468c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_TOD))
7478c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sTime_Of_Day_Seconds", (printed++ ? delim : ""));
7488c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Package))
7498c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));
7508c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Die))
7518c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sDie", (printed++ ? delim : ""));
7528c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Node))
7538c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sNode", (printed++ ? delim : ""));
7548c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Core))
7558c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
7568c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU))
7578c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
7588c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_APIC))
7598c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));
7608c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_X2APIC))
7618c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));
7628c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Avg_MHz))
7638c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
7648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Busy))
7658c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));
7668c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Bzy_MHz))
7678c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));
7688c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_TSC_MHz))
7698c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_IRQ)) {
7728c2ecf20Sopenharmony_ci		if (sums_need_wide_columns)
7738c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s     IRQ", (printed++ ? delim : ""));
7748c2ecf20Sopenharmony_ci		else
7758c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SMI))
7798c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	for (mp = sys.tp; mp; mp = mp->next) {
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW) {
7848c2ecf20Sopenharmony_ci			if (mp->width == 64)
7858c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%18.18s", (printed++ ? delim : ""), mp->name);
7868c2ecf20Sopenharmony_ci			else
7878c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%10.10s", (printed++ ? delim : ""), mp->name);
7888c2ecf20Sopenharmony_ci		} else {
7898c2ecf20Sopenharmony_ci			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
7908c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%8s", (printed++ ? delim : ""), mp->name);
7918c2ecf20Sopenharmony_ci			else
7928c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), mp->name);
7938c2ecf20Sopenharmony_ci		}
7948c2ecf20Sopenharmony_ci	}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c1))
7978c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));
7988c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c3))
7998c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));
8008c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c6))
8018c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));
8028c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c7))
8038c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Mod_c6))
8068c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CoreTmp))
8098c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	if (do_rapl && !rapl_joules) {
8128c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
8138c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
8148c2ecf20Sopenharmony_ci	} else if (do_rapl && rapl_joules) {
8158c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY))
8168c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
8178c2ecf20Sopenharmony_ci	}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	for (mp = sys.cp; mp; mp = mp->next) {
8208c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW) {
8218c2ecf20Sopenharmony_ci			if (mp->width == 64)
8228c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%18.18s", delim, mp->name);
8238c2ecf20Sopenharmony_ci			else
8248c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%10.10s", delim, mp->name);
8258c2ecf20Sopenharmony_ci		} else {
8268c2ecf20Sopenharmony_ci			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
8278c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%8s", delim, mp->name);
8288c2ecf20Sopenharmony_ci			else
8298c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%s", delim, mp->name);
8308c2ecf20Sopenharmony_ci		}
8318c2ecf20Sopenharmony_ci	}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_PkgTmp))
8348c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_rc6))
8378c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXMHz))
8408c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXACTMHz))
8438c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Totl_c0))
8468c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
8478c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Any_c0))
8488c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));
8498c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_c0))
8508c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));
8518c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPUGFX))
8528c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc2))
8558c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));
8568c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
8578c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));
8588c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6))
8598c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));
8608c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
8618c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));
8628c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc8))
8638c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));
8648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc9))
8658c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));
8668c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc10))
8678c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));
8688c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_LPI))
8698c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sCPU%%LPI", (printed++ ? delim : ""));
8708c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SYS_LPI))
8718c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	if (do_rapl && !rapl_joules) {
8748c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_PkgWatt))
8758c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));
8768c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY))
8778c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
8788c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_GFXWatt))
8798c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));
8808c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_RAMWatt))
8818c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));
8828c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_PKG__))
8838c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
8848c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_RAM__))
8858c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
8868c2ecf20Sopenharmony_ci	} else if (do_rapl && rapl_joules) {
8878c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Pkg_J))
8888c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));
8898c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY))
8908c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));
8918c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_GFX_J))
8928c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));
8938c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_RAM_J))
8948c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));
8958c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_PKG__))
8968c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));
8978c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_RAM__))
8988c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
8998c2ecf20Sopenharmony_ci	}
9008c2ecf20Sopenharmony_ci	for (mp = sys.pp; mp; mp = mp->next) {
9018c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW) {
9028c2ecf20Sopenharmony_ci			if (mp->width == 64)
9038c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%18.18s", delim, mp->name);
9048c2ecf20Sopenharmony_ci			else
9058c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%10.10s", delim, mp->name);
9068c2ecf20Sopenharmony_ci		} else {
9078c2ecf20Sopenharmony_ci			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
9088c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%8s", delim, mp->name);
9098c2ecf20Sopenharmony_ci			else
9108c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%s", delim, mp->name);
9118c2ecf20Sopenharmony_ci		}
9128c2ecf20Sopenharmony_ci	}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	outp += sprintf(outp, "\n");
9158c2ecf20Sopenharmony_ci}
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ciint dump_counters(struct thread_data *t, struct core_data *c,
9188c2ecf20Sopenharmony_ci	struct pkg_data *p)
9198c2ecf20Sopenharmony_ci{
9208c2ecf20Sopenharmony_ci	int i;
9218c2ecf20Sopenharmony_ci	struct msr_counter *mp;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	if (t) {
9268c2ecf20Sopenharmony_ci		outp += sprintf(outp, "CPU: %d flags 0x%x\n",
9278c2ecf20Sopenharmony_ci			t->cpu_id, t->flags);
9288c2ecf20Sopenharmony_ci		outp += sprintf(outp, "TSC: %016llX\n", t->tsc);
9298c2ecf20Sopenharmony_ci		outp += sprintf(outp, "aperf: %016llX\n", t->aperf);
9308c2ecf20Sopenharmony_ci		outp += sprintf(outp, "mperf: %016llX\n", t->mperf);
9318c2ecf20Sopenharmony_ci		outp += sprintf(outp, "c1: %016llX\n", t->c1);
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_IRQ))
9348c2ecf20Sopenharmony_ci			outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);
9358c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_SMI))
9368c2ecf20Sopenharmony_ci			outp += sprintf(outp, "SMI: %d\n", t->smi_count);
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci		for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
9398c2ecf20Sopenharmony_ci			outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n",
9408c2ecf20Sopenharmony_ci				i, mp->msr_num, t->counter[i]);
9418c2ecf20Sopenharmony_ci		}
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	if (c) {
9458c2ecf20Sopenharmony_ci		outp += sprintf(outp, "core: %d\n", c->core_id);
9468c2ecf20Sopenharmony_ci		outp += sprintf(outp, "c3: %016llX\n", c->c3);
9478c2ecf20Sopenharmony_ci		outp += sprintf(outp, "c6: %016llX\n", c->c6);
9488c2ecf20Sopenharmony_ci		outp += sprintf(outp, "c7: %016llX\n", c->c7);
9498c2ecf20Sopenharmony_ci		outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c);
9508c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Joules: %0X\n", c->core_energy);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci		for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
9538c2ecf20Sopenharmony_ci			outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n",
9548c2ecf20Sopenharmony_ci				i, mp->msr_num, c->counter[i]);
9558c2ecf20Sopenharmony_ci		}
9568c2ecf20Sopenharmony_ci		outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	if (p) {
9608c2ecf20Sopenharmony_ci		outp += sprintf(outp, "package: %d\n", p->package_id);
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0);
9638c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0);
9648c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0);
9658c2ecf20Sopenharmony_ci		outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci		outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
9688c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Pkgpc3))
9698c2ecf20Sopenharmony_ci			outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
9708c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Pkgpc6))
9718c2ecf20Sopenharmony_ci			outp += sprintf(outp, "pc6: %016llX\n", p->pc6);
9728c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Pkgpc7))
9738c2ecf20Sopenharmony_ci			outp += sprintf(outp, "pc7: %016llX\n", p->pc7);
9748c2ecf20Sopenharmony_ci		outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
9758c2ecf20Sopenharmony_ci		outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
9768c2ecf20Sopenharmony_ci		outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
9778c2ecf20Sopenharmony_ci		outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
9788c2ecf20Sopenharmony_ci		outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
9798c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg);
9808c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores);
9818c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx);
9828c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram);
9838c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Throttle PKG: %0llX\n",
9848c2ecf20Sopenharmony_ci			p->rapl_pkg_perf_status);
9858c2ecf20Sopenharmony_ci		outp += sprintf(outp, "Throttle RAM: %0llX\n",
9868c2ecf20Sopenharmony_ci			p->rapl_dram_perf_status);
9878c2ecf20Sopenharmony_ci		outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci		for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
9908c2ecf20Sopenharmony_ci			outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n",
9918c2ecf20Sopenharmony_ci				i, mp->msr_num, p->counter[i]);
9928c2ecf20Sopenharmony_ci		}
9938c2ecf20Sopenharmony_ci	}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	outp += sprintf(outp, "\n");
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	return 0;
9988c2ecf20Sopenharmony_ci}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci/*
10018c2ecf20Sopenharmony_ci * column formatting convention & formats
10028c2ecf20Sopenharmony_ci */
10038c2ecf20Sopenharmony_ciint format_counters(struct thread_data *t, struct core_data *c,
10048c2ecf20Sopenharmony_ci	struct pkg_data *p)
10058c2ecf20Sopenharmony_ci{
10068c2ecf20Sopenharmony_ci	double interval_float, tsc;
10078c2ecf20Sopenharmony_ci	char *fmt8;
10088c2ecf20Sopenharmony_ci	int i;
10098c2ecf20Sopenharmony_ci	struct msr_counter *mp;
10108c2ecf20Sopenharmony_ci	char *delim = "\t";
10118c2ecf20Sopenharmony_ci	int printed = 0;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	 /* if showing only 1st thread in core and this isn't one, bail out */
10148c2ecf20Sopenharmony_ci	if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
10158c2ecf20Sopenharmony_ci		return 0;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	 /* if showing only 1st thread in pkg and this isn't one, bail out */
10188c2ecf20Sopenharmony_ci	if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
10198c2ecf20Sopenharmony_ci		return 0;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	/*if not summary line and --cpu is used */
10228c2ecf20Sopenharmony_ci	if ((t != &average.threads) &&
10238c2ecf20Sopenharmony_ci		(cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
10248c2ecf20Sopenharmony_ci		return 0;
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_USEC)) {
10278c2ecf20Sopenharmony_ci		/* on each row, print how many usec each timestamp took to gather */
10288c2ecf20Sopenharmony_ci		struct timeval tv;
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci		timersub(&t->tv_end, &t->tv_begin, &tv);
10318c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec);
10328c2ecf20Sopenharmony_ci	}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	/* Time_Of_Day_Seconds: on each row, print sec.usec last timestamp taken */
10358c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_TOD))
10368c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0;
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	tsc = t->tsc * tsc_tweak;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	/* topo columns, print blanks on 1st (average) line */
10438c2ecf20Sopenharmony_ci	if (t == &average.threads) {
10448c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Package))
10458c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10468c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Die))
10478c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10488c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Node))
10498c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10508c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Core))
10518c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10528c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_CPU))
10538c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10548c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_APIC))
10558c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10568c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_X2APIC))
10578c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10588c2ecf20Sopenharmony_ci	} else {
10598c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Package)) {
10608c2ecf20Sopenharmony_ci			if (p)
10618c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->package_id);
10628c2ecf20Sopenharmony_ci			else
10638c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10648c2ecf20Sopenharmony_ci		}
10658c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Die)) {
10668c2ecf20Sopenharmony_ci			if (c)
10678c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].die_id);
10688c2ecf20Sopenharmony_ci			else
10698c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10708c2ecf20Sopenharmony_ci		}
10718c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Node)) {
10728c2ecf20Sopenharmony_ci			if (t)
10738c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%d",
10748c2ecf20Sopenharmony_ci						(printed++ ? delim : ""),
10758c2ecf20Sopenharmony_ci					      cpus[t->cpu_id].physical_node_id);
10768c2ecf20Sopenharmony_ci			else
10778c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s-",
10788c2ecf20Sopenharmony_ci						(printed++ ? delim : ""));
10798c2ecf20Sopenharmony_ci		}
10808c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_Core)) {
10818c2ecf20Sopenharmony_ci			if (c)
10828c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_id);
10838c2ecf20Sopenharmony_ci			else
10848c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
10858c2ecf20Sopenharmony_ci		}
10868c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_CPU))
10878c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
10888c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_APIC))
10898c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);
10908c2ecf20Sopenharmony_ci		if (DO_BIC(BIC_X2APIC))
10918c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);
10928c2ecf20Sopenharmony_ci	}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Avg_MHz))
10958c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
10968c2ecf20Sopenharmony_ci			1.0 / units * t->aperf / interval_float);
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Busy))
10998c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf/tsc);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Bzy_MHz)) {
11028c2ecf20Sopenharmony_ci		if (has_base_hz)
11038c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
11048c2ecf20Sopenharmony_ci		else
11058c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
11068c2ecf20Sopenharmony_ci				tsc / units * t->aperf / t->mperf / interval_float);
11078c2ecf20Sopenharmony_ci	}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_TSC_MHz))
11108c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc/units/interval_float);
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	/* IRQ */
11138c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_IRQ)) {
11148c2ecf20Sopenharmony_ci		if (sums_need_wide_columns)
11158c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);
11168c2ecf20Sopenharmony_ci		else
11178c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);
11188c2ecf20Sopenharmony_ci	}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	/* SMI */
11218c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SMI))
11228c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	/* Added counters */
11258c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
11268c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW) {
11278c2ecf20Sopenharmony_ci			if (mp->width == 32)
11288c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) t->counter[i]);
11298c2ecf20Sopenharmony_ci			else
11308c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
11318c2ecf20Sopenharmony_ci		} else if (mp->format == FORMAT_DELTA) {
11328c2ecf20Sopenharmony_ci			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
11338c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->counter[i]);
11348c2ecf20Sopenharmony_ci			else
11358c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);
11368c2ecf20Sopenharmony_ci		} else if (mp->format == FORMAT_PERCENT) {
11378c2ecf20Sopenharmony_ci			if (mp->type == COUNTER_USEC)
11388c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), t->counter[i]/interval_float/10000);
11398c2ecf20Sopenharmony_ci			else
11408c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i]/tsc);
11418c2ecf20Sopenharmony_ci		}
11428c2ecf20Sopenharmony_ci	}
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	/* C1 */
11458c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c1))
11468c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1/tsc);
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	/* print per-core data only for 1st thread in core */
11508c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
11518c2ecf20Sopenharmony_ci		goto done;
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c3))
11548c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3/tsc);
11558c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c6))
11568c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6/tsc);
11578c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c7))
11588c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7/tsc);
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	/* Mod%c6 */
11618c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Mod_c6))
11628c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->mc6_us / tsc);
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CoreTmp))
11658c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
11688c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW) {
11698c2ecf20Sopenharmony_ci			if (mp->width == 32)
11708c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) c->counter[i]);
11718c2ecf20Sopenharmony_ci			else
11728c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
11738c2ecf20Sopenharmony_ci		} else if (mp->format == FORMAT_DELTA) {
11748c2ecf20Sopenharmony_ci			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
11758c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), c->counter[i]);
11768c2ecf20Sopenharmony_ci			else
11778c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);
11788c2ecf20Sopenharmony_ci		} else if (mp->format == FORMAT_PERCENT) {
11798c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i]/tsc);
11808c2ecf20Sopenharmony_ci		}
11818c2ecf20Sopenharmony_ci	}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	fmt8 = "%s%.2f";
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
11868c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
11878c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY))
11888c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	/* print per-package data only for 1st core in package */
11918c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
11928c2ecf20Sopenharmony_ci		goto done;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	/* PkgTmp */
11958c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_PkgTmp))
11968c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	/* GFXrc6 */
11998c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_rc6)) {
12008c2ecf20Sopenharmony_ci		if (p->gfx_rc6_ms == -1) {	/* detect GFX counter reset */
12018c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
12028c2ecf20Sopenharmony_ci		} else {
12038c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
12048c2ecf20Sopenharmony_ci				p->gfx_rc6_ms / 10.0 / interval_float);
12058c2ecf20Sopenharmony_ci		}
12068c2ecf20Sopenharmony_ci	}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	/* GFXMHz */
12098c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXMHz))
12108c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	/* GFXACTMHz */
12138c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXACTMHz))
12148c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
12178c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Totl_c0))
12188c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
12198c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Any_c0))
12208c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc);
12218c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_c0))
12228c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc);
12238c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPUGFX))
12248c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc);
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc2))
12278c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc);
12288c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
12298c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3/tsc);
12308c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6))
12318c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6/tsc);
12328c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
12338c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7/tsc);
12348c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc8))
12358c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8/tsc);
12368c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc9))
12378c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9/tsc);
12388c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc10))
12398c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10/tsc);
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_LPI))
12428c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
12438c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SYS_LPI))
12448c2ecf20Sopenharmony_ci		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float);
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_PkgWatt))
12478c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
12488c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY))
12498c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
12508c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXWatt))
12518c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
12528c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_RAMWatt))
12538c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units / interval_float);
12548c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkg_J))
12558c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units);
12568c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY))
12578c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units);
12588c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_J))
12598c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units);
12608c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_RAM_J))
12618c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units);
12628c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_PKG__))
12638c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
12648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_RAM__))
12658c2ecf20Sopenharmony_ci		outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
12688c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW) {
12698c2ecf20Sopenharmony_ci			if (mp->width == 32)
12708c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) p->counter[i]);
12718c2ecf20Sopenharmony_ci			else
12728c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
12738c2ecf20Sopenharmony_ci		} else if (mp->format == FORMAT_DELTA) {
12748c2ecf20Sopenharmony_ci			if ((mp->type == COUNTER_ITEMS) && sums_need_wide_columns)
12758c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), p->counter[i]);
12768c2ecf20Sopenharmony_ci			else
12778c2ecf20Sopenharmony_ci				outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);
12788c2ecf20Sopenharmony_ci		} else if (mp->format == FORMAT_PERCENT) {
12798c2ecf20Sopenharmony_ci			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i]/tsc);
12808c2ecf20Sopenharmony_ci		}
12818c2ecf20Sopenharmony_ci	}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_cidone:
12848c2ecf20Sopenharmony_ci	if (*(outp - 1) != '\n')
12858c2ecf20Sopenharmony_ci		outp += sprintf(outp, "\n");
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	return 0;
12888c2ecf20Sopenharmony_ci}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_civoid flush_output_stdout(void)
12918c2ecf20Sopenharmony_ci{
12928c2ecf20Sopenharmony_ci	FILE *filep;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	if (outf == stderr)
12958c2ecf20Sopenharmony_ci		filep = stdout;
12968c2ecf20Sopenharmony_ci	else
12978c2ecf20Sopenharmony_ci		filep = outf;
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	fputs(output_buffer, filep);
13008c2ecf20Sopenharmony_ci	fflush(filep);
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	outp = output_buffer;
13038c2ecf20Sopenharmony_ci}
13048c2ecf20Sopenharmony_civoid flush_output_stderr(void)
13058c2ecf20Sopenharmony_ci{
13068c2ecf20Sopenharmony_ci	fputs(output_buffer, outf);
13078c2ecf20Sopenharmony_ci	fflush(outf);
13088c2ecf20Sopenharmony_ci	outp = output_buffer;
13098c2ecf20Sopenharmony_ci}
13108c2ecf20Sopenharmony_civoid format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
13118c2ecf20Sopenharmony_ci{
13128c2ecf20Sopenharmony_ci	static int printed;
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	if (!printed || !summary_only)
13158c2ecf20Sopenharmony_ci		print_header("\t");
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	format_counters(&average.threads, &average.cores, &average.packages);
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	printed = 1;
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	if (summary_only)
13228c2ecf20Sopenharmony_ci		return;
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	for_all_cpus(format_counters, t, c, p);
13258c2ecf20Sopenharmony_ci}
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci#define DELTA_WRAP32(new, old)			\
13288c2ecf20Sopenharmony_ci	old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ciint
13318c2ecf20Sopenharmony_cidelta_package(struct pkg_data *new, struct pkg_data *old)
13328c2ecf20Sopenharmony_ci{
13338c2ecf20Sopenharmony_ci	int i;
13348c2ecf20Sopenharmony_ci	struct msr_counter *mp;
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Totl_c0))
13388c2ecf20Sopenharmony_ci		old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;
13398c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Any_c0))
13408c2ecf20Sopenharmony_ci		old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;
13418c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_c0))
13428c2ecf20Sopenharmony_ci		old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;
13438c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPUGFX))
13448c2ecf20Sopenharmony_ci		old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	old->pc2 = new->pc2 - old->pc2;
13478c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
13488c2ecf20Sopenharmony_ci		old->pc3 = new->pc3 - old->pc3;
13498c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6))
13508c2ecf20Sopenharmony_ci		old->pc6 = new->pc6 - old->pc6;
13518c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
13528c2ecf20Sopenharmony_ci		old->pc7 = new->pc7 - old->pc7;
13538c2ecf20Sopenharmony_ci	old->pc8 = new->pc8 - old->pc8;
13548c2ecf20Sopenharmony_ci	old->pc9 = new->pc9 - old->pc9;
13558c2ecf20Sopenharmony_ci	old->pc10 = new->pc10 - old->pc10;
13568c2ecf20Sopenharmony_ci	old->cpu_lpi = new->cpu_lpi - old->cpu_lpi;
13578c2ecf20Sopenharmony_ci	old->sys_lpi = new->sys_lpi - old->sys_lpi;
13588c2ecf20Sopenharmony_ci	old->pkg_temp_c = new->pkg_temp_c;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	/* flag an error when rc6 counter resets/wraps */
13618c2ecf20Sopenharmony_ci	if (old->gfx_rc6_ms >  new->gfx_rc6_ms)
13628c2ecf20Sopenharmony_ci		old->gfx_rc6_ms = -1;
13638c2ecf20Sopenharmony_ci	else
13648c2ecf20Sopenharmony_ci		old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	old->gfx_mhz = new->gfx_mhz;
13678c2ecf20Sopenharmony_ci	old->gfx_act_mhz = new->gfx_act_mhz;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	old->energy_pkg = new->energy_pkg - old->energy_pkg;
13708c2ecf20Sopenharmony_ci	old->energy_cores = new->energy_cores - old->energy_cores;
13718c2ecf20Sopenharmony_ci	old->energy_gfx = new->energy_gfx - old->energy_gfx;
13728c2ecf20Sopenharmony_ci	old->energy_dram = new->energy_dram - old->energy_dram;
13738c2ecf20Sopenharmony_ci	old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status;
13748c2ecf20Sopenharmony_ci	old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
13778c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
13788c2ecf20Sopenharmony_ci			old->counter[i] = new->counter[i];
13798c2ecf20Sopenharmony_ci		else
13808c2ecf20Sopenharmony_ci			old->counter[i] = new->counter[i] - old->counter[i];
13818c2ecf20Sopenharmony_ci	}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	return 0;
13848c2ecf20Sopenharmony_ci}
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_civoid
13878c2ecf20Sopenharmony_cidelta_core(struct core_data *new, struct core_data *old)
13888c2ecf20Sopenharmony_ci{
13898c2ecf20Sopenharmony_ci	int i;
13908c2ecf20Sopenharmony_ci	struct msr_counter *mp;
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	old->c3 = new->c3 - old->c3;
13938c2ecf20Sopenharmony_ci	old->c6 = new->c6 - old->c6;
13948c2ecf20Sopenharmony_ci	old->c7 = new->c7 - old->c7;
13958c2ecf20Sopenharmony_ci	old->core_temp_c = new->core_temp_c;
13968c2ecf20Sopenharmony_ci	old->mc6_us = new->mc6_us - old->mc6_us;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	DELTA_WRAP32(new->core_energy, old->core_energy);
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
14018c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
14028c2ecf20Sopenharmony_ci			old->counter[i] = new->counter[i];
14038c2ecf20Sopenharmony_ci		else
14048c2ecf20Sopenharmony_ci			old->counter[i] = new->counter[i] - old->counter[i];
14058c2ecf20Sopenharmony_ci	}
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ciint soft_c1_residency_display(int bic)
14098c2ecf20Sopenharmony_ci{
14108c2ecf20Sopenharmony_ci	if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr)
14118c2ecf20Sopenharmony_ci		return 0;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	return DO_BIC_READ(bic);
14148c2ecf20Sopenharmony_ci}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci/*
14178c2ecf20Sopenharmony_ci * old = new - old
14188c2ecf20Sopenharmony_ci */
14198c2ecf20Sopenharmony_ciint
14208c2ecf20Sopenharmony_cidelta_thread(struct thread_data *new, struct thread_data *old,
14218c2ecf20Sopenharmony_ci	struct core_data *core_delta)
14228c2ecf20Sopenharmony_ci{
14238c2ecf20Sopenharmony_ci	int i;
14248c2ecf20Sopenharmony_ci	struct msr_counter *mp;
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	/* we run cpuid just the 1st time, copy the results */
14278c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_APIC))
14288c2ecf20Sopenharmony_ci		new->apic_id = old->apic_id;
14298c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_X2APIC))
14308c2ecf20Sopenharmony_ci		new->x2apic_id = old->x2apic_id;
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	/*
14338c2ecf20Sopenharmony_ci	 * the timestamps from start of measurement interval are in "old"
14348c2ecf20Sopenharmony_ci	 * the timestamp from end of measurement interval are in "new"
14358c2ecf20Sopenharmony_ci	 * over-write old w/ new so we can print end of interval values
14368c2ecf20Sopenharmony_ci	 */
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
14398c2ecf20Sopenharmony_ci	old->tv_begin = new->tv_begin;
14408c2ecf20Sopenharmony_ci	old->tv_end = new->tv_end;
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	old->tsc = new->tsc - old->tsc;
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	/* check for TSC < 1 Mcycles over interval */
14458c2ecf20Sopenharmony_ci	if (old->tsc < (1000 * 1000))
14468c2ecf20Sopenharmony_ci		errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n"
14478c2ecf20Sopenharmony_ci		     "You can disable all c-states by booting with \"idle=poll\"\n"
14488c2ecf20Sopenharmony_ci		     "or just the deep ones with \"processor.max_cstate=1\"");
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	old->c1 = new->c1 - old->c1;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
14538c2ecf20Sopenharmony_ci	    soft_c1_residency_display(BIC_Avg_MHz)) {
14548c2ecf20Sopenharmony_ci		if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
14558c2ecf20Sopenharmony_ci			old->aperf = new->aperf - old->aperf;
14568c2ecf20Sopenharmony_ci			old->mperf = new->mperf - old->mperf;
14578c2ecf20Sopenharmony_ci		} else {
14588c2ecf20Sopenharmony_ci			return -1;
14598c2ecf20Sopenharmony_ci		}
14608c2ecf20Sopenharmony_ci	}
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	if (use_c1_residency_msr) {
14648c2ecf20Sopenharmony_ci		/*
14658c2ecf20Sopenharmony_ci		 * Some models have a dedicated C1 residency MSR,
14668c2ecf20Sopenharmony_ci		 * which should be more accurate than the derivation below.
14678c2ecf20Sopenharmony_ci		 */
14688c2ecf20Sopenharmony_ci	} else {
14698c2ecf20Sopenharmony_ci		/*
14708c2ecf20Sopenharmony_ci		 * As counter collection is not atomic,
14718c2ecf20Sopenharmony_ci		 * it is possible for mperf's non-halted cycles + idle states
14728c2ecf20Sopenharmony_ci		 * to exceed TSC's all cycles: show c1 = 0% in that case.
14738c2ecf20Sopenharmony_ci		 */
14748c2ecf20Sopenharmony_ci		if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > (old->tsc * tsc_tweak))
14758c2ecf20Sopenharmony_ci			old->c1 = 0;
14768c2ecf20Sopenharmony_ci		else {
14778c2ecf20Sopenharmony_ci			/* normal case, derive c1 */
14788c2ecf20Sopenharmony_ci			old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3
14798c2ecf20Sopenharmony_ci				- core_delta->c6 - core_delta->c7;
14808c2ecf20Sopenharmony_ci		}
14818c2ecf20Sopenharmony_ci	}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci	if (old->mperf == 0) {
14848c2ecf20Sopenharmony_ci		if (debug > 1)
14858c2ecf20Sopenharmony_ci			fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);
14868c2ecf20Sopenharmony_ci		old->mperf = 1;	/* divide by 0 protection */
14878c2ecf20Sopenharmony_ci	}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_IRQ))
14908c2ecf20Sopenharmony_ci		old->irq_count = new->irq_count - old->irq_count;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SMI))
14938c2ecf20Sopenharmony_ci		old->smi_count = new->smi_count - old->smi_count;
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
14968c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
14978c2ecf20Sopenharmony_ci			old->counter[i] = new->counter[i];
14988c2ecf20Sopenharmony_ci		else
14998c2ecf20Sopenharmony_ci			old->counter[i] = new->counter[i] - old->counter[i];
15008c2ecf20Sopenharmony_ci	}
15018c2ecf20Sopenharmony_ci	return 0;
15028c2ecf20Sopenharmony_ci}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ciint delta_cpu(struct thread_data *t, struct core_data *c,
15058c2ecf20Sopenharmony_ci	struct pkg_data *p, struct thread_data *t2,
15068c2ecf20Sopenharmony_ci	struct core_data *c2, struct pkg_data *p2)
15078c2ecf20Sopenharmony_ci{
15088c2ecf20Sopenharmony_ci	int retval = 0;
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci	/* calculate core delta only for 1st thread in core */
15118c2ecf20Sopenharmony_ci	if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE)
15128c2ecf20Sopenharmony_ci		delta_core(c, c2);
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	/* always calculate thread delta */
15158c2ecf20Sopenharmony_ci	retval = delta_thread(t, t2, c2);	/* c2 is core delta */
15168c2ecf20Sopenharmony_ci	if (retval)
15178c2ecf20Sopenharmony_ci		return retval;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	/* calculate package delta only for 1st core in package */
15208c2ecf20Sopenharmony_ci	if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)
15218c2ecf20Sopenharmony_ci		retval = delta_package(p, p2);
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	return retval;
15248c2ecf20Sopenharmony_ci}
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_civoid clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
15278c2ecf20Sopenharmony_ci{
15288c2ecf20Sopenharmony_ci	int i;
15298c2ecf20Sopenharmony_ci	struct msr_counter  *mp;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	t->tv_begin.tv_sec = 0;
15328c2ecf20Sopenharmony_ci	t->tv_begin.tv_usec = 0;
15338c2ecf20Sopenharmony_ci	t->tv_end.tv_sec = 0;
15348c2ecf20Sopenharmony_ci	t->tv_end.tv_usec = 0;
15358c2ecf20Sopenharmony_ci	t->tv_delta.tv_sec = 0;
15368c2ecf20Sopenharmony_ci	t->tv_delta.tv_usec = 0;
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	t->tsc = 0;
15398c2ecf20Sopenharmony_ci	t->aperf = 0;
15408c2ecf20Sopenharmony_ci	t->mperf = 0;
15418c2ecf20Sopenharmony_ci	t->c1 = 0;
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	t->irq_count = 0;
15448c2ecf20Sopenharmony_ci	t->smi_count = 0;
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	/* tells format_counters to dump all fields from this set */
15478c2ecf20Sopenharmony_ci	t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	c->c3 = 0;
15508c2ecf20Sopenharmony_ci	c->c6 = 0;
15518c2ecf20Sopenharmony_ci	c->c7 = 0;
15528c2ecf20Sopenharmony_ci	c->mc6_us = 0;
15538c2ecf20Sopenharmony_ci	c->core_temp_c = 0;
15548c2ecf20Sopenharmony_ci	c->core_energy = 0;
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	p->pkg_wtd_core_c0 = 0;
15578c2ecf20Sopenharmony_ci	p->pkg_any_core_c0 = 0;
15588c2ecf20Sopenharmony_ci	p->pkg_any_gfxe_c0 = 0;
15598c2ecf20Sopenharmony_ci	p->pkg_both_core_gfxe_c0 = 0;
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	p->pc2 = 0;
15628c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
15638c2ecf20Sopenharmony_ci		p->pc3 = 0;
15648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6))
15658c2ecf20Sopenharmony_ci		p->pc6 = 0;
15668c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
15678c2ecf20Sopenharmony_ci		p->pc7 = 0;
15688c2ecf20Sopenharmony_ci	p->pc8 = 0;
15698c2ecf20Sopenharmony_ci	p->pc9 = 0;
15708c2ecf20Sopenharmony_ci	p->pc10 = 0;
15718c2ecf20Sopenharmony_ci	p->cpu_lpi = 0;
15728c2ecf20Sopenharmony_ci	p->sys_lpi = 0;
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_ci	p->energy_pkg = 0;
15758c2ecf20Sopenharmony_ci	p->energy_dram = 0;
15768c2ecf20Sopenharmony_ci	p->energy_cores = 0;
15778c2ecf20Sopenharmony_ci	p->energy_gfx = 0;
15788c2ecf20Sopenharmony_ci	p->rapl_pkg_perf_status = 0;
15798c2ecf20Sopenharmony_ci	p->rapl_dram_perf_status = 0;
15808c2ecf20Sopenharmony_ci	p->pkg_temp_c = 0;
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	p->gfx_rc6_ms = 0;
15838c2ecf20Sopenharmony_ci	p->gfx_mhz = 0;
15848c2ecf20Sopenharmony_ci	p->gfx_act_mhz = 0;
15858c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
15868c2ecf20Sopenharmony_ci		t->counter[i] = 0;
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next)
15898c2ecf20Sopenharmony_ci		c->counter[i] = 0;
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next)
15928c2ecf20Sopenharmony_ci		p->counter[i] = 0;
15938c2ecf20Sopenharmony_ci}
15948c2ecf20Sopenharmony_ciint sum_counters(struct thread_data *t, struct core_data *c,
15958c2ecf20Sopenharmony_ci	struct pkg_data *p)
15968c2ecf20Sopenharmony_ci{
15978c2ecf20Sopenharmony_ci	int i;
15988c2ecf20Sopenharmony_ci	struct msr_counter *mp;
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	/* copy un-changing apic_id's */
16018c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_APIC))
16028c2ecf20Sopenharmony_ci		average.threads.apic_id = t->apic_id;
16038c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_X2APIC))
16048c2ecf20Sopenharmony_ci		average.threads.x2apic_id = t->x2apic_id;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	/* remember first tv_begin */
16078c2ecf20Sopenharmony_ci	if (average.threads.tv_begin.tv_sec == 0)
16088c2ecf20Sopenharmony_ci		average.threads.tv_begin = t->tv_begin;
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	/* remember last tv_end */
16118c2ecf20Sopenharmony_ci	average.threads.tv_end = t->tv_end;
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	average.threads.tsc += t->tsc;
16148c2ecf20Sopenharmony_ci	average.threads.aperf += t->aperf;
16158c2ecf20Sopenharmony_ci	average.threads.mperf += t->mperf;
16168c2ecf20Sopenharmony_ci	average.threads.c1 += t->c1;
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	average.threads.irq_count += t->irq_count;
16198c2ecf20Sopenharmony_ci	average.threads.smi_count += t->smi_count;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
16228c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
16238c2ecf20Sopenharmony_ci			continue;
16248c2ecf20Sopenharmony_ci		average.threads.counter[i] += t->counter[i];
16258c2ecf20Sopenharmony_ci	}
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	/* sum per-core values only for 1st thread in core */
16288c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
16298c2ecf20Sopenharmony_ci		return 0;
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	average.cores.c3 += c->c3;
16328c2ecf20Sopenharmony_ci	average.cores.c6 += c->c6;
16338c2ecf20Sopenharmony_ci	average.cores.c7 += c->c7;
16348c2ecf20Sopenharmony_ci	average.cores.mc6_us += c->mc6_us;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	average.cores.core_energy += c->core_energy;
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
16418c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
16428c2ecf20Sopenharmony_ci			continue;
16438c2ecf20Sopenharmony_ci		average.cores.counter[i] += c->counter[i];
16448c2ecf20Sopenharmony_ci	}
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci	/* sum per-pkg values only for 1st core in pkg */
16478c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
16488c2ecf20Sopenharmony_ci		return 0;
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Totl_c0))
16518c2ecf20Sopenharmony_ci		average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0;
16528c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Any_c0))
16538c2ecf20Sopenharmony_ci		average.packages.pkg_any_core_c0 += p->pkg_any_core_c0;
16548c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_c0))
16558c2ecf20Sopenharmony_ci		average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;
16568c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPUGFX))
16578c2ecf20Sopenharmony_ci		average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	average.packages.pc2 += p->pc2;
16608c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
16618c2ecf20Sopenharmony_ci		average.packages.pc3 += p->pc3;
16628c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6))
16638c2ecf20Sopenharmony_ci		average.packages.pc6 += p->pc6;
16648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
16658c2ecf20Sopenharmony_ci		average.packages.pc7 += p->pc7;
16668c2ecf20Sopenharmony_ci	average.packages.pc8 += p->pc8;
16678c2ecf20Sopenharmony_ci	average.packages.pc9 += p->pc9;
16688c2ecf20Sopenharmony_ci	average.packages.pc10 += p->pc10;
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	average.packages.cpu_lpi = p->cpu_lpi;
16718c2ecf20Sopenharmony_ci	average.packages.sys_lpi = p->sys_lpi;
16728c2ecf20Sopenharmony_ci
16738c2ecf20Sopenharmony_ci	average.packages.energy_pkg += p->energy_pkg;
16748c2ecf20Sopenharmony_ci	average.packages.energy_dram += p->energy_dram;
16758c2ecf20Sopenharmony_ci	average.packages.energy_cores += p->energy_cores;
16768c2ecf20Sopenharmony_ci	average.packages.energy_gfx += p->energy_gfx;
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci	average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
16798c2ecf20Sopenharmony_ci	average.packages.gfx_mhz = p->gfx_mhz;
16808c2ecf20Sopenharmony_ci	average.packages.gfx_act_mhz = p->gfx_act_mhz;
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status;
16858c2ecf20Sopenharmony_ci	average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status;
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
16888c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
16898c2ecf20Sopenharmony_ci			continue;
16908c2ecf20Sopenharmony_ci		average.packages.counter[i] += p->counter[i];
16918c2ecf20Sopenharmony_ci	}
16928c2ecf20Sopenharmony_ci	return 0;
16938c2ecf20Sopenharmony_ci}
16948c2ecf20Sopenharmony_ci/*
16958c2ecf20Sopenharmony_ci * sum the counters for all cpus in the system
16968c2ecf20Sopenharmony_ci * compute the weighted average
16978c2ecf20Sopenharmony_ci */
16988c2ecf20Sopenharmony_civoid compute_average(struct thread_data *t, struct core_data *c,
16998c2ecf20Sopenharmony_ci	struct pkg_data *p)
17008c2ecf20Sopenharmony_ci{
17018c2ecf20Sopenharmony_ci	int i;
17028c2ecf20Sopenharmony_ci	struct msr_counter *mp;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	clear_counters(&average.threads, &average.cores, &average.packages);
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	for_all_cpus(sum_counters, t, c, p);
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	/* Use the global time delta for the average. */
17098c2ecf20Sopenharmony_ci	average.threads.tv_delta = tv_delta;
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	average.threads.tsc /= topo.num_cpus;
17128c2ecf20Sopenharmony_ci	average.threads.aperf /= topo.num_cpus;
17138c2ecf20Sopenharmony_ci	average.threads.mperf /= topo.num_cpus;
17148c2ecf20Sopenharmony_ci	average.threads.c1 /= topo.num_cpus;
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci	if (average.threads.irq_count > 9999999)
17178c2ecf20Sopenharmony_ci		sums_need_wide_columns = 1;
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	average.cores.c3 /= topo.num_cores;
17208c2ecf20Sopenharmony_ci	average.cores.c6 /= topo.num_cores;
17218c2ecf20Sopenharmony_ci	average.cores.c7 /= topo.num_cores;
17228c2ecf20Sopenharmony_ci	average.cores.mc6_us /= topo.num_cores;
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Totl_c0))
17258c2ecf20Sopenharmony_ci		average.packages.pkg_wtd_core_c0 /= topo.num_packages;
17268c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Any_c0))
17278c2ecf20Sopenharmony_ci		average.packages.pkg_any_core_c0 /= topo.num_packages;
17288c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_c0))
17298c2ecf20Sopenharmony_ci		average.packages.pkg_any_gfxe_c0 /= topo.num_packages;
17308c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPUGFX))
17318c2ecf20Sopenharmony_ci		average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages;
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci	average.packages.pc2 /= topo.num_packages;
17348c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
17358c2ecf20Sopenharmony_ci		average.packages.pc3 /= topo.num_packages;
17368c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6))
17378c2ecf20Sopenharmony_ci		average.packages.pc6 /= topo.num_packages;
17388c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
17398c2ecf20Sopenharmony_ci		average.packages.pc7 /= topo.num_packages;
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	average.packages.pc8 /= topo.num_packages;
17428c2ecf20Sopenharmony_ci	average.packages.pc9 /= topo.num_packages;
17438c2ecf20Sopenharmony_ci	average.packages.pc10 /= topo.num_packages;
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
17468c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
17478c2ecf20Sopenharmony_ci			continue;
17488c2ecf20Sopenharmony_ci		if (mp->type == COUNTER_ITEMS) {
17498c2ecf20Sopenharmony_ci			if (average.threads.counter[i] > 9999999)
17508c2ecf20Sopenharmony_ci				sums_need_wide_columns = 1;
17518c2ecf20Sopenharmony_ci			continue;
17528c2ecf20Sopenharmony_ci		}
17538c2ecf20Sopenharmony_ci		average.threads.counter[i] /= topo.num_cpus;
17548c2ecf20Sopenharmony_ci	}
17558c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
17568c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
17578c2ecf20Sopenharmony_ci			continue;
17588c2ecf20Sopenharmony_ci		if (mp->type == COUNTER_ITEMS) {
17598c2ecf20Sopenharmony_ci			if (average.cores.counter[i] > 9999999)
17608c2ecf20Sopenharmony_ci				sums_need_wide_columns = 1;
17618c2ecf20Sopenharmony_ci		}
17628c2ecf20Sopenharmony_ci		average.cores.counter[i] /= topo.num_cores;
17638c2ecf20Sopenharmony_ci	}
17648c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
17658c2ecf20Sopenharmony_ci		if (mp->format == FORMAT_RAW)
17668c2ecf20Sopenharmony_ci			continue;
17678c2ecf20Sopenharmony_ci		if (mp->type == COUNTER_ITEMS) {
17688c2ecf20Sopenharmony_ci			if (average.packages.counter[i] > 9999999)
17698c2ecf20Sopenharmony_ci				sums_need_wide_columns = 1;
17708c2ecf20Sopenharmony_ci		}
17718c2ecf20Sopenharmony_ci		average.packages.counter[i] /= topo.num_packages;
17728c2ecf20Sopenharmony_ci	}
17738c2ecf20Sopenharmony_ci}
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_cistatic unsigned long long rdtsc(void)
17768c2ecf20Sopenharmony_ci{
17778c2ecf20Sopenharmony_ci	unsigned int low, high;
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	asm volatile("rdtsc" : "=a" (low), "=d" (high));
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	return low | ((unsigned long long)high) << 32;
17828c2ecf20Sopenharmony_ci}
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ci/*
17858c2ecf20Sopenharmony_ci * Open a file, and exit on failure
17868c2ecf20Sopenharmony_ci */
17878c2ecf20Sopenharmony_ciFILE *fopen_or_die(const char *path, const char *mode)
17888c2ecf20Sopenharmony_ci{
17898c2ecf20Sopenharmony_ci	FILE *filep = fopen(path, mode);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	if (!filep)
17928c2ecf20Sopenharmony_ci		err(1, "%s: open failed", path);
17938c2ecf20Sopenharmony_ci	return filep;
17948c2ecf20Sopenharmony_ci}
17958c2ecf20Sopenharmony_ci/*
17968c2ecf20Sopenharmony_ci * snapshot_sysfs_counter()
17978c2ecf20Sopenharmony_ci *
17988c2ecf20Sopenharmony_ci * return snapshot of given counter
17998c2ecf20Sopenharmony_ci */
18008c2ecf20Sopenharmony_ciunsigned long long snapshot_sysfs_counter(char *path)
18018c2ecf20Sopenharmony_ci{
18028c2ecf20Sopenharmony_ci	FILE *fp;
18038c2ecf20Sopenharmony_ci	int retval;
18048c2ecf20Sopenharmony_ci	unsigned long long counter;
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	fp = fopen_or_die(path, "r");
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci	retval = fscanf(fp, "%lld", &counter);
18098c2ecf20Sopenharmony_ci	if (retval != 1)
18108c2ecf20Sopenharmony_ci		err(1, "snapshot_sysfs_counter(%s)", path);
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	fclose(fp);
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	return counter;
18158c2ecf20Sopenharmony_ci}
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ciint get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
18188c2ecf20Sopenharmony_ci{
18198c2ecf20Sopenharmony_ci	if (mp->msr_num != 0) {
18208c2ecf20Sopenharmony_ci		if (get_msr(cpu, mp->msr_num, counterp))
18218c2ecf20Sopenharmony_ci			return -1;
18228c2ecf20Sopenharmony_ci	} else {
18238c2ecf20Sopenharmony_ci		char path[128 + PATH_BYTES];
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci		if (mp->flags & SYSFS_PERCPU) {
18268c2ecf20Sopenharmony_ci			sprintf(path, "/sys/devices/system/cpu/cpu%d/%s",
18278c2ecf20Sopenharmony_ci				 cpu, mp->path);
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci			*counterp = snapshot_sysfs_counter(path);
18308c2ecf20Sopenharmony_ci		} else {
18318c2ecf20Sopenharmony_ci			*counterp = snapshot_sysfs_counter(mp->path);
18328c2ecf20Sopenharmony_ci		}
18338c2ecf20Sopenharmony_ci	}
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	return 0;
18368c2ecf20Sopenharmony_ci}
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_civoid get_apic_id(struct thread_data *t)
18398c2ecf20Sopenharmony_ci{
18408c2ecf20Sopenharmony_ci	unsigned int eax, ebx, ecx, edx;
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_APIC)) {
18438c2ecf20Sopenharmony_ci		eax = ebx = ecx = edx = 0;
18448c2ecf20Sopenharmony_ci		__cpuid(1, eax, ebx, ecx, edx);
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci		t->apic_id = (ebx >> 24) & 0xff;
18478c2ecf20Sopenharmony_ci	}
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ci	if (!DO_BIC(BIC_X2APIC))
18508c2ecf20Sopenharmony_ci		return;
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci	if (authentic_amd || hygon_genuine) {
18538c2ecf20Sopenharmony_ci		unsigned int topology_extensions;
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci		if (max_extended_level < 0x8000001e)
18568c2ecf20Sopenharmony_ci			return;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci		eax = ebx = ecx = edx = 0;
18598c2ecf20Sopenharmony_ci		__cpuid(0x80000001, eax, ebx, ecx, edx);
18608c2ecf20Sopenharmony_ci			topology_extensions = ecx & (1 << 22);
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci		if (topology_extensions == 0)
18638c2ecf20Sopenharmony_ci			return;
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci		eax = ebx = ecx = edx = 0;
18668c2ecf20Sopenharmony_ci		__cpuid(0x8000001e, eax, ebx, ecx, edx);
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci		t->x2apic_id = eax;
18698c2ecf20Sopenharmony_ci		return;
18708c2ecf20Sopenharmony_ci	}
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci	if (!genuine_intel)
18738c2ecf20Sopenharmony_ci		return;
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci	if (max_level < 0xb)
18768c2ecf20Sopenharmony_ci		return;
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_ci	ecx = 0;
18798c2ecf20Sopenharmony_ci	__cpuid(0xb, eax, ebx, ecx, edx);
18808c2ecf20Sopenharmony_ci	t->x2apic_id = edx;
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	if (debug && (t->apic_id != (t->x2apic_id & 0xff)))
18838c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n",
18848c2ecf20Sopenharmony_ci				t->cpu_id, t->apic_id, t->x2apic_id);
18858c2ecf20Sopenharmony_ci}
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci/*
18888c2ecf20Sopenharmony_ci * get_counters(...)
18898c2ecf20Sopenharmony_ci * migrate to cpu
18908c2ecf20Sopenharmony_ci * acquire and record local counters for that cpu
18918c2ecf20Sopenharmony_ci */
18928c2ecf20Sopenharmony_ciint get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
18938c2ecf20Sopenharmony_ci{
18948c2ecf20Sopenharmony_ci	int cpu = t->cpu_id;
18958c2ecf20Sopenharmony_ci	unsigned long long msr;
18968c2ecf20Sopenharmony_ci	int aperf_mperf_retry_count = 0;
18978c2ecf20Sopenharmony_ci	struct msr_counter *mp;
18988c2ecf20Sopenharmony_ci	int i;
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
19018c2ecf20Sopenharmony_ci		fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu);
19028c2ecf20Sopenharmony_ci		return -1;
19038c2ecf20Sopenharmony_ci	}
19048c2ecf20Sopenharmony_ci
19058c2ecf20Sopenharmony_ci	gettimeofday(&t->tv_begin, (struct timezone *)NULL);
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	if (first_counter_read)
19088c2ecf20Sopenharmony_ci		get_apic_id(t);
19098c2ecf20Sopenharmony_ciretry:
19108c2ecf20Sopenharmony_ci	t->tsc = rdtsc();	/* we are running on local CPU of interest */
19118c2ecf20Sopenharmony_ci
19128c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
19138c2ecf20Sopenharmony_ci	    soft_c1_residency_display(BIC_Avg_MHz)) {
19148c2ecf20Sopenharmony_ci		unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ci		/*
19178c2ecf20Sopenharmony_ci		 * The TSC, APERF and MPERF must be read together for
19188c2ecf20Sopenharmony_ci		 * APERF/MPERF and MPERF/TSC to give accurate results.
19198c2ecf20Sopenharmony_ci		 *
19208c2ecf20Sopenharmony_ci		 * Unfortunately, APERF and MPERF are read by
19218c2ecf20Sopenharmony_ci		 * individual system call, so delays may occur
19228c2ecf20Sopenharmony_ci		 * between them.  If the time to read them
19238c2ecf20Sopenharmony_ci		 * varies by a large amount, we re-read them.
19248c2ecf20Sopenharmony_ci		 */
19258c2ecf20Sopenharmony_ci
19268c2ecf20Sopenharmony_ci		/*
19278c2ecf20Sopenharmony_ci		 * This initial dummy APERF read has been seen to
19288c2ecf20Sopenharmony_ci		 * reduce jitter in the subsequent reads.
19298c2ecf20Sopenharmony_ci		 */
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
19328c2ecf20Sopenharmony_ci			return -3;
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci		t->tsc = rdtsc();	/* re-read close to APERF */
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci		tsc_before = t->tsc;
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
19398c2ecf20Sopenharmony_ci			return -3;
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci		tsc_between = rdtsc();
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf))
19448c2ecf20Sopenharmony_ci			return -4;
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci		tsc_after = rdtsc();
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci		aperf_time = tsc_between - tsc_before;
19498c2ecf20Sopenharmony_ci		mperf_time = tsc_after - tsc_between;
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci		/*
19528c2ecf20Sopenharmony_ci		 * If the system call latency to read APERF and MPERF
19538c2ecf20Sopenharmony_ci		 * differ by more than 2x, then try again.
19548c2ecf20Sopenharmony_ci		 */
19558c2ecf20Sopenharmony_ci		if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) {
19568c2ecf20Sopenharmony_ci			aperf_mperf_retry_count++;
19578c2ecf20Sopenharmony_ci			if (aperf_mperf_retry_count < 5)
19588c2ecf20Sopenharmony_ci				goto retry;
19598c2ecf20Sopenharmony_ci			else
19608c2ecf20Sopenharmony_ci				warnx("cpu%d jitter %lld %lld",
19618c2ecf20Sopenharmony_ci					cpu, aperf_time, mperf_time);
19628c2ecf20Sopenharmony_ci		}
19638c2ecf20Sopenharmony_ci		aperf_mperf_retry_count = 0;
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci		t->aperf = t->aperf * aperf_mperf_multiplier;
19668c2ecf20Sopenharmony_ci		t->mperf = t->mperf * aperf_mperf_multiplier;
19678c2ecf20Sopenharmony_ci	}
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_IRQ))
19708c2ecf20Sopenharmony_ci		t->irq_count = irqs_per_cpu[cpu];
19718c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SMI)) {
19728c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_SMI_COUNT, &msr))
19738c2ecf20Sopenharmony_ci			return -5;
19748c2ecf20Sopenharmony_ci		t->smi_count = msr & 0xFFFFFFFF;
19758c2ecf20Sopenharmony_ci	}
19768c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c1) && use_c1_residency_msr) {
19778c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
19788c2ecf20Sopenharmony_ci			return -6;
19798c2ecf20Sopenharmony_ci	}
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
19828c2ecf20Sopenharmony_ci		if (get_mp(cpu, mp, &t->counter[i]))
19838c2ecf20Sopenharmony_ci			return -10;
19848c2ecf20Sopenharmony_ci	}
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	/* collect core counters only for 1st thread in core */
19878c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
19888c2ecf20Sopenharmony_ci		goto done;
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) {
19918c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
19928c2ecf20Sopenharmony_ci			return -6;
19938c2ecf20Sopenharmony_ci	}
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) {
19968c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
19978c2ecf20Sopenharmony_ci			return -7;
19988c2ecf20Sopenharmony_ci	} else if (do_knl_cstates && soft_c1_residency_display(BIC_CPU_c6)) {
19998c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
20008c2ecf20Sopenharmony_ci			return -7;
20018c2ecf20Sopenharmony_ci	}
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7))
20048c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
20058c2ecf20Sopenharmony_ci			return -8;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Mod_c6))
20088c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))
20098c2ecf20Sopenharmony_ci			return -8;
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CoreTmp)) {
20128c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
20138c2ecf20Sopenharmony_ci			return -9;
20148c2ecf20Sopenharmony_ci		c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
20158c2ecf20Sopenharmony_ci	}
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_AMD_F17H) {
20188c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr))
20198c2ecf20Sopenharmony_ci			return -14;
20208c2ecf20Sopenharmony_ci		c->core_energy = msr & 0xFFFFFFFF;
20218c2ecf20Sopenharmony_ci	}
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
20248c2ecf20Sopenharmony_ci		if (get_mp(cpu, mp, &c->counter[i]))
20258c2ecf20Sopenharmony_ci			return -10;
20268c2ecf20Sopenharmony_ci	}
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	/* collect package counters only for 1st core in package */
20298c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
20308c2ecf20Sopenharmony_ci		goto done;
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Totl_c0)) {
20338c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))
20348c2ecf20Sopenharmony_ci			return -10;
20358c2ecf20Sopenharmony_ci	}
20368c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Any_c0)) {
20378c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))
20388c2ecf20Sopenharmony_ci			return -11;
20398c2ecf20Sopenharmony_ci	}
20408c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_c0)) {
20418c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))
20428c2ecf20Sopenharmony_ci			return -12;
20438c2ecf20Sopenharmony_ci	}
20448c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPUGFX)) {
20458c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
20468c2ecf20Sopenharmony_ci			return -13;
20478c2ecf20Sopenharmony_ci	}
20488c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc3))
20498c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
20508c2ecf20Sopenharmony_ci			return -9;
20518c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc6)) {
20528c2ecf20Sopenharmony_ci		if (do_slm_cstates) {
20538c2ecf20Sopenharmony_ci			if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6))
20548c2ecf20Sopenharmony_ci				return -10;
20558c2ecf20Sopenharmony_ci		} else {
20568c2ecf20Sopenharmony_ci			if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
20578c2ecf20Sopenharmony_ci				return -10;
20588c2ecf20Sopenharmony_ci		}
20598c2ecf20Sopenharmony_ci	}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc2))
20628c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2))
20638c2ecf20Sopenharmony_ci			return -11;
20648c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc7))
20658c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
20668c2ecf20Sopenharmony_ci			return -12;
20678c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc8))
20688c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
20698c2ecf20Sopenharmony_ci			return -13;
20708c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc9))
20718c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9))
20728c2ecf20Sopenharmony_ci			return -13;
20738c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_Pkgpc10))
20748c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10))
20758c2ecf20Sopenharmony_ci			return -13;
20768c2ecf20Sopenharmony_ci
20778c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_LPI))
20788c2ecf20Sopenharmony_ci		p->cpu_lpi = cpuidle_cur_cpu_lpi_us;
20798c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SYS_LPI))
20808c2ecf20Sopenharmony_ci		p->sys_lpi = cpuidle_cur_sys_lpi_us;
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_PKG) {
20838c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr))
20848c2ecf20Sopenharmony_ci			return -13;
20858c2ecf20Sopenharmony_ci		p->energy_pkg = msr;
20868c2ecf20Sopenharmony_ci	}
20878c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_CORES_ENERGY_STATUS) {
20888c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr))
20898c2ecf20Sopenharmony_ci			return -14;
20908c2ecf20Sopenharmony_ci		p->energy_cores = msr;
20918c2ecf20Sopenharmony_ci	}
20928c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_DRAM) {
20938c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
20948c2ecf20Sopenharmony_ci			return -15;
20958c2ecf20Sopenharmony_ci		p->energy_dram = msr;
20968c2ecf20Sopenharmony_ci	}
20978c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_GFX) {
20988c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr))
20998c2ecf20Sopenharmony_ci			return -16;
21008c2ecf20Sopenharmony_ci		p->energy_gfx = msr;
21018c2ecf20Sopenharmony_ci	}
21028c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_PKG_PERF_STATUS) {
21038c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr))
21048c2ecf20Sopenharmony_ci			return -16;
21058c2ecf20Sopenharmony_ci		p->rapl_pkg_perf_status = msr;
21068c2ecf20Sopenharmony_ci	}
21078c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_DRAM_PERF_STATUS) {
21088c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr))
21098c2ecf20Sopenharmony_ci			return -16;
21108c2ecf20Sopenharmony_ci		p->rapl_dram_perf_status = msr;
21118c2ecf20Sopenharmony_ci	}
21128c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_AMD_F17H) {
21138c2ecf20Sopenharmony_ci		if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr))
21148c2ecf20Sopenharmony_ci			return -13;
21158c2ecf20Sopenharmony_ci		p->energy_pkg = msr;
21168c2ecf20Sopenharmony_ci	}
21178c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_PkgTmp)) {
21188c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
21198c2ecf20Sopenharmony_ci			return -17;
21208c2ecf20Sopenharmony_ci		p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
21218c2ecf20Sopenharmony_ci	}
21228c2ecf20Sopenharmony_ci
21238c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_rc6))
21248c2ecf20Sopenharmony_ci		p->gfx_rc6_ms = gfx_cur_rc6_ms;
21258c2ecf20Sopenharmony_ci
21268c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXMHz))
21278c2ecf20Sopenharmony_ci		p->gfx_mhz = gfx_cur_mhz;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXACTMHz))
21308c2ecf20Sopenharmony_ci		p->gfx_act_mhz = gfx_act_mhz;
21318c2ecf20Sopenharmony_ci
21328c2ecf20Sopenharmony_ci	for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
21338c2ecf20Sopenharmony_ci		if (get_mp(cpu, mp, &p->counter[i]))
21348c2ecf20Sopenharmony_ci			return -10;
21358c2ecf20Sopenharmony_ci	}
21368c2ecf20Sopenharmony_cidone:
21378c2ecf20Sopenharmony_ci	gettimeofday(&t->tv_end, (struct timezone *)NULL);
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	return 0;
21408c2ecf20Sopenharmony_ci}
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci/*
21438c2ecf20Sopenharmony_ci * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:
21448c2ecf20Sopenharmony_ci * If you change the values, note they are used both in comparisons
21458c2ecf20Sopenharmony_ci * (>= PCL__7) and to index pkg_cstate_limit_strings[].
21468c2ecf20Sopenharmony_ci */
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci#define PCLUKN 0 /* Unknown */
21498c2ecf20Sopenharmony_ci#define PCLRSV 1 /* Reserved */
21508c2ecf20Sopenharmony_ci#define PCL__0 2 /* PC0 */
21518c2ecf20Sopenharmony_ci#define PCL__1 3 /* PC1 */
21528c2ecf20Sopenharmony_ci#define PCL__2 4 /* PC2 */
21538c2ecf20Sopenharmony_ci#define PCL__3 5 /* PC3 */
21548c2ecf20Sopenharmony_ci#define PCL__4 6 /* PC4 */
21558c2ecf20Sopenharmony_ci#define PCL__6 7 /* PC6 */
21568c2ecf20Sopenharmony_ci#define PCL_6N 8 /* PC6 No Retention */
21578c2ecf20Sopenharmony_ci#define PCL_6R 9 /* PC6 Retention */
21588c2ecf20Sopenharmony_ci#define PCL__7 10 /* PC7 */
21598c2ecf20Sopenharmony_ci#define PCL_7S 11 /* PC7 Shrink */
21608c2ecf20Sopenharmony_ci#define PCL__8 12 /* PC8 */
21618c2ecf20Sopenharmony_ci#define PCL__9 13 /* PC9 */
21628c2ecf20Sopenharmony_ci#define PCL_10 14 /* PC10 */
21638c2ecf20Sopenharmony_ci#define PCLUNL 15 /* Unlimited */
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ciint pkg_cstate_limit = PCLUKN;
21668c2ecf20Sopenharmony_cichar *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
21678c2ecf20Sopenharmony_ci	"pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"};
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ciint nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21708c2ecf20Sopenharmony_ciint snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21718c2ecf20Sopenharmony_ciint hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21728c2ecf20Sopenharmony_ciint slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
21738c2ecf20Sopenharmony_ciint amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21748c2ecf20Sopenharmony_ciint phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21758c2ecf20Sopenharmony_ciint glm_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21768c2ecf20Sopenharmony_ciint skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
21778c2ecf20Sopenharmony_ci
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_cistatic void
21808c2ecf20Sopenharmony_cicalculate_tsc_tweak()
21818c2ecf20Sopenharmony_ci{
21828c2ecf20Sopenharmony_ci	tsc_tweak = base_hz / tsc_hz;
21838c2ecf20Sopenharmony_ci}
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_cistatic void
21868c2ecf20Sopenharmony_cidump_nhm_platform_info(void)
21878c2ecf20Sopenharmony_ci{
21888c2ecf20Sopenharmony_ci	unsigned long long msr;
21898c2ecf20Sopenharmony_ci	unsigned int ratio;
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	ratio = (msr >> 40) & 0xFF;
21968c2ecf20Sopenharmony_ci	fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n",
21978c2ecf20Sopenharmony_ci		ratio, bclk, ratio * bclk);
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci	ratio = (msr >> 8) & 0xFF;
22008c2ecf20Sopenharmony_ci	fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
22018c2ecf20Sopenharmony_ci		ratio, bclk, ratio * bclk);
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
22048c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
22058c2ecf20Sopenharmony_ci		base_cpu, msr, msr & 0x2 ? "EN" : "DIS");
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	return;
22088c2ecf20Sopenharmony_ci}
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_cistatic void
22118c2ecf20Sopenharmony_cidump_hsw_turbo_ratio_limits(void)
22128c2ecf20Sopenharmony_ci{
22138c2ecf20Sopenharmony_ci	unsigned long long msr;
22148c2ecf20Sopenharmony_ci	unsigned int ratio;
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);
22178c2ecf20Sopenharmony_ci
22188c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci	ratio = (msr >> 8) & 0xFF;
22218c2ecf20Sopenharmony_ci	if (ratio)
22228c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n",
22238c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22248c2ecf20Sopenharmony_ci
22258c2ecf20Sopenharmony_ci	ratio = (msr >> 0) & 0xFF;
22268c2ecf20Sopenharmony_ci	if (ratio)
22278c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n",
22288c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22298c2ecf20Sopenharmony_ci	return;
22308c2ecf20Sopenharmony_ci}
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_cistatic void
22338c2ecf20Sopenharmony_cidump_ivt_turbo_ratio_limits(void)
22348c2ecf20Sopenharmony_ci{
22358c2ecf20Sopenharmony_ci	unsigned long long msr;
22368c2ecf20Sopenharmony_ci	unsigned int ratio;
22378c2ecf20Sopenharmony_ci
22388c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci	ratio = (msr >> 56) & 0xFF;
22438c2ecf20Sopenharmony_ci	if (ratio)
22448c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n",
22458c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	ratio = (msr >> 48) & 0xFF;
22488c2ecf20Sopenharmony_ci	if (ratio)
22498c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n",
22508c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci	ratio = (msr >> 40) & 0xFF;
22538c2ecf20Sopenharmony_ci	if (ratio)
22548c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n",
22558c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22568c2ecf20Sopenharmony_ci
22578c2ecf20Sopenharmony_ci	ratio = (msr >> 32) & 0xFF;
22588c2ecf20Sopenharmony_ci	if (ratio)
22598c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n",
22608c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci	ratio = (msr >> 24) & 0xFF;
22638c2ecf20Sopenharmony_ci	if (ratio)
22648c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n",
22658c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	ratio = (msr >> 16) & 0xFF;
22688c2ecf20Sopenharmony_ci	if (ratio)
22698c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n",
22708c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci	ratio = (msr >> 8) & 0xFF;
22738c2ecf20Sopenharmony_ci	if (ratio)
22748c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n",
22758c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_ci	ratio = (msr >> 0) & 0xFF;
22788c2ecf20Sopenharmony_ci	if (ratio)
22798c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n",
22808c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
22818c2ecf20Sopenharmony_ci	return;
22828c2ecf20Sopenharmony_ci}
22838c2ecf20Sopenharmony_ciint has_turbo_ratio_group_limits(int family, int model)
22848c2ecf20Sopenharmony_ci{
22858c2ecf20Sopenharmony_ci
22868c2ecf20Sopenharmony_ci	if (!genuine_intel)
22878c2ecf20Sopenharmony_ci		return 0;
22888c2ecf20Sopenharmony_ci
22898c2ecf20Sopenharmony_ci	switch (model) {
22908c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT:
22918c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:
22928c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_D:
22938c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT_D:
22948c2ecf20Sopenharmony_ci		return 1;
22958c2ecf20Sopenharmony_ci	}
22968c2ecf20Sopenharmony_ci	return 0;
22978c2ecf20Sopenharmony_ci}
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_cistatic void
23008c2ecf20Sopenharmony_cidump_turbo_ratio_limits(int family, int model)
23018c2ecf20Sopenharmony_ci{
23028c2ecf20Sopenharmony_ci	unsigned long long msr, core_counts;
23038c2ecf20Sopenharmony_ci	unsigned int ratio, group_size;
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
23068c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	if (has_turbo_ratio_group_limits(family, model)) {
23098c2ecf20Sopenharmony_ci		get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
23108c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts);
23118c2ecf20Sopenharmony_ci	} else {
23128c2ecf20Sopenharmony_ci		core_counts = 0x0807060504030201;
23138c2ecf20Sopenharmony_ci	}
23148c2ecf20Sopenharmony_ci
23158c2ecf20Sopenharmony_ci	ratio = (msr >> 56) & 0xFF;
23168c2ecf20Sopenharmony_ci	group_size = (core_counts >> 56) & 0xFF;
23178c2ecf20Sopenharmony_ci	if (ratio)
23188c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23198c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	ratio = (msr >> 48) & 0xFF;
23228c2ecf20Sopenharmony_ci	group_size = (core_counts >> 48) & 0xFF;
23238c2ecf20Sopenharmony_ci	if (ratio)
23248c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23258c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	ratio = (msr >> 40) & 0xFF;
23288c2ecf20Sopenharmony_ci	group_size = (core_counts >> 40) & 0xFF;
23298c2ecf20Sopenharmony_ci	if (ratio)
23308c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23318c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci	ratio = (msr >> 32) & 0xFF;
23348c2ecf20Sopenharmony_ci	group_size = (core_counts >> 32) & 0xFF;
23358c2ecf20Sopenharmony_ci	if (ratio)
23368c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23378c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	ratio = (msr >> 24) & 0xFF;
23408c2ecf20Sopenharmony_ci	group_size = (core_counts >> 24) & 0xFF;
23418c2ecf20Sopenharmony_ci	if (ratio)
23428c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23438c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci	ratio = (msr >> 16) & 0xFF;
23468c2ecf20Sopenharmony_ci	group_size = (core_counts >> 16) & 0xFF;
23478c2ecf20Sopenharmony_ci	if (ratio)
23488c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23498c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci	ratio = (msr >> 8) & 0xFF;
23528c2ecf20Sopenharmony_ci	group_size = (core_counts >> 8) & 0xFF;
23538c2ecf20Sopenharmony_ci	if (ratio)
23548c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23558c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci	ratio = (msr >> 0) & 0xFF;
23588c2ecf20Sopenharmony_ci	group_size = (core_counts >> 0) & 0xFF;
23598c2ecf20Sopenharmony_ci	if (ratio)
23608c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
23618c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk, group_size);
23628c2ecf20Sopenharmony_ci	return;
23638c2ecf20Sopenharmony_ci}
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_cistatic void
23668c2ecf20Sopenharmony_cidump_atom_turbo_ratio_limits(void)
23678c2ecf20Sopenharmony_ci{
23688c2ecf20Sopenharmony_ci	unsigned long long msr;
23698c2ecf20Sopenharmony_ci	unsigned int ratio;
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_ATOM_CORE_RATIOS, &msr);
23728c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_ci	ratio = (msr >> 0) & 0x3F;
23758c2ecf20Sopenharmony_ci	if (ratio)
23768c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n",
23778c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	ratio = (msr >> 8) & 0x3F;
23808c2ecf20Sopenharmony_ci	if (ratio)
23818c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n",
23828c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_ci	ratio = (msr >> 16) & 0x3F;
23858c2ecf20Sopenharmony_ci	if (ratio)
23868c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
23878c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
23888c2ecf20Sopenharmony_ci
23898c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
23908c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci	ratio = (msr >> 24) & 0x3F;
23938c2ecf20Sopenharmony_ci	if (ratio)
23948c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
23958c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ci	ratio = (msr >> 16) & 0x3F;
23988c2ecf20Sopenharmony_ci	if (ratio)
23998c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
24008c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci	ratio = (msr >> 8) & 0x3F;
24038c2ecf20Sopenharmony_ci	if (ratio)
24048c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
24058c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_ci	ratio = (msr >> 0) & 0x3F;
24088c2ecf20Sopenharmony_ci	if (ratio)
24098c2ecf20Sopenharmony_ci		fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n",
24108c2ecf20Sopenharmony_ci			ratio, bclk, ratio * bclk);
24118c2ecf20Sopenharmony_ci}
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_cistatic void
24148c2ecf20Sopenharmony_cidump_knl_turbo_ratio_limits(void)
24158c2ecf20Sopenharmony_ci{
24168c2ecf20Sopenharmony_ci	const unsigned int buckets_no = 7;
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci	unsigned long long msr;
24198c2ecf20Sopenharmony_ci	int delta_cores, delta_ratio;
24208c2ecf20Sopenharmony_ci	int i, b_nr;
24218c2ecf20Sopenharmony_ci	unsigned int cores[buckets_no];
24228c2ecf20Sopenharmony_ci	unsigned int ratio[buckets_no];
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
24258c2ecf20Sopenharmony_ci
24268c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
24278c2ecf20Sopenharmony_ci		base_cpu, msr);
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	/**
24308c2ecf20Sopenharmony_ci	 * Turbo encoding in KNL is as follows:
24318c2ecf20Sopenharmony_ci	 * [0] -- Reserved
24328c2ecf20Sopenharmony_ci	 * [7:1] -- Base value of number of active cores of bucket 1.
24338c2ecf20Sopenharmony_ci	 * [15:8] -- Base value of freq ratio of bucket 1.
24348c2ecf20Sopenharmony_ci	 * [20:16] -- +ve delta of number of active cores of bucket 2.
24358c2ecf20Sopenharmony_ci	 * i.e. active cores of bucket 2 =
24368c2ecf20Sopenharmony_ci	 * active cores of bucket 1 + delta
24378c2ecf20Sopenharmony_ci	 * [23:21] -- Negative delta of freq ratio of bucket 2.
24388c2ecf20Sopenharmony_ci	 * i.e. freq ratio of bucket 2 =
24398c2ecf20Sopenharmony_ci	 * freq ratio of bucket 1 - delta
24408c2ecf20Sopenharmony_ci	 * [28:24]-- +ve delta of number of active cores of bucket 3.
24418c2ecf20Sopenharmony_ci	 * [31:29]-- -ve delta of freq ratio of bucket 3.
24428c2ecf20Sopenharmony_ci	 * [36:32]-- +ve delta of number of active cores of bucket 4.
24438c2ecf20Sopenharmony_ci	 * [39:37]-- -ve delta of freq ratio of bucket 4.
24448c2ecf20Sopenharmony_ci	 * [44:40]-- +ve delta of number of active cores of bucket 5.
24458c2ecf20Sopenharmony_ci	 * [47:45]-- -ve delta of freq ratio of bucket 5.
24468c2ecf20Sopenharmony_ci	 * [52:48]-- +ve delta of number of active cores of bucket 6.
24478c2ecf20Sopenharmony_ci	 * [55:53]-- -ve delta of freq ratio of bucket 6.
24488c2ecf20Sopenharmony_ci	 * [60:56]-- +ve delta of number of active cores of bucket 7.
24498c2ecf20Sopenharmony_ci	 * [63:61]-- -ve delta of freq ratio of bucket 7.
24508c2ecf20Sopenharmony_ci	 */
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	b_nr = 0;
24538c2ecf20Sopenharmony_ci	cores[b_nr] = (msr & 0xFF) >> 1;
24548c2ecf20Sopenharmony_ci	ratio[b_nr] = (msr >> 8) & 0xFF;
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci	for (i = 16; i < 64; i += 8) {
24578c2ecf20Sopenharmony_ci		delta_cores = (msr >> i) & 0x1F;
24588c2ecf20Sopenharmony_ci		delta_ratio = (msr >> (i + 5)) & 0x7;
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci		cores[b_nr + 1] = cores[b_nr] + delta_cores;
24618c2ecf20Sopenharmony_ci		ratio[b_nr + 1] = ratio[b_nr] - delta_ratio;
24628c2ecf20Sopenharmony_ci		b_nr++;
24638c2ecf20Sopenharmony_ci	}
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	for (i = buckets_no - 1; i >= 0; i--)
24668c2ecf20Sopenharmony_ci		if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
24678c2ecf20Sopenharmony_ci			fprintf(outf,
24688c2ecf20Sopenharmony_ci				"%d * %.1f = %.1f MHz max turbo %d active cores\n",
24698c2ecf20Sopenharmony_ci				ratio[i], bclk, ratio[i] * bclk, cores[i]);
24708c2ecf20Sopenharmony_ci}
24718c2ecf20Sopenharmony_ci
24728c2ecf20Sopenharmony_cistatic void
24738c2ecf20Sopenharmony_cidump_nhm_cst_cfg(void)
24748c2ecf20Sopenharmony_ci{
24758c2ecf20Sopenharmony_ci	unsigned long long msr;
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
24788c2ecf20Sopenharmony_ci
24798c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr);
24808c2ecf20Sopenharmony_ci
24818c2ecf20Sopenharmony_ci	fprintf(outf, " (%s%s%s%s%slocked, pkg-cstate-limit=%d (%s)",
24828c2ecf20Sopenharmony_ci		(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
24838c2ecf20Sopenharmony_ci		(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
24848c2ecf20Sopenharmony_ci		(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
24858c2ecf20Sopenharmony_ci		(msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
24868c2ecf20Sopenharmony_ci		(msr & (1 << 15)) ? "" : "UN",
24878c2ecf20Sopenharmony_ci		(unsigned int)msr & 0xF,
24888c2ecf20Sopenharmony_ci		pkg_cstate_limit_strings[pkg_cstate_limit]);
24898c2ecf20Sopenharmony_ci
24908c2ecf20Sopenharmony_ci#define AUTOMATIC_CSTATE_CONVERSION		(1UL << 16)
24918c2ecf20Sopenharmony_ci	if (has_automatic_cstate_conversion) {
24928c2ecf20Sopenharmony_ci		fprintf(outf, ", automatic c-state conversion=%s",
24938c2ecf20Sopenharmony_ci			(msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");
24948c2ecf20Sopenharmony_ci	}
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	fprintf(outf, ")\n");
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_ci	return;
24998c2ecf20Sopenharmony_ci}
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_cistatic void
25028c2ecf20Sopenharmony_cidump_config_tdp(void)
25038c2ecf20Sopenharmony_ci{
25048c2ecf20Sopenharmony_ci	unsigned long long msr;
25058c2ecf20Sopenharmony_ci
25068c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);
25078c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
25088c2ecf20Sopenharmony_ci	fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);
25118c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
25128c2ecf20Sopenharmony_ci	if (msr) {
25138c2ecf20Sopenharmony_ci		fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
25148c2ecf20Sopenharmony_ci		fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
25158c2ecf20Sopenharmony_ci		fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
25168c2ecf20Sopenharmony_ci		fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);
25178c2ecf20Sopenharmony_ci	}
25188c2ecf20Sopenharmony_ci	fprintf(outf, ")\n");
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);
25218c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
25228c2ecf20Sopenharmony_ci	if (msr) {
25238c2ecf20Sopenharmony_ci		fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
25248c2ecf20Sopenharmony_ci		fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
25258c2ecf20Sopenharmony_ci		fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
25268c2ecf20Sopenharmony_ci		fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);
25278c2ecf20Sopenharmony_ci	}
25288c2ecf20Sopenharmony_ci	fprintf(outf, ")\n");
25298c2ecf20Sopenharmony_ci
25308c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr);
25318c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);
25328c2ecf20Sopenharmony_ci	if ((msr) & 0x3)
25338c2ecf20Sopenharmony_ci		fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);
25348c2ecf20Sopenharmony_ci	fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
25358c2ecf20Sopenharmony_ci	fprintf(outf, ")\n");
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
25388c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
25398c2ecf20Sopenharmony_ci	fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);
25408c2ecf20Sopenharmony_ci	fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
25418c2ecf20Sopenharmony_ci	fprintf(outf, ")\n");
25428c2ecf20Sopenharmony_ci}
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_ciunsigned int irtl_time_units[] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_civoid print_irtl(void)
25478c2ecf20Sopenharmony_ci{
25488c2ecf20Sopenharmony_ci	unsigned long long msr;
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKGC3_IRTL, &msr);
25518c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr);
25528c2ecf20Sopenharmony_ci	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
25538c2ecf20Sopenharmony_ci		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKGC6_IRTL, &msr);
25568c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr);
25578c2ecf20Sopenharmony_ci	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
25588c2ecf20Sopenharmony_ci		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKGC7_IRTL, &msr);
25618c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr);
25628c2ecf20Sopenharmony_ci	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
25638c2ecf20Sopenharmony_ci		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci	if (!do_irtl_hsw)
25668c2ecf20Sopenharmony_ci		return;
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKGC8_IRTL, &msr);
25698c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr);
25708c2ecf20Sopenharmony_ci	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
25718c2ecf20Sopenharmony_ci		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKGC9_IRTL, &msr);
25748c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr);
25758c2ecf20Sopenharmony_ci	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
25768c2ecf20Sopenharmony_ci		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
25778c2ecf20Sopenharmony_ci
25788c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKGC10_IRTL, &msr);
25798c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr);
25808c2ecf20Sopenharmony_ci	fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT",
25818c2ecf20Sopenharmony_ci		(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_ci}
25848c2ecf20Sopenharmony_civoid free_fd_percpu(void)
25858c2ecf20Sopenharmony_ci{
25868c2ecf20Sopenharmony_ci	int i;
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	for (i = 0; i < topo.max_cpu_num + 1; ++i) {
25898c2ecf20Sopenharmony_ci		if (fd_percpu[i] != 0)
25908c2ecf20Sopenharmony_ci			close(fd_percpu[i]);
25918c2ecf20Sopenharmony_ci	}
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci	free(fd_percpu);
25948c2ecf20Sopenharmony_ci}
25958c2ecf20Sopenharmony_ci
25968c2ecf20Sopenharmony_civoid free_all_buffers(void)
25978c2ecf20Sopenharmony_ci{
25988c2ecf20Sopenharmony_ci	int i;
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_ci	CPU_FREE(cpu_present_set);
26018c2ecf20Sopenharmony_ci	cpu_present_set = NULL;
26028c2ecf20Sopenharmony_ci	cpu_present_setsize = 0;
26038c2ecf20Sopenharmony_ci
26048c2ecf20Sopenharmony_ci	CPU_FREE(cpu_affinity_set);
26058c2ecf20Sopenharmony_ci	cpu_affinity_set = NULL;
26068c2ecf20Sopenharmony_ci	cpu_affinity_setsize = 0;
26078c2ecf20Sopenharmony_ci
26088c2ecf20Sopenharmony_ci	free(thread_even);
26098c2ecf20Sopenharmony_ci	free(core_even);
26108c2ecf20Sopenharmony_ci	free(package_even);
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci	thread_even = NULL;
26138c2ecf20Sopenharmony_ci	core_even = NULL;
26148c2ecf20Sopenharmony_ci	package_even = NULL;
26158c2ecf20Sopenharmony_ci
26168c2ecf20Sopenharmony_ci	free(thread_odd);
26178c2ecf20Sopenharmony_ci	free(core_odd);
26188c2ecf20Sopenharmony_ci	free(package_odd);
26198c2ecf20Sopenharmony_ci
26208c2ecf20Sopenharmony_ci	thread_odd = NULL;
26218c2ecf20Sopenharmony_ci	core_odd = NULL;
26228c2ecf20Sopenharmony_ci	package_odd = NULL;
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	free(output_buffer);
26258c2ecf20Sopenharmony_ci	output_buffer = NULL;
26268c2ecf20Sopenharmony_ci	outp = NULL;
26278c2ecf20Sopenharmony_ci
26288c2ecf20Sopenharmony_ci	free_fd_percpu();
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_ci	free(irq_column_2_cpu);
26318c2ecf20Sopenharmony_ci	free(irqs_per_cpu);
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci	for (i = 0; i <= topo.max_cpu_num; ++i) {
26348c2ecf20Sopenharmony_ci		if (cpus[i].put_ids)
26358c2ecf20Sopenharmony_ci			CPU_FREE(cpus[i].put_ids);
26368c2ecf20Sopenharmony_ci	}
26378c2ecf20Sopenharmony_ci	free(cpus);
26388c2ecf20Sopenharmony_ci}
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci/*
26428c2ecf20Sopenharmony_ci * Parse a file containing a single int.
26438c2ecf20Sopenharmony_ci * Return 0 if file can not be opened
26448c2ecf20Sopenharmony_ci * Exit if file can be opened, but can not be parsed
26458c2ecf20Sopenharmony_ci */
26468c2ecf20Sopenharmony_ciint parse_int_file(const char *fmt, ...)
26478c2ecf20Sopenharmony_ci{
26488c2ecf20Sopenharmony_ci	va_list args;
26498c2ecf20Sopenharmony_ci	char path[PATH_MAX];
26508c2ecf20Sopenharmony_ci	FILE *filep;
26518c2ecf20Sopenharmony_ci	int value;
26528c2ecf20Sopenharmony_ci
26538c2ecf20Sopenharmony_ci	va_start(args, fmt);
26548c2ecf20Sopenharmony_ci	vsnprintf(path, sizeof(path), fmt, args);
26558c2ecf20Sopenharmony_ci	va_end(args);
26568c2ecf20Sopenharmony_ci	filep = fopen(path, "r");
26578c2ecf20Sopenharmony_ci	if (!filep)
26588c2ecf20Sopenharmony_ci		return 0;
26598c2ecf20Sopenharmony_ci	if (fscanf(filep, "%d", &value) != 1)
26608c2ecf20Sopenharmony_ci		err(1, "%s: failed to parse number from file", path);
26618c2ecf20Sopenharmony_ci	fclose(filep);
26628c2ecf20Sopenharmony_ci	return value;
26638c2ecf20Sopenharmony_ci}
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci/*
26668c2ecf20Sopenharmony_ci * cpu_is_first_core_in_package(cpu)
26678c2ecf20Sopenharmony_ci * return 1 if given CPU is 1st core in package
26688c2ecf20Sopenharmony_ci */
26698c2ecf20Sopenharmony_ciint cpu_is_first_core_in_package(int cpu)
26708c2ecf20Sopenharmony_ci{
26718c2ecf20Sopenharmony_ci	return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu);
26728c2ecf20Sopenharmony_ci}
26738c2ecf20Sopenharmony_ci
26748c2ecf20Sopenharmony_ciint get_physical_package_id(int cpu)
26758c2ecf20Sopenharmony_ci{
26768c2ecf20Sopenharmony_ci	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
26778c2ecf20Sopenharmony_ci}
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_ciint get_die_id(int cpu)
26808c2ecf20Sopenharmony_ci{
26818c2ecf20Sopenharmony_ci	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/die_id", cpu);
26828c2ecf20Sopenharmony_ci}
26838c2ecf20Sopenharmony_ci
26848c2ecf20Sopenharmony_ciint get_core_id(int cpu)
26858c2ecf20Sopenharmony_ci{
26868c2ecf20Sopenharmony_ci	return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
26878c2ecf20Sopenharmony_ci}
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_civoid set_node_data(void)
26908c2ecf20Sopenharmony_ci{
26918c2ecf20Sopenharmony_ci	int pkg, node, lnode, cpu, cpux;
26928c2ecf20Sopenharmony_ci	int cpu_count;
26938c2ecf20Sopenharmony_ci
26948c2ecf20Sopenharmony_ci	/* initialize logical_node_id */
26958c2ecf20Sopenharmony_ci	for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu)
26968c2ecf20Sopenharmony_ci		cpus[cpu].logical_node_id = -1;
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	cpu_count = 0;
26998c2ecf20Sopenharmony_ci	for (pkg = 0; pkg < topo.num_packages; pkg++) {
27008c2ecf20Sopenharmony_ci		lnode = 0;
27018c2ecf20Sopenharmony_ci		for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {
27028c2ecf20Sopenharmony_ci			if (cpus[cpu].physical_package_id != pkg)
27038c2ecf20Sopenharmony_ci				continue;
27048c2ecf20Sopenharmony_ci			/* find a cpu with an unset logical_node_id */
27058c2ecf20Sopenharmony_ci			if (cpus[cpu].logical_node_id != -1)
27068c2ecf20Sopenharmony_ci				continue;
27078c2ecf20Sopenharmony_ci			cpus[cpu].logical_node_id = lnode;
27088c2ecf20Sopenharmony_ci			node = cpus[cpu].physical_node_id;
27098c2ecf20Sopenharmony_ci			cpu_count++;
27108c2ecf20Sopenharmony_ci			/*
27118c2ecf20Sopenharmony_ci			 * find all matching cpus on this pkg and set
27128c2ecf20Sopenharmony_ci			 * the logical_node_id
27138c2ecf20Sopenharmony_ci			 */
27148c2ecf20Sopenharmony_ci			for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) {
27158c2ecf20Sopenharmony_ci				if ((cpus[cpux].physical_package_id == pkg) &&
27168c2ecf20Sopenharmony_ci				   (cpus[cpux].physical_node_id == node)) {
27178c2ecf20Sopenharmony_ci					cpus[cpux].logical_node_id = lnode;
27188c2ecf20Sopenharmony_ci					cpu_count++;
27198c2ecf20Sopenharmony_ci				}
27208c2ecf20Sopenharmony_ci			}
27218c2ecf20Sopenharmony_ci			lnode++;
27228c2ecf20Sopenharmony_ci			if (lnode > topo.nodes_per_pkg)
27238c2ecf20Sopenharmony_ci				topo.nodes_per_pkg = lnode;
27248c2ecf20Sopenharmony_ci		}
27258c2ecf20Sopenharmony_ci		if (cpu_count >= topo.max_cpu_num)
27268c2ecf20Sopenharmony_ci			break;
27278c2ecf20Sopenharmony_ci	}
27288c2ecf20Sopenharmony_ci}
27298c2ecf20Sopenharmony_ci
27308c2ecf20Sopenharmony_ciint get_physical_node_id(struct cpu_topology *thiscpu)
27318c2ecf20Sopenharmony_ci{
27328c2ecf20Sopenharmony_ci	char path[80];
27338c2ecf20Sopenharmony_ci	FILE *filep;
27348c2ecf20Sopenharmony_ci	int i;
27358c2ecf20Sopenharmony_ci	int cpu = thiscpu->logical_cpu_id;
27368c2ecf20Sopenharmony_ci
27378c2ecf20Sopenharmony_ci	for (i = 0; i <= topo.max_cpu_num; i++) {
27388c2ecf20Sopenharmony_ci		sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist",
27398c2ecf20Sopenharmony_ci			cpu, i);
27408c2ecf20Sopenharmony_ci		filep = fopen(path, "r");
27418c2ecf20Sopenharmony_ci		if (!filep)
27428c2ecf20Sopenharmony_ci			continue;
27438c2ecf20Sopenharmony_ci		fclose(filep);
27448c2ecf20Sopenharmony_ci		return i;
27458c2ecf20Sopenharmony_ci	}
27468c2ecf20Sopenharmony_ci	return -1;
27478c2ecf20Sopenharmony_ci}
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ciint get_thread_siblings(struct cpu_topology *thiscpu)
27508c2ecf20Sopenharmony_ci{
27518c2ecf20Sopenharmony_ci	char path[80], character;
27528c2ecf20Sopenharmony_ci	FILE *filep;
27538c2ecf20Sopenharmony_ci	unsigned long map;
27548c2ecf20Sopenharmony_ci	int so, shift, sib_core;
27558c2ecf20Sopenharmony_ci	int cpu = thiscpu->logical_cpu_id;
27568c2ecf20Sopenharmony_ci	int offset = topo.max_cpu_num + 1;
27578c2ecf20Sopenharmony_ci	size_t size;
27588c2ecf20Sopenharmony_ci	int thread_id = 0;
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ci	thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1));
27618c2ecf20Sopenharmony_ci	if (thiscpu->thread_id < 0)
27628c2ecf20Sopenharmony_ci		thiscpu->thread_id = thread_id++;
27638c2ecf20Sopenharmony_ci	if (!thiscpu->put_ids)
27648c2ecf20Sopenharmony_ci		return -1;
27658c2ecf20Sopenharmony_ci
27668c2ecf20Sopenharmony_ci	size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
27678c2ecf20Sopenharmony_ci	CPU_ZERO_S(size, thiscpu->put_ids);
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci	sprintf(path,
27708c2ecf20Sopenharmony_ci		"/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
27718c2ecf20Sopenharmony_ci	filep = fopen(path, "r");
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	if (!filep) {
27748c2ecf20Sopenharmony_ci		warnx("%s: open failed", path);
27758c2ecf20Sopenharmony_ci		return -1;
27768c2ecf20Sopenharmony_ci	}
27778c2ecf20Sopenharmony_ci	do {
27788c2ecf20Sopenharmony_ci		offset -= BITMASK_SIZE;
27798c2ecf20Sopenharmony_ci		if (fscanf(filep, "%lx%c", &map, &character) != 2)
27808c2ecf20Sopenharmony_ci			err(1, "%s: failed to parse file", path);
27818c2ecf20Sopenharmony_ci		for (shift = 0; shift < BITMASK_SIZE; shift++) {
27828c2ecf20Sopenharmony_ci			if ((map >> shift) & 0x1) {
27838c2ecf20Sopenharmony_ci				so = shift + offset;
27848c2ecf20Sopenharmony_ci				sib_core = get_core_id(so);
27858c2ecf20Sopenharmony_ci				if (sib_core == thiscpu->physical_core_id) {
27868c2ecf20Sopenharmony_ci					CPU_SET_S(so, size, thiscpu->put_ids);
27878c2ecf20Sopenharmony_ci					if ((so != cpu) &&
27888c2ecf20Sopenharmony_ci					    (cpus[so].thread_id < 0))
27898c2ecf20Sopenharmony_ci						cpus[so].thread_id =
27908c2ecf20Sopenharmony_ci								    thread_id++;
27918c2ecf20Sopenharmony_ci				}
27928c2ecf20Sopenharmony_ci			}
27938c2ecf20Sopenharmony_ci		}
27948c2ecf20Sopenharmony_ci	} while (!strncmp(&character, ",", 1));
27958c2ecf20Sopenharmony_ci	fclose(filep);
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci	return CPU_COUNT_S(size, thiscpu->put_ids);
27988c2ecf20Sopenharmony_ci}
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ci/*
28018c2ecf20Sopenharmony_ci * run func(thread, core, package) in topology order
28028c2ecf20Sopenharmony_ci * skip non-present cpus
28038c2ecf20Sopenharmony_ci */
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ciint for_all_cpus_2(int (func)(struct thread_data *, struct core_data *,
28068c2ecf20Sopenharmony_ci	struct pkg_data *, struct thread_data *, struct core_data *,
28078c2ecf20Sopenharmony_ci	struct pkg_data *), struct thread_data *thread_base,
28088c2ecf20Sopenharmony_ci	struct core_data *core_base, struct pkg_data *pkg_base,
28098c2ecf20Sopenharmony_ci	struct thread_data *thread_base2, struct core_data *core_base2,
28108c2ecf20Sopenharmony_ci	struct pkg_data *pkg_base2)
28118c2ecf20Sopenharmony_ci{
28128c2ecf20Sopenharmony_ci	int retval, pkg_no, node_no, core_no, thread_no;
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_ci	for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
28158c2ecf20Sopenharmony_ci		for (node_no = 0; node_no < topo.nodes_per_pkg; ++node_no) {
28168c2ecf20Sopenharmony_ci			for (core_no = 0; core_no < topo.cores_per_node;
28178c2ecf20Sopenharmony_ci			     ++core_no) {
28188c2ecf20Sopenharmony_ci				for (thread_no = 0; thread_no <
28198c2ecf20Sopenharmony_ci					topo.threads_per_core; ++thread_no) {
28208c2ecf20Sopenharmony_ci					struct thread_data *t, *t2;
28218c2ecf20Sopenharmony_ci					struct core_data *c, *c2;
28228c2ecf20Sopenharmony_ci					struct pkg_data *p, *p2;
28238c2ecf20Sopenharmony_ci
28248c2ecf20Sopenharmony_ci					t = GET_THREAD(thread_base, thread_no,
28258c2ecf20Sopenharmony_ci						       core_no, node_no,
28268c2ecf20Sopenharmony_ci						       pkg_no);
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_ci					if (cpu_is_not_present(t->cpu_id))
28298c2ecf20Sopenharmony_ci						continue;
28308c2ecf20Sopenharmony_ci
28318c2ecf20Sopenharmony_ci					t2 = GET_THREAD(thread_base2, thread_no,
28328c2ecf20Sopenharmony_ci							core_no, node_no,
28338c2ecf20Sopenharmony_ci							pkg_no);
28348c2ecf20Sopenharmony_ci
28358c2ecf20Sopenharmony_ci					c = GET_CORE(core_base, core_no,
28368c2ecf20Sopenharmony_ci						     node_no, pkg_no);
28378c2ecf20Sopenharmony_ci					c2 = GET_CORE(core_base2, core_no,
28388c2ecf20Sopenharmony_ci						      node_no,
28398c2ecf20Sopenharmony_ci						      pkg_no);
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci					p = GET_PKG(pkg_base, pkg_no);
28428c2ecf20Sopenharmony_ci					p2 = GET_PKG(pkg_base2, pkg_no);
28438c2ecf20Sopenharmony_ci
28448c2ecf20Sopenharmony_ci					retval = func(t, c, p, t2, c2, p2);
28458c2ecf20Sopenharmony_ci					if (retval)
28468c2ecf20Sopenharmony_ci						return retval;
28478c2ecf20Sopenharmony_ci				}
28488c2ecf20Sopenharmony_ci			}
28498c2ecf20Sopenharmony_ci		}
28508c2ecf20Sopenharmony_ci	}
28518c2ecf20Sopenharmony_ci	return 0;
28528c2ecf20Sopenharmony_ci}
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci/*
28558c2ecf20Sopenharmony_ci * run func(cpu) on every cpu in /proc/stat
28568c2ecf20Sopenharmony_ci * return max_cpu number
28578c2ecf20Sopenharmony_ci */
28588c2ecf20Sopenharmony_ciint for_all_proc_cpus(int (func)(int))
28598c2ecf20Sopenharmony_ci{
28608c2ecf20Sopenharmony_ci	FILE *fp;
28618c2ecf20Sopenharmony_ci	int cpu_num;
28628c2ecf20Sopenharmony_ci	int retval;
28638c2ecf20Sopenharmony_ci
28648c2ecf20Sopenharmony_ci	fp = fopen_or_die(proc_stat, "r");
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ci	retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
28678c2ecf20Sopenharmony_ci	if (retval != 0)
28688c2ecf20Sopenharmony_ci		err(1, "%s: failed to parse format", proc_stat);
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci	while (1) {
28718c2ecf20Sopenharmony_ci		retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
28728c2ecf20Sopenharmony_ci		if (retval != 1)
28738c2ecf20Sopenharmony_ci			break;
28748c2ecf20Sopenharmony_ci
28758c2ecf20Sopenharmony_ci		retval = func(cpu_num);
28768c2ecf20Sopenharmony_ci		if (retval) {
28778c2ecf20Sopenharmony_ci			fclose(fp);
28788c2ecf20Sopenharmony_ci			return(retval);
28798c2ecf20Sopenharmony_ci		}
28808c2ecf20Sopenharmony_ci	}
28818c2ecf20Sopenharmony_ci	fclose(fp);
28828c2ecf20Sopenharmony_ci	return 0;
28838c2ecf20Sopenharmony_ci}
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_civoid re_initialize(void)
28868c2ecf20Sopenharmony_ci{
28878c2ecf20Sopenharmony_ci	free_all_buffers();
28888c2ecf20Sopenharmony_ci	setup_all_buffers();
28898c2ecf20Sopenharmony_ci	fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
28908c2ecf20Sopenharmony_ci}
28918c2ecf20Sopenharmony_ci
28928c2ecf20Sopenharmony_civoid set_max_cpu_num(void)
28938c2ecf20Sopenharmony_ci{
28948c2ecf20Sopenharmony_ci	FILE *filep;
28958c2ecf20Sopenharmony_ci	int base_cpu;
28968c2ecf20Sopenharmony_ci	unsigned long dummy;
28978c2ecf20Sopenharmony_ci	char pathname[64];
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci	base_cpu = sched_getcpu();
29008c2ecf20Sopenharmony_ci	if (base_cpu < 0)
29018c2ecf20Sopenharmony_ci		err(1, "cannot find calling cpu ID");
29028c2ecf20Sopenharmony_ci	sprintf(pathname,
29038c2ecf20Sopenharmony_ci		"/sys/devices/system/cpu/cpu%d/topology/thread_siblings",
29048c2ecf20Sopenharmony_ci		base_cpu);
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	filep = fopen_or_die(pathname, "r");
29078c2ecf20Sopenharmony_ci	topo.max_cpu_num = 0;
29088c2ecf20Sopenharmony_ci	while (fscanf(filep, "%lx,", &dummy) == 1)
29098c2ecf20Sopenharmony_ci		topo.max_cpu_num += BITMASK_SIZE;
29108c2ecf20Sopenharmony_ci	fclose(filep);
29118c2ecf20Sopenharmony_ci	topo.max_cpu_num--; /* 0 based */
29128c2ecf20Sopenharmony_ci}
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci/*
29158c2ecf20Sopenharmony_ci * count_cpus()
29168c2ecf20Sopenharmony_ci * remember the last one seen, it will be the max
29178c2ecf20Sopenharmony_ci */
29188c2ecf20Sopenharmony_ciint count_cpus(int cpu)
29198c2ecf20Sopenharmony_ci{
29208c2ecf20Sopenharmony_ci	topo.num_cpus++;
29218c2ecf20Sopenharmony_ci	return 0;
29228c2ecf20Sopenharmony_ci}
29238c2ecf20Sopenharmony_ciint mark_cpu_present(int cpu)
29248c2ecf20Sopenharmony_ci{
29258c2ecf20Sopenharmony_ci	CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
29268c2ecf20Sopenharmony_ci	return 0;
29278c2ecf20Sopenharmony_ci}
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ciint init_thread_id(int cpu)
29308c2ecf20Sopenharmony_ci{
29318c2ecf20Sopenharmony_ci	cpus[cpu].thread_id = -1;
29328c2ecf20Sopenharmony_ci	return 0;
29338c2ecf20Sopenharmony_ci}
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci/*
29368c2ecf20Sopenharmony_ci * snapshot_proc_interrupts()
29378c2ecf20Sopenharmony_ci *
29388c2ecf20Sopenharmony_ci * read and record summary of /proc/interrupts
29398c2ecf20Sopenharmony_ci *
29408c2ecf20Sopenharmony_ci * return 1 if config change requires a restart, else return 0
29418c2ecf20Sopenharmony_ci */
29428c2ecf20Sopenharmony_ciint snapshot_proc_interrupts(void)
29438c2ecf20Sopenharmony_ci{
29448c2ecf20Sopenharmony_ci	static FILE *fp;
29458c2ecf20Sopenharmony_ci	int column, retval;
29468c2ecf20Sopenharmony_ci
29478c2ecf20Sopenharmony_ci	if (fp == NULL)
29488c2ecf20Sopenharmony_ci		fp = fopen_or_die("/proc/interrupts", "r");
29498c2ecf20Sopenharmony_ci	else
29508c2ecf20Sopenharmony_ci		rewind(fp);
29518c2ecf20Sopenharmony_ci
29528c2ecf20Sopenharmony_ci	/* read 1st line of /proc/interrupts to get cpu* name for each column */
29538c2ecf20Sopenharmony_ci	for (column = 0; column < topo.num_cpus; ++column) {
29548c2ecf20Sopenharmony_ci		int cpu_number;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci		retval = fscanf(fp, " CPU%d", &cpu_number);
29578c2ecf20Sopenharmony_ci		if (retval != 1)
29588c2ecf20Sopenharmony_ci			break;
29598c2ecf20Sopenharmony_ci
29608c2ecf20Sopenharmony_ci		if (cpu_number > topo.max_cpu_num) {
29618c2ecf20Sopenharmony_ci			warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);
29628c2ecf20Sopenharmony_ci			return 1;
29638c2ecf20Sopenharmony_ci		}
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci		irq_column_2_cpu[column] = cpu_number;
29668c2ecf20Sopenharmony_ci		irqs_per_cpu[cpu_number] = 0;
29678c2ecf20Sopenharmony_ci	}
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_ci	/* read /proc/interrupt count lines and sum up irqs per cpu */
29708c2ecf20Sopenharmony_ci	while (1) {
29718c2ecf20Sopenharmony_ci		int column;
29728c2ecf20Sopenharmony_ci		char buf[64];
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci		retval = fscanf(fp, " %s:", buf);	/* flush irq# "N:" */
29758c2ecf20Sopenharmony_ci		if (retval != 1)
29768c2ecf20Sopenharmony_ci			break;
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_ci		/* read the count per cpu */
29798c2ecf20Sopenharmony_ci		for (column = 0; column < topo.num_cpus; ++column) {
29808c2ecf20Sopenharmony_ci
29818c2ecf20Sopenharmony_ci			int cpu_number, irq_count;
29828c2ecf20Sopenharmony_ci
29838c2ecf20Sopenharmony_ci			retval = fscanf(fp, " %d", &irq_count);
29848c2ecf20Sopenharmony_ci			if (retval != 1)
29858c2ecf20Sopenharmony_ci				break;
29868c2ecf20Sopenharmony_ci
29878c2ecf20Sopenharmony_ci			cpu_number = irq_column_2_cpu[column];
29888c2ecf20Sopenharmony_ci			irqs_per_cpu[cpu_number] += irq_count;
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci		}
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci		while (getc(fp) != '\n')
29938c2ecf20Sopenharmony_ci			;	/* flush interrupt description */
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci	}
29968c2ecf20Sopenharmony_ci	return 0;
29978c2ecf20Sopenharmony_ci}
29988c2ecf20Sopenharmony_ci/*
29998c2ecf20Sopenharmony_ci * snapshot_gfx_rc6_ms()
30008c2ecf20Sopenharmony_ci *
30018c2ecf20Sopenharmony_ci * record snapshot of
30028c2ecf20Sopenharmony_ci * /sys/class/drm/card0/power/rc6_residency_ms
30038c2ecf20Sopenharmony_ci *
30048c2ecf20Sopenharmony_ci * return 1 if config change requires a restart, else return 0
30058c2ecf20Sopenharmony_ci */
30068c2ecf20Sopenharmony_ciint snapshot_gfx_rc6_ms(void)
30078c2ecf20Sopenharmony_ci{
30088c2ecf20Sopenharmony_ci	FILE *fp;
30098c2ecf20Sopenharmony_ci	int retval;
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ci	fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r");
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_ci	retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms);
30148c2ecf20Sopenharmony_ci	if (retval != 1)
30158c2ecf20Sopenharmony_ci		err(1, "GFX rc6");
30168c2ecf20Sopenharmony_ci
30178c2ecf20Sopenharmony_ci	fclose(fp);
30188c2ecf20Sopenharmony_ci
30198c2ecf20Sopenharmony_ci	return 0;
30208c2ecf20Sopenharmony_ci}
30218c2ecf20Sopenharmony_ci/*
30228c2ecf20Sopenharmony_ci * snapshot_gfx_mhz()
30238c2ecf20Sopenharmony_ci *
30248c2ecf20Sopenharmony_ci * record snapshot of
30258c2ecf20Sopenharmony_ci * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz
30268c2ecf20Sopenharmony_ci *
30278c2ecf20Sopenharmony_ci * return 1 if config change requires a restart, else return 0
30288c2ecf20Sopenharmony_ci */
30298c2ecf20Sopenharmony_ciint snapshot_gfx_mhz(void)
30308c2ecf20Sopenharmony_ci{
30318c2ecf20Sopenharmony_ci	static FILE *fp;
30328c2ecf20Sopenharmony_ci	int retval;
30338c2ecf20Sopenharmony_ci
30348c2ecf20Sopenharmony_ci	if (fp == NULL)
30358c2ecf20Sopenharmony_ci		fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r");
30368c2ecf20Sopenharmony_ci	else {
30378c2ecf20Sopenharmony_ci		rewind(fp);
30388c2ecf20Sopenharmony_ci		fflush(fp);
30398c2ecf20Sopenharmony_ci	}
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci	retval = fscanf(fp, "%d", &gfx_cur_mhz);
30428c2ecf20Sopenharmony_ci	if (retval != 1)
30438c2ecf20Sopenharmony_ci		err(1, "GFX MHz");
30448c2ecf20Sopenharmony_ci
30458c2ecf20Sopenharmony_ci	return 0;
30468c2ecf20Sopenharmony_ci}
30478c2ecf20Sopenharmony_ci
30488c2ecf20Sopenharmony_ci/*
30498c2ecf20Sopenharmony_ci * snapshot_gfx_cur_mhz()
30508c2ecf20Sopenharmony_ci *
30518c2ecf20Sopenharmony_ci * record snapshot of
30528c2ecf20Sopenharmony_ci * /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz
30538c2ecf20Sopenharmony_ci *
30548c2ecf20Sopenharmony_ci * return 1 if config change requires a restart, else return 0
30558c2ecf20Sopenharmony_ci */
30568c2ecf20Sopenharmony_ciint snapshot_gfx_act_mhz(void)
30578c2ecf20Sopenharmony_ci{
30588c2ecf20Sopenharmony_ci	static FILE *fp;
30598c2ecf20Sopenharmony_ci	int retval;
30608c2ecf20Sopenharmony_ci
30618c2ecf20Sopenharmony_ci	if (fp == NULL)
30628c2ecf20Sopenharmony_ci		fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r");
30638c2ecf20Sopenharmony_ci	else {
30648c2ecf20Sopenharmony_ci		rewind(fp);
30658c2ecf20Sopenharmony_ci		fflush(fp);
30668c2ecf20Sopenharmony_ci	}
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_ci	retval = fscanf(fp, "%d", &gfx_act_mhz);
30698c2ecf20Sopenharmony_ci	if (retval != 1)
30708c2ecf20Sopenharmony_ci		err(1, "GFX ACT MHz");
30718c2ecf20Sopenharmony_ci
30728c2ecf20Sopenharmony_ci	return 0;
30738c2ecf20Sopenharmony_ci}
30748c2ecf20Sopenharmony_ci
30758c2ecf20Sopenharmony_ci/*
30768c2ecf20Sopenharmony_ci * snapshot_cpu_lpi()
30778c2ecf20Sopenharmony_ci *
30788c2ecf20Sopenharmony_ci * record snapshot of
30798c2ecf20Sopenharmony_ci * /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us
30808c2ecf20Sopenharmony_ci */
30818c2ecf20Sopenharmony_ciint snapshot_cpu_lpi_us(void)
30828c2ecf20Sopenharmony_ci{
30838c2ecf20Sopenharmony_ci	FILE *fp;
30848c2ecf20Sopenharmony_ci	int retval;
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	fp = fopen_or_die("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", "r");
30878c2ecf20Sopenharmony_ci
30888c2ecf20Sopenharmony_ci	retval = fscanf(fp, "%lld", &cpuidle_cur_cpu_lpi_us);
30898c2ecf20Sopenharmony_ci	if (retval != 1) {
30908c2ecf20Sopenharmony_ci		fprintf(stderr, "Disabling Low Power Idle CPU output\n");
30918c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_LPI);
30928c2ecf20Sopenharmony_ci		fclose(fp);
30938c2ecf20Sopenharmony_ci		return -1;
30948c2ecf20Sopenharmony_ci	}
30958c2ecf20Sopenharmony_ci
30968c2ecf20Sopenharmony_ci	fclose(fp);
30978c2ecf20Sopenharmony_ci
30988c2ecf20Sopenharmony_ci	return 0;
30998c2ecf20Sopenharmony_ci}
31008c2ecf20Sopenharmony_ci/*
31018c2ecf20Sopenharmony_ci * snapshot_sys_lpi()
31028c2ecf20Sopenharmony_ci *
31038c2ecf20Sopenharmony_ci * record snapshot of sys_lpi_file
31048c2ecf20Sopenharmony_ci */
31058c2ecf20Sopenharmony_ciint snapshot_sys_lpi_us(void)
31068c2ecf20Sopenharmony_ci{
31078c2ecf20Sopenharmony_ci	FILE *fp;
31088c2ecf20Sopenharmony_ci	int retval;
31098c2ecf20Sopenharmony_ci
31108c2ecf20Sopenharmony_ci	fp = fopen_or_die(sys_lpi_file, "r");
31118c2ecf20Sopenharmony_ci
31128c2ecf20Sopenharmony_ci	retval = fscanf(fp, "%lld", &cpuidle_cur_sys_lpi_us);
31138c2ecf20Sopenharmony_ci	if (retval != 1) {
31148c2ecf20Sopenharmony_ci		fprintf(stderr, "Disabling Low Power Idle System output\n");
31158c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_SYS_LPI);
31168c2ecf20Sopenharmony_ci		fclose(fp);
31178c2ecf20Sopenharmony_ci		return -1;
31188c2ecf20Sopenharmony_ci	}
31198c2ecf20Sopenharmony_ci	fclose(fp);
31208c2ecf20Sopenharmony_ci
31218c2ecf20Sopenharmony_ci	return 0;
31228c2ecf20Sopenharmony_ci}
31238c2ecf20Sopenharmony_ci/*
31248c2ecf20Sopenharmony_ci * snapshot /proc and /sys files
31258c2ecf20Sopenharmony_ci *
31268c2ecf20Sopenharmony_ci * return 1 if configuration restart needed, else return 0
31278c2ecf20Sopenharmony_ci */
31288c2ecf20Sopenharmony_ciint snapshot_proc_sysfs_files(void)
31298c2ecf20Sopenharmony_ci{
31308c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_IRQ))
31318c2ecf20Sopenharmony_ci		if (snapshot_proc_interrupts())
31328c2ecf20Sopenharmony_ci			return 1;
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFX_rc6))
31358c2ecf20Sopenharmony_ci		snapshot_gfx_rc6_ms();
31368c2ecf20Sopenharmony_ci
31378c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXMHz))
31388c2ecf20Sopenharmony_ci		snapshot_gfx_mhz();
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_GFXACTMHz))
31418c2ecf20Sopenharmony_ci		snapshot_gfx_act_mhz();
31428c2ecf20Sopenharmony_ci
31438c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_CPU_LPI))
31448c2ecf20Sopenharmony_ci		snapshot_cpu_lpi_us();
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci	if (DO_BIC(BIC_SYS_LPI))
31478c2ecf20Sopenharmony_ci		snapshot_sys_lpi_us();
31488c2ecf20Sopenharmony_ci
31498c2ecf20Sopenharmony_ci	return 0;
31508c2ecf20Sopenharmony_ci}
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ciint exit_requested;
31538c2ecf20Sopenharmony_ci
31548c2ecf20Sopenharmony_cistatic void signal_handler (int signal)
31558c2ecf20Sopenharmony_ci{
31568c2ecf20Sopenharmony_ci	switch (signal) {
31578c2ecf20Sopenharmony_ci	case SIGINT:
31588c2ecf20Sopenharmony_ci		exit_requested = 1;
31598c2ecf20Sopenharmony_ci		if (debug)
31608c2ecf20Sopenharmony_ci			fprintf(stderr, " SIGINT\n");
31618c2ecf20Sopenharmony_ci		break;
31628c2ecf20Sopenharmony_ci	case SIGUSR1:
31638c2ecf20Sopenharmony_ci		if (debug > 1)
31648c2ecf20Sopenharmony_ci			fprintf(stderr, "SIGUSR1\n");
31658c2ecf20Sopenharmony_ci		break;
31668c2ecf20Sopenharmony_ci	}
31678c2ecf20Sopenharmony_ci}
31688c2ecf20Sopenharmony_ci
31698c2ecf20Sopenharmony_civoid setup_signal_handler(void)
31708c2ecf20Sopenharmony_ci{
31718c2ecf20Sopenharmony_ci	struct sigaction sa;
31728c2ecf20Sopenharmony_ci
31738c2ecf20Sopenharmony_ci	memset(&sa, 0, sizeof(sa));
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	sa.sa_handler = &signal_handler;
31768c2ecf20Sopenharmony_ci
31778c2ecf20Sopenharmony_ci	if (sigaction(SIGINT, &sa, NULL) < 0)
31788c2ecf20Sopenharmony_ci		err(1, "sigaction SIGINT");
31798c2ecf20Sopenharmony_ci	if (sigaction(SIGUSR1, &sa, NULL) < 0)
31808c2ecf20Sopenharmony_ci		err(1, "sigaction SIGUSR1");
31818c2ecf20Sopenharmony_ci}
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_civoid do_sleep(void)
31848c2ecf20Sopenharmony_ci{
31858c2ecf20Sopenharmony_ci	struct timeval tout;
31868c2ecf20Sopenharmony_ci	struct timespec rest;
31878c2ecf20Sopenharmony_ci	fd_set readfds;
31888c2ecf20Sopenharmony_ci	int retval;
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	FD_ZERO(&readfds);
31918c2ecf20Sopenharmony_ci	FD_SET(0, &readfds);
31928c2ecf20Sopenharmony_ci
31938c2ecf20Sopenharmony_ci	if (ignore_stdin) {
31948c2ecf20Sopenharmony_ci		nanosleep(&interval_ts, NULL);
31958c2ecf20Sopenharmony_ci		return;
31968c2ecf20Sopenharmony_ci	}
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ci	tout = interval_tv;
31998c2ecf20Sopenharmony_ci	retval = select(1, &readfds, NULL, NULL, &tout);
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_ci	if (retval == 1) {
32028c2ecf20Sopenharmony_ci		switch (getc(stdin)) {
32038c2ecf20Sopenharmony_ci		case 'q':
32048c2ecf20Sopenharmony_ci			exit_requested = 1;
32058c2ecf20Sopenharmony_ci			break;
32068c2ecf20Sopenharmony_ci		case EOF:
32078c2ecf20Sopenharmony_ci			/*
32088c2ecf20Sopenharmony_ci			 * 'stdin' is a pipe closed on the other end. There
32098c2ecf20Sopenharmony_ci			 * won't be any further input.
32108c2ecf20Sopenharmony_ci			 */
32118c2ecf20Sopenharmony_ci			ignore_stdin = 1;
32128c2ecf20Sopenharmony_ci			/* Sleep the rest of the time */
32138c2ecf20Sopenharmony_ci			rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);
32148c2ecf20Sopenharmony_ci			rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;
32158c2ecf20Sopenharmony_ci			nanosleep(&rest, NULL);
32168c2ecf20Sopenharmony_ci		}
32178c2ecf20Sopenharmony_ci	}
32188c2ecf20Sopenharmony_ci}
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ciint get_msr_sum(int cpu, off_t offset, unsigned long long *msr)
32218c2ecf20Sopenharmony_ci{
32228c2ecf20Sopenharmony_ci	int ret, idx;
32238c2ecf20Sopenharmony_ci	unsigned long long msr_cur, msr_last;
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci	if (!per_cpu_msr_sum)
32268c2ecf20Sopenharmony_ci		return 1;
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	idx = offset_to_idx(offset);
32298c2ecf20Sopenharmony_ci	if (idx < 0)
32308c2ecf20Sopenharmony_ci		return idx;
32318c2ecf20Sopenharmony_ci	/* get_msr_sum() = sum + (get_msr() - last) */
32328c2ecf20Sopenharmony_ci	ret = get_msr(cpu, offset, &msr_cur);
32338c2ecf20Sopenharmony_ci	if (ret)
32348c2ecf20Sopenharmony_ci		return ret;
32358c2ecf20Sopenharmony_ci	msr_last = per_cpu_msr_sum[cpu].entries[idx].last;
32368c2ecf20Sopenharmony_ci	DELTA_WRAP32(msr_cur, msr_last);
32378c2ecf20Sopenharmony_ci	*msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	return 0;
32408c2ecf20Sopenharmony_ci}
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_citimer_t timerid;
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_ci/* Timer callback, update the sum of MSRs periodically. */
32458c2ecf20Sopenharmony_cistatic int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)
32468c2ecf20Sopenharmony_ci{
32478c2ecf20Sopenharmony_ci	int i, ret;
32488c2ecf20Sopenharmony_ci	int cpu = t->cpu_id;
32498c2ecf20Sopenharmony_ci
32508c2ecf20Sopenharmony_ci	for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {
32518c2ecf20Sopenharmony_ci		unsigned long long msr_cur, msr_last;
32528c2ecf20Sopenharmony_ci		off_t offset;
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci		if (!idx_valid(i))
32558c2ecf20Sopenharmony_ci			continue;
32568c2ecf20Sopenharmony_ci		offset = idx_to_offset(i);
32578c2ecf20Sopenharmony_ci		if (offset < 0)
32588c2ecf20Sopenharmony_ci			continue;
32598c2ecf20Sopenharmony_ci		ret = get_msr(cpu, offset, &msr_cur);
32608c2ecf20Sopenharmony_ci		if (ret) {
32618c2ecf20Sopenharmony_ci			fprintf(outf, "Can not update msr(0x%llx)\n",
32628c2ecf20Sopenharmony_ci				(unsigned long long)offset);
32638c2ecf20Sopenharmony_ci			continue;
32648c2ecf20Sopenharmony_ci		}
32658c2ecf20Sopenharmony_ci
32668c2ecf20Sopenharmony_ci		msr_last = per_cpu_msr_sum[cpu].entries[i].last;
32678c2ecf20Sopenharmony_ci		per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;
32688c2ecf20Sopenharmony_ci
32698c2ecf20Sopenharmony_ci		DELTA_WRAP32(msr_cur, msr_last);
32708c2ecf20Sopenharmony_ci		per_cpu_msr_sum[cpu].entries[i].sum += msr_last;
32718c2ecf20Sopenharmony_ci	}
32728c2ecf20Sopenharmony_ci	return 0;
32738c2ecf20Sopenharmony_ci}
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_cistatic void
32768c2ecf20Sopenharmony_cimsr_record_handler(union sigval v)
32778c2ecf20Sopenharmony_ci{
32788c2ecf20Sopenharmony_ci	for_all_cpus(update_msr_sum, EVEN_COUNTERS);
32798c2ecf20Sopenharmony_ci}
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_civoid msr_sum_record(void)
32828c2ecf20Sopenharmony_ci{
32838c2ecf20Sopenharmony_ci	struct itimerspec its;
32848c2ecf20Sopenharmony_ci	struct sigevent sev;
32858c2ecf20Sopenharmony_ci
32868c2ecf20Sopenharmony_ci	per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));
32878c2ecf20Sopenharmony_ci	if (!per_cpu_msr_sum) {
32888c2ecf20Sopenharmony_ci		fprintf(outf, "Can not allocate memory for long time MSR.\n");
32898c2ecf20Sopenharmony_ci		return;
32908c2ecf20Sopenharmony_ci	}
32918c2ecf20Sopenharmony_ci	/*
32928c2ecf20Sopenharmony_ci	 * Signal handler might be restricted, so use thread notifier instead.
32938c2ecf20Sopenharmony_ci	 */
32948c2ecf20Sopenharmony_ci	memset(&sev, 0, sizeof(struct sigevent));
32958c2ecf20Sopenharmony_ci	sev.sigev_notify = SIGEV_THREAD;
32968c2ecf20Sopenharmony_ci	sev.sigev_notify_function = msr_record_handler;
32978c2ecf20Sopenharmony_ci
32988c2ecf20Sopenharmony_ci	sev.sigev_value.sival_ptr = &timerid;
32998c2ecf20Sopenharmony_ci	if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
33008c2ecf20Sopenharmony_ci		fprintf(outf, "Can not create timer.\n");
33018c2ecf20Sopenharmony_ci		goto release_msr;
33028c2ecf20Sopenharmony_ci	}
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci	its.it_value.tv_sec = 0;
33058c2ecf20Sopenharmony_ci	its.it_value.tv_nsec = 1;
33068c2ecf20Sopenharmony_ci	/*
33078c2ecf20Sopenharmony_ci	 * A wraparound time has been calculated early.
33088c2ecf20Sopenharmony_ci	 * Some sources state that the peak power for a
33098c2ecf20Sopenharmony_ci	 * microprocessor is usually 1.5 times the TDP rating,
33108c2ecf20Sopenharmony_ci	 * use 2 * TDP for safety.
33118c2ecf20Sopenharmony_ci	 */
33128c2ecf20Sopenharmony_ci	its.it_interval.tv_sec = rapl_joule_counter_range / 2;
33138c2ecf20Sopenharmony_ci	its.it_interval.tv_nsec = 0;
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_ci	if (timer_settime(timerid, 0, &its, NULL) == -1) {
33168c2ecf20Sopenharmony_ci		fprintf(outf, "Can not set timer.\n");
33178c2ecf20Sopenharmony_ci		goto release_timer;
33188c2ecf20Sopenharmony_ci	}
33198c2ecf20Sopenharmony_ci	return;
33208c2ecf20Sopenharmony_ci
33218c2ecf20Sopenharmony_ci release_timer:
33228c2ecf20Sopenharmony_ci	timer_delete(timerid);
33238c2ecf20Sopenharmony_ci release_msr:
33248c2ecf20Sopenharmony_ci	free(per_cpu_msr_sum);
33258c2ecf20Sopenharmony_ci}
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_civoid turbostat_loop()
33288c2ecf20Sopenharmony_ci{
33298c2ecf20Sopenharmony_ci	int retval;
33308c2ecf20Sopenharmony_ci	int restarted = 0;
33318c2ecf20Sopenharmony_ci	int done_iters = 0;
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	setup_signal_handler();
33348c2ecf20Sopenharmony_ci
33358c2ecf20Sopenharmony_cirestart:
33368c2ecf20Sopenharmony_ci	restarted++;
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	snapshot_proc_sysfs_files();
33398c2ecf20Sopenharmony_ci	retval = for_all_cpus(get_counters, EVEN_COUNTERS);
33408c2ecf20Sopenharmony_ci	first_counter_read = 0;
33418c2ecf20Sopenharmony_ci	if (retval < -1) {
33428c2ecf20Sopenharmony_ci		exit(retval);
33438c2ecf20Sopenharmony_ci	} else if (retval == -1) {
33448c2ecf20Sopenharmony_ci		if (restarted > 10) {
33458c2ecf20Sopenharmony_ci			exit(retval);
33468c2ecf20Sopenharmony_ci		}
33478c2ecf20Sopenharmony_ci		re_initialize();
33488c2ecf20Sopenharmony_ci		goto restart;
33498c2ecf20Sopenharmony_ci	}
33508c2ecf20Sopenharmony_ci	restarted = 0;
33518c2ecf20Sopenharmony_ci	done_iters = 0;
33528c2ecf20Sopenharmony_ci	gettimeofday(&tv_even, (struct timezone *)NULL);
33538c2ecf20Sopenharmony_ci
33548c2ecf20Sopenharmony_ci	while (1) {
33558c2ecf20Sopenharmony_ci		if (for_all_proc_cpus(cpu_is_not_present)) {
33568c2ecf20Sopenharmony_ci			re_initialize();
33578c2ecf20Sopenharmony_ci			goto restart;
33588c2ecf20Sopenharmony_ci		}
33598c2ecf20Sopenharmony_ci		do_sleep();
33608c2ecf20Sopenharmony_ci		if (snapshot_proc_sysfs_files())
33618c2ecf20Sopenharmony_ci			goto restart;
33628c2ecf20Sopenharmony_ci		retval = for_all_cpus(get_counters, ODD_COUNTERS);
33638c2ecf20Sopenharmony_ci		if (retval < -1) {
33648c2ecf20Sopenharmony_ci			exit(retval);
33658c2ecf20Sopenharmony_ci		} else if (retval == -1) {
33668c2ecf20Sopenharmony_ci			re_initialize();
33678c2ecf20Sopenharmony_ci			goto restart;
33688c2ecf20Sopenharmony_ci		}
33698c2ecf20Sopenharmony_ci		gettimeofday(&tv_odd, (struct timezone *)NULL);
33708c2ecf20Sopenharmony_ci		timersub(&tv_odd, &tv_even, &tv_delta);
33718c2ecf20Sopenharmony_ci		if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) {
33728c2ecf20Sopenharmony_ci			re_initialize();
33738c2ecf20Sopenharmony_ci			goto restart;
33748c2ecf20Sopenharmony_ci		}
33758c2ecf20Sopenharmony_ci		compute_average(EVEN_COUNTERS);
33768c2ecf20Sopenharmony_ci		format_all_counters(EVEN_COUNTERS);
33778c2ecf20Sopenharmony_ci		flush_output_stdout();
33788c2ecf20Sopenharmony_ci		if (exit_requested)
33798c2ecf20Sopenharmony_ci			break;
33808c2ecf20Sopenharmony_ci		if (num_iterations && ++done_iters >= num_iterations)
33818c2ecf20Sopenharmony_ci			break;
33828c2ecf20Sopenharmony_ci		do_sleep();
33838c2ecf20Sopenharmony_ci		if (snapshot_proc_sysfs_files())
33848c2ecf20Sopenharmony_ci			goto restart;
33858c2ecf20Sopenharmony_ci		retval = for_all_cpus(get_counters, EVEN_COUNTERS);
33868c2ecf20Sopenharmony_ci		if (retval < -1) {
33878c2ecf20Sopenharmony_ci			exit(retval);
33888c2ecf20Sopenharmony_ci		} else if (retval == -1) {
33898c2ecf20Sopenharmony_ci			re_initialize();
33908c2ecf20Sopenharmony_ci			goto restart;
33918c2ecf20Sopenharmony_ci		}
33928c2ecf20Sopenharmony_ci		gettimeofday(&tv_even, (struct timezone *)NULL);
33938c2ecf20Sopenharmony_ci		timersub(&tv_even, &tv_odd, &tv_delta);
33948c2ecf20Sopenharmony_ci		if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) {
33958c2ecf20Sopenharmony_ci			re_initialize();
33968c2ecf20Sopenharmony_ci			goto restart;
33978c2ecf20Sopenharmony_ci		}
33988c2ecf20Sopenharmony_ci		compute_average(ODD_COUNTERS);
33998c2ecf20Sopenharmony_ci		format_all_counters(ODD_COUNTERS);
34008c2ecf20Sopenharmony_ci		flush_output_stdout();
34018c2ecf20Sopenharmony_ci		if (exit_requested)
34028c2ecf20Sopenharmony_ci			break;
34038c2ecf20Sopenharmony_ci		if (num_iterations && ++done_iters >= num_iterations)
34048c2ecf20Sopenharmony_ci			break;
34058c2ecf20Sopenharmony_ci	}
34068c2ecf20Sopenharmony_ci}
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_civoid check_dev_msr()
34098c2ecf20Sopenharmony_ci{
34108c2ecf20Sopenharmony_ci	struct stat sb;
34118c2ecf20Sopenharmony_ci	char pathname[32];
34128c2ecf20Sopenharmony_ci
34138c2ecf20Sopenharmony_ci	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
34148c2ecf20Sopenharmony_ci	if (stat(pathname, &sb))
34158c2ecf20Sopenharmony_ci 		if (system("/sbin/modprobe msr > /dev/null 2>&1"))
34168c2ecf20Sopenharmony_ci			err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
34178c2ecf20Sopenharmony_ci}
34188c2ecf20Sopenharmony_ci
34198c2ecf20Sopenharmony_ci/*
34208c2ecf20Sopenharmony_ci * check for CAP_SYS_RAWIO
34218c2ecf20Sopenharmony_ci * return 0 on success
34228c2ecf20Sopenharmony_ci * return 1 on fail
34238c2ecf20Sopenharmony_ci */
34248c2ecf20Sopenharmony_ciint check_for_cap_sys_rawio(void)
34258c2ecf20Sopenharmony_ci{
34268c2ecf20Sopenharmony_ci	cap_t caps;
34278c2ecf20Sopenharmony_ci	cap_flag_value_t cap_flag_value;
34288c2ecf20Sopenharmony_ci
34298c2ecf20Sopenharmony_ci	caps = cap_get_proc();
34308c2ecf20Sopenharmony_ci	if (caps == NULL)
34318c2ecf20Sopenharmony_ci		err(-6, "cap_get_proc\n");
34328c2ecf20Sopenharmony_ci
34338c2ecf20Sopenharmony_ci	if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value))
34348c2ecf20Sopenharmony_ci		err(-6, "cap_get\n");
34358c2ecf20Sopenharmony_ci
34368c2ecf20Sopenharmony_ci	if (cap_flag_value != CAP_SET) {
34378c2ecf20Sopenharmony_ci		warnx("capget(CAP_SYS_RAWIO) failed,"
34388c2ecf20Sopenharmony_ci			" try \"# setcap cap_sys_rawio=ep %s\"", progname);
34398c2ecf20Sopenharmony_ci		return 1;
34408c2ecf20Sopenharmony_ci	}
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_ci	if (cap_free(caps) == -1)
34438c2ecf20Sopenharmony_ci		err(-6, "cap_free\n");
34448c2ecf20Sopenharmony_ci
34458c2ecf20Sopenharmony_ci	return 0;
34468c2ecf20Sopenharmony_ci}
34478c2ecf20Sopenharmony_civoid check_permissions(void)
34488c2ecf20Sopenharmony_ci{
34498c2ecf20Sopenharmony_ci	int do_exit = 0;
34508c2ecf20Sopenharmony_ci	char pathname[32];
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	/* check for CAP_SYS_RAWIO */
34538c2ecf20Sopenharmony_ci	do_exit += check_for_cap_sys_rawio();
34548c2ecf20Sopenharmony_ci
34558c2ecf20Sopenharmony_ci	/* test file permissions */
34568c2ecf20Sopenharmony_ci	sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
34578c2ecf20Sopenharmony_ci	if (euidaccess(pathname, R_OK)) {
34588c2ecf20Sopenharmony_ci		do_exit++;
34598c2ecf20Sopenharmony_ci		warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr");
34608c2ecf20Sopenharmony_ci	}
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_ci	/* if all else fails, thell them to be root */
34638c2ecf20Sopenharmony_ci	if (do_exit)
34648c2ecf20Sopenharmony_ci		if (getuid() != 0)
34658c2ecf20Sopenharmony_ci			warnx("... or simply run as root");
34668c2ecf20Sopenharmony_ci
34678c2ecf20Sopenharmony_ci	if (do_exit)
34688c2ecf20Sopenharmony_ci		exit(-6);
34698c2ecf20Sopenharmony_ci}
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_ci/*
34728c2ecf20Sopenharmony_ci * NHM adds support for additional MSRs:
34738c2ecf20Sopenharmony_ci *
34748c2ecf20Sopenharmony_ci * MSR_SMI_COUNT                   0x00000034
34758c2ecf20Sopenharmony_ci *
34768c2ecf20Sopenharmony_ci * MSR_PLATFORM_INFO               0x000000ce
34778c2ecf20Sopenharmony_ci * MSR_PKG_CST_CONFIG_CONTROL     0x000000e2
34788c2ecf20Sopenharmony_ci *
34798c2ecf20Sopenharmony_ci * MSR_MISC_PWR_MGMT               0x000001aa
34808c2ecf20Sopenharmony_ci *
34818c2ecf20Sopenharmony_ci * MSR_PKG_C3_RESIDENCY            0x000003f8
34828c2ecf20Sopenharmony_ci * MSR_PKG_C6_RESIDENCY            0x000003f9
34838c2ecf20Sopenharmony_ci * MSR_CORE_C3_RESIDENCY           0x000003fc
34848c2ecf20Sopenharmony_ci * MSR_CORE_C6_RESIDENCY           0x000003fd
34858c2ecf20Sopenharmony_ci *
34868c2ecf20Sopenharmony_ci * Side effect:
34878c2ecf20Sopenharmony_ci * sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL
34888c2ecf20Sopenharmony_ci * sets has_misc_feature_control
34898c2ecf20Sopenharmony_ci */
34908c2ecf20Sopenharmony_ciint probe_nhm_msrs(unsigned int family, unsigned int model)
34918c2ecf20Sopenharmony_ci{
34928c2ecf20Sopenharmony_ci	unsigned long long msr;
34938c2ecf20Sopenharmony_ci	unsigned int base_ratio;
34948c2ecf20Sopenharmony_ci	int *pkg_cstate_limits;
34958c2ecf20Sopenharmony_ci
34968c2ecf20Sopenharmony_ci	if (!genuine_intel)
34978c2ecf20Sopenharmony_ci		return 0;
34988c2ecf20Sopenharmony_ci
34998c2ecf20Sopenharmony_ci	if (family != 6)
35008c2ecf20Sopenharmony_ci		return 0;
35018c2ecf20Sopenharmony_ci
35028c2ecf20Sopenharmony_ci	bclk = discover_bclk(family, model);
35038c2ecf20Sopenharmony_ci
35048c2ecf20Sopenharmony_ci	switch (model) {
35058c2ecf20Sopenharmony_ci	case INTEL_FAM6_NEHALEM:	/* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
35068c2ecf20Sopenharmony_ci	case INTEL_FAM6_NEHALEM_EX:	/* Nehalem-EX Xeon - Beckton */
35078c2ecf20Sopenharmony_ci		pkg_cstate_limits = nhm_pkg_cstate_limits;
35088c2ecf20Sopenharmony_ci		break;
35098c2ecf20Sopenharmony_ci	case INTEL_FAM6_SANDYBRIDGE:	/* SNB */
35108c2ecf20Sopenharmony_ci	case INTEL_FAM6_SANDYBRIDGE_X:	/* SNB Xeon */
35118c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE:	/* IVB */
35128c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE_X:	/* IVB Xeon */
35138c2ecf20Sopenharmony_ci		pkg_cstate_limits = snb_pkg_cstate_limits;
35148c2ecf20Sopenharmony_ci		has_misc_feature_control = 1;
35158c2ecf20Sopenharmony_ci		break;
35168c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL:	/* HSW */
35178c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_G:	/* HSW */
35188c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSX */
35198c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_L:	/* HSW */
35208c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL:	/* BDW */
35218c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_G:	/* BDW */
35228c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:	/* BDX */
35238c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
35248c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
35258c2ecf20Sopenharmony_ci		pkg_cstate_limits = hsw_pkg_cstate_limits;
35268c2ecf20Sopenharmony_ci		has_misc_feature_control = 1;
35278c2ecf20Sopenharmony_ci		break;
35288c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
35298c2ecf20Sopenharmony_ci		pkg_cstate_limits = skx_pkg_cstate_limits;
35308c2ecf20Sopenharmony_ci		has_misc_feature_control = 1;
35318c2ecf20Sopenharmony_ci		break;
35328c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT:	/* BYT */
35338c2ecf20Sopenharmony_ci		no_MSR_MISC_PWR_MGMT = 1;
35348c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT_D:	/* AVN */
35358c2ecf20Sopenharmony_ci		pkg_cstate_limits = slv_pkg_cstate_limits;
35368c2ecf20Sopenharmony_ci		break;
35378c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_AIRMONT:	/* AMT */
35388c2ecf20Sopenharmony_ci		pkg_cstate_limits = amt_pkg_cstate_limits;
35398c2ecf20Sopenharmony_ci		no_MSR_MISC_PWR_MGMT = 1;
35408c2ecf20Sopenharmony_ci		break;
35418c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* PHI */
35428c2ecf20Sopenharmony_ci		pkg_cstate_limits = phi_pkg_cstate_limits;
35438c2ecf20Sopenharmony_ci		break;
35448c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
35458c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
35468c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
35478c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT:	/* EHL */
35488c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
35498c2ecf20Sopenharmony_ci		pkg_cstate_limits = glm_pkg_cstate_limits;
35508c2ecf20Sopenharmony_ci		break;
35518c2ecf20Sopenharmony_ci	default:
35528c2ecf20Sopenharmony_ci		return 0;
35538c2ecf20Sopenharmony_ci	}
35548c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);
35558c2ecf20Sopenharmony_ci	pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
35568c2ecf20Sopenharmony_ci
35578c2ecf20Sopenharmony_ci	get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
35588c2ecf20Sopenharmony_ci	base_ratio = (msr >> 8) & 0xFF;
35598c2ecf20Sopenharmony_ci
35608c2ecf20Sopenharmony_ci	base_hz = base_ratio * bclk * 1000000;
35618c2ecf20Sopenharmony_ci	has_base_hz = 1;
35628c2ecf20Sopenharmony_ci	return 1;
35638c2ecf20Sopenharmony_ci}
35648c2ecf20Sopenharmony_ci/*
35658c2ecf20Sopenharmony_ci * SLV client has support for unique MSRs:
35668c2ecf20Sopenharmony_ci *
35678c2ecf20Sopenharmony_ci * MSR_CC6_DEMOTION_POLICY_CONFIG
35688c2ecf20Sopenharmony_ci * MSR_MC6_DEMOTION_POLICY_CONFIG
35698c2ecf20Sopenharmony_ci */
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ciint has_slv_msrs(unsigned int family, unsigned int model)
35728c2ecf20Sopenharmony_ci{
35738c2ecf20Sopenharmony_ci	if (!genuine_intel)
35748c2ecf20Sopenharmony_ci		return 0;
35758c2ecf20Sopenharmony_ci
35768c2ecf20Sopenharmony_ci	switch (model) {
35778c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT:
35788c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT_MID:
35798c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_AIRMONT_MID:
35808c2ecf20Sopenharmony_ci		return 1;
35818c2ecf20Sopenharmony_ci	}
35828c2ecf20Sopenharmony_ci	return 0;
35838c2ecf20Sopenharmony_ci}
35848c2ecf20Sopenharmony_ciint is_dnv(unsigned int family, unsigned int model)
35858c2ecf20Sopenharmony_ci{
35868c2ecf20Sopenharmony_ci
35878c2ecf20Sopenharmony_ci	if (!genuine_intel)
35888c2ecf20Sopenharmony_ci		return 0;
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci	switch (model) {
35918c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_D:
35928c2ecf20Sopenharmony_ci		return 1;
35938c2ecf20Sopenharmony_ci	}
35948c2ecf20Sopenharmony_ci	return 0;
35958c2ecf20Sopenharmony_ci}
35968c2ecf20Sopenharmony_ciint is_bdx(unsigned int family, unsigned int model)
35978c2ecf20Sopenharmony_ci{
35988c2ecf20Sopenharmony_ci
35998c2ecf20Sopenharmony_ci	if (!genuine_intel)
36008c2ecf20Sopenharmony_ci		return 0;
36018c2ecf20Sopenharmony_ci
36028c2ecf20Sopenharmony_ci	switch (model) {
36038c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:
36048c2ecf20Sopenharmony_ci		return 1;
36058c2ecf20Sopenharmony_ci	}
36068c2ecf20Sopenharmony_ci	return 0;
36078c2ecf20Sopenharmony_ci}
36088c2ecf20Sopenharmony_ciint is_skx(unsigned int family, unsigned int model)
36098c2ecf20Sopenharmony_ci{
36108c2ecf20Sopenharmony_ci
36118c2ecf20Sopenharmony_ci	if (!genuine_intel)
36128c2ecf20Sopenharmony_ci		return 0;
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ci	switch (model) {
36158c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:
36168c2ecf20Sopenharmony_ci		return 1;
36178c2ecf20Sopenharmony_ci	}
36188c2ecf20Sopenharmony_ci	return 0;
36198c2ecf20Sopenharmony_ci}
36208c2ecf20Sopenharmony_ciint is_ehl(unsigned int family, unsigned int model)
36218c2ecf20Sopenharmony_ci{
36228c2ecf20Sopenharmony_ci	if (!genuine_intel)
36238c2ecf20Sopenharmony_ci		return 0;
36248c2ecf20Sopenharmony_ci
36258c2ecf20Sopenharmony_ci	switch (model) {
36268c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT:
36278c2ecf20Sopenharmony_ci		return 1;
36288c2ecf20Sopenharmony_ci	}
36298c2ecf20Sopenharmony_ci	return 0;
36308c2ecf20Sopenharmony_ci}
36318c2ecf20Sopenharmony_ciint is_jvl(unsigned int family, unsigned int model)
36328c2ecf20Sopenharmony_ci{
36338c2ecf20Sopenharmony_ci	if (!genuine_intel)
36348c2ecf20Sopenharmony_ci		return 0;
36358c2ecf20Sopenharmony_ci
36368c2ecf20Sopenharmony_ci	switch (model) {
36378c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT_D:
36388c2ecf20Sopenharmony_ci		return 1;
36398c2ecf20Sopenharmony_ci	}
36408c2ecf20Sopenharmony_ci	return 0;
36418c2ecf20Sopenharmony_ci}
36428c2ecf20Sopenharmony_ci
36438c2ecf20Sopenharmony_ciint has_turbo_ratio_limit(unsigned int family, unsigned int model)
36448c2ecf20Sopenharmony_ci{
36458c2ecf20Sopenharmony_ci	if (has_slv_msrs(family, model))
36468c2ecf20Sopenharmony_ci		return 0;
36478c2ecf20Sopenharmony_ci
36488c2ecf20Sopenharmony_ci	switch (model) {
36498c2ecf20Sopenharmony_ci	/* Nehalem compatible, but do not include turbo-ratio limit support */
36508c2ecf20Sopenharmony_ci	case INTEL_FAM6_NEHALEM_EX:	/* Nehalem-EX Xeon - Beckton */
36518c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* PHI - Knights Landing (different MSR definition) */
36528c2ecf20Sopenharmony_ci		return 0;
36538c2ecf20Sopenharmony_ci	default:
36548c2ecf20Sopenharmony_ci		return 1;
36558c2ecf20Sopenharmony_ci	}
36568c2ecf20Sopenharmony_ci}
36578c2ecf20Sopenharmony_ciint has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
36588c2ecf20Sopenharmony_ci{
36598c2ecf20Sopenharmony_ci	if (has_slv_msrs(family, model))
36608c2ecf20Sopenharmony_ci		return 1;
36618c2ecf20Sopenharmony_ci
36628c2ecf20Sopenharmony_ci	return 0;
36638c2ecf20Sopenharmony_ci}
36648c2ecf20Sopenharmony_ciint has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
36658c2ecf20Sopenharmony_ci{
36668c2ecf20Sopenharmony_ci	if (!genuine_intel)
36678c2ecf20Sopenharmony_ci		return 0;
36688c2ecf20Sopenharmony_ci
36698c2ecf20Sopenharmony_ci	if (family != 6)
36708c2ecf20Sopenharmony_ci		return 0;
36718c2ecf20Sopenharmony_ci
36728c2ecf20Sopenharmony_ci	switch (model) {
36738c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE_X:	/* IVB Xeon */
36748c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSW Xeon */
36758c2ecf20Sopenharmony_ci		return 1;
36768c2ecf20Sopenharmony_ci	default:
36778c2ecf20Sopenharmony_ci		return 0;
36788c2ecf20Sopenharmony_ci	}
36798c2ecf20Sopenharmony_ci}
36808c2ecf20Sopenharmony_ciint has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model)
36818c2ecf20Sopenharmony_ci{
36828c2ecf20Sopenharmony_ci	if (!genuine_intel)
36838c2ecf20Sopenharmony_ci		return 0;
36848c2ecf20Sopenharmony_ci
36858c2ecf20Sopenharmony_ci	if (family != 6)
36868c2ecf20Sopenharmony_ci		return 0;
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci	switch (model) {
36898c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSW Xeon */
36908c2ecf20Sopenharmony_ci		return 1;
36918c2ecf20Sopenharmony_ci	default:
36928c2ecf20Sopenharmony_ci		return 0;
36938c2ecf20Sopenharmony_ci	}
36948c2ecf20Sopenharmony_ci}
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_ciint has_knl_turbo_ratio_limit(unsigned int family, unsigned int model)
36978c2ecf20Sopenharmony_ci{
36988c2ecf20Sopenharmony_ci	if (!genuine_intel)
36998c2ecf20Sopenharmony_ci		return 0;
37008c2ecf20Sopenharmony_ci
37018c2ecf20Sopenharmony_ci	if (family != 6)
37028c2ecf20Sopenharmony_ci		return 0;
37038c2ecf20Sopenharmony_ci
37048c2ecf20Sopenharmony_ci	switch (model) {
37058c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* Knights Landing */
37068c2ecf20Sopenharmony_ci		return 1;
37078c2ecf20Sopenharmony_ci	default:
37088c2ecf20Sopenharmony_ci		return 0;
37098c2ecf20Sopenharmony_ci	}
37108c2ecf20Sopenharmony_ci}
37118c2ecf20Sopenharmony_ciint has_glm_turbo_ratio_limit(unsigned int family, unsigned int model)
37128c2ecf20Sopenharmony_ci{
37138c2ecf20Sopenharmony_ci	if (!genuine_intel)
37148c2ecf20Sopenharmony_ci		return 0;
37158c2ecf20Sopenharmony_ci
37168c2ecf20Sopenharmony_ci	if (family != 6)
37178c2ecf20Sopenharmony_ci		return 0;
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_ci	switch (model) {
37208c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT:
37218c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:
37228c2ecf20Sopenharmony_ci		return 1;
37238c2ecf20Sopenharmony_ci	default:
37248c2ecf20Sopenharmony_ci		return 0;
37258c2ecf20Sopenharmony_ci	}
37268c2ecf20Sopenharmony_ci}
37278c2ecf20Sopenharmony_ciint has_config_tdp(unsigned int family, unsigned int model)
37288c2ecf20Sopenharmony_ci{
37298c2ecf20Sopenharmony_ci	if (!genuine_intel)
37308c2ecf20Sopenharmony_ci		return 0;
37318c2ecf20Sopenharmony_ci
37328c2ecf20Sopenharmony_ci	if (family != 6)
37338c2ecf20Sopenharmony_ci		return 0;
37348c2ecf20Sopenharmony_ci
37358c2ecf20Sopenharmony_ci	switch (model) {
37368c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE:	/* IVB */
37378c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL:	/* HSW */
37388c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSX */
37398c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_L:	/* HSW */
37408c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_G:	/* HSW */
37418c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL:	/* BDW */
37428c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_G:	/* BDW */
37438c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:	/* BDX */
37448c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
37458c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
37468c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
37478c2ecf20Sopenharmony_ci
37488c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* Knights Landing */
37498c2ecf20Sopenharmony_ci		return 1;
37508c2ecf20Sopenharmony_ci	default:
37518c2ecf20Sopenharmony_ci		return 0;
37528c2ecf20Sopenharmony_ci	}
37538c2ecf20Sopenharmony_ci}
37548c2ecf20Sopenharmony_ci
37558c2ecf20Sopenharmony_cistatic void
37568c2ecf20Sopenharmony_ciremove_underbar(char *s)
37578c2ecf20Sopenharmony_ci{
37588c2ecf20Sopenharmony_ci	char *to = s;
37598c2ecf20Sopenharmony_ci
37608c2ecf20Sopenharmony_ci	while (*s) {
37618c2ecf20Sopenharmony_ci		if (*s != '_')
37628c2ecf20Sopenharmony_ci			*to++ = *s;
37638c2ecf20Sopenharmony_ci		s++;
37648c2ecf20Sopenharmony_ci	}
37658c2ecf20Sopenharmony_ci
37668c2ecf20Sopenharmony_ci	*to = 0;
37678c2ecf20Sopenharmony_ci}
37688c2ecf20Sopenharmony_ci
37698c2ecf20Sopenharmony_cistatic void
37708c2ecf20Sopenharmony_cidump_cstate_pstate_config_info(unsigned int family, unsigned int model)
37718c2ecf20Sopenharmony_ci{
37728c2ecf20Sopenharmony_ci	if (!do_nhm_platform_info)
37738c2ecf20Sopenharmony_ci		return;
37748c2ecf20Sopenharmony_ci
37758c2ecf20Sopenharmony_ci	dump_nhm_platform_info();
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci	if (has_hsw_turbo_ratio_limit(family, model))
37788c2ecf20Sopenharmony_ci		dump_hsw_turbo_ratio_limits();
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ci	if (has_ivt_turbo_ratio_limit(family, model))
37818c2ecf20Sopenharmony_ci		dump_ivt_turbo_ratio_limits();
37828c2ecf20Sopenharmony_ci
37838c2ecf20Sopenharmony_ci	if (has_turbo_ratio_limit(family, model))
37848c2ecf20Sopenharmony_ci		dump_turbo_ratio_limits(family, model);
37858c2ecf20Sopenharmony_ci
37868c2ecf20Sopenharmony_ci	if (has_atom_turbo_ratio_limit(family, model))
37878c2ecf20Sopenharmony_ci		dump_atom_turbo_ratio_limits();
37888c2ecf20Sopenharmony_ci
37898c2ecf20Sopenharmony_ci	if (has_knl_turbo_ratio_limit(family, model))
37908c2ecf20Sopenharmony_ci		dump_knl_turbo_ratio_limits();
37918c2ecf20Sopenharmony_ci
37928c2ecf20Sopenharmony_ci	if (has_config_tdp(family, model))
37938c2ecf20Sopenharmony_ci		dump_config_tdp();
37948c2ecf20Sopenharmony_ci
37958c2ecf20Sopenharmony_ci	dump_nhm_cst_cfg();
37968c2ecf20Sopenharmony_ci}
37978c2ecf20Sopenharmony_ci
37988c2ecf20Sopenharmony_cistatic void dump_sysfs_file(char *path)
37998c2ecf20Sopenharmony_ci{
38008c2ecf20Sopenharmony_ci	FILE *input;
38018c2ecf20Sopenharmony_ci	char cpuidle_buf[64];
38028c2ecf20Sopenharmony_ci
38038c2ecf20Sopenharmony_ci	input = fopen(path, "r");
38048c2ecf20Sopenharmony_ci	if (input == NULL) {
38058c2ecf20Sopenharmony_ci		if (debug)
38068c2ecf20Sopenharmony_ci			fprintf(outf, "NSFOD %s\n", path);
38078c2ecf20Sopenharmony_ci		return;
38088c2ecf20Sopenharmony_ci	}
38098c2ecf20Sopenharmony_ci	if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input))
38108c2ecf20Sopenharmony_ci		err(1, "%s: failed to read file", path);
38118c2ecf20Sopenharmony_ci	fclose(input);
38128c2ecf20Sopenharmony_ci
38138c2ecf20Sopenharmony_ci	fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);
38148c2ecf20Sopenharmony_ci}
38158c2ecf20Sopenharmony_cistatic void
38168c2ecf20Sopenharmony_cidump_sysfs_cstate_config(void)
38178c2ecf20Sopenharmony_ci{
38188c2ecf20Sopenharmony_ci	char path[64];
38198c2ecf20Sopenharmony_ci	char name_buf[16];
38208c2ecf20Sopenharmony_ci	char desc[64];
38218c2ecf20Sopenharmony_ci	FILE *input;
38228c2ecf20Sopenharmony_ci	int state;
38238c2ecf20Sopenharmony_ci	char *sp;
38248c2ecf20Sopenharmony_ci
38258c2ecf20Sopenharmony_ci	if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {
38268c2ecf20Sopenharmony_ci		fprintf(outf, "cpuidle not loaded\n");
38278c2ecf20Sopenharmony_ci		return;
38288c2ecf20Sopenharmony_ci	}
38298c2ecf20Sopenharmony_ci
38308c2ecf20Sopenharmony_ci	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver");
38318c2ecf20Sopenharmony_ci	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor");
38328c2ecf20Sopenharmony_ci	dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro");
38338c2ecf20Sopenharmony_ci
38348c2ecf20Sopenharmony_ci	for (state = 0; state < 10; ++state) {
38358c2ecf20Sopenharmony_ci
38368c2ecf20Sopenharmony_ci		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
38378c2ecf20Sopenharmony_ci			base_cpu, state);
38388c2ecf20Sopenharmony_ci		input = fopen(path, "r");
38398c2ecf20Sopenharmony_ci		if (input == NULL)
38408c2ecf20Sopenharmony_ci			continue;
38418c2ecf20Sopenharmony_ci		if (!fgets(name_buf, sizeof(name_buf), input))
38428c2ecf20Sopenharmony_ci			err(1, "%s: failed to read file", path);
38438c2ecf20Sopenharmony_ci
38448c2ecf20Sopenharmony_ci		 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
38458c2ecf20Sopenharmony_ci		sp = strchr(name_buf, '-');
38468c2ecf20Sopenharmony_ci		if (!sp)
38478c2ecf20Sopenharmony_ci			sp = strchrnul(name_buf, '\n');
38488c2ecf20Sopenharmony_ci		*sp = '\0';
38498c2ecf20Sopenharmony_ci		fclose(input);
38508c2ecf20Sopenharmony_ci
38518c2ecf20Sopenharmony_ci		remove_underbar(name_buf);
38528c2ecf20Sopenharmony_ci
38538c2ecf20Sopenharmony_ci		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
38548c2ecf20Sopenharmony_ci			base_cpu, state);
38558c2ecf20Sopenharmony_ci		input = fopen(path, "r");
38568c2ecf20Sopenharmony_ci		if (input == NULL)
38578c2ecf20Sopenharmony_ci			continue;
38588c2ecf20Sopenharmony_ci		if (!fgets(desc, sizeof(desc), input))
38598c2ecf20Sopenharmony_ci			err(1, "%s: failed to read file", path);
38608c2ecf20Sopenharmony_ci
38618c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: %s: %s", base_cpu, name_buf, desc);
38628c2ecf20Sopenharmony_ci		fclose(input);
38638c2ecf20Sopenharmony_ci	}
38648c2ecf20Sopenharmony_ci}
38658c2ecf20Sopenharmony_cistatic void
38668c2ecf20Sopenharmony_cidump_sysfs_pstate_config(void)
38678c2ecf20Sopenharmony_ci{
38688c2ecf20Sopenharmony_ci	char path[64];
38698c2ecf20Sopenharmony_ci	char driver_buf[64];
38708c2ecf20Sopenharmony_ci	char governor_buf[64];
38718c2ecf20Sopenharmony_ci	FILE *input;
38728c2ecf20Sopenharmony_ci	int turbo;
38738c2ecf20Sopenharmony_ci
38748c2ecf20Sopenharmony_ci	sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver",
38758c2ecf20Sopenharmony_ci			base_cpu);
38768c2ecf20Sopenharmony_ci	input = fopen(path, "r");
38778c2ecf20Sopenharmony_ci	if (input == NULL) {
38788c2ecf20Sopenharmony_ci		fprintf(outf, "NSFOD %s\n", path);
38798c2ecf20Sopenharmony_ci		return;
38808c2ecf20Sopenharmony_ci	}
38818c2ecf20Sopenharmony_ci	if (!fgets(driver_buf, sizeof(driver_buf), input))
38828c2ecf20Sopenharmony_ci		err(1, "%s: failed to read file", path);
38838c2ecf20Sopenharmony_ci	fclose(input);
38848c2ecf20Sopenharmony_ci
38858c2ecf20Sopenharmony_ci	sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor",
38868c2ecf20Sopenharmony_ci			base_cpu);
38878c2ecf20Sopenharmony_ci	input = fopen(path, "r");
38888c2ecf20Sopenharmony_ci	if (input == NULL) {
38898c2ecf20Sopenharmony_ci		fprintf(outf, "NSFOD %s\n", path);
38908c2ecf20Sopenharmony_ci		return;
38918c2ecf20Sopenharmony_ci	}
38928c2ecf20Sopenharmony_ci	if (!fgets(governor_buf, sizeof(governor_buf), input))
38938c2ecf20Sopenharmony_ci		err(1, "%s: failed to read file", path);
38948c2ecf20Sopenharmony_ci	fclose(input);
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: cpufreq driver: %s", base_cpu, driver_buf);
38978c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: cpufreq governor: %s", base_cpu, governor_buf);
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci	sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");
39008c2ecf20Sopenharmony_ci	input = fopen(path, "r");
39018c2ecf20Sopenharmony_ci	if (input != NULL) {
39028c2ecf20Sopenharmony_ci		if (fscanf(input, "%d", &turbo) != 1)
39038c2ecf20Sopenharmony_ci			err(1, "%s: failed to parse number from file", path);
39048c2ecf20Sopenharmony_ci		fprintf(outf, "cpufreq boost: %d\n", turbo);
39058c2ecf20Sopenharmony_ci		fclose(input);
39068c2ecf20Sopenharmony_ci	}
39078c2ecf20Sopenharmony_ci
39088c2ecf20Sopenharmony_ci	sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");
39098c2ecf20Sopenharmony_ci	input = fopen(path, "r");
39108c2ecf20Sopenharmony_ci	if (input != NULL) {
39118c2ecf20Sopenharmony_ci		if (fscanf(input, "%d", &turbo) != 1)
39128c2ecf20Sopenharmony_ci			err(1, "%s: failed to parse number from file", path);
39138c2ecf20Sopenharmony_ci		fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);
39148c2ecf20Sopenharmony_ci		fclose(input);
39158c2ecf20Sopenharmony_ci	}
39168c2ecf20Sopenharmony_ci}
39178c2ecf20Sopenharmony_ci
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_ci/*
39208c2ecf20Sopenharmony_ci * print_epb()
39218c2ecf20Sopenharmony_ci * Decode the ENERGY_PERF_BIAS MSR
39228c2ecf20Sopenharmony_ci */
39238c2ecf20Sopenharmony_ciint print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
39248c2ecf20Sopenharmony_ci{
39258c2ecf20Sopenharmony_ci	unsigned long long msr;
39268c2ecf20Sopenharmony_ci	char *epb_string;
39278c2ecf20Sopenharmony_ci	int cpu;
39288c2ecf20Sopenharmony_ci
39298c2ecf20Sopenharmony_ci	if (!has_epb)
39308c2ecf20Sopenharmony_ci		return 0;
39318c2ecf20Sopenharmony_ci
39328c2ecf20Sopenharmony_ci	cpu = t->cpu_id;
39338c2ecf20Sopenharmony_ci
39348c2ecf20Sopenharmony_ci	/* EPB is per-package */
39358c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
39368c2ecf20Sopenharmony_ci		return 0;
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
39398c2ecf20Sopenharmony_ci		fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);
39408c2ecf20Sopenharmony_ci		return -1;
39418c2ecf20Sopenharmony_ci	}
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci	if (get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr))
39448c2ecf20Sopenharmony_ci		return 0;
39458c2ecf20Sopenharmony_ci
39468c2ecf20Sopenharmony_ci	switch (msr & 0xF) {
39478c2ecf20Sopenharmony_ci	case ENERGY_PERF_BIAS_PERFORMANCE:
39488c2ecf20Sopenharmony_ci		epb_string = "performance";
39498c2ecf20Sopenharmony_ci		break;
39508c2ecf20Sopenharmony_ci	case ENERGY_PERF_BIAS_NORMAL:
39518c2ecf20Sopenharmony_ci		epb_string = "balanced";
39528c2ecf20Sopenharmony_ci		break;
39538c2ecf20Sopenharmony_ci	case ENERGY_PERF_BIAS_POWERSAVE:
39548c2ecf20Sopenharmony_ci		epb_string = "powersave";
39558c2ecf20Sopenharmony_ci		break;
39568c2ecf20Sopenharmony_ci	default:
39578c2ecf20Sopenharmony_ci		epb_string = "custom";
39588c2ecf20Sopenharmony_ci		break;
39598c2ecf20Sopenharmony_ci	}
39608c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string);
39618c2ecf20Sopenharmony_ci
39628c2ecf20Sopenharmony_ci	return 0;
39638c2ecf20Sopenharmony_ci}
39648c2ecf20Sopenharmony_ci/*
39658c2ecf20Sopenharmony_ci * print_hwp()
39668c2ecf20Sopenharmony_ci * Decode the MSR_HWP_CAPABILITIES
39678c2ecf20Sopenharmony_ci */
39688c2ecf20Sopenharmony_ciint print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
39698c2ecf20Sopenharmony_ci{
39708c2ecf20Sopenharmony_ci	unsigned long long msr;
39718c2ecf20Sopenharmony_ci	int cpu;
39728c2ecf20Sopenharmony_ci
39738c2ecf20Sopenharmony_ci	if (!has_hwp)
39748c2ecf20Sopenharmony_ci		return 0;
39758c2ecf20Sopenharmony_ci
39768c2ecf20Sopenharmony_ci	cpu = t->cpu_id;
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ci	/* MSR_HWP_CAPABILITIES is per-package */
39798c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
39808c2ecf20Sopenharmony_ci		return 0;
39818c2ecf20Sopenharmony_ci
39828c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
39838c2ecf20Sopenharmony_ci		fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);
39848c2ecf20Sopenharmony_ci		return -1;
39858c2ecf20Sopenharmony_ci	}
39868c2ecf20Sopenharmony_ci
39878c2ecf20Sopenharmony_ci	if (get_msr(cpu, MSR_PM_ENABLE, &msr))
39888c2ecf20Sopenharmony_ci		return 0;
39898c2ecf20Sopenharmony_ci
39908c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n",
39918c2ecf20Sopenharmony_ci		cpu, msr, (msr & (1 << 0)) ? "" : "No-");
39928c2ecf20Sopenharmony_ci
39938c2ecf20Sopenharmony_ci	/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
39948c2ecf20Sopenharmony_ci	if ((msr & (1 << 0)) == 0)
39958c2ecf20Sopenharmony_ci		return 0;
39968c2ecf20Sopenharmony_ci
39978c2ecf20Sopenharmony_ci	if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))
39988c2ecf20Sopenharmony_ci		return 0;
39998c2ecf20Sopenharmony_ci
40008c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "
40018c2ecf20Sopenharmony_ci			"(high %d guar %d eff %d low %d)\n",
40028c2ecf20Sopenharmony_ci			cpu, msr,
40038c2ecf20Sopenharmony_ci			(unsigned int)HWP_HIGHEST_PERF(msr),
40048c2ecf20Sopenharmony_ci			(unsigned int)HWP_GUARANTEED_PERF(msr),
40058c2ecf20Sopenharmony_ci			(unsigned int)HWP_MOSTEFFICIENT_PERF(msr),
40068c2ecf20Sopenharmony_ci			(unsigned int)HWP_LOWEST_PERF(msr));
40078c2ecf20Sopenharmony_ci
40088c2ecf20Sopenharmony_ci	if (get_msr(cpu, MSR_HWP_REQUEST, &msr))
40098c2ecf20Sopenharmony_ci		return 0;
40108c2ecf20Sopenharmony_ci
40118c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "
40128c2ecf20Sopenharmony_ci			"(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",
40138c2ecf20Sopenharmony_ci			cpu, msr,
40148c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 0) & 0xff),
40158c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 8) & 0xff),
40168c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 16) & 0xff),
40178c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 24) & 0xff),
40188c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 32) & 0xff3),
40198c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 42) & 0x1));
40208c2ecf20Sopenharmony_ci
40218c2ecf20Sopenharmony_ci	if (has_hwp_pkg) {
40228c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))
40238c2ecf20Sopenharmony_ci			return 0;
40248c2ecf20Sopenharmony_ci
40258c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "
40268c2ecf20Sopenharmony_ci			"(min %d max %d des %d epp 0x%x window 0x%x)\n",
40278c2ecf20Sopenharmony_ci			cpu, msr,
40288c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 0) & 0xff),
40298c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 8) & 0xff),
40308c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 16) & 0xff),
40318c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 24) & 0xff),
40328c2ecf20Sopenharmony_ci			(unsigned int)(((msr) >> 32) & 0xff3));
40338c2ecf20Sopenharmony_ci	}
40348c2ecf20Sopenharmony_ci	if (has_hwp_notify) {
40358c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))
40368c2ecf20Sopenharmony_ci			return 0;
40378c2ecf20Sopenharmony_ci
40388c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "
40398c2ecf20Sopenharmony_ci			"(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",
40408c2ecf20Sopenharmony_ci			cpu, msr,
40418c2ecf20Sopenharmony_ci			((msr) & 0x1) ? "EN" : "Dis",
40428c2ecf20Sopenharmony_ci			((msr) & 0x2) ? "EN" : "Dis");
40438c2ecf20Sopenharmony_ci	}
40448c2ecf20Sopenharmony_ci	if (get_msr(cpu, MSR_HWP_STATUS, &msr))
40458c2ecf20Sopenharmony_ci		return 0;
40468c2ecf20Sopenharmony_ci
40478c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
40488c2ecf20Sopenharmony_ci			"(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
40498c2ecf20Sopenharmony_ci			cpu, msr,
40508c2ecf20Sopenharmony_ci			((msr) & 0x1) ? "" : "No-",
40518c2ecf20Sopenharmony_ci			((msr) & 0x2) ? "" : "No-");
40528c2ecf20Sopenharmony_ci
40538c2ecf20Sopenharmony_ci	return 0;
40548c2ecf20Sopenharmony_ci}
40558c2ecf20Sopenharmony_ci
40568c2ecf20Sopenharmony_ci/*
40578c2ecf20Sopenharmony_ci * print_perf_limit()
40588c2ecf20Sopenharmony_ci */
40598c2ecf20Sopenharmony_ciint print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data *p)
40608c2ecf20Sopenharmony_ci{
40618c2ecf20Sopenharmony_ci	unsigned long long msr;
40628c2ecf20Sopenharmony_ci	int cpu;
40638c2ecf20Sopenharmony_ci
40648c2ecf20Sopenharmony_ci	cpu = t->cpu_id;
40658c2ecf20Sopenharmony_ci
40668c2ecf20Sopenharmony_ci	/* per-package */
40678c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
40688c2ecf20Sopenharmony_ci		return 0;
40698c2ecf20Sopenharmony_ci
40708c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
40718c2ecf20Sopenharmony_ci		fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);
40728c2ecf20Sopenharmony_ci		return -1;
40738c2ecf20Sopenharmony_ci	}
40748c2ecf20Sopenharmony_ci
40758c2ecf20Sopenharmony_ci	if (do_core_perf_limit_reasons) {
40768c2ecf20Sopenharmony_ci		get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
40778c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
40788c2ecf20Sopenharmony_ci		fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
40798c2ecf20Sopenharmony_ci			(msr & 1 << 15) ? "bit15, " : "",
40808c2ecf20Sopenharmony_ci			(msr & 1 << 14) ? "bit14, " : "",
40818c2ecf20Sopenharmony_ci			(msr & 1 << 13) ? "Transitions, " : "",
40828c2ecf20Sopenharmony_ci			(msr & 1 << 12) ? "MultiCoreTurbo, " : "",
40838c2ecf20Sopenharmony_ci			(msr & 1 << 11) ? "PkgPwrL2, " : "",
40848c2ecf20Sopenharmony_ci			(msr & 1 << 10) ? "PkgPwrL1, " : "",
40858c2ecf20Sopenharmony_ci			(msr & 1 << 9) ? "CorePwr, " : "",
40868c2ecf20Sopenharmony_ci			(msr & 1 << 8) ? "Amps, " : "",
40878c2ecf20Sopenharmony_ci			(msr & 1 << 6) ? "VR-Therm, " : "",
40888c2ecf20Sopenharmony_ci			(msr & 1 << 5) ? "Auto-HWP, " : "",
40898c2ecf20Sopenharmony_ci			(msr & 1 << 4) ? "Graphics, " : "",
40908c2ecf20Sopenharmony_ci			(msr & 1 << 2) ? "bit2, " : "",
40918c2ecf20Sopenharmony_ci			(msr & 1 << 1) ? "ThermStatus, " : "",
40928c2ecf20Sopenharmony_ci			(msr & 1 << 0) ? "PROCHOT, " : "");
40938c2ecf20Sopenharmony_ci		fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
40948c2ecf20Sopenharmony_ci			(msr & 1 << 31) ? "bit31, " : "",
40958c2ecf20Sopenharmony_ci			(msr & 1 << 30) ? "bit30, " : "",
40968c2ecf20Sopenharmony_ci			(msr & 1 << 29) ? "Transitions, " : "",
40978c2ecf20Sopenharmony_ci			(msr & 1 << 28) ? "MultiCoreTurbo, " : "",
40988c2ecf20Sopenharmony_ci			(msr & 1 << 27) ? "PkgPwrL2, " : "",
40998c2ecf20Sopenharmony_ci			(msr & 1 << 26) ? "PkgPwrL1, " : "",
41008c2ecf20Sopenharmony_ci			(msr & 1 << 25) ? "CorePwr, " : "",
41018c2ecf20Sopenharmony_ci			(msr & 1 << 24) ? "Amps, " : "",
41028c2ecf20Sopenharmony_ci			(msr & 1 << 22) ? "VR-Therm, " : "",
41038c2ecf20Sopenharmony_ci			(msr & 1 << 21) ? "Auto-HWP, " : "",
41048c2ecf20Sopenharmony_ci			(msr & 1 << 20) ? "Graphics, " : "",
41058c2ecf20Sopenharmony_ci			(msr & 1 << 18) ? "bit18, " : "",
41068c2ecf20Sopenharmony_ci			(msr & 1 << 17) ? "ThermStatus, " : "",
41078c2ecf20Sopenharmony_ci			(msr & 1 << 16) ? "PROCHOT, " : "");
41088c2ecf20Sopenharmony_ci
41098c2ecf20Sopenharmony_ci	}
41108c2ecf20Sopenharmony_ci	if (do_gfx_perf_limit_reasons) {
41118c2ecf20Sopenharmony_ci		get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);
41128c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
41138c2ecf20Sopenharmony_ci		fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",
41148c2ecf20Sopenharmony_ci			(msr & 1 << 0) ? "PROCHOT, " : "",
41158c2ecf20Sopenharmony_ci			(msr & 1 << 1) ? "ThermStatus, " : "",
41168c2ecf20Sopenharmony_ci			(msr & 1 << 4) ? "Graphics, " : "",
41178c2ecf20Sopenharmony_ci			(msr & 1 << 6) ? "VR-Therm, " : "",
41188c2ecf20Sopenharmony_ci			(msr & 1 << 8) ? "Amps, " : "",
41198c2ecf20Sopenharmony_ci			(msr & 1 << 9) ? "GFXPwr, " : "",
41208c2ecf20Sopenharmony_ci			(msr & 1 << 10) ? "PkgPwrL1, " : "",
41218c2ecf20Sopenharmony_ci			(msr & 1 << 11) ? "PkgPwrL2, " : "");
41228c2ecf20Sopenharmony_ci		fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",
41238c2ecf20Sopenharmony_ci			(msr & 1 << 16) ? "PROCHOT, " : "",
41248c2ecf20Sopenharmony_ci			(msr & 1 << 17) ? "ThermStatus, " : "",
41258c2ecf20Sopenharmony_ci			(msr & 1 << 20) ? "Graphics, " : "",
41268c2ecf20Sopenharmony_ci			(msr & 1 << 22) ? "VR-Therm, " : "",
41278c2ecf20Sopenharmony_ci			(msr & 1 << 24) ? "Amps, " : "",
41288c2ecf20Sopenharmony_ci			(msr & 1 << 25) ? "GFXPwr, " : "",
41298c2ecf20Sopenharmony_ci			(msr & 1 << 26) ? "PkgPwrL1, " : "",
41308c2ecf20Sopenharmony_ci			(msr & 1 << 27) ? "PkgPwrL2, " : "");
41318c2ecf20Sopenharmony_ci	}
41328c2ecf20Sopenharmony_ci	if (do_ring_perf_limit_reasons) {
41338c2ecf20Sopenharmony_ci		get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
41348c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
41358c2ecf20Sopenharmony_ci		fprintf(outf, " (Active: %s%s%s%s%s%s)",
41368c2ecf20Sopenharmony_ci			(msr & 1 << 0) ? "PROCHOT, " : "",
41378c2ecf20Sopenharmony_ci			(msr & 1 << 1) ? "ThermStatus, " : "",
41388c2ecf20Sopenharmony_ci			(msr & 1 << 6) ? "VR-Therm, " : "",
41398c2ecf20Sopenharmony_ci			(msr & 1 << 8) ? "Amps, " : "",
41408c2ecf20Sopenharmony_ci			(msr & 1 << 10) ? "PkgPwrL1, " : "",
41418c2ecf20Sopenharmony_ci			(msr & 1 << 11) ? "PkgPwrL2, " : "");
41428c2ecf20Sopenharmony_ci		fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",
41438c2ecf20Sopenharmony_ci			(msr & 1 << 16) ? "PROCHOT, " : "",
41448c2ecf20Sopenharmony_ci			(msr & 1 << 17) ? "ThermStatus, " : "",
41458c2ecf20Sopenharmony_ci			(msr & 1 << 22) ? "VR-Therm, " : "",
41468c2ecf20Sopenharmony_ci			(msr & 1 << 24) ? "Amps, " : "",
41478c2ecf20Sopenharmony_ci			(msr & 1 << 26) ? "PkgPwrL1, " : "",
41488c2ecf20Sopenharmony_ci			(msr & 1 << 27) ? "PkgPwrL2, " : "");
41498c2ecf20Sopenharmony_ci	}
41508c2ecf20Sopenharmony_ci	return 0;
41518c2ecf20Sopenharmony_ci}
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_ci#define	RAPL_POWER_GRANULARITY	0x7FFF	/* 15 bit power granularity */
41548c2ecf20Sopenharmony_ci#define	RAPL_TIME_GRANULARITY	0x3F /* 6 bit time granularity */
41558c2ecf20Sopenharmony_ci
41568c2ecf20Sopenharmony_cidouble get_tdp_intel(unsigned int model)
41578c2ecf20Sopenharmony_ci{
41588c2ecf20Sopenharmony_ci	unsigned long long msr;
41598c2ecf20Sopenharmony_ci
41608c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_PKG_POWER_INFO)
41618c2ecf20Sopenharmony_ci		if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr))
41628c2ecf20Sopenharmony_ci			return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;
41638c2ecf20Sopenharmony_ci
41648c2ecf20Sopenharmony_ci	switch (model) {
41658c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT:
41668c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT_D:
41678c2ecf20Sopenharmony_ci		return 30.0;
41688c2ecf20Sopenharmony_ci	default:
41698c2ecf20Sopenharmony_ci		return 135.0;
41708c2ecf20Sopenharmony_ci	}
41718c2ecf20Sopenharmony_ci}
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_cidouble get_tdp_amd(unsigned int family)
41748c2ecf20Sopenharmony_ci{
41758c2ecf20Sopenharmony_ci	/* This is the max stock TDP of HEDT/Server Fam17h+ chips */
41768c2ecf20Sopenharmony_ci	return 280.0;
41778c2ecf20Sopenharmony_ci}
41788c2ecf20Sopenharmony_ci
41798c2ecf20Sopenharmony_ci/*
41808c2ecf20Sopenharmony_ci * rapl_dram_energy_units_probe()
41818c2ecf20Sopenharmony_ci * Energy units are either hard-coded, or come from RAPL Energy Unit MSR.
41828c2ecf20Sopenharmony_ci */
41838c2ecf20Sopenharmony_cistatic double
41848c2ecf20Sopenharmony_cirapl_dram_energy_units_probe(int  model, double rapl_energy_units)
41858c2ecf20Sopenharmony_ci{
41868c2ecf20Sopenharmony_ci	/* only called for genuine_intel, family 6 */
41878c2ecf20Sopenharmony_ci
41888c2ecf20Sopenharmony_ci	switch (model) {
41898c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSX */
41908c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:	/* BDX */
41918c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* KNL */
41928c2ecf20Sopenharmony_ci	case INTEL_FAM6_ICELAKE_X:	/* ICX */
41938c2ecf20Sopenharmony_ci		return (rapl_dram_energy_units = 15.3 / 1000000);
41948c2ecf20Sopenharmony_ci	default:
41958c2ecf20Sopenharmony_ci		return (rapl_energy_units);
41968c2ecf20Sopenharmony_ci	}
41978c2ecf20Sopenharmony_ci}
41988c2ecf20Sopenharmony_ci
41998c2ecf20Sopenharmony_civoid rapl_probe_intel(unsigned int family, unsigned int model)
42008c2ecf20Sopenharmony_ci{
42018c2ecf20Sopenharmony_ci	unsigned long long msr;
42028c2ecf20Sopenharmony_ci	unsigned int time_unit;
42038c2ecf20Sopenharmony_ci	double tdp;
42048c2ecf20Sopenharmony_ci
42058c2ecf20Sopenharmony_ci	if (family != 6)
42068c2ecf20Sopenharmony_ci		return;
42078c2ecf20Sopenharmony_ci
42088c2ecf20Sopenharmony_ci	switch (model) {
42098c2ecf20Sopenharmony_ci	case INTEL_FAM6_SANDYBRIDGE:
42108c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE:
42118c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL:	/* HSW */
42128c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_L:	/* HSW */
42138c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_G:	/* HSW */
42148c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL:	/* BDW */
42158c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_G:	/* BDW */
42168c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
42178c2ecf20Sopenharmony_ci		if (rapl_joules) {
42188c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42198c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Cor_J);
42208c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_GFX_J);
42218c2ecf20Sopenharmony_ci		} else {
42228c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
42238c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_CorWatt);
42248c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_GFXWatt);
42258c2ecf20Sopenharmony_ci		}
42268c2ecf20Sopenharmony_ci		break;
42278c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
42288c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
42298c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO;
42308c2ecf20Sopenharmony_ci		if (rapl_joules)
42318c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42328c2ecf20Sopenharmony_ci		else
42338c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
42348c2ecf20Sopenharmony_ci		break;
42358c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT:	/* EHL */
42368c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
42378c2ecf20Sopenharmony_ci		if (rapl_joules) {
42388c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42398c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Cor_J);
42408c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAM_J);
42418c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_GFX_J);
42428c2ecf20Sopenharmony_ci		} else {
42438c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
42448c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_CorWatt);
42458c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAMWatt);
42468c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_GFXWatt);
42478c2ecf20Sopenharmony_ci		}
42488c2ecf20Sopenharmony_ci		break;
42498c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT_D:	/* JVL */
42508c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
42518c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PKG__);
42528c2ecf20Sopenharmony_ci		if (rapl_joules)
42538c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42548c2ecf20Sopenharmony_ci		else
42558c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
42568c2ecf20Sopenharmony_ci		break;
42578c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
42588c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
42598c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
42608c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PKG__);
42618c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_RAM__);
42628c2ecf20Sopenharmony_ci		if (rapl_joules) {
42638c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42648c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Cor_J);
42658c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAM_J);
42668c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_GFX_J);
42678c2ecf20Sopenharmony_ci		} else {
42688c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
42698c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_CorWatt);
42708c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAMWatt);
42718c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_GFXWatt);
42728c2ecf20Sopenharmony_ci		}
42738c2ecf20Sopenharmony_ci		break;
42748c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSX */
42758c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:	/* BDX */
42768c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:	/* SKX */
42778c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* KNL */
42788c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
42798c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PKG__);
42808c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_RAM__);
42818c2ecf20Sopenharmony_ci		if (rapl_joules) {
42828c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42838c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAM_J);
42848c2ecf20Sopenharmony_ci		} else {
42858c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
42868c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAMWatt);
42878c2ecf20Sopenharmony_ci		}
42888c2ecf20Sopenharmony_ci		break;
42898c2ecf20Sopenharmony_ci	case INTEL_FAM6_SANDYBRIDGE_X:
42908c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE_X:
42918c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
42928c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PKG__);
42938c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_RAM__);
42948c2ecf20Sopenharmony_ci		if (rapl_joules) {
42958c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
42968c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Cor_J);
42978c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAM_J);
42988c2ecf20Sopenharmony_ci		} else {
42998c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
43008c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_CorWatt);
43018c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAMWatt);
43028c2ecf20Sopenharmony_ci		}
43038c2ecf20Sopenharmony_ci		break;
43048c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT:	/* BYT */
43058c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT_D:	/* AVN */
43068c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_CORES;
43078c2ecf20Sopenharmony_ci		if (rapl_joules) {
43088c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
43098c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Cor_J);
43108c2ecf20Sopenharmony_ci		} else {
43118c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
43128c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_CorWatt);
43138c2ecf20Sopenharmony_ci		}
43148c2ecf20Sopenharmony_ci		break;
43158c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
43168c2ecf20Sopenharmony_ci		do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
43178c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PKG__);
43188c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_RAM__);
43198c2ecf20Sopenharmony_ci		if (rapl_joules) {
43208c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkg_J);
43218c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Cor_J);
43228c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAM_J);
43238c2ecf20Sopenharmony_ci		} else {
43248c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_PkgWatt);
43258c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_CorWatt);
43268c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_RAMWatt);
43278c2ecf20Sopenharmony_ci		}
43288c2ecf20Sopenharmony_ci		break;
43298c2ecf20Sopenharmony_ci	default:
43308c2ecf20Sopenharmony_ci		return;
43318c2ecf20Sopenharmony_ci	}
43328c2ecf20Sopenharmony_ci
43338c2ecf20Sopenharmony_ci	/* units on package 0, verify later other packages match */
43348c2ecf20Sopenharmony_ci	if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr))
43358c2ecf20Sopenharmony_ci		return;
43368c2ecf20Sopenharmony_ci
43378c2ecf20Sopenharmony_ci	rapl_power_units = 1.0 / (1 << (msr & 0xF));
43388c2ecf20Sopenharmony_ci	if (model == INTEL_FAM6_ATOM_SILVERMONT)
43398c2ecf20Sopenharmony_ci		rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
43408c2ecf20Sopenharmony_ci	else
43418c2ecf20Sopenharmony_ci		rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
43428c2ecf20Sopenharmony_ci
43438c2ecf20Sopenharmony_ci	rapl_dram_energy_units = rapl_dram_energy_units_probe(model, rapl_energy_units);
43448c2ecf20Sopenharmony_ci
43458c2ecf20Sopenharmony_ci	time_unit = msr >> 16 & 0xF;
43468c2ecf20Sopenharmony_ci	if (time_unit == 0)
43478c2ecf20Sopenharmony_ci		time_unit = 0xA;
43488c2ecf20Sopenharmony_ci
43498c2ecf20Sopenharmony_ci	rapl_time_units = 1.0 / (1 << (time_unit));
43508c2ecf20Sopenharmony_ci
43518c2ecf20Sopenharmony_ci	tdp = get_tdp_intel(model);
43528c2ecf20Sopenharmony_ci
43538c2ecf20Sopenharmony_ci	rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
43548c2ecf20Sopenharmony_ci	if (!quiet)
43558c2ecf20Sopenharmony_ci		fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
43568c2ecf20Sopenharmony_ci}
43578c2ecf20Sopenharmony_ci
43588c2ecf20Sopenharmony_civoid rapl_probe_amd(unsigned int family, unsigned int model)
43598c2ecf20Sopenharmony_ci{
43608c2ecf20Sopenharmony_ci	unsigned long long msr;
43618c2ecf20Sopenharmony_ci	unsigned int eax, ebx, ecx, edx;
43628c2ecf20Sopenharmony_ci	unsigned int has_rapl = 0;
43638c2ecf20Sopenharmony_ci	double tdp;
43648c2ecf20Sopenharmony_ci
43658c2ecf20Sopenharmony_ci	if (max_extended_level >= 0x80000007) {
43668c2ecf20Sopenharmony_ci		__cpuid(0x80000007, eax, ebx, ecx, edx);
43678c2ecf20Sopenharmony_ci		/* RAPL (Fam 17h+) */
43688c2ecf20Sopenharmony_ci		has_rapl = edx & (1 << 14);
43698c2ecf20Sopenharmony_ci	}
43708c2ecf20Sopenharmony_ci
43718c2ecf20Sopenharmony_ci	if (!has_rapl || family < 0x17)
43728c2ecf20Sopenharmony_ci		return;
43738c2ecf20Sopenharmony_ci
43748c2ecf20Sopenharmony_ci	do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
43758c2ecf20Sopenharmony_ci	if (rapl_joules) {
43768c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Pkg_J);
43778c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Cor_J);
43788c2ecf20Sopenharmony_ci	} else {
43798c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PkgWatt);
43808c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CorWatt);
43818c2ecf20Sopenharmony_ci	}
43828c2ecf20Sopenharmony_ci
43838c2ecf20Sopenharmony_ci	if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
43848c2ecf20Sopenharmony_ci		return;
43858c2ecf20Sopenharmony_ci
43868c2ecf20Sopenharmony_ci	rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf));
43878c2ecf20Sopenharmony_ci	rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));
43888c2ecf20Sopenharmony_ci	rapl_power_units = ldexp(1.0, -(msr & 0xf));
43898c2ecf20Sopenharmony_ci
43908c2ecf20Sopenharmony_ci	tdp = get_tdp_amd(family);
43918c2ecf20Sopenharmony_ci
43928c2ecf20Sopenharmony_ci	rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
43938c2ecf20Sopenharmony_ci	if (!quiet)
43948c2ecf20Sopenharmony_ci		fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
43958c2ecf20Sopenharmony_ci}
43968c2ecf20Sopenharmony_ci
43978c2ecf20Sopenharmony_ci/*
43988c2ecf20Sopenharmony_ci * rapl_probe()
43998c2ecf20Sopenharmony_ci *
44008c2ecf20Sopenharmony_ci * sets do_rapl, rapl_power_units, rapl_energy_units, rapl_time_units
44018c2ecf20Sopenharmony_ci */
44028c2ecf20Sopenharmony_civoid rapl_probe(unsigned int family, unsigned int model)
44038c2ecf20Sopenharmony_ci{
44048c2ecf20Sopenharmony_ci	if (genuine_intel)
44058c2ecf20Sopenharmony_ci		rapl_probe_intel(family, model);
44068c2ecf20Sopenharmony_ci	if (authentic_amd || hygon_genuine)
44078c2ecf20Sopenharmony_ci		rapl_probe_amd(family, model);
44088c2ecf20Sopenharmony_ci}
44098c2ecf20Sopenharmony_ci
44108c2ecf20Sopenharmony_civoid perf_limit_reasons_probe(unsigned int family, unsigned int model)
44118c2ecf20Sopenharmony_ci{
44128c2ecf20Sopenharmony_ci	if (!genuine_intel)
44138c2ecf20Sopenharmony_ci		return;
44148c2ecf20Sopenharmony_ci
44158c2ecf20Sopenharmony_ci	if (family != 6)
44168c2ecf20Sopenharmony_ci		return;
44178c2ecf20Sopenharmony_ci
44188c2ecf20Sopenharmony_ci	switch (model) {
44198c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL:	/* HSW */
44208c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_L:	/* HSW */
44218c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_G:	/* HSW */
44228c2ecf20Sopenharmony_ci		do_gfx_perf_limit_reasons = 1;
44238c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:	/* HSX */
44248c2ecf20Sopenharmony_ci		do_core_perf_limit_reasons = 1;
44258c2ecf20Sopenharmony_ci		do_ring_perf_limit_reasons = 1;
44268c2ecf20Sopenharmony_ci	default:
44278c2ecf20Sopenharmony_ci		return;
44288c2ecf20Sopenharmony_ci	}
44298c2ecf20Sopenharmony_ci}
44308c2ecf20Sopenharmony_ci
44318c2ecf20Sopenharmony_civoid automatic_cstate_conversion_probe(unsigned int family, unsigned int model)
44328c2ecf20Sopenharmony_ci{
44338c2ecf20Sopenharmony_ci	if (is_skx(family, model) || is_bdx(family, model))
44348c2ecf20Sopenharmony_ci		has_automatic_cstate_conversion = 1;
44358c2ecf20Sopenharmony_ci}
44368c2ecf20Sopenharmony_ci
44378c2ecf20Sopenharmony_ciint print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p)
44388c2ecf20Sopenharmony_ci{
44398c2ecf20Sopenharmony_ci	unsigned long long msr;
44408c2ecf20Sopenharmony_ci	unsigned int dts, dts2;
44418c2ecf20Sopenharmony_ci	int cpu;
44428c2ecf20Sopenharmony_ci
44438c2ecf20Sopenharmony_ci	if (!(do_dts || do_ptm))
44448c2ecf20Sopenharmony_ci		return 0;
44458c2ecf20Sopenharmony_ci
44468c2ecf20Sopenharmony_ci	cpu = t->cpu_id;
44478c2ecf20Sopenharmony_ci
44488c2ecf20Sopenharmony_ci	/* DTS is per-core, no need to print for each thread */
44498c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
44508c2ecf20Sopenharmony_ci		return 0;
44518c2ecf20Sopenharmony_ci
44528c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
44538c2ecf20Sopenharmony_ci		fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);
44548c2ecf20Sopenharmony_ci		return -1;
44558c2ecf20Sopenharmony_ci	}
44568c2ecf20Sopenharmony_ci
44578c2ecf20Sopenharmony_ci	if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) {
44588c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
44598c2ecf20Sopenharmony_ci			return 0;
44608c2ecf20Sopenharmony_ci
44618c2ecf20Sopenharmony_ci		dts = (msr >> 16) & 0x7F;
44628c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n",
44638c2ecf20Sopenharmony_ci			cpu, msr, tcc_activation_temp - dts);
44648c2ecf20Sopenharmony_ci
44658c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr))
44668c2ecf20Sopenharmony_ci			return 0;
44678c2ecf20Sopenharmony_ci
44688c2ecf20Sopenharmony_ci		dts = (msr >> 16) & 0x7F;
44698c2ecf20Sopenharmony_ci		dts2 = (msr >> 8) & 0x7F;
44708c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
44718c2ecf20Sopenharmony_ci			cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
44728c2ecf20Sopenharmony_ci	}
44738c2ecf20Sopenharmony_ci
44748c2ecf20Sopenharmony_ci
44758c2ecf20Sopenharmony_ci	if (do_dts && debug) {
44768c2ecf20Sopenharmony_ci		unsigned int resolution;
44778c2ecf20Sopenharmony_ci
44788c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
44798c2ecf20Sopenharmony_ci			return 0;
44808c2ecf20Sopenharmony_ci
44818c2ecf20Sopenharmony_ci		dts = (msr >> 16) & 0x7F;
44828c2ecf20Sopenharmony_ci		resolution = (msr >> 27) & 0xF;
44838c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
44848c2ecf20Sopenharmony_ci			cpu, msr, tcc_activation_temp - dts, resolution);
44858c2ecf20Sopenharmony_ci
44868c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr))
44878c2ecf20Sopenharmony_ci			return 0;
44888c2ecf20Sopenharmony_ci
44898c2ecf20Sopenharmony_ci		dts = (msr >> 16) & 0x7F;
44908c2ecf20Sopenharmony_ci		dts2 = (msr >> 8) & 0x7F;
44918c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
44928c2ecf20Sopenharmony_ci			cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
44938c2ecf20Sopenharmony_ci	}
44948c2ecf20Sopenharmony_ci
44958c2ecf20Sopenharmony_ci	return 0;
44968c2ecf20Sopenharmony_ci}
44978c2ecf20Sopenharmony_ci
44988c2ecf20Sopenharmony_civoid print_power_limit_msr(int cpu, unsigned long long msr, char *label)
44998c2ecf20Sopenharmony_ci{
45008c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n",
45018c2ecf20Sopenharmony_ci		cpu, label,
45028c2ecf20Sopenharmony_ci		((msr >> 15) & 1) ? "EN" : "DIS",
45038c2ecf20Sopenharmony_ci		((msr >> 0) & 0x7FFF) * rapl_power_units,
45048c2ecf20Sopenharmony_ci		(1.0 + (((msr >> 22) & 0x3)/4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units,
45058c2ecf20Sopenharmony_ci		(((msr >> 16) & 1) ? "EN" : "DIS"));
45068c2ecf20Sopenharmony_ci
45078c2ecf20Sopenharmony_ci	return;
45088c2ecf20Sopenharmony_ci}
45098c2ecf20Sopenharmony_ci
45108c2ecf20Sopenharmony_ciint print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
45118c2ecf20Sopenharmony_ci{
45128c2ecf20Sopenharmony_ci	unsigned long long msr;
45138c2ecf20Sopenharmony_ci	const char *msr_name;
45148c2ecf20Sopenharmony_ci	int cpu;
45158c2ecf20Sopenharmony_ci
45168c2ecf20Sopenharmony_ci	if (!do_rapl)
45178c2ecf20Sopenharmony_ci		return 0;
45188c2ecf20Sopenharmony_ci
45198c2ecf20Sopenharmony_ci	/* RAPL counters are per package, so print only for 1st thread/package */
45208c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
45218c2ecf20Sopenharmony_ci		return 0;
45228c2ecf20Sopenharmony_ci
45238c2ecf20Sopenharmony_ci	cpu = t->cpu_id;
45248c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
45258c2ecf20Sopenharmony_ci		fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);
45268c2ecf20Sopenharmony_ci		return -1;
45278c2ecf20Sopenharmony_ci	}
45288c2ecf20Sopenharmony_ci
45298c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_AMD_F17H) {
45308c2ecf20Sopenharmony_ci		msr_name = "MSR_RAPL_PWR_UNIT";
45318c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr))
45328c2ecf20Sopenharmony_ci			return -1;
45338c2ecf20Sopenharmony_ci	} else {
45348c2ecf20Sopenharmony_ci		msr_name = "MSR_RAPL_POWER_UNIT";
45358c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))
45368c2ecf20Sopenharmony_ci			return -1;
45378c2ecf20Sopenharmony_ci	}
45388c2ecf20Sopenharmony_ci
45398c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr,
45408c2ecf20Sopenharmony_ci		rapl_power_units, rapl_energy_units, rapl_time_units);
45418c2ecf20Sopenharmony_ci
45428c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_PKG_POWER_INFO) {
45438c2ecf20Sopenharmony_ci
45448c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
45458c2ecf20Sopenharmony_ci                	return -5;
45468c2ecf20Sopenharmony_ci
45478c2ecf20Sopenharmony_ci
45488c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
45498c2ecf20Sopenharmony_ci			cpu, msr,
45508c2ecf20Sopenharmony_ci			((msr >>  0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
45518c2ecf20Sopenharmony_ci			((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
45528c2ecf20Sopenharmony_ci			((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
45538c2ecf20Sopenharmony_ci			((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
45548c2ecf20Sopenharmony_ci
45558c2ecf20Sopenharmony_ci	}
45568c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_PKG) {
45578c2ecf20Sopenharmony_ci
45588c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
45598c2ecf20Sopenharmony_ci			return -9;
45608c2ecf20Sopenharmony_ci
45618c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
45628c2ecf20Sopenharmony_ci			cpu, msr, (msr >> 63) & 1 ? "" : "UN");
45638c2ecf20Sopenharmony_ci
45648c2ecf20Sopenharmony_ci		print_power_limit_msr(cpu, msr, "PKG Limit #1");
45658c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
45668c2ecf20Sopenharmony_ci			cpu,
45678c2ecf20Sopenharmony_ci			((msr >> 47) & 1) ? "EN" : "DIS",
45688c2ecf20Sopenharmony_ci			((msr >> 32) & 0x7FFF) * rapl_power_units,
45698c2ecf20Sopenharmony_ci			(1.0 + (((msr >> 54) & 0x3)/4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units,
45708c2ecf20Sopenharmony_ci			((msr >> 48) & 1) ? "EN" : "DIS");
45718c2ecf20Sopenharmony_ci	}
45728c2ecf20Sopenharmony_ci
45738c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_DRAM_POWER_INFO) {
45748c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
45758c2ecf20Sopenharmony_ci                	return -6;
45768c2ecf20Sopenharmony_ci
45778c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
45788c2ecf20Sopenharmony_ci			cpu, msr,
45798c2ecf20Sopenharmony_ci			((msr >>  0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
45808c2ecf20Sopenharmony_ci			((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
45818c2ecf20Sopenharmony_ci			((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
45828c2ecf20Sopenharmony_ci			((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
45838c2ecf20Sopenharmony_ci	}
45848c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_DRAM) {
45858c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
45868c2ecf20Sopenharmony_ci			return -9;
45878c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
45888c2ecf20Sopenharmony_ci				cpu, msr, (msr >> 31) & 1 ? "" : "UN");
45898c2ecf20Sopenharmony_ci
45908c2ecf20Sopenharmony_ci		print_power_limit_msr(cpu, msr, "DRAM Limit");
45918c2ecf20Sopenharmony_ci	}
45928c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_CORE_POLICY) {
45938c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PP0_POLICY, &msr))
45948c2ecf20Sopenharmony_ci			return -7;
45958c2ecf20Sopenharmony_ci
45968c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
45978c2ecf20Sopenharmony_ci	}
45988c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_CORES_POWER_LIMIT) {
45998c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
46008c2ecf20Sopenharmony_ci			return -9;
46018c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
46028c2ecf20Sopenharmony_ci				cpu, msr, (msr >> 31) & 1 ? "" : "UN");
46038c2ecf20Sopenharmony_ci		print_power_limit_msr(cpu, msr, "Cores Limit");
46048c2ecf20Sopenharmony_ci	}
46058c2ecf20Sopenharmony_ci	if (do_rapl & RAPL_GFX) {
46068c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PP1_POLICY, &msr))
46078c2ecf20Sopenharmony_ci			return -8;
46088c2ecf20Sopenharmony_ci
46098c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci		if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
46128c2ecf20Sopenharmony_ci			return -9;
46138c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
46148c2ecf20Sopenharmony_ci				cpu, msr, (msr >> 31) & 1 ? "" : "UN");
46158c2ecf20Sopenharmony_ci		print_power_limit_msr(cpu, msr, "GFX Limit");
46168c2ecf20Sopenharmony_ci	}
46178c2ecf20Sopenharmony_ci	return 0;
46188c2ecf20Sopenharmony_ci}
46198c2ecf20Sopenharmony_ci
46208c2ecf20Sopenharmony_ci/*
46218c2ecf20Sopenharmony_ci * SNB adds support for additional MSRs:
46228c2ecf20Sopenharmony_ci *
46238c2ecf20Sopenharmony_ci * MSR_PKG_C7_RESIDENCY            0x000003fa
46248c2ecf20Sopenharmony_ci * MSR_CORE_C7_RESIDENCY           0x000003fe
46258c2ecf20Sopenharmony_ci * MSR_PKG_C2_RESIDENCY            0x0000060d
46268c2ecf20Sopenharmony_ci */
46278c2ecf20Sopenharmony_ci
46288c2ecf20Sopenharmony_ciint has_snb_msrs(unsigned int family, unsigned int model)
46298c2ecf20Sopenharmony_ci{
46308c2ecf20Sopenharmony_ci	if (!genuine_intel)
46318c2ecf20Sopenharmony_ci		return 0;
46328c2ecf20Sopenharmony_ci
46338c2ecf20Sopenharmony_ci	switch (model) {
46348c2ecf20Sopenharmony_ci	case INTEL_FAM6_SANDYBRIDGE:
46358c2ecf20Sopenharmony_ci	case INTEL_FAM6_SANDYBRIDGE_X:
46368c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE:		/* IVB */
46378c2ecf20Sopenharmony_ci	case INTEL_FAM6_IVYBRIDGE_X:		/* IVB Xeon */
46388c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL:		/* HSW */
46398c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_X:		/* HSW */
46408c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_L:		/* HSW */
46418c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_G:		/* HSW */
46428c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL:		/* BDW */
46438c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_G:		/* BDW */
46448c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:		/* BDX */
46458c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:		/* SKL */
46468c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L:		/* CNL */
46478c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_X:		/* SKX */
46488c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT:		/* BXT */
46498c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
46508c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
46518c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT:		/* EHL */
46528c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT_D:		/* JVL */
46538c2ecf20Sopenharmony_ci		return 1;
46548c2ecf20Sopenharmony_ci	}
46558c2ecf20Sopenharmony_ci	return 0;
46568c2ecf20Sopenharmony_ci}
46578c2ecf20Sopenharmony_ci
46588c2ecf20Sopenharmony_ci/*
46598c2ecf20Sopenharmony_ci * HSW ULT added support for C8/C9/C10 MSRs:
46608c2ecf20Sopenharmony_ci *
46618c2ecf20Sopenharmony_ci * MSR_PKG_C8_RESIDENCY		0x00000630
46628c2ecf20Sopenharmony_ci * MSR_PKG_C9_RESIDENCY		0x00000631
46638c2ecf20Sopenharmony_ci * MSR_PKG_C10_RESIDENCY	0x00000632
46648c2ecf20Sopenharmony_ci *
46658c2ecf20Sopenharmony_ci * MSR_PKGC8_IRTL		0x00000633
46668c2ecf20Sopenharmony_ci * MSR_PKGC9_IRTL		0x00000634
46678c2ecf20Sopenharmony_ci * MSR_PKGC10_IRTL		0x00000635
46688c2ecf20Sopenharmony_ci *
46698c2ecf20Sopenharmony_ci */
46708c2ecf20Sopenharmony_ciint has_c8910_msrs(unsigned int family, unsigned int model)
46718c2ecf20Sopenharmony_ci{
46728c2ecf20Sopenharmony_ci	if (!genuine_intel)
46738c2ecf20Sopenharmony_ci		return 0;
46748c2ecf20Sopenharmony_ci
46758c2ecf20Sopenharmony_ci	switch (model) {
46768c2ecf20Sopenharmony_ci	case INTEL_FAM6_HASWELL_L:	/* HSW */
46778c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL:	/* BDW */
46788c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
46798c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
46808c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
46818c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
46828c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT:	/* EHL */
46838c2ecf20Sopenharmony_ci		return 1;
46848c2ecf20Sopenharmony_ci	}
46858c2ecf20Sopenharmony_ci	return 0;
46868c2ecf20Sopenharmony_ci}
46878c2ecf20Sopenharmony_ci
46888c2ecf20Sopenharmony_ci/*
46898c2ecf20Sopenharmony_ci * SKL adds support for additional MSRS:
46908c2ecf20Sopenharmony_ci *
46918c2ecf20Sopenharmony_ci * MSR_PKG_WEIGHTED_CORE_C0_RES    0x00000658
46928c2ecf20Sopenharmony_ci * MSR_PKG_ANY_CORE_C0_RES         0x00000659
46938c2ecf20Sopenharmony_ci * MSR_PKG_ANY_GFXE_C0_RES         0x0000065A
46948c2ecf20Sopenharmony_ci * MSR_PKG_BOTH_CORE_GFXE_C0_RES   0x0000065B
46958c2ecf20Sopenharmony_ci */
46968c2ecf20Sopenharmony_ciint has_skl_msrs(unsigned int family, unsigned int model)
46978c2ecf20Sopenharmony_ci{
46988c2ecf20Sopenharmony_ci	if (!genuine_intel)
46998c2ecf20Sopenharmony_ci		return 0;
47008c2ecf20Sopenharmony_ci
47018c2ecf20Sopenharmony_ci	switch (model) {
47028c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:	/* SKL */
47038c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L:	/* CNL */
47048c2ecf20Sopenharmony_ci		return 1;
47058c2ecf20Sopenharmony_ci	}
47068c2ecf20Sopenharmony_ci	return 0;
47078c2ecf20Sopenharmony_ci}
47088c2ecf20Sopenharmony_ci
47098c2ecf20Sopenharmony_ciint is_slm(unsigned int family, unsigned int model)
47108c2ecf20Sopenharmony_ci{
47118c2ecf20Sopenharmony_ci	if (!genuine_intel)
47128c2ecf20Sopenharmony_ci		return 0;
47138c2ecf20Sopenharmony_ci	switch (model) {
47148c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT:	/* BYT */
47158c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_SILVERMONT_D:	/* AVN */
47168c2ecf20Sopenharmony_ci		return 1;
47178c2ecf20Sopenharmony_ci	}
47188c2ecf20Sopenharmony_ci	return 0;
47198c2ecf20Sopenharmony_ci}
47208c2ecf20Sopenharmony_ci
47218c2ecf20Sopenharmony_ciint is_knl(unsigned int family, unsigned int model)
47228c2ecf20Sopenharmony_ci{
47238c2ecf20Sopenharmony_ci	if (!genuine_intel)
47248c2ecf20Sopenharmony_ci		return 0;
47258c2ecf20Sopenharmony_ci	switch (model) {
47268c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNL:	/* KNL */
47278c2ecf20Sopenharmony_ci		return 1;
47288c2ecf20Sopenharmony_ci	}
47298c2ecf20Sopenharmony_ci	return 0;
47308c2ecf20Sopenharmony_ci}
47318c2ecf20Sopenharmony_ci
47328c2ecf20Sopenharmony_ciint is_cnl(unsigned int family, unsigned int model)
47338c2ecf20Sopenharmony_ci{
47348c2ecf20Sopenharmony_ci	if (!genuine_intel)
47358c2ecf20Sopenharmony_ci		return 0;
47368c2ecf20Sopenharmony_ci
47378c2ecf20Sopenharmony_ci	switch (model) {
47388c2ecf20Sopenharmony_ci	case INTEL_FAM6_CANNONLAKE_L: /* CNL */
47398c2ecf20Sopenharmony_ci		return 1;
47408c2ecf20Sopenharmony_ci	}
47418c2ecf20Sopenharmony_ci
47428c2ecf20Sopenharmony_ci	return 0;
47438c2ecf20Sopenharmony_ci}
47448c2ecf20Sopenharmony_ci
47458c2ecf20Sopenharmony_ciunsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model)
47468c2ecf20Sopenharmony_ci{
47478c2ecf20Sopenharmony_ci	if (is_knl(family, model))
47488c2ecf20Sopenharmony_ci		return 1024;
47498c2ecf20Sopenharmony_ci	return 1;
47508c2ecf20Sopenharmony_ci}
47518c2ecf20Sopenharmony_ci
47528c2ecf20Sopenharmony_ci#define SLM_BCLK_FREQS 5
47538c2ecf20Sopenharmony_cidouble slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0};
47548c2ecf20Sopenharmony_ci
47558c2ecf20Sopenharmony_cidouble slm_bclk(void)
47568c2ecf20Sopenharmony_ci{
47578c2ecf20Sopenharmony_ci	unsigned long long msr = 3;
47588c2ecf20Sopenharmony_ci	unsigned int i;
47598c2ecf20Sopenharmony_ci	double freq;
47608c2ecf20Sopenharmony_ci
47618c2ecf20Sopenharmony_ci	if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))
47628c2ecf20Sopenharmony_ci		fprintf(outf, "SLM BCLK: unknown\n");
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_ci	i = msr & 0xf;
47658c2ecf20Sopenharmony_ci	if (i >= SLM_BCLK_FREQS) {
47668c2ecf20Sopenharmony_ci		fprintf(outf, "SLM BCLK[%d] invalid\n", i);
47678c2ecf20Sopenharmony_ci		i = 3;
47688c2ecf20Sopenharmony_ci	}
47698c2ecf20Sopenharmony_ci	freq = slm_freq_table[i];
47708c2ecf20Sopenharmony_ci
47718c2ecf20Sopenharmony_ci	if (!quiet)
47728c2ecf20Sopenharmony_ci		fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
47738c2ecf20Sopenharmony_ci
47748c2ecf20Sopenharmony_ci	return freq;
47758c2ecf20Sopenharmony_ci}
47768c2ecf20Sopenharmony_ci
47778c2ecf20Sopenharmony_cidouble discover_bclk(unsigned int family, unsigned int model)
47788c2ecf20Sopenharmony_ci{
47798c2ecf20Sopenharmony_ci	if (has_snb_msrs(family, model) || is_knl(family, model))
47808c2ecf20Sopenharmony_ci		return 100.00;
47818c2ecf20Sopenharmony_ci	else if (is_slm(family, model))
47828c2ecf20Sopenharmony_ci		return slm_bclk();
47838c2ecf20Sopenharmony_ci	else
47848c2ecf20Sopenharmony_ci		return 133.33;
47858c2ecf20Sopenharmony_ci}
47868c2ecf20Sopenharmony_ci
47878c2ecf20Sopenharmony_ci/*
47888c2ecf20Sopenharmony_ci * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where
47898c2ecf20Sopenharmony_ci * the Thermal Control Circuit (TCC) activates.
47908c2ecf20Sopenharmony_ci * This is usually equal to tjMax.
47918c2ecf20Sopenharmony_ci *
47928c2ecf20Sopenharmony_ci * Older processors do not have this MSR, so there we guess,
47938c2ecf20Sopenharmony_ci * but also allow cmdline over-ride with -T.
47948c2ecf20Sopenharmony_ci *
47958c2ecf20Sopenharmony_ci * Several MSR temperature values are in units of degrees-C
47968c2ecf20Sopenharmony_ci * below this value, including the Digital Thermal Sensor (DTS),
47978c2ecf20Sopenharmony_ci * Package Thermal Management Sensor (PTM), and thermal event thresholds.
47988c2ecf20Sopenharmony_ci */
47998c2ecf20Sopenharmony_ciint set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
48008c2ecf20Sopenharmony_ci{
48018c2ecf20Sopenharmony_ci	unsigned long long msr;
48028c2ecf20Sopenharmony_ci	unsigned int target_c_local;
48038c2ecf20Sopenharmony_ci	int cpu;
48048c2ecf20Sopenharmony_ci
48058c2ecf20Sopenharmony_ci	/* tcc_activation_temp is used only for dts or ptm */
48068c2ecf20Sopenharmony_ci	if (!(do_dts || do_ptm))
48078c2ecf20Sopenharmony_ci		return 0;
48088c2ecf20Sopenharmony_ci
48098c2ecf20Sopenharmony_ci	/* this is a per-package concept */
48108c2ecf20Sopenharmony_ci	if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
48118c2ecf20Sopenharmony_ci		return 0;
48128c2ecf20Sopenharmony_ci
48138c2ecf20Sopenharmony_ci	cpu = t->cpu_id;
48148c2ecf20Sopenharmony_ci	if (cpu_migrate(cpu)) {
48158c2ecf20Sopenharmony_ci		fprintf(outf, "Could not migrate to CPU %d\n", cpu);
48168c2ecf20Sopenharmony_ci		return -1;
48178c2ecf20Sopenharmony_ci	}
48188c2ecf20Sopenharmony_ci
48198c2ecf20Sopenharmony_ci	if (tcc_activation_temp_override != 0) {
48208c2ecf20Sopenharmony_ci		tcc_activation_temp = tcc_activation_temp_override;
48218c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n",
48228c2ecf20Sopenharmony_ci			cpu, tcc_activation_temp);
48238c2ecf20Sopenharmony_ci		return 0;
48248c2ecf20Sopenharmony_ci	}
48258c2ecf20Sopenharmony_ci
48268c2ecf20Sopenharmony_ci	/* Temperature Target MSR is Nehalem and newer only */
48278c2ecf20Sopenharmony_ci	if (!do_nhm_platform_info)
48288c2ecf20Sopenharmony_ci		goto guess;
48298c2ecf20Sopenharmony_ci
48308c2ecf20Sopenharmony_ci	if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))
48318c2ecf20Sopenharmony_ci		goto guess;
48328c2ecf20Sopenharmony_ci
48338c2ecf20Sopenharmony_ci	target_c_local = (msr >> 16) & 0xFF;
48348c2ecf20Sopenharmony_ci
48358c2ecf20Sopenharmony_ci	if (!quiet)
48368c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
48378c2ecf20Sopenharmony_ci			cpu, msr, target_c_local);
48388c2ecf20Sopenharmony_ci
48398c2ecf20Sopenharmony_ci	if (!target_c_local)
48408c2ecf20Sopenharmony_ci		goto guess;
48418c2ecf20Sopenharmony_ci
48428c2ecf20Sopenharmony_ci	tcc_activation_temp = target_c_local;
48438c2ecf20Sopenharmony_ci
48448c2ecf20Sopenharmony_ci	return 0;
48458c2ecf20Sopenharmony_ci
48468c2ecf20Sopenharmony_ciguess:
48478c2ecf20Sopenharmony_ci	tcc_activation_temp = TJMAX_DEFAULT;
48488c2ecf20Sopenharmony_ci	fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
48498c2ecf20Sopenharmony_ci		cpu, tcc_activation_temp);
48508c2ecf20Sopenharmony_ci
48518c2ecf20Sopenharmony_ci	return 0;
48528c2ecf20Sopenharmony_ci}
48538c2ecf20Sopenharmony_ci
48548c2ecf20Sopenharmony_civoid decode_feature_control_msr(void)
48558c2ecf20Sopenharmony_ci{
48568c2ecf20Sopenharmony_ci	unsigned long long msr;
48578c2ecf20Sopenharmony_ci
48588c2ecf20Sopenharmony_ci	if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr))
48598c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
48608c2ecf20Sopenharmony_ci			base_cpu, msr,
48618c2ecf20Sopenharmony_ci			msr & FEAT_CTL_LOCKED ? "" : "UN-",
48628c2ecf20Sopenharmony_ci			msr & (1 << 18) ? "SGX" : "");
48638c2ecf20Sopenharmony_ci}
48648c2ecf20Sopenharmony_ci
48658c2ecf20Sopenharmony_civoid decode_misc_enable_msr(void)
48668c2ecf20Sopenharmony_ci{
48678c2ecf20Sopenharmony_ci	unsigned long long msr;
48688c2ecf20Sopenharmony_ci
48698c2ecf20Sopenharmony_ci	if (!genuine_intel)
48708c2ecf20Sopenharmony_ci		return;
48718c2ecf20Sopenharmony_ci
48728c2ecf20Sopenharmony_ci	if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
48738c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",
48748c2ecf20Sopenharmony_ci			base_cpu, msr,
48758c2ecf20Sopenharmony_ci			msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",
48768c2ecf20Sopenharmony_ci			msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",
48778c2ecf20Sopenharmony_ci			msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-",
48788c2ecf20Sopenharmony_ci			msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "",
48798c2ecf20Sopenharmony_ci			msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");
48808c2ecf20Sopenharmony_ci}
48818c2ecf20Sopenharmony_ci
48828c2ecf20Sopenharmony_civoid decode_misc_feature_control(void)
48838c2ecf20Sopenharmony_ci{
48848c2ecf20Sopenharmony_ci	unsigned long long msr;
48858c2ecf20Sopenharmony_ci
48868c2ecf20Sopenharmony_ci	if (!has_misc_feature_control)
48878c2ecf20Sopenharmony_ci		return;
48888c2ecf20Sopenharmony_ci
48898c2ecf20Sopenharmony_ci	if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))
48908c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
48918c2ecf20Sopenharmony_ci			base_cpu, msr,
48928c2ecf20Sopenharmony_ci			msr & (0 << 0) ? "No-" : "",
48938c2ecf20Sopenharmony_ci			msr & (1 << 0) ? "No-" : "",
48948c2ecf20Sopenharmony_ci			msr & (2 << 0) ? "No-" : "",
48958c2ecf20Sopenharmony_ci			msr & (3 << 0) ? "No-" : "");
48968c2ecf20Sopenharmony_ci}
48978c2ecf20Sopenharmony_ci/*
48988c2ecf20Sopenharmony_ci * Decode MSR_MISC_PWR_MGMT
48998c2ecf20Sopenharmony_ci *
49008c2ecf20Sopenharmony_ci * Decode the bits according to the Nehalem documentation
49018c2ecf20Sopenharmony_ci * bit[0] seems to continue to have same meaning going forward
49028c2ecf20Sopenharmony_ci * bit[1] less so...
49038c2ecf20Sopenharmony_ci */
49048c2ecf20Sopenharmony_civoid decode_misc_pwr_mgmt_msr(void)
49058c2ecf20Sopenharmony_ci{
49068c2ecf20Sopenharmony_ci	unsigned long long msr;
49078c2ecf20Sopenharmony_ci
49088c2ecf20Sopenharmony_ci	if (!do_nhm_platform_info)
49098c2ecf20Sopenharmony_ci		return;
49108c2ecf20Sopenharmony_ci
49118c2ecf20Sopenharmony_ci	if (no_MSR_MISC_PWR_MGMT)
49128c2ecf20Sopenharmony_ci		return;
49138c2ecf20Sopenharmony_ci
49148c2ecf20Sopenharmony_ci	if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
49158c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",
49168c2ecf20Sopenharmony_ci			base_cpu, msr,
49178c2ecf20Sopenharmony_ci			msr & (1 << 0) ? "DIS" : "EN",
49188c2ecf20Sopenharmony_ci			msr & (1 << 1) ? "EN" : "DIS",
49198c2ecf20Sopenharmony_ci			msr & (1 << 8) ? "EN" : "DIS");
49208c2ecf20Sopenharmony_ci}
49218c2ecf20Sopenharmony_ci/*
49228c2ecf20Sopenharmony_ci * Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
49238c2ecf20Sopenharmony_ci *
49248c2ecf20Sopenharmony_ci * This MSRs are present on Silvermont processors,
49258c2ecf20Sopenharmony_ci * Intel Atom processor E3000 series (Baytrail), and friends.
49268c2ecf20Sopenharmony_ci */
49278c2ecf20Sopenharmony_civoid decode_c6_demotion_policy_msr(void)
49288c2ecf20Sopenharmony_ci{
49298c2ecf20Sopenharmony_ci	unsigned long long msr;
49308c2ecf20Sopenharmony_ci
49318c2ecf20Sopenharmony_ci	if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))
49328c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n",
49338c2ecf20Sopenharmony_ci			base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
49348c2ecf20Sopenharmony_ci
49358c2ecf20Sopenharmony_ci	if (!get_msr(base_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))
49368c2ecf20Sopenharmony_ci		fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n",
49378c2ecf20Sopenharmony_ci			base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");
49388c2ecf20Sopenharmony_ci}
49398c2ecf20Sopenharmony_ci
49408c2ecf20Sopenharmony_ci/*
49418c2ecf20Sopenharmony_ci * When models are the same, for the purpose of turbostat, reuse
49428c2ecf20Sopenharmony_ci */
49438c2ecf20Sopenharmony_ciunsigned int intel_model_duplicates(unsigned int model)
49448c2ecf20Sopenharmony_ci{
49458c2ecf20Sopenharmony_ci
49468c2ecf20Sopenharmony_ci	switch(model) {
49478c2ecf20Sopenharmony_ci	case INTEL_FAM6_NEHALEM_EP:	/* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
49488c2ecf20Sopenharmony_ci	case INTEL_FAM6_NEHALEM:	/* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
49498c2ecf20Sopenharmony_ci	case 0x1F:	/* Core i7 and i5 Processor - Nehalem */
49508c2ecf20Sopenharmony_ci	case INTEL_FAM6_WESTMERE:	/* Westmere Client - Clarkdale, Arrandale */
49518c2ecf20Sopenharmony_ci	case INTEL_FAM6_WESTMERE_EP:	/* Westmere EP - Gulftown */
49528c2ecf20Sopenharmony_ci		return INTEL_FAM6_NEHALEM;
49538c2ecf20Sopenharmony_ci
49548c2ecf20Sopenharmony_ci	case INTEL_FAM6_NEHALEM_EX:	/* Nehalem-EX Xeon - Beckton */
49558c2ecf20Sopenharmony_ci	case INTEL_FAM6_WESTMERE_EX:	/* Westmere-EX Xeon - Eagleton */
49568c2ecf20Sopenharmony_ci		return INTEL_FAM6_NEHALEM_EX;
49578c2ecf20Sopenharmony_ci
49588c2ecf20Sopenharmony_ci	case INTEL_FAM6_XEON_PHI_KNM:
49598c2ecf20Sopenharmony_ci		return INTEL_FAM6_XEON_PHI_KNL;
49608c2ecf20Sopenharmony_ci
49618c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_X:
49628c2ecf20Sopenharmony_ci	case INTEL_FAM6_BROADWELL_D:	/* BDX-DE */
49638c2ecf20Sopenharmony_ci		return INTEL_FAM6_BROADWELL_X;
49648c2ecf20Sopenharmony_ci
49658c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE_L:
49668c2ecf20Sopenharmony_ci	case INTEL_FAM6_SKYLAKE:
49678c2ecf20Sopenharmony_ci	case INTEL_FAM6_KABYLAKE_L:
49688c2ecf20Sopenharmony_ci	case INTEL_FAM6_KABYLAKE:
49698c2ecf20Sopenharmony_ci	case INTEL_FAM6_COMETLAKE_L:
49708c2ecf20Sopenharmony_ci	case INTEL_FAM6_COMETLAKE:
49718c2ecf20Sopenharmony_ci		return INTEL_FAM6_SKYLAKE_L;
49728c2ecf20Sopenharmony_ci
49738c2ecf20Sopenharmony_ci	case INTEL_FAM6_ICELAKE_L:
49748c2ecf20Sopenharmony_ci	case INTEL_FAM6_ICELAKE_NNPI:
49758c2ecf20Sopenharmony_ci	case INTEL_FAM6_TIGERLAKE_L:
49768c2ecf20Sopenharmony_ci	case INTEL_FAM6_TIGERLAKE:
49778c2ecf20Sopenharmony_ci	case INTEL_FAM6_ROCKETLAKE:
49788c2ecf20Sopenharmony_ci	case INTEL_FAM6_LAKEFIELD:
49798c2ecf20Sopenharmony_ci	case INTEL_FAM6_ALDERLAKE:
49808c2ecf20Sopenharmony_ci		return INTEL_FAM6_CANNONLAKE_L;
49818c2ecf20Sopenharmony_ci
49828c2ecf20Sopenharmony_ci	case INTEL_FAM6_ATOM_TREMONT_L:
49838c2ecf20Sopenharmony_ci		return INTEL_FAM6_ATOM_TREMONT;
49848c2ecf20Sopenharmony_ci
49858c2ecf20Sopenharmony_ci	case INTEL_FAM6_ICELAKE_X:
49868c2ecf20Sopenharmony_ci	case INTEL_FAM6_SAPPHIRERAPIDS_X:
49878c2ecf20Sopenharmony_ci		return INTEL_FAM6_SKYLAKE_X;
49888c2ecf20Sopenharmony_ci	}
49898c2ecf20Sopenharmony_ci	return model;
49908c2ecf20Sopenharmony_ci}
49918c2ecf20Sopenharmony_ci
49928c2ecf20Sopenharmony_civoid print_dev_latency(void)
49938c2ecf20Sopenharmony_ci{
49948c2ecf20Sopenharmony_ci	char *path = "/dev/cpu_dma_latency";
49958c2ecf20Sopenharmony_ci	int fd;
49968c2ecf20Sopenharmony_ci	int value;
49978c2ecf20Sopenharmony_ci	int retval;
49988c2ecf20Sopenharmony_ci
49998c2ecf20Sopenharmony_ci	fd = open(path, O_RDONLY);
50008c2ecf20Sopenharmony_ci	if (fd < 0) {
50018c2ecf20Sopenharmony_ci		warn("fopen %s\n", path);
50028c2ecf20Sopenharmony_ci		return;
50038c2ecf20Sopenharmony_ci	}
50048c2ecf20Sopenharmony_ci
50058c2ecf20Sopenharmony_ci	retval = read(fd, (void *)&value, sizeof(int));
50068c2ecf20Sopenharmony_ci	if (retval != sizeof(int)) {
50078c2ecf20Sopenharmony_ci		warn("read failed %s\n", path);
50088c2ecf20Sopenharmony_ci		close(fd);
50098c2ecf20Sopenharmony_ci		return;
50108c2ecf20Sopenharmony_ci	}
50118c2ecf20Sopenharmony_ci	fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n",
50128c2ecf20Sopenharmony_ci		value, value == 2000000000 ? "default" : "constrained");
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_ci	close(fd);
50158c2ecf20Sopenharmony_ci}
50168c2ecf20Sopenharmony_ci
50178c2ecf20Sopenharmony_civoid process_cpuid()
50188c2ecf20Sopenharmony_ci{
50198c2ecf20Sopenharmony_ci	unsigned int eax, ebx, ecx, edx;
50208c2ecf20Sopenharmony_ci	unsigned int fms, family, model, stepping, ecx_flags, edx_flags;
50218c2ecf20Sopenharmony_ci	unsigned int has_turbo;
50228c2ecf20Sopenharmony_ci
50238c2ecf20Sopenharmony_ci	eax = ebx = ecx = edx = 0;
50248c2ecf20Sopenharmony_ci
50258c2ecf20Sopenharmony_ci	__cpuid(0, max_level, ebx, ecx, edx);
50268c2ecf20Sopenharmony_ci
50278c2ecf20Sopenharmony_ci	if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
50288c2ecf20Sopenharmony_ci		genuine_intel = 1;
50298c2ecf20Sopenharmony_ci	else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
50308c2ecf20Sopenharmony_ci		authentic_amd = 1;
50318c2ecf20Sopenharmony_ci	else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)
50328c2ecf20Sopenharmony_ci		hygon_genuine = 1;
50338c2ecf20Sopenharmony_ci
50348c2ecf20Sopenharmony_ci	if (!quiet)
50358c2ecf20Sopenharmony_ci		fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
50368c2ecf20Sopenharmony_ci			(char *)&ebx, (char *)&edx, (char *)&ecx);
50378c2ecf20Sopenharmony_ci
50388c2ecf20Sopenharmony_ci	__cpuid(1, fms, ebx, ecx, edx);
50398c2ecf20Sopenharmony_ci	family = (fms >> 8) & 0xf;
50408c2ecf20Sopenharmony_ci	model = (fms >> 4) & 0xf;
50418c2ecf20Sopenharmony_ci	stepping = fms & 0xf;
50428c2ecf20Sopenharmony_ci	if (family == 0xf)
50438c2ecf20Sopenharmony_ci		family += (fms >> 20) & 0xff;
50448c2ecf20Sopenharmony_ci	if (family >= 6)
50458c2ecf20Sopenharmony_ci		model += ((fms >> 16) & 0xf) << 4;
50468c2ecf20Sopenharmony_ci	ecx_flags = ecx;
50478c2ecf20Sopenharmony_ci	edx_flags = edx;
50488c2ecf20Sopenharmony_ci
50498c2ecf20Sopenharmony_ci	/*
50508c2ecf20Sopenharmony_ci	 * check max extended function levels of CPUID.
50518c2ecf20Sopenharmony_ci	 * This is needed to check for invariant TSC.
50528c2ecf20Sopenharmony_ci	 * This check is valid for both Intel and AMD.
50538c2ecf20Sopenharmony_ci	 */
50548c2ecf20Sopenharmony_ci	ebx = ecx = edx = 0;
50558c2ecf20Sopenharmony_ci	__cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
50568c2ecf20Sopenharmony_ci
50578c2ecf20Sopenharmony_ci	if (!quiet) {
50588c2ecf20Sopenharmony_ci		fprintf(outf, "0x%x CPUID levels; 0x%x xlevels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
50598c2ecf20Sopenharmony_ci			max_level, max_extended_level, family, model, stepping, family, model, stepping);
50608c2ecf20Sopenharmony_ci		fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",
50618c2ecf20Sopenharmony_ci			ecx_flags & (1 << 0) ? "SSE3" : "-",
50628c2ecf20Sopenharmony_ci			ecx_flags & (1 << 3) ? "MONITOR" : "-",
50638c2ecf20Sopenharmony_ci			ecx_flags & (1 << 6) ? "SMX" : "-",
50648c2ecf20Sopenharmony_ci			ecx_flags & (1 << 7) ? "EIST" : "-",
50658c2ecf20Sopenharmony_ci			ecx_flags & (1 << 8) ? "TM2" : "-",
50668c2ecf20Sopenharmony_ci			edx_flags & (1 << 4) ? "TSC" : "-",
50678c2ecf20Sopenharmony_ci			edx_flags & (1 << 5) ? "MSR" : "-",
50688c2ecf20Sopenharmony_ci			edx_flags & (1 << 22) ? "ACPI-TM" : "-",
50698c2ecf20Sopenharmony_ci			edx_flags & (1 << 28) ? "HT" : "-",
50708c2ecf20Sopenharmony_ci			edx_flags & (1 << 29) ? "TM" : "-");
50718c2ecf20Sopenharmony_ci	}
50728c2ecf20Sopenharmony_ci	if (genuine_intel)
50738c2ecf20Sopenharmony_ci		model = intel_model_duplicates(model);
50748c2ecf20Sopenharmony_ci
50758c2ecf20Sopenharmony_ci	if (!(edx_flags & (1 << 5)))
50768c2ecf20Sopenharmony_ci		errx(1, "CPUID: no MSR");
50778c2ecf20Sopenharmony_ci
50788c2ecf20Sopenharmony_ci	if (max_extended_level >= 0x80000007) {
50798c2ecf20Sopenharmony_ci
50808c2ecf20Sopenharmony_ci		/*
50818c2ecf20Sopenharmony_ci		 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
50828c2ecf20Sopenharmony_ci		 * this check is valid for both Intel and AMD
50838c2ecf20Sopenharmony_ci		 */
50848c2ecf20Sopenharmony_ci		__cpuid(0x80000007, eax, ebx, ecx, edx);
50858c2ecf20Sopenharmony_ci		has_invariant_tsc = edx & (1 << 8);
50868c2ecf20Sopenharmony_ci	}
50878c2ecf20Sopenharmony_ci
50888c2ecf20Sopenharmony_ci	/*
50898c2ecf20Sopenharmony_ci	 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
50908c2ecf20Sopenharmony_ci	 * this check is valid for both Intel and AMD
50918c2ecf20Sopenharmony_ci	 */
50928c2ecf20Sopenharmony_ci
50938c2ecf20Sopenharmony_ci	__cpuid(0x6, eax, ebx, ecx, edx);
50948c2ecf20Sopenharmony_ci	has_aperf = ecx & (1 << 0);
50958c2ecf20Sopenharmony_ci	if (has_aperf) {
50968c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Avg_MHz);
50978c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Busy);
50988c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Bzy_MHz);
50998c2ecf20Sopenharmony_ci	}
51008c2ecf20Sopenharmony_ci	do_dts = eax & (1 << 0);
51018c2ecf20Sopenharmony_ci	if (do_dts)
51028c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CoreTmp);
51038c2ecf20Sopenharmony_ci	has_turbo = eax & (1 << 1);
51048c2ecf20Sopenharmony_ci	do_ptm = eax & (1 << 6);
51058c2ecf20Sopenharmony_ci	if (do_ptm)
51068c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_PkgTmp);
51078c2ecf20Sopenharmony_ci	has_hwp = eax & (1 << 7);
51088c2ecf20Sopenharmony_ci	has_hwp_notify = eax & (1 << 8);
51098c2ecf20Sopenharmony_ci	has_hwp_activity_window = eax & (1 << 9);
51108c2ecf20Sopenharmony_ci	has_hwp_epp = eax & (1 << 10);
51118c2ecf20Sopenharmony_ci	has_hwp_pkg = eax & (1 << 11);
51128c2ecf20Sopenharmony_ci	has_epb = ecx & (1 << 3);
51138c2ecf20Sopenharmony_ci
51148c2ecf20Sopenharmony_ci	if (!quiet)
51158c2ecf20Sopenharmony_ci		fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "
51168c2ecf20Sopenharmony_ci			"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
51178c2ecf20Sopenharmony_ci			has_aperf ? "" : "No-",
51188c2ecf20Sopenharmony_ci			has_turbo ? "" : "No-",
51198c2ecf20Sopenharmony_ci			do_dts ? "" : "No-",
51208c2ecf20Sopenharmony_ci			do_ptm ? "" : "No-",
51218c2ecf20Sopenharmony_ci			has_hwp ? "" : "No-",
51228c2ecf20Sopenharmony_ci			has_hwp_notify ? "" : "No-",
51238c2ecf20Sopenharmony_ci			has_hwp_activity_window ? "" : "No-",
51248c2ecf20Sopenharmony_ci			has_hwp_epp ? "" : "No-",
51258c2ecf20Sopenharmony_ci			has_hwp_pkg ? "" : "No-",
51268c2ecf20Sopenharmony_ci			has_epb ? "" : "No-");
51278c2ecf20Sopenharmony_ci
51288c2ecf20Sopenharmony_ci	if (!quiet)
51298c2ecf20Sopenharmony_ci		decode_misc_enable_msr();
51308c2ecf20Sopenharmony_ci
51318c2ecf20Sopenharmony_ci
51328c2ecf20Sopenharmony_ci	if (max_level >= 0x7 && !quiet) {
51338c2ecf20Sopenharmony_ci		int has_sgx;
51348c2ecf20Sopenharmony_ci
51358c2ecf20Sopenharmony_ci		ecx = 0;
51368c2ecf20Sopenharmony_ci
51378c2ecf20Sopenharmony_ci		__cpuid_count(0x7, 0, eax, ebx, ecx, edx);
51388c2ecf20Sopenharmony_ci
51398c2ecf20Sopenharmony_ci		has_sgx = ebx & (1 << 2);
51408c2ecf20Sopenharmony_ci		fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-");
51418c2ecf20Sopenharmony_ci
51428c2ecf20Sopenharmony_ci		if (has_sgx)
51438c2ecf20Sopenharmony_ci			decode_feature_control_msr();
51448c2ecf20Sopenharmony_ci	}
51458c2ecf20Sopenharmony_ci
51468c2ecf20Sopenharmony_ci	if (max_level >= 0x15) {
51478c2ecf20Sopenharmony_ci		unsigned int eax_crystal;
51488c2ecf20Sopenharmony_ci		unsigned int ebx_tsc;
51498c2ecf20Sopenharmony_ci
51508c2ecf20Sopenharmony_ci		/*
51518c2ecf20Sopenharmony_ci		 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz
51528c2ecf20Sopenharmony_ci		 */
51538c2ecf20Sopenharmony_ci		eax_crystal = ebx_tsc = crystal_hz = edx = 0;
51548c2ecf20Sopenharmony_ci		__cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);
51558c2ecf20Sopenharmony_ci
51568c2ecf20Sopenharmony_ci		if (ebx_tsc != 0) {
51578c2ecf20Sopenharmony_ci
51588c2ecf20Sopenharmony_ci			if (!quiet && (ebx != 0))
51598c2ecf20Sopenharmony_ci				fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
51608c2ecf20Sopenharmony_ci					eax_crystal, ebx_tsc, crystal_hz);
51618c2ecf20Sopenharmony_ci
51628c2ecf20Sopenharmony_ci			if (crystal_hz == 0)
51638c2ecf20Sopenharmony_ci				switch(model) {
51648c2ecf20Sopenharmony_ci				case INTEL_FAM6_SKYLAKE_L:	/* SKL */
51658c2ecf20Sopenharmony_ci					crystal_hz = 24000000;	/* 24.0 MHz */
51668c2ecf20Sopenharmony_ci					break;
51678c2ecf20Sopenharmony_ci				case INTEL_FAM6_ATOM_GOLDMONT_D:	/* DNV */
51688c2ecf20Sopenharmony_ci					crystal_hz = 25000000;	/* 25.0 MHz */
51698c2ecf20Sopenharmony_ci					break;
51708c2ecf20Sopenharmony_ci				case INTEL_FAM6_ATOM_GOLDMONT:	/* BXT */
51718c2ecf20Sopenharmony_ci				case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
51728c2ecf20Sopenharmony_ci					crystal_hz = 19200000;	/* 19.2 MHz */
51738c2ecf20Sopenharmony_ci					break;
51748c2ecf20Sopenharmony_ci				default:
51758c2ecf20Sopenharmony_ci					crystal_hz = 0;
51768c2ecf20Sopenharmony_ci			}
51778c2ecf20Sopenharmony_ci
51788c2ecf20Sopenharmony_ci			if (crystal_hz) {
51798c2ecf20Sopenharmony_ci				tsc_hz =  (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
51808c2ecf20Sopenharmony_ci				if (!quiet)
51818c2ecf20Sopenharmony_ci					fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
51828c2ecf20Sopenharmony_ci						tsc_hz / 1000000, crystal_hz, ebx_tsc,  eax_crystal);
51838c2ecf20Sopenharmony_ci			}
51848c2ecf20Sopenharmony_ci		}
51858c2ecf20Sopenharmony_ci	}
51868c2ecf20Sopenharmony_ci	if (max_level >= 0x16) {
51878c2ecf20Sopenharmony_ci		unsigned int base_mhz, max_mhz, bus_mhz, edx;
51888c2ecf20Sopenharmony_ci
51898c2ecf20Sopenharmony_ci		/*
51908c2ecf20Sopenharmony_ci		 * CPUID 16H Base MHz, Max MHz, Bus MHz
51918c2ecf20Sopenharmony_ci		 */
51928c2ecf20Sopenharmony_ci		base_mhz = max_mhz = bus_mhz = edx = 0;
51938c2ecf20Sopenharmony_ci
51948c2ecf20Sopenharmony_ci		__cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
51958c2ecf20Sopenharmony_ci		if (!quiet)
51968c2ecf20Sopenharmony_ci			fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
51978c2ecf20Sopenharmony_ci				base_mhz, max_mhz, bus_mhz);
51988c2ecf20Sopenharmony_ci	}
51998c2ecf20Sopenharmony_ci
52008c2ecf20Sopenharmony_ci	if (has_aperf)
52018c2ecf20Sopenharmony_ci		aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model);
52028c2ecf20Sopenharmony_ci
52038c2ecf20Sopenharmony_ci	BIC_PRESENT(BIC_IRQ);
52048c2ecf20Sopenharmony_ci	BIC_PRESENT(BIC_TSC_MHz);
52058c2ecf20Sopenharmony_ci
52068c2ecf20Sopenharmony_ci	if (probe_nhm_msrs(family, model)) {
52078c2ecf20Sopenharmony_ci		do_nhm_platform_info = 1;
52088c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU_c1);
52098c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU_c3);
52108c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU_c6);
52118c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_SMI);
52128c2ecf20Sopenharmony_ci	}
52138c2ecf20Sopenharmony_ci	do_snb_cstates = has_snb_msrs(family, model);
52148c2ecf20Sopenharmony_ci
52158c2ecf20Sopenharmony_ci	if (do_snb_cstates)
52168c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU_c7);
52178c2ecf20Sopenharmony_ci
52188c2ecf20Sopenharmony_ci	do_irtl_snb = has_snb_msrs(family, model);
52198c2ecf20Sopenharmony_ci	if (do_snb_cstates && (pkg_cstate_limit >= PCL__2))
52208c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Pkgpc2);
52218c2ecf20Sopenharmony_ci	if (pkg_cstate_limit >= PCL__3)
52228c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Pkgpc3);
52238c2ecf20Sopenharmony_ci	if (pkg_cstate_limit >= PCL__6)
52248c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Pkgpc6);
52258c2ecf20Sopenharmony_ci	if (do_snb_cstates && (pkg_cstate_limit >= PCL__7))
52268c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Pkgpc7);
52278c2ecf20Sopenharmony_ci	if (has_slv_msrs(family, model)) {
52288c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc2);
52298c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc3);
52308c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Pkgpc6);
52318c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc7);
52328c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Mod_c6);
52338c2ecf20Sopenharmony_ci		use_c1_residency_msr = 1;
52348c2ecf20Sopenharmony_ci	}
52358c2ecf20Sopenharmony_ci	if (is_jvl(family, model)) {
52368c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c3);
52378c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c7);
52388c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc2);
52398c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc3);
52408c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc6);
52418c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc7);
52428c2ecf20Sopenharmony_ci	}
52438c2ecf20Sopenharmony_ci	if (is_dnv(family, model)) {
52448c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU_c1);
52458c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c3);
52468c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc3);
52478c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c7);
52488c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc7);
52498c2ecf20Sopenharmony_ci		use_c1_residency_msr = 1;
52508c2ecf20Sopenharmony_ci	}
52518c2ecf20Sopenharmony_ci	if (is_skx(family, model)) {
52528c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c3);
52538c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc3);
52548c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c7);
52558c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc7);
52568c2ecf20Sopenharmony_ci	}
52578c2ecf20Sopenharmony_ci	if (is_bdx(family, model)) {
52588c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c7);
52598c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_Pkgpc7);
52608c2ecf20Sopenharmony_ci	}
52618c2ecf20Sopenharmony_ci	if (has_c8910_msrs(family, model)) {
52628c2ecf20Sopenharmony_ci		if (pkg_cstate_limit >= PCL__8)
52638c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkgpc8);
52648c2ecf20Sopenharmony_ci		if (pkg_cstate_limit >= PCL__9)
52658c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkgpc9);
52668c2ecf20Sopenharmony_ci		if (pkg_cstate_limit >= PCL_10)
52678c2ecf20Sopenharmony_ci			BIC_PRESENT(BIC_Pkgpc10);
52688c2ecf20Sopenharmony_ci	}
52698c2ecf20Sopenharmony_ci	do_irtl_hsw = has_c8910_msrs(family, model);
52708c2ecf20Sopenharmony_ci	if (has_skl_msrs(family, model)) {
52718c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Totl_c0);
52728c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Any_c0);
52738c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_GFX_c0);
52748c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPUGFX);
52758c2ecf20Sopenharmony_ci	}
52768c2ecf20Sopenharmony_ci	do_slm_cstates = is_slm(family, model);
52778c2ecf20Sopenharmony_ci	do_knl_cstates  = is_knl(family, model);
52788c2ecf20Sopenharmony_ci
52798c2ecf20Sopenharmony_ci	if (do_slm_cstates || do_knl_cstates || is_cnl(family, model) ||
52808c2ecf20Sopenharmony_ci	    is_ehl(family, model))
52818c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_c3);
52828c2ecf20Sopenharmony_ci
52838c2ecf20Sopenharmony_ci	if (!quiet)
52848c2ecf20Sopenharmony_ci		decode_misc_pwr_mgmt_msr();
52858c2ecf20Sopenharmony_ci
52868c2ecf20Sopenharmony_ci	if (!quiet && has_slv_msrs(family, model))
52878c2ecf20Sopenharmony_ci		decode_c6_demotion_policy_msr();
52888c2ecf20Sopenharmony_ci
52898c2ecf20Sopenharmony_ci	rapl_probe(family, model);
52908c2ecf20Sopenharmony_ci	perf_limit_reasons_probe(family, model);
52918c2ecf20Sopenharmony_ci	automatic_cstate_conversion_probe(family, model);
52928c2ecf20Sopenharmony_ci
52938c2ecf20Sopenharmony_ci	if (!quiet)
52948c2ecf20Sopenharmony_ci		dump_cstate_pstate_config_info(family, model);
52958c2ecf20Sopenharmony_ci
52968c2ecf20Sopenharmony_ci	if (!quiet)
52978c2ecf20Sopenharmony_ci		print_dev_latency();
52988c2ecf20Sopenharmony_ci	if (!quiet)
52998c2ecf20Sopenharmony_ci		dump_sysfs_cstate_config();
53008c2ecf20Sopenharmony_ci	if (!quiet)
53018c2ecf20Sopenharmony_ci		dump_sysfs_pstate_config();
53028c2ecf20Sopenharmony_ci
53038c2ecf20Sopenharmony_ci	if (has_skl_msrs(family, model))
53048c2ecf20Sopenharmony_ci		calculate_tsc_tweak();
53058c2ecf20Sopenharmony_ci
53068c2ecf20Sopenharmony_ci	if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
53078c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_GFX_rc6);
53088c2ecf20Sopenharmony_ci
53098c2ecf20Sopenharmony_ci	if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
53108c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_GFXMHz);
53118c2ecf20Sopenharmony_ci
53128c2ecf20Sopenharmony_ci	if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
53138c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_GFXACTMHz);
53148c2ecf20Sopenharmony_ci
53158c2ecf20Sopenharmony_ci	if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))
53168c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU_LPI);
53178c2ecf20Sopenharmony_ci	else
53188c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_CPU_LPI);
53198c2ecf20Sopenharmony_ci
53208c2ecf20Sopenharmony_ci	if (!access(sys_lpi_file_sysfs, R_OK)) {
53218c2ecf20Sopenharmony_ci		sys_lpi_file = sys_lpi_file_sysfs;
53228c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_SYS_LPI);
53238c2ecf20Sopenharmony_ci	} else if (!access(sys_lpi_file_debugfs, R_OK)) {
53248c2ecf20Sopenharmony_ci		sys_lpi_file = sys_lpi_file_debugfs;
53258c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_SYS_LPI);
53268c2ecf20Sopenharmony_ci	} else {
53278c2ecf20Sopenharmony_ci		sys_lpi_file_sysfs = NULL;
53288c2ecf20Sopenharmony_ci		BIC_NOT_PRESENT(BIC_SYS_LPI);
53298c2ecf20Sopenharmony_ci	}
53308c2ecf20Sopenharmony_ci
53318c2ecf20Sopenharmony_ci	if (!quiet)
53328c2ecf20Sopenharmony_ci		decode_misc_feature_control();
53338c2ecf20Sopenharmony_ci
53348c2ecf20Sopenharmony_ci	return;
53358c2ecf20Sopenharmony_ci}
53368c2ecf20Sopenharmony_ci
53378c2ecf20Sopenharmony_ci/*
53388c2ecf20Sopenharmony_ci * in /dev/cpu/ return success for names that are numbers
53398c2ecf20Sopenharmony_ci * ie. filter out ".", "..", "microcode".
53408c2ecf20Sopenharmony_ci */
53418c2ecf20Sopenharmony_ciint dir_filter(const struct dirent *dirp)
53428c2ecf20Sopenharmony_ci{
53438c2ecf20Sopenharmony_ci	if (isdigit(dirp->d_name[0]))
53448c2ecf20Sopenharmony_ci		return 1;
53458c2ecf20Sopenharmony_ci	else
53468c2ecf20Sopenharmony_ci		return 0;
53478c2ecf20Sopenharmony_ci}
53488c2ecf20Sopenharmony_ci
53498c2ecf20Sopenharmony_ciint open_dev_cpu_msr(int dummy1)
53508c2ecf20Sopenharmony_ci{
53518c2ecf20Sopenharmony_ci	return 0;
53528c2ecf20Sopenharmony_ci}
53538c2ecf20Sopenharmony_ci
53548c2ecf20Sopenharmony_civoid topology_probe()
53558c2ecf20Sopenharmony_ci{
53568c2ecf20Sopenharmony_ci	int i;
53578c2ecf20Sopenharmony_ci	int max_core_id = 0;
53588c2ecf20Sopenharmony_ci	int max_package_id = 0;
53598c2ecf20Sopenharmony_ci	int max_die_id = 0;
53608c2ecf20Sopenharmony_ci	int max_siblings = 0;
53618c2ecf20Sopenharmony_ci
53628c2ecf20Sopenharmony_ci	/* Initialize num_cpus, max_cpu_num */
53638c2ecf20Sopenharmony_ci	set_max_cpu_num();
53648c2ecf20Sopenharmony_ci	topo.num_cpus = 0;
53658c2ecf20Sopenharmony_ci	for_all_proc_cpus(count_cpus);
53668c2ecf20Sopenharmony_ci	if (!summary_only && topo.num_cpus > 1)
53678c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_CPU);
53688c2ecf20Sopenharmony_ci
53698c2ecf20Sopenharmony_ci	if (debug > 1)
53708c2ecf20Sopenharmony_ci		fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
53718c2ecf20Sopenharmony_ci
53728c2ecf20Sopenharmony_ci	cpus = calloc(1, (topo.max_cpu_num  + 1) * sizeof(struct cpu_topology));
53738c2ecf20Sopenharmony_ci	if (cpus == NULL)
53748c2ecf20Sopenharmony_ci		err(1, "calloc cpus");
53758c2ecf20Sopenharmony_ci
53768c2ecf20Sopenharmony_ci	/*
53778c2ecf20Sopenharmony_ci	 * Allocate and initialize cpu_present_set
53788c2ecf20Sopenharmony_ci	 */
53798c2ecf20Sopenharmony_ci	cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1));
53808c2ecf20Sopenharmony_ci	if (cpu_present_set == NULL)
53818c2ecf20Sopenharmony_ci		err(3, "CPU_ALLOC");
53828c2ecf20Sopenharmony_ci	cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
53838c2ecf20Sopenharmony_ci	CPU_ZERO_S(cpu_present_setsize, cpu_present_set);
53848c2ecf20Sopenharmony_ci	for_all_proc_cpus(mark_cpu_present);
53858c2ecf20Sopenharmony_ci
53868c2ecf20Sopenharmony_ci	/*
53878c2ecf20Sopenharmony_ci	 * Validate that all cpus in cpu_subset are also in cpu_present_set
53888c2ecf20Sopenharmony_ci	 */
53898c2ecf20Sopenharmony_ci	for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {
53908c2ecf20Sopenharmony_ci		if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset))
53918c2ecf20Sopenharmony_ci			if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set))
53928c2ecf20Sopenharmony_ci				err(1, "cpu%d not present", i);
53938c2ecf20Sopenharmony_ci	}
53948c2ecf20Sopenharmony_ci
53958c2ecf20Sopenharmony_ci	/*
53968c2ecf20Sopenharmony_ci	 * Allocate and initialize cpu_affinity_set
53978c2ecf20Sopenharmony_ci	 */
53988c2ecf20Sopenharmony_ci	cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));
53998c2ecf20Sopenharmony_ci	if (cpu_affinity_set == NULL)
54008c2ecf20Sopenharmony_ci		err(3, "CPU_ALLOC");
54018c2ecf20Sopenharmony_ci	cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
54028c2ecf20Sopenharmony_ci	CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
54038c2ecf20Sopenharmony_ci
54048c2ecf20Sopenharmony_ci	for_all_proc_cpus(init_thread_id);
54058c2ecf20Sopenharmony_ci
54068c2ecf20Sopenharmony_ci	/*
54078c2ecf20Sopenharmony_ci	 * For online cpus
54088c2ecf20Sopenharmony_ci	 * find max_core_id, max_package_id
54098c2ecf20Sopenharmony_ci	 */
54108c2ecf20Sopenharmony_ci	for (i = 0; i <= topo.max_cpu_num; ++i) {
54118c2ecf20Sopenharmony_ci		int siblings;
54128c2ecf20Sopenharmony_ci
54138c2ecf20Sopenharmony_ci		if (cpu_is_not_present(i)) {
54148c2ecf20Sopenharmony_ci			if (debug > 1)
54158c2ecf20Sopenharmony_ci				fprintf(outf, "cpu%d NOT PRESENT\n", i);
54168c2ecf20Sopenharmony_ci			continue;
54178c2ecf20Sopenharmony_ci		}
54188c2ecf20Sopenharmony_ci
54198c2ecf20Sopenharmony_ci		cpus[i].logical_cpu_id = i;
54208c2ecf20Sopenharmony_ci
54218c2ecf20Sopenharmony_ci		/* get package information */
54228c2ecf20Sopenharmony_ci		cpus[i].physical_package_id = get_physical_package_id(i);
54238c2ecf20Sopenharmony_ci		if (cpus[i].physical_package_id > max_package_id)
54248c2ecf20Sopenharmony_ci			max_package_id = cpus[i].physical_package_id;
54258c2ecf20Sopenharmony_ci
54268c2ecf20Sopenharmony_ci		/* get die information */
54278c2ecf20Sopenharmony_ci		cpus[i].die_id = get_die_id(i);
54288c2ecf20Sopenharmony_ci		if (cpus[i].die_id > max_die_id)
54298c2ecf20Sopenharmony_ci			max_die_id = cpus[i].die_id;
54308c2ecf20Sopenharmony_ci
54318c2ecf20Sopenharmony_ci		/* get numa node information */
54328c2ecf20Sopenharmony_ci		cpus[i].physical_node_id = get_physical_node_id(&cpus[i]);
54338c2ecf20Sopenharmony_ci		if (cpus[i].physical_node_id > topo.max_node_num)
54348c2ecf20Sopenharmony_ci			topo.max_node_num = cpus[i].physical_node_id;
54358c2ecf20Sopenharmony_ci
54368c2ecf20Sopenharmony_ci		/* get core information */
54378c2ecf20Sopenharmony_ci		cpus[i].physical_core_id = get_core_id(i);
54388c2ecf20Sopenharmony_ci		if (cpus[i].physical_core_id > max_core_id)
54398c2ecf20Sopenharmony_ci			max_core_id = cpus[i].physical_core_id;
54408c2ecf20Sopenharmony_ci
54418c2ecf20Sopenharmony_ci		/* get thread information */
54428c2ecf20Sopenharmony_ci		siblings = get_thread_siblings(&cpus[i]);
54438c2ecf20Sopenharmony_ci		if (siblings > max_siblings)
54448c2ecf20Sopenharmony_ci			max_siblings = siblings;
54458c2ecf20Sopenharmony_ci		if (cpus[i].thread_id == 0)
54468c2ecf20Sopenharmony_ci			topo.num_cores++;
54478c2ecf20Sopenharmony_ci	}
54488c2ecf20Sopenharmony_ci
54498c2ecf20Sopenharmony_ci	topo.cores_per_node = max_core_id + 1;
54508c2ecf20Sopenharmony_ci	if (debug > 1)
54518c2ecf20Sopenharmony_ci		fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
54528c2ecf20Sopenharmony_ci			max_core_id, topo.cores_per_node);
54538c2ecf20Sopenharmony_ci	if (!summary_only && topo.cores_per_node > 1)
54548c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Core);
54558c2ecf20Sopenharmony_ci
54568c2ecf20Sopenharmony_ci	topo.num_die = max_die_id + 1;
54578c2ecf20Sopenharmony_ci	if (debug > 1)
54588c2ecf20Sopenharmony_ci		fprintf(outf, "max_die_id %d, sizing for %d die\n",
54598c2ecf20Sopenharmony_ci				max_die_id, topo.num_die);
54608c2ecf20Sopenharmony_ci	if (!summary_only && topo.num_die > 1)
54618c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Die);
54628c2ecf20Sopenharmony_ci
54638c2ecf20Sopenharmony_ci	topo.num_packages = max_package_id + 1;
54648c2ecf20Sopenharmony_ci	if (debug > 1)
54658c2ecf20Sopenharmony_ci		fprintf(outf, "max_package_id %d, sizing for %d packages\n",
54668c2ecf20Sopenharmony_ci			max_package_id, topo.num_packages);
54678c2ecf20Sopenharmony_ci	if (!summary_only && topo.num_packages > 1)
54688c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Package);
54698c2ecf20Sopenharmony_ci
54708c2ecf20Sopenharmony_ci	set_node_data();
54718c2ecf20Sopenharmony_ci	if (debug > 1)
54728c2ecf20Sopenharmony_ci		fprintf(outf, "nodes_per_pkg %d\n", topo.nodes_per_pkg);
54738c2ecf20Sopenharmony_ci	if (!summary_only && topo.nodes_per_pkg > 1)
54748c2ecf20Sopenharmony_ci		BIC_PRESENT(BIC_Node);
54758c2ecf20Sopenharmony_ci
54768c2ecf20Sopenharmony_ci	topo.threads_per_core = max_siblings;
54778c2ecf20Sopenharmony_ci	if (debug > 1)
54788c2ecf20Sopenharmony_ci		fprintf(outf, "max_siblings %d\n", max_siblings);
54798c2ecf20Sopenharmony_ci
54808c2ecf20Sopenharmony_ci	if (debug < 1)
54818c2ecf20Sopenharmony_ci		return;
54828c2ecf20Sopenharmony_ci
54838c2ecf20Sopenharmony_ci	for (i = 0; i <= topo.max_cpu_num; ++i) {
54848c2ecf20Sopenharmony_ci		if (cpu_is_not_present(i))
54858c2ecf20Sopenharmony_ci			continue;
54868c2ecf20Sopenharmony_ci		fprintf(outf,
54878c2ecf20Sopenharmony_ci			"cpu %d pkg %d die %d node %d lnode %d core %d thread %d\n",
54888c2ecf20Sopenharmony_ci			i, cpus[i].physical_package_id, cpus[i].die_id,
54898c2ecf20Sopenharmony_ci			cpus[i].physical_node_id,
54908c2ecf20Sopenharmony_ci			cpus[i].logical_node_id,
54918c2ecf20Sopenharmony_ci			cpus[i].physical_core_id,
54928c2ecf20Sopenharmony_ci			cpus[i].thread_id);
54938c2ecf20Sopenharmony_ci	}
54948c2ecf20Sopenharmony_ci
54958c2ecf20Sopenharmony_ci}
54968c2ecf20Sopenharmony_ci
54978c2ecf20Sopenharmony_civoid
54988c2ecf20Sopenharmony_ciallocate_counters(struct thread_data **t, struct core_data **c,
54998c2ecf20Sopenharmony_ci		  struct pkg_data **p)
55008c2ecf20Sopenharmony_ci{
55018c2ecf20Sopenharmony_ci	int i;
55028c2ecf20Sopenharmony_ci	int num_cores = topo.cores_per_node * topo.nodes_per_pkg *
55038c2ecf20Sopenharmony_ci			topo.num_packages;
55048c2ecf20Sopenharmony_ci	int num_threads = topo.threads_per_core * num_cores;
55058c2ecf20Sopenharmony_ci
55068c2ecf20Sopenharmony_ci	*t = calloc(num_threads, sizeof(struct thread_data));
55078c2ecf20Sopenharmony_ci	if (*t == NULL)
55088c2ecf20Sopenharmony_ci		goto error;
55098c2ecf20Sopenharmony_ci
55108c2ecf20Sopenharmony_ci	for (i = 0; i < num_threads; i++)
55118c2ecf20Sopenharmony_ci		(*t)[i].cpu_id = -1;
55128c2ecf20Sopenharmony_ci
55138c2ecf20Sopenharmony_ci	*c = calloc(num_cores, sizeof(struct core_data));
55148c2ecf20Sopenharmony_ci	if (*c == NULL)
55158c2ecf20Sopenharmony_ci		goto error;
55168c2ecf20Sopenharmony_ci
55178c2ecf20Sopenharmony_ci	for (i = 0; i < num_cores; i++)
55188c2ecf20Sopenharmony_ci		(*c)[i].core_id = -1;
55198c2ecf20Sopenharmony_ci
55208c2ecf20Sopenharmony_ci	*p = calloc(topo.num_packages, sizeof(struct pkg_data));
55218c2ecf20Sopenharmony_ci	if (*p == NULL)
55228c2ecf20Sopenharmony_ci		goto error;
55238c2ecf20Sopenharmony_ci
55248c2ecf20Sopenharmony_ci	for (i = 0; i < topo.num_packages; i++)
55258c2ecf20Sopenharmony_ci		(*p)[i].package_id = i;
55268c2ecf20Sopenharmony_ci
55278c2ecf20Sopenharmony_ci	return;
55288c2ecf20Sopenharmony_cierror:
55298c2ecf20Sopenharmony_ci	err(1, "calloc counters");
55308c2ecf20Sopenharmony_ci}
55318c2ecf20Sopenharmony_ci/*
55328c2ecf20Sopenharmony_ci * init_counter()
55338c2ecf20Sopenharmony_ci *
55348c2ecf20Sopenharmony_ci * set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE
55358c2ecf20Sopenharmony_ci */
55368c2ecf20Sopenharmony_civoid init_counter(struct thread_data *thread_base, struct core_data *core_base,
55378c2ecf20Sopenharmony_ci	struct pkg_data *pkg_base, int cpu_id)
55388c2ecf20Sopenharmony_ci{
55398c2ecf20Sopenharmony_ci	int pkg_id = cpus[cpu_id].physical_package_id;
55408c2ecf20Sopenharmony_ci	int node_id = cpus[cpu_id].logical_node_id;
55418c2ecf20Sopenharmony_ci	int core_id = cpus[cpu_id].physical_core_id;
55428c2ecf20Sopenharmony_ci	int thread_id = cpus[cpu_id].thread_id;
55438c2ecf20Sopenharmony_ci	struct thread_data *t;
55448c2ecf20Sopenharmony_ci	struct core_data *c;
55458c2ecf20Sopenharmony_ci	struct pkg_data *p;
55468c2ecf20Sopenharmony_ci
55478c2ecf20Sopenharmony_ci
55488c2ecf20Sopenharmony_ci	/* Workaround for systems where physical_node_id==-1
55498c2ecf20Sopenharmony_ci	 * and logical_node_id==(-1 - topo.num_cpus)
55508c2ecf20Sopenharmony_ci	 */
55518c2ecf20Sopenharmony_ci	if (node_id < 0)
55528c2ecf20Sopenharmony_ci		node_id = 0;
55538c2ecf20Sopenharmony_ci
55548c2ecf20Sopenharmony_ci	t = GET_THREAD(thread_base, thread_id, core_id, node_id, pkg_id);
55558c2ecf20Sopenharmony_ci	c = GET_CORE(core_base, core_id, node_id, pkg_id);
55568c2ecf20Sopenharmony_ci	p = GET_PKG(pkg_base, pkg_id);
55578c2ecf20Sopenharmony_ci
55588c2ecf20Sopenharmony_ci	t->cpu_id = cpu_id;
55598c2ecf20Sopenharmony_ci	if (thread_id == 0) {
55608c2ecf20Sopenharmony_ci		t->flags |= CPU_IS_FIRST_THREAD_IN_CORE;
55618c2ecf20Sopenharmony_ci		if (cpu_is_first_core_in_package(cpu_id))
55628c2ecf20Sopenharmony_ci			t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE;
55638c2ecf20Sopenharmony_ci	}
55648c2ecf20Sopenharmony_ci
55658c2ecf20Sopenharmony_ci	c->core_id = core_id;
55668c2ecf20Sopenharmony_ci	p->package_id = pkg_id;
55678c2ecf20Sopenharmony_ci}
55688c2ecf20Sopenharmony_ci
55698c2ecf20Sopenharmony_ci
55708c2ecf20Sopenharmony_ciint initialize_counters(int cpu_id)
55718c2ecf20Sopenharmony_ci{
55728c2ecf20Sopenharmony_ci	init_counter(EVEN_COUNTERS, cpu_id);
55738c2ecf20Sopenharmony_ci	init_counter(ODD_COUNTERS, cpu_id);
55748c2ecf20Sopenharmony_ci	return 0;
55758c2ecf20Sopenharmony_ci}
55768c2ecf20Sopenharmony_ci
55778c2ecf20Sopenharmony_civoid allocate_output_buffer()
55788c2ecf20Sopenharmony_ci{
55798c2ecf20Sopenharmony_ci	output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);
55808c2ecf20Sopenharmony_ci	outp = output_buffer;
55818c2ecf20Sopenharmony_ci	if (outp == NULL)
55828c2ecf20Sopenharmony_ci		err(-1, "calloc output buffer");
55838c2ecf20Sopenharmony_ci}
55848c2ecf20Sopenharmony_civoid allocate_fd_percpu(void)
55858c2ecf20Sopenharmony_ci{
55868c2ecf20Sopenharmony_ci	fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
55878c2ecf20Sopenharmony_ci	if (fd_percpu == NULL)
55888c2ecf20Sopenharmony_ci		err(-1, "calloc fd_percpu");
55898c2ecf20Sopenharmony_ci}
55908c2ecf20Sopenharmony_civoid allocate_irq_buffers(void)
55918c2ecf20Sopenharmony_ci{
55928c2ecf20Sopenharmony_ci	irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
55938c2ecf20Sopenharmony_ci	if (irq_column_2_cpu == NULL)
55948c2ecf20Sopenharmony_ci		err(-1, "calloc %d", topo.num_cpus);
55958c2ecf20Sopenharmony_ci
55968c2ecf20Sopenharmony_ci	irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int));
55978c2ecf20Sopenharmony_ci	if (irqs_per_cpu == NULL)
55988c2ecf20Sopenharmony_ci		err(-1, "calloc %d", topo.max_cpu_num + 1);
55998c2ecf20Sopenharmony_ci}
56008c2ecf20Sopenharmony_civoid setup_all_buffers(void)
56018c2ecf20Sopenharmony_ci{
56028c2ecf20Sopenharmony_ci	topology_probe();
56038c2ecf20Sopenharmony_ci	allocate_irq_buffers();
56048c2ecf20Sopenharmony_ci	allocate_fd_percpu();
56058c2ecf20Sopenharmony_ci	allocate_counters(&thread_even, &core_even, &package_even);
56068c2ecf20Sopenharmony_ci	allocate_counters(&thread_odd, &core_odd, &package_odd);
56078c2ecf20Sopenharmony_ci	allocate_output_buffer();
56088c2ecf20Sopenharmony_ci	for_all_proc_cpus(initialize_counters);
56098c2ecf20Sopenharmony_ci}
56108c2ecf20Sopenharmony_ci
56118c2ecf20Sopenharmony_civoid set_base_cpu(void)
56128c2ecf20Sopenharmony_ci{
56138c2ecf20Sopenharmony_ci	base_cpu = sched_getcpu();
56148c2ecf20Sopenharmony_ci	if (base_cpu < 0)
56158c2ecf20Sopenharmony_ci		err(-ENODEV, "No valid cpus found");
56168c2ecf20Sopenharmony_ci
56178c2ecf20Sopenharmony_ci	if (debug > 1)
56188c2ecf20Sopenharmony_ci		fprintf(outf, "base_cpu = %d\n", base_cpu);
56198c2ecf20Sopenharmony_ci}
56208c2ecf20Sopenharmony_ci
56218c2ecf20Sopenharmony_civoid turbostat_init()
56228c2ecf20Sopenharmony_ci{
56238c2ecf20Sopenharmony_ci	setup_all_buffers();
56248c2ecf20Sopenharmony_ci	set_base_cpu();
56258c2ecf20Sopenharmony_ci	check_dev_msr();
56268c2ecf20Sopenharmony_ci	check_permissions();
56278c2ecf20Sopenharmony_ci	process_cpuid();
56288c2ecf20Sopenharmony_ci
56298c2ecf20Sopenharmony_ci
56308c2ecf20Sopenharmony_ci	if (!quiet)
56318c2ecf20Sopenharmony_ci		for_all_cpus(print_hwp, ODD_COUNTERS);
56328c2ecf20Sopenharmony_ci
56338c2ecf20Sopenharmony_ci	if (!quiet)
56348c2ecf20Sopenharmony_ci		for_all_cpus(print_epb, ODD_COUNTERS);
56358c2ecf20Sopenharmony_ci
56368c2ecf20Sopenharmony_ci	if (!quiet)
56378c2ecf20Sopenharmony_ci		for_all_cpus(print_perf_limit, ODD_COUNTERS);
56388c2ecf20Sopenharmony_ci
56398c2ecf20Sopenharmony_ci	if (!quiet)
56408c2ecf20Sopenharmony_ci		for_all_cpus(print_rapl, ODD_COUNTERS);
56418c2ecf20Sopenharmony_ci
56428c2ecf20Sopenharmony_ci	for_all_cpus(set_temperature_target, ODD_COUNTERS);
56438c2ecf20Sopenharmony_ci
56448c2ecf20Sopenharmony_ci	if (!quiet)
56458c2ecf20Sopenharmony_ci		for_all_cpus(print_thermal, ODD_COUNTERS);
56468c2ecf20Sopenharmony_ci
56478c2ecf20Sopenharmony_ci	if (!quiet && do_irtl_snb)
56488c2ecf20Sopenharmony_ci		print_irtl();
56498c2ecf20Sopenharmony_ci}
56508c2ecf20Sopenharmony_ci
56518c2ecf20Sopenharmony_ciint fork_it(char **argv)
56528c2ecf20Sopenharmony_ci{
56538c2ecf20Sopenharmony_ci	pid_t child_pid;
56548c2ecf20Sopenharmony_ci	int status;
56558c2ecf20Sopenharmony_ci
56568c2ecf20Sopenharmony_ci	snapshot_proc_sysfs_files();
56578c2ecf20Sopenharmony_ci	status = for_all_cpus(get_counters, EVEN_COUNTERS);
56588c2ecf20Sopenharmony_ci	first_counter_read = 0;
56598c2ecf20Sopenharmony_ci	if (status)
56608c2ecf20Sopenharmony_ci		exit(status);
56618c2ecf20Sopenharmony_ci	/* clear affinity side-effect of get_counters() */
56628c2ecf20Sopenharmony_ci	sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
56638c2ecf20Sopenharmony_ci	gettimeofday(&tv_even, (struct timezone *)NULL);
56648c2ecf20Sopenharmony_ci
56658c2ecf20Sopenharmony_ci	child_pid = fork();
56668c2ecf20Sopenharmony_ci	if (!child_pid) {
56678c2ecf20Sopenharmony_ci		/* child */
56688c2ecf20Sopenharmony_ci		execvp(argv[0], argv);
56698c2ecf20Sopenharmony_ci		err(errno, "exec %s", argv[0]);
56708c2ecf20Sopenharmony_ci	} else {
56718c2ecf20Sopenharmony_ci
56728c2ecf20Sopenharmony_ci		/* parent */
56738c2ecf20Sopenharmony_ci		if (child_pid == -1)
56748c2ecf20Sopenharmony_ci			err(1, "fork");
56758c2ecf20Sopenharmony_ci
56768c2ecf20Sopenharmony_ci		signal(SIGINT, SIG_IGN);
56778c2ecf20Sopenharmony_ci		signal(SIGQUIT, SIG_IGN);
56788c2ecf20Sopenharmony_ci		if (waitpid(child_pid, &status, 0) == -1)
56798c2ecf20Sopenharmony_ci			err(status, "waitpid");
56808c2ecf20Sopenharmony_ci
56818c2ecf20Sopenharmony_ci		if (WIFEXITED(status))
56828c2ecf20Sopenharmony_ci			status = WEXITSTATUS(status);
56838c2ecf20Sopenharmony_ci	}
56848c2ecf20Sopenharmony_ci	/*
56858c2ecf20Sopenharmony_ci	 * n.b. fork_it() does not check for errors from for_all_cpus()
56868c2ecf20Sopenharmony_ci	 * because re-starting is problematic when forking
56878c2ecf20Sopenharmony_ci	 */
56888c2ecf20Sopenharmony_ci	snapshot_proc_sysfs_files();
56898c2ecf20Sopenharmony_ci	for_all_cpus(get_counters, ODD_COUNTERS);
56908c2ecf20Sopenharmony_ci	gettimeofday(&tv_odd, (struct timezone *)NULL);
56918c2ecf20Sopenharmony_ci	timersub(&tv_odd, &tv_even, &tv_delta);
56928c2ecf20Sopenharmony_ci	if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS))
56938c2ecf20Sopenharmony_ci		fprintf(outf, "%s: Counter reset detected\n", progname);
56948c2ecf20Sopenharmony_ci	else {
56958c2ecf20Sopenharmony_ci		compute_average(EVEN_COUNTERS);
56968c2ecf20Sopenharmony_ci		format_all_counters(EVEN_COUNTERS);
56978c2ecf20Sopenharmony_ci	}
56988c2ecf20Sopenharmony_ci
56998c2ecf20Sopenharmony_ci	fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
57008c2ecf20Sopenharmony_ci
57018c2ecf20Sopenharmony_ci	flush_output_stderr();
57028c2ecf20Sopenharmony_ci
57038c2ecf20Sopenharmony_ci	return status;
57048c2ecf20Sopenharmony_ci}
57058c2ecf20Sopenharmony_ci
57068c2ecf20Sopenharmony_ciint get_and_dump_counters(void)
57078c2ecf20Sopenharmony_ci{
57088c2ecf20Sopenharmony_ci	int status;
57098c2ecf20Sopenharmony_ci
57108c2ecf20Sopenharmony_ci	snapshot_proc_sysfs_files();
57118c2ecf20Sopenharmony_ci	status = for_all_cpus(get_counters, ODD_COUNTERS);
57128c2ecf20Sopenharmony_ci	if (status)
57138c2ecf20Sopenharmony_ci		return status;
57148c2ecf20Sopenharmony_ci
57158c2ecf20Sopenharmony_ci	status = for_all_cpus(dump_counters, ODD_COUNTERS);
57168c2ecf20Sopenharmony_ci	if (status)
57178c2ecf20Sopenharmony_ci		return status;
57188c2ecf20Sopenharmony_ci
57198c2ecf20Sopenharmony_ci	flush_output_stdout();
57208c2ecf20Sopenharmony_ci
57218c2ecf20Sopenharmony_ci	return status;
57228c2ecf20Sopenharmony_ci}
57238c2ecf20Sopenharmony_ci
57248c2ecf20Sopenharmony_civoid print_version() {
57258c2ecf20Sopenharmony_ci	fprintf(outf, "turbostat version 20.09.30"
57268c2ecf20Sopenharmony_ci		" - Len Brown <lenb@kernel.org>\n");
57278c2ecf20Sopenharmony_ci}
57288c2ecf20Sopenharmony_ci
57298c2ecf20Sopenharmony_ciint add_counter(unsigned int msr_num, char *path, char *name,
57308c2ecf20Sopenharmony_ci	unsigned int width, enum counter_scope scope,
57318c2ecf20Sopenharmony_ci	enum counter_type type, enum counter_format format, int flags)
57328c2ecf20Sopenharmony_ci{
57338c2ecf20Sopenharmony_ci	struct msr_counter *msrp;
57348c2ecf20Sopenharmony_ci
57358c2ecf20Sopenharmony_ci	msrp = calloc(1, sizeof(struct msr_counter));
57368c2ecf20Sopenharmony_ci	if (msrp == NULL) {
57378c2ecf20Sopenharmony_ci		perror("calloc");
57388c2ecf20Sopenharmony_ci		exit(1);
57398c2ecf20Sopenharmony_ci	}
57408c2ecf20Sopenharmony_ci
57418c2ecf20Sopenharmony_ci	msrp->msr_num = msr_num;
57428c2ecf20Sopenharmony_ci	strncpy(msrp->name, name, NAME_BYTES - 1);
57438c2ecf20Sopenharmony_ci	if (path)
57448c2ecf20Sopenharmony_ci		strncpy(msrp->path, path, PATH_BYTES - 1);
57458c2ecf20Sopenharmony_ci	msrp->width = width;
57468c2ecf20Sopenharmony_ci	msrp->type = type;
57478c2ecf20Sopenharmony_ci	msrp->format = format;
57488c2ecf20Sopenharmony_ci	msrp->flags = flags;
57498c2ecf20Sopenharmony_ci
57508c2ecf20Sopenharmony_ci	switch (scope) {
57518c2ecf20Sopenharmony_ci
57528c2ecf20Sopenharmony_ci	case SCOPE_CPU:
57538c2ecf20Sopenharmony_ci		msrp->next = sys.tp;
57548c2ecf20Sopenharmony_ci		sys.tp = msrp;
57558c2ecf20Sopenharmony_ci		sys.added_thread_counters++;
57568c2ecf20Sopenharmony_ci		if (sys.added_thread_counters > MAX_ADDED_THREAD_COUNTERS) {
57578c2ecf20Sopenharmony_ci			fprintf(stderr, "exceeded max %d added thread counters\n",
57588c2ecf20Sopenharmony_ci				MAX_ADDED_COUNTERS);
57598c2ecf20Sopenharmony_ci			exit(-1);
57608c2ecf20Sopenharmony_ci		}
57618c2ecf20Sopenharmony_ci		break;
57628c2ecf20Sopenharmony_ci
57638c2ecf20Sopenharmony_ci	case SCOPE_CORE:
57648c2ecf20Sopenharmony_ci		msrp->next = sys.cp;
57658c2ecf20Sopenharmony_ci		sys.cp = msrp;
57668c2ecf20Sopenharmony_ci		sys.added_core_counters++;
57678c2ecf20Sopenharmony_ci		if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
57688c2ecf20Sopenharmony_ci			fprintf(stderr, "exceeded max %d added core counters\n",
57698c2ecf20Sopenharmony_ci				MAX_ADDED_COUNTERS);
57708c2ecf20Sopenharmony_ci			exit(-1);
57718c2ecf20Sopenharmony_ci		}
57728c2ecf20Sopenharmony_ci		break;
57738c2ecf20Sopenharmony_ci
57748c2ecf20Sopenharmony_ci	case SCOPE_PACKAGE:
57758c2ecf20Sopenharmony_ci		msrp->next = sys.pp;
57768c2ecf20Sopenharmony_ci		sys.pp = msrp;
57778c2ecf20Sopenharmony_ci		sys.added_package_counters++;
57788c2ecf20Sopenharmony_ci		if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
57798c2ecf20Sopenharmony_ci			fprintf(stderr, "exceeded max %d added package counters\n",
57808c2ecf20Sopenharmony_ci				MAX_ADDED_COUNTERS);
57818c2ecf20Sopenharmony_ci			exit(-1);
57828c2ecf20Sopenharmony_ci		}
57838c2ecf20Sopenharmony_ci		break;
57848c2ecf20Sopenharmony_ci	}
57858c2ecf20Sopenharmony_ci
57868c2ecf20Sopenharmony_ci	return 0;
57878c2ecf20Sopenharmony_ci}
57888c2ecf20Sopenharmony_ci
57898c2ecf20Sopenharmony_civoid parse_add_command(char *add_command)
57908c2ecf20Sopenharmony_ci{
57918c2ecf20Sopenharmony_ci	int msr_num = 0;
57928c2ecf20Sopenharmony_ci	char *path = NULL;
57938c2ecf20Sopenharmony_ci	char name_buffer[NAME_BYTES] = "";
57948c2ecf20Sopenharmony_ci	int width = 64;
57958c2ecf20Sopenharmony_ci	int fail = 0;
57968c2ecf20Sopenharmony_ci	enum counter_scope scope = SCOPE_CPU;
57978c2ecf20Sopenharmony_ci	enum counter_type type = COUNTER_CYCLES;
57988c2ecf20Sopenharmony_ci	enum counter_format format = FORMAT_DELTA;
57998c2ecf20Sopenharmony_ci
58008c2ecf20Sopenharmony_ci	while (add_command) {
58018c2ecf20Sopenharmony_ci
58028c2ecf20Sopenharmony_ci		if (sscanf(add_command, "msr0x%x", &msr_num) == 1)
58038c2ecf20Sopenharmony_ci			goto next;
58048c2ecf20Sopenharmony_ci
58058c2ecf20Sopenharmony_ci		if (sscanf(add_command, "msr%d", &msr_num) == 1)
58068c2ecf20Sopenharmony_ci			goto next;
58078c2ecf20Sopenharmony_ci
58088c2ecf20Sopenharmony_ci		if (*add_command == '/') {
58098c2ecf20Sopenharmony_ci			path = add_command;
58108c2ecf20Sopenharmony_ci			goto next;
58118c2ecf20Sopenharmony_ci		}
58128c2ecf20Sopenharmony_ci
58138c2ecf20Sopenharmony_ci		if (sscanf(add_command, "u%d", &width) == 1) {
58148c2ecf20Sopenharmony_ci			if ((width == 32) || (width == 64))
58158c2ecf20Sopenharmony_ci				goto next;
58168c2ecf20Sopenharmony_ci			width = 64;
58178c2ecf20Sopenharmony_ci		}
58188c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "cpu", strlen("cpu"))) {
58198c2ecf20Sopenharmony_ci			scope = SCOPE_CPU;
58208c2ecf20Sopenharmony_ci			goto next;
58218c2ecf20Sopenharmony_ci		}
58228c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "core", strlen("core"))) {
58238c2ecf20Sopenharmony_ci			scope = SCOPE_CORE;
58248c2ecf20Sopenharmony_ci			goto next;
58258c2ecf20Sopenharmony_ci		}
58268c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "package", strlen("package"))) {
58278c2ecf20Sopenharmony_ci			scope = SCOPE_PACKAGE;
58288c2ecf20Sopenharmony_ci			goto next;
58298c2ecf20Sopenharmony_ci		}
58308c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "cycles", strlen("cycles"))) {
58318c2ecf20Sopenharmony_ci			type = COUNTER_CYCLES;
58328c2ecf20Sopenharmony_ci			goto next;
58338c2ecf20Sopenharmony_ci		}
58348c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "seconds", strlen("seconds"))) {
58358c2ecf20Sopenharmony_ci			type = COUNTER_SECONDS;
58368c2ecf20Sopenharmony_ci			goto next;
58378c2ecf20Sopenharmony_ci		}
58388c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "usec", strlen("usec"))) {
58398c2ecf20Sopenharmony_ci			type = COUNTER_USEC;
58408c2ecf20Sopenharmony_ci			goto next;
58418c2ecf20Sopenharmony_ci		}
58428c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "raw", strlen("raw"))) {
58438c2ecf20Sopenharmony_ci			format = FORMAT_RAW;
58448c2ecf20Sopenharmony_ci			goto next;
58458c2ecf20Sopenharmony_ci		}
58468c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "delta", strlen("delta"))) {
58478c2ecf20Sopenharmony_ci			format = FORMAT_DELTA;
58488c2ecf20Sopenharmony_ci			goto next;
58498c2ecf20Sopenharmony_ci		}
58508c2ecf20Sopenharmony_ci		if (!strncmp(add_command, "percent", strlen("percent"))) {
58518c2ecf20Sopenharmony_ci			format = FORMAT_PERCENT;
58528c2ecf20Sopenharmony_ci			goto next;
58538c2ecf20Sopenharmony_ci		}
58548c2ecf20Sopenharmony_ci
58558c2ecf20Sopenharmony_ci		if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) {	/* 18 < NAME_BYTES */
58568c2ecf20Sopenharmony_ci			char *eos;
58578c2ecf20Sopenharmony_ci
58588c2ecf20Sopenharmony_ci			eos = strchr(name_buffer, ',');
58598c2ecf20Sopenharmony_ci			if (eos)
58608c2ecf20Sopenharmony_ci				*eos = '\0';
58618c2ecf20Sopenharmony_ci			goto next;
58628c2ecf20Sopenharmony_ci		}
58638c2ecf20Sopenharmony_ci
58648c2ecf20Sopenharmony_cinext:
58658c2ecf20Sopenharmony_ci		add_command = strchr(add_command, ',');
58668c2ecf20Sopenharmony_ci		if (add_command) {
58678c2ecf20Sopenharmony_ci			*add_command = '\0';
58688c2ecf20Sopenharmony_ci			add_command++;
58698c2ecf20Sopenharmony_ci		}
58708c2ecf20Sopenharmony_ci
58718c2ecf20Sopenharmony_ci	}
58728c2ecf20Sopenharmony_ci	if ((msr_num == 0) && (path == NULL)) {
58738c2ecf20Sopenharmony_ci		fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter ) required\n");
58748c2ecf20Sopenharmony_ci		fail++;
58758c2ecf20Sopenharmony_ci	}
58768c2ecf20Sopenharmony_ci
58778c2ecf20Sopenharmony_ci	/* generate default column header */
58788c2ecf20Sopenharmony_ci	if (*name_buffer == '\0') {
58798c2ecf20Sopenharmony_ci		if (width == 32)
58808c2ecf20Sopenharmony_ci			sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
58818c2ecf20Sopenharmony_ci		else
58828c2ecf20Sopenharmony_ci			sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");
58838c2ecf20Sopenharmony_ci	}
58848c2ecf20Sopenharmony_ci
58858c2ecf20Sopenharmony_ci	if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0))
58868c2ecf20Sopenharmony_ci		fail++;
58878c2ecf20Sopenharmony_ci
58888c2ecf20Sopenharmony_ci	if (fail) {
58898c2ecf20Sopenharmony_ci		help();
58908c2ecf20Sopenharmony_ci		exit(1);
58918c2ecf20Sopenharmony_ci	}
58928c2ecf20Sopenharmony_ci}
58938c2ecf20Sopenharmony_ci
58948c2ecf20Sopenharmony_ciint is_deferred_skip(char *name)
58958c2ecf20Sopenharmony_ci{
58968c2ecf20Sopenharmony_ci	int i;
58978c2ecf20Sopenharmony_ci
58988c2ecf20Sopenharmony_ci	for (i = 0; i < deferred_skip_index; ++i)
58998c2ecf20Sopenharmony_ci		if (!strcmp(name, deferred_skip_names[i]))
59008c2ecf20Sopenharmony_ci			return 1;
59018c2ecf20Sopenharmony_ci	return 0;
59028c2ecf20Sopenharmony_ci}
59038c2ecf20Sopenharmony_ci
59048c2ecf20Sopenharmony_civoid probe_sysfs(void)
59058c2ecf20Sopenharmony_ci{
59068c2ecf20Sopenharmony_ci	char path[64];
59078c2ecf20Sopenharmony_ci	char name_buf[16];
59088c2ecf20Sopenharmony_ci	FILE *input;
59098c2ecf20Sopenharmony_ci	int state;
59108c2ecf20Sopenharmony_ci	char *sp;
59118c2ecf20Sopenharmony_ci
59128c2ecf20Sopenharmony_ci	if (!DO_BIC(BIC_sysfs))
59138c2ecf20Sopenharmony_ci		return;
59148c2ecf20Sopenharmony_ci
59158c2ecf20Sopenharmony_ci	for (state = 10; state >= 0; --state) {
59168c2ecf20Sopenharmony_ci
59178c2ecf20Sopenharmony_ci		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
59188c2ecf20Sopenharmony_ci			base_cpu, state);
59198c2ecf20Sopenharmony_ci		input = fopen(path, "r");
59208c2ecf20Sopenharmony_ci		if (input == NULL)
59218c2ecf20Sopenharmony_ci			continue;
59228c2ecf20Sopenharmony_ci		if (!fgets(name_buf, sizeof(name_buf), input))
59238c2ecf20Sopenharmony_ci			err(1, "%s: failed to read file", path);
59248c2ecf20Sopenharmony_ci
59258c2ecf20Sopenharmony_ci		 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
59268c2ecf20Sopenharmony_ci		sp = strchr(name_buf, '-');
59278c2ecf20Sopenharmony_ci		if (!sp)
59288c2ecf20Sopenharmony_ci			sp = strchrnul(name_buf, '\n');
59298c2ecf20Sopenharmony_ci		*sp = '%';
59308c2ecf20Sopenharmony_ci		*(sp + 1) = '\0';
59318c2ecf20Sopenharmony_ci
59328c2ecf20Sopenharmony_ci		remove_underbar(name_buf);
59338c2ecf20Sopenharmony_ci
59348c2ecf20Sopenharmony_ci		fclose(input);
59358c2ecf20Sopenharmony_ci
59368c2ecf20Sopenharmony_ci		sprintf(path, "cpuidle/state%d/time", state);
59378c2ecf20Sopenharmony_ci
59388c2ecf20Sopenharmony_ci		if (is_deferred_skip(name_buf))
59398c2ecf20Sopenharmony_ci			continue;
59408c2ecf20Sopenharmony_ci
59418c2ecf20Sopenharmony_ci		add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC,
59428c2ecf20Sopenharmony_ci				FORMAT_PERCENT, SYSFS_PERCPU);
59438c2ecf20Sopenharmony_ci	}
59448c2ecf20Sopenharmony_ci
59458c2ecf20Sopenharmony_ci	for (state = 10; state >= 0; --state) {
59468c2ecf20Sopenharmony_ci
59478c2ecf20Sopenharmony_ci		sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
59488c2ecf20Sopenharmony_ci			base_cpu, state);
59498c2ecf20Sopenharmony_ci		input = fopen(path, "r");
59508c2ecf20Sopenharmony_ci		if (input == NULL)
59518c2ecf20Sopenharmony_ci			continue;
59528c2ecf20Sopenharmony_ci		if (!fgets(name_buf, sizeof(name_buf), input))
59538c2ecf20Sopenharmony_ci			err(1, "%s: failed to read file", path);
59548c2ecf20Sopenharmony_ci		 /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
59558c2ecf20Sopenharmony_ci		sp = strchr(name_buf, '-');
59568c2ecf20Sopenharmony_ci		if (!sp)
59578c2ecf20Sopenharmony_ci			sp = strchrnul(name_buf, '\n');
59588c2ecf20Sopenharmony_ci		*sp = '\0';
59598c2ecf20Sopenharmony_ci		fclose(input);
59608c2ecf20Sopenharmony_ci
59618c2ecf20Sopenharmony_ci		remove_underbar(name_buf);
59628c2ecf20Sopenharmony_ci
59638c2ecf20Sopenharmony_ci		sprintf(path, "cpuidle/state%d/usage", state);
59648c2ecf20Sopenharmony_ci
59658c2ecf20Sopenharmony_ci		if (is_deferred_skip(name_buf))
59668c2ecf20Sopenharmony_ci			continue;
59678c2ecf20Sopenharmony_ci
59688c2ecf20Sopenharmony_ci		add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS,
59698c2ecf20Sopenharmony_ci				FORMAT_DELTA, SYSFS_PERCPU);
59708c2ecf20Sopenharmony_ci	}
59718c2ecf20Sopenharmony_ci
59728c2ecf20Sopenharmony_ci}
59738c2ecf20Sopenharmony_ci
59748c2ecf20Sopenharmony_ci
59758c2ecf20Sopenharmony_ci/*
59768c2ecf20Sopenharmony_ci * parse cpuset with following syntax
59778c2ecf20Sopenharmony_ci * 1,2,4..6,8-10 and set bits in cpu_subset
59788c2ecf20Sopenharmony_ci */
59798c2ecf20Sopenharmony_civoid parse_cpu_command(char *optarg)
59808c2ecf20Sopenharmony_ci{
59818c2ecf20Sopenharmony_ci	unsigned int start, end;
59828c2ecf20Sopenharmony_ci	char *next;
59838c2ecf20Sopenharmony_ci
59848c2ecf20Sopenharmony_ci	if (!strcmp(optarg, "core")) {
59858c2ecf20Sopenharmony_ci		if (cpu_subset)
59868c2ecf20Sopenharmony_ci			goto error;
59878c2ecf20Sopenharmony_ci		show_core_only++;
59888c2ecf20Sopenharmony_ci		return;
59898c2ecf20Sopenharmony_ci	}
59908c2ecf20Sopenharmony_ci	if (!strcmp(optarg, "package")) {
59918c2ecf20Sopenharmony_ci		if (cpu_subset)
59928c2ecf20Sopenharmony_ci			goto error;
59938c2ecf20Sopenharmony_ci		show_pkg_only++;
59948c2ecf20Sopenharmony_ci		return;
59958c2ecf20Sopenharmony_ci	}
59968c2ecf20Sopenharmony_ci	if (show_core_only || show_pkg_only)
59978c2ecf20Sopenharmony_ci		goto error;
59988c2ecf20Sopenharmony_ci
59998c2ecf20Sopenharmony_ci	cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);
60008c2ecf20Sopenharmony_ci	if (cpu_subset == NULL)
60018c2ecf20Sopenharmony_ci		err(3, "CPU_ALLOC");
60028c2ecf20Sopenharmony_ci	cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);
60038c2ecf20Sopenharmony_ci
60048c2ecf20Sopenharmony_ci	CPU_ZERO_S(cpu_subset_size, cpu_subset);
60058c2ecf20Sopenharmony_ci
60068c2ecf20Sopenharmony_ci	next = optarg;
60078c2ecf20Sopenharmony_ci
60088c2ecf20Sopenharmony_ci	while (next && *next) {
60098c2ecf20Sopenharmony_ci
60108c2ecf20Sopenharmony_ci		if (*next == '-')	/* no negative cpu numbers */
60118c2ecf20Sopenharmony_ci			goto error;
60128c2ecf20Sopenharmony_ci
60138c2ecf20Sopenharmony_ci		start = strtoul(next, &next, 10);
60148c2ecf20Sopenharmony_ci
60158c2ecf20Sopenharmony_ci		if (start >= CPU_SUBSET_MAXCPUS)
60168c2ecf20Sopenharmony_ci			goto error;
60178c2ecf20Sopenharmony_ci		CPU_SET_S(start, cpu_subset_size, cpu_subset);
60188c2ecf20Sopenharmony_ci
60198c2ecf20Sopenharmony_ci		if (*next == '\0')
60208c2ecf20Sopenharmony_ci			break;
60218c2ecf20Sopenharmony_ci
60228c2ecf20Sopenharmony_ci		if (*next == ',') {
60238c2ecf20Sopenharmony_ci			next += 1;
60248c2ecf20Sopenharmony_ci			continue;
60258c2ecf20Sopenharmony_ci		}
60268c2ecf20Sopenharmony_ci
60278c2ecf20Sopenharmony_ci		if (*next == '-') {
60288c2ecf20Sopenharmony_ci			next += 1;	/* start range */
60298c2ecf20Sopenharmony_ci		} else if (*next == '.') {
60308c2ecf20Sopenharmony_ci			next += 1;
60318c2ecf20Sopenharmony_ci			if (*next == '.')
60328c2ecf20Sopenharmony_ci				next += 1;	/* start range */
60338c2ecf20Sopenharmony_ci			else
60348c2ecf20Sopenharmony_ci				goto error;
60358c2ecf20Sopenharmony_ci		}
60368c2ecf20Sopenharmony_ci
60378c2ecf20Sopenharmony_ci		end = strtoul(next, &next, 10);
60388c2ecf20Sopenharmony_ci		if (end <= start)
60398c2ecf20Sopenharmony_ci			goto error;
60408c2ecf20Sopenharmony_ci
60418c2ecf20Sopenharmony_ci		while (++start <= end) {
60428c2ecf20Sopenharmony_ci			if (start >= CPU_SUBSET_MAXCPUS)
60438c2ecf20Sopenharmony_ci				goto error;
60448c2ecf20Sopenharmony_ci			CPU_SET_S(start, cpu_subset_size, cpu_subset);
60458c2ecf20Sopenharmony_ci		}
60468c2ecf20Sopenharmony_ci
60478c2ecf20Sopenharmony_ci		if (*next == ',')
60488c2ecf20Sopenharmony_ci			next += 1;
60498c2ecf20Sopenharmony_ci		else if (*next != '\0')
60508c2ecf20Sopenharmony_ci			goto error;
60518c2ecf20Sopenharmony_ci	}
60528c2ecf20Sopenharmony_ci
60538c2ecf20Sopenharmony_ci	return;
60548c2ecf20Sopenharmony_ci
60558c2ecf20Sopenharmony_cierror:
60568c2ecf20Sopenharmony_ci	fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
60578c2ecf20Sopenharmony_ci	help();
60588c2ecf20Sopenharmony_ci	exit(-1);
60598c2ecf20Sopenharmony_ci}
60608c2ecf20Sopenharmony_ci
60618c2ecf20Sopenharmony_ci
60628c2ecf20Sopenharmony_civoid cmdline(int argc, char **argv)
60638c2ecf20Sopenharmony_ci{
60648c2ecf20Sopenharmony_ci	int opt;
60658c2ecf20Sopenharmony_ci	int option_index = 0;
60668c2ecf20Sopenharmony_ci	static struct option long_options[] = {
60678c2ecf20Sopenharmony_ci		{"add",		required_argument,	0, 'a'},
60688c2ecf20Sopenharmony_ci		{"cpu",		required_argument,	0, 'c'},
60698c2ecf20Sopenharmony_ci		{"Dump",	no_argument,		0, 'D'},
60708c2ecf20Sopenharmony_ci		{"debug",	no_argument,		0, 'd'},	/* internal, not documented */
60718c2ecf20Sopenharmony_ci		{"enable",	required_argument,	0, 'e'},
60728c2ecf20Sopenharmony_ci		{"interval",	required_argument,	0, 'i'},
60738c2ecf20Sopenharmony_ci		{"num_iterations",	required_argument,	0, 'n'},
60748c2ecf20Sopenharmony_ci		{"help",	no_argument,		0, 'h'},
60758c2ecf20Sopenharmony_ci		{"hide",	required_argument,	0, 'H'},	// meh, -h taken by --help
60768c2ecf20Sopenharmony_ci		{"Joules",	no_argument,		0, 'J'},
60778c2ecf20Sopenharmony_ci		{"list",	no_argument,		0, 'l'},
60788c2ecf20Sopenharmony_ci		{"out",		required_argument,	0, 'o'},
60798c2ecf20Sopenharmony_ci		{"quiet",	no_argument,		0, 'q'},
60808c2ecf20Sopenharmony_ci		{"show",	required_argument,	0, 's'},
60818c2ecf20Sopenharmony_ci		{"Summary",	no_argument,		0, 'S'},
60828c2ecf20Sopenharmony_ci		{"TCC",		required_argument,	0, 'T'},
60838c2ecf20Sopenharmony_ci		{"version",	no_argument,		0, 'v' },
60848c2ecf20Sopenharmony_ci		{0,		0,			0,  0 }
60858c2ecf20Sopenharmony_ci	};
60868c2ecf20Sopenharmony_ci
60878c2ecf20Sopenharmony_ci	progname = argv[0];
60888c2ecf20Sopenharmony_ci
60898c2ecf20Sopenharmony_ci	while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qST:v",
60908c2ecf20Sopenharmony_ci				long_options, &option_index)) != -1) {
60918c2ecf20Sopenharmony_ci		switch (opt) {
60928c2ecf20Sopenharmony_ci		case 'a':
60938c2ecf20Sopenharmony_ci			parse_add_command(optarg);
60948c2ecf20Sopenharmony_ci			break;
60958c2ecf20Sopenharmony_ci		case 'c':
60968c2ecf20Sopenharmony_ci			parse_cpu_command(optarg);
60978c2ecf20Sopenharmony_ci			break;
60988c2ecf20Sopenharmony_ci		case 'D':
60998c2ecf20Sopenharmony_ci			dump_only++;
61008c2ecf20Sopenharmony_ci			break;
61018c2ecf20Sopenharmony_ci		case 'e':
61028c2ecf20Sopenharmony_ci			/* --enable specified counter */
61038c2ecf20Sopenharmony_ci			bic_enabled = bic_enabled | bic_lookup(optarg, SHOW_LIST);
61048c2ecf20Sopenharmony_ci			break;
61058c2ecf20Sopenharmony_ci		case 'd':
61068c2ecf20Sopenharmony_ci			debug++;
61078c2ecf20Sopenharmony_ci			ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);
61088c2ecf20Sopenharmony_ci			break;
61098c2ecf20Sopenharmony_ci		case 'H':
61108c2ecf20Sopenharmony_ci			/*
61118c2ecf20Sopenharmony_ci			 * --hide: do not show those specified
61128c2ecf20Sopenharmony_ci			 *  multiple invocations simply clear more bits in enabled mask
61138c2ecf20Sopenharmony_ci			 */
61148c2ecf20Sopenharmony_ci			bic_enabled &= ~bic_lookup(optarg, HIDE_LIST);
61158c2ecf20Sopenharmony_ci			break;
61168c2ecf20Sopenharmony_ci		case 'h':
61178c2ecf20Sopenharmony_ci		default:
61188c2ecf20Sopenharmony_ci			help();
61198c2ecf20Sopenharmony_ci			exit(1);
61208c2ecf20Sopenharmony_ci		case 'i':
61218c2ecf20Sopenharmony_ci			{
61228c2ecf20Sopenharmony_ci				double interval = strtod(optarg, NULL);
61238c2ecf20Sopenharmony_ci
61248c2ecf20Sopenharmony_ci				if (interval < 0.001) {
61258c2ecf20Sopenharmony_ci					fprintf(outf, "interval %f seconds is too small\n",
61268c2ecf20Sopenharmony_ci						interval);
61278c2ecf20Sopenharmony_ci					exit(2);
61288c2ecf20Sopenharmony_ci				}
61298c2ecf20Sopenharmony_ci
61308c2ecf20Sopenharmony_ci				interval_tv.tv_sec = interval_ts.tv_sec = interval;
61318c2ecf20Sopenharmony_ci				interval_tv.tv_usec = (interval - interval_tv.tv_sec) * 1000000;
61328c2ecf20Sopenharmony_ci				interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000;
61338c2ecf20Sopenharmony_ci			}
61348c2ecf20Sopenharmony_ci			break;
61358c2ecf20Sopenharmony_ci		case 'J':
61368c2ecf20Sopenharmony_ci			rapl_joules++;
61378c2ecf20Sopenharmony_ci			break;
61388c2ecf20Sopenharmony_ci		case 'l':
61398c2ecf20Sopenharmony_ci			ENABLE_BIC(BIC_DISABLED_BY_DEFAULT);
61408c2ecf20Sopenharmony_ci			list_header_only++;
61418c2ecf20Sopenharmony_ci			quiet++;
61428c2ecf20Sopenharmony_ci			break;
61438c2ecf20Sopenharmony_ci		case 'o':
61448c2ecf20Sopenharmony_ci			outf = fopen_or_die(optarg, "w");
61458c2ecf20Sopenharmony_ci			break;
61468c2ecf20Sopenharmony_ci		case 'q':
61478c2ecf20Sopenharmony_ci			quiet = 1;
61488c2ecf20Sopenharmony_ci			break;
61498c2ecf20Sopenharmony_ci		case 'n':
61508c2ecf20Sopenharmony_ci			num_iterations = strtod(optarg, NULL);
61518c2ecf20Sopenharmony_ci
61528c2ecf20Sopenharmony_ci			if (num_iterations <= 0) {
61538c2ecf20Sopenharmony_ci				fprintf(outf, "iterations %d should be positive number\n",
61548c2ecf20Sopenharmony_ci					num_iterations);
61558c2ecf20Sopenharmony_ci				exit(2);
61568c2ecf20Sopenharmony_ci			}
61578c2ecf20Sopenharmony_ci			break;
61588c2ecf20Sopenharmony_ci		case 's':
61598c2ecf20Sopenharmony_ci			/*
61608c2ecf20Sopenharmony_ci			 * --show: show only those specified
61618c2ecf20Sopenharmony_ci			 *  The 1st invocation will clear and replace the enabled mask
61628c2ecf20Sopenharmony_ci			 *  subsequent invocations can add to it.
61638c2ecf20Sopenharmony_ci			 */
61648c2ecf20Sopenharmony_ci			if (shown == 0)
61658c2ecf20Sopenharmony_ci				bic_enabled = bic_lookup(optarg, SHOW_LIST);
61668c2ecf20Sopenharmony_ci			else
61678c2ecf20Sopenharmony_ci				bic_enabled |= bic_lookup(optarg, SHOW_LIST);
61688c2ecf20Sopenharmony_ci			shown = 1;
61698c2ecf20Sopenharmony_ci			break;
61708c2ecf20Sopenharmony_ci		case 'S':
61718c2ecf20Sopenharmony_ci			summary_only++;
61728c2ecf20Sopenharmony_ci			break;
61738c2ecf20Sopenharmony_ci		case 'T':
61748c2ecf20Sopenharmony_ci			tcc_activation_temp_override = atoi(optarg);
61758c2ecf20Sopenharmony_ci			break;
61768c2ecf20Sopenharmony_ci		case 'v':
61778c2ecf20Sopenharmony_ci			print_version();
61788c2ecf20Sopenharmony_ci			exit(0);
61798c2ecf20Sopenharmony_ci			break;
61808c2ecf20Sopenharmony_ci		}
61818c2ecf20Sopenharmony_ci	}
61828c2ecf20Sopenharmony_ci}
61838c2ecf20Sopenharmony_ci
61848c2ecf20Sopenharmony_ciint main(int argc, char **argv)
61858c2ecf20Sopenharmony_ci{
61868c2ecf20Sopenharmony_ci	outf = stderr;
61878c2ecf20Sopenharmony_ci	cmdline(argc, argv);
61888c2ecf20Sopenharmony_ci
61898c2ecf20Sopenharmony_ci	if (!quiet)
61908c2ecf20Sopenharmony_ci		print_version();
61918c2ecf20Sopenharmony_ci
61928c2ecf20Sopenharmony_ci	probe_sysfs();
61938c2ecf20Sopenharmony_ci
61948c2ecf20Sopenharmony_ci	turbostat_init();
61958c2ecf20Sopenharmony_ci
61968c2ecf20Sopenharmony_ci	/* dump counters and exit */
61978c2ecf20Sopenharmony_ci	if (dump_only)
61988c2ecf20Sopenharmony_ci		return get_and_dump_counters();
61998c2ecf20Sopenharmony_ci
62008c2ecf20Sopenharmony_ci	/* list header and exit */
62018c2ecf20Sopenharmony_ci	if (list_header_only) {
62028c2ecf20Sopenharmony_ci		print_header(",");
62038c2ecf20Sopenharmony_ci		flush_output_stdout();
62048c2ecf20Sopenharmony_ci		return 0;
62058c2ecf20Sopenharmony_ci	}
62068c2ecf20Sopenharmony_ci
62078c2ecf20Sopenharmony_ci	msr_sum_record();
62088c2ecf20Sopenharmony_ci	/*
62098c2ecf20Sopenharmony_ci	 * if any params left, it must be a command to fork
62108c2ecf20Sopenharmony_ci	 */
62118c2ecf20Sopenharmony_ci	if (argc - optind)
62128c2ecf20Sopenharmony_ci		return fork_it(argv + optind);
62138c2ecf20Sopenharmony_ci	else
62148c2ecf20Sopenharmony_ci		turbostat_loop();
62158c2ecf20Sopenharmony_ci
62168c2ecf20Sopenharmony_ci	return 0;
62178c2ecf20Sopenharmony_ci}
6218