Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/tools/power/x86/turbostat/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 293 kB image not shown  

Quelle  turbostat.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * turbostat -- show CPU frequency and C-state residency
 * on modern Intel and AMD processors.
 *
 * Copyright (c) 2025 Intel Corporation.
 * Len Brown <len.brown@intel.com>
 */


#define _GNU_SOURCE
#include MSRHEADER

// copied from arch/x86/include/asm/cpu_device_id.h
#define VFM_MODEL_BIT 0
#define VFM_FAMILY_BIT 8
#define VFM_VENDOR_BIT 16
#define VFM_RSVD_BIT 24

#define VFM_MODEL_MASK GENMASK(VFM_FAMILY_BIT - 1, VFM_MODEL_BIT)
#define VFM_FAMILY_MASK GENMASK(VFM_VENDOR_BIT - 1, VFM_FAMILY_BIT)
#define VFM_VENDOR_MASK GENMASK(VFM_RSVD_BIT - 1, VFM_VENDOR_BIT)

#define VFM_MODEL(vfm) (((vfm) & VFM_MODEL_MASK) >> VFM_MODEL_BIT)
#define VFM_FAMILY(vfm) (((vfm) & VFM_FAMILY_MASK) >> VFM_FAMILY_BIT)
#define VFM_VENDOR(vfm) (((vfm) & VFM_VENDOR_MASK) >> VFM_VENDOR_BIT)

#define VFM_MAKE(_vendor, _family, _model) ( \
 ((_model) << VFM_MODEL_BIT) |  \
 ((_family) << VFM_FAMILY_BIT) |  \
 ((_vendor) << VFM_VENDOR_BIT)  \
)
// end copied section

#define CPUID_LEAF_MODEL_ID   0x1A
#define CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT 24

#define X86_VENDOR_INTEL 0

#include INTEL_FAMILY_HEADER
#include BUILD_BUG_HEADER
#include <stdarg.h>
#include <stdio.h>
#include <err.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/resource.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>
#include <getopt.h>
#include <dirent.h>
#include <string.h>
#include <ctype.h>
#include <sched.h>
#include <time.h>
#include <cpuid.h>
#include <sys/capability.h>
#include <errno.h>
#include <math.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>
#include <stdbool.h>
#include <assert.h>
#include <linux/kernel.h>
#include <limits.h>

#define UNUSED(x) (void)(x)

/*
 * This list matches the column headers, except
 * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
 * 2. Core and CPU are moved to the end, we can't have strings that contain them
 *    matching on them for --show and --hide.
 */


/*
 * buffer size used by sscanf() for added column names
 * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
 */

#define NAME_BYTES 20
#define PATH_BYTES 128
#define PERF_NAME_BYTES 128

#define MAX_NOFILE 0x8000

#define COUNTER_KIND_PERF_PREFIX "perf/"
#define COUNTER_KIND_PERF_PREFIX_LEN strlen(COUNTER_KIND_PERF_PREFIX)
#define PERF_DEV_NAME_BYTES 32
#define PERF_EVT_NAME_BYTES 32

#define INTEL_ECORE_TYPE 0x20
#define INTEL_PCORE_TYPE 0x40

#define ROUND_UP_TO_PAGE_SIZE(n) (((n) + 0x1000UL-1UL) & ~(0x1000UL-1UL))

enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };
enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M };
enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT, FORMAT_AVERAGE };
enum counter_source { COUNTER_SOURCE_NONE, COUNTER_SOURCE_PERF, COUNTER_SOURCE_MSR };

struct perf_counter_info {
 struct perf_counter_info *next;

 /* How to open the counter / What counter it is. */
 char device[PERF_DEV_NAME_BYTES];
 char event[PERF_EVT_NAME_BYTES];

 /* How to show/format the counter. */
 char name[PERF_NAME_BYTES];
 unsigned int width;
 enum counter_scope scope;
 enum counter_type type;
 enum counter_format format;
 double scale;

 /* For reading the counter. */
 int *fd_perf_per_domain;
 size_t num_domains;
};

struct sysfs_path {
 char path[PATH_BYTES];
 int id;
 struct sysfs_path *next;
};

struct msr_counter {
 unsigned int msr_num;
 char name[NAME_BYTES];
 struct sysfs_path *sp;
 unsigned int width;
 enum counter_type type;
 enum counter_format format;
 struct msr_counter *next;
 unsigned int flags;
#define FLAGS_HIDE (1 << 0)
#define FLAGS_SHOW (1 << 1)
#define SYSFS_PERCPU (1 << 1)
};

struct msr_counter bic[] = {
 { 0x0, "usec", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Time_Of_Day_Seconds", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Package", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Node", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Avg_MHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Busy%", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Bzy_MHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "TSC_MHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "IRQ", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "SMI", NULL, 32, 0, FORMAT_DELTA, NULL, 0 },
 { 0x0, "cpuidle", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU%c1", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU%c3", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU%c6", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU%c7", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "ThreadC", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CoreTmp", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CoreCnt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "PkgTmp", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "GFX%rc6", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "GFXMHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg%pc2", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg%pc3", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg%pc6", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg%pc7", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg%pc8", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg%pc9", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pk%pc10", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU%LPI", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "SYS%LPI", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "PkgWatt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CorWatt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "GFXWatt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "PkgCnt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "RAMWatt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "PKG_%", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "RAM_%", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Pkg_J", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Cor_J", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "GFX_J", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "RAM_J", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Mod%c6", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Totl%C0", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Any%C0", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "GFX%C0", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPUGFX%", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Core", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "APIC", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "X2APIC", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Die", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "L3", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "GFXAMHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "IPC", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CoreThr", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "UncMHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "SAM%mc6", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "SAMMHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "SAMAMHz", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Die%c6", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "SysWatt", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "Sys_J", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "NMI", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "CPU%c1e", NULL, 0, 0, 0, NULL, 0 },
 { 0x0, "pct_idle", NULL, 0, 0, 0, NULL, 0 },
};

/* n.b. bic_names must match the order in bic[], above */
enum bic_names {
 BIC_USEC,
 BIC_TOD,
 BIC_Package,
 BIC_Node,
 BIC_Avg_MHz,
 BIC_Busy,
 BIC_Bzy_MHz,
 BIC_TSC_MHz,
 BIC_IRQ,
 BIC_SMI,
 BIC_cpuidle,
 BIC_CPU_c1,
 BIC_CPU_c3,
 BIC_CPU_c6,
 BIC_CPU_c7,
 BIC_ThreadC,
 BIC_CoreTmp,
 BIC_CoreCnt,
 BIC_PkgTmp,
 BIC_GFX_rc6,
 BIC_GFXMHz,
 BIC_Pkgpc2,
 BIC_Pkgpc3,
 BIC_Pkgpc6,
 BIC_Pkgpc7,
 BIC_Pkgpc8,
 BIC_Pkgpc9,
 BIC_Pkgpc10,
 BIC_CPU_LPI,
 BIC_SYS_LPI,
 BIC_PkgWatt,
 BIC_CorWatt,
 BIC_GFXWatt,
 BIC_PkgCnt,
 BIC_RAMWatt,
 BIC_PKG__,
 BIC_RAM__,
 BIC_Pkg_J,
 BIC_Cor_J,
 BIC_GFX_J,
 BIC_RAM_J,
 BIC_Mod_c6,
 BIC_Totl_c0,
 BIC_Any_c0,
 BIC_GFX_c0,
 BIC_CPUGFX,
 BIC_Core,
 BIC_CPU,
 BIC_APIC,
 BIC_X2APIC,
 BIC_Die,
 BIC_L3,
 BIC_GFXACTMHz,
 BIC_IPC,
 BIC_CORE_THROT_CNT,
 BIC_UNCORE_MHZ,
 BIC_SAM_mc6,
 BIC_SAMMHz,
 BIC_SAMACTMHz,
 BIC_Diec6,
 BIC_SysWatt,
 BIC_Sys_J,
 BIC_NMI,
 BIC_CPU_c1e,
 BIC_pct_idle,
 MAX_BIC
};

void print_bic_set(char *s, cpu_set_t *set)
{
 int i;

 assert(MAX_BIC < CPU_SETSIZE);

 printf("%s:", s);

 for (i = 0; i <= MAX_BIC; ++i) {

  if (CPU_ISSET(i, set)) {
   assert(i < MAX_BIC);
   printf(" %s", bic[i].name);
  }
 }
 putchar('\n');
}

static cpu_set_t bic_group_topology;
static cpu_set_t bic_group_thermal_pwr;
static cpu_set_t bic_group_frequency;
static cpu_set_t bic_group_hw_idle;
static cpu_set_t bic_group_sw_idle;
static cpu_set_t bic_group_idle;
static cpu_set_t bic_group_other;
static cpu_set_t bic_group_disabled_by_default;
static cpu_set_t bic_enabled;
static cpu_set_t bic_present;

/* modify */
#define BIC_INIT(set) CPU_ZERO(set)

#define SET_BIC(COUNTER_NUMBER, set) CPU_SET(COUNTER_NUMBER, set)
#define CLR_BIC(COUNTER_NUMBER, set) CPU_CLR(COUNTER_NUMBER, set)

#define BIC_PRESENT(COUNTER_NUMBER) SET_BIC(COUNTER_NUMBER, &bic_present)
#define BIC_NOT_PRESENT(COUNTER_NUMBER) CPU_CLR(COUNTER_NUMBER, &bic_present)

/* test */
#define BIC_IS_ENABLED(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_enabled)
#define DO_BIC_READ(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_present)
#define DO_BIC(COUNTER_NUMBER) (CPU_ISSET(COUNTER_NUMBER, &bic_enabled) && CPU_ISSET(COUNTER_NUMBER, &bic_present))

static void bic_set_all(cpu_set_t *set)
{
 int i;

 assert(MAX_BIC < CPU_SETSIZE);

 for (i = 0; i < MAX_BIC; ++i)
  SET_BIC(i, set);
}

/*
 * bic_clear_bits()
 * clear all the bits from "clr" in "dst"
 */

static void bic_clear_bits(cpu_set_t *dst, cpu_set_t *clr)
{
 int i;

 assert(MAX_BIC < CPU_SETSIZE);

 for (i = 0; i < MAX_BIC; ++i)
  if (CPU_ISSET(i, clr))
   CLR_BIC(i, dst);
}

static void bic_groups_init(void)
{
 BIC_INIT(&bic_group_topology);
 SET_BIC(BIC_Package, &bic_group_topology);
 SET_BIC(BIC_Node, &bic_group_topology);
 SET_BIC(BIC_CoreCnt, &bic_group_topology);
 SET_BIC(BIC_PkgCnt, &bic_group_topology);
 SET_BIC(BIC_Core, &bic_group_topology);
 SET_BIC(BIC_CPU, &bic_group_topology);
 SET_BIC(BIC_Die, &bic_group_topology);
 SET_BIC(BIC_L3, &bic_group_topology);

 BIC_INIT(&bic_group_thermal_pwr);
 SET_BIC(BIC_CoreTmp, &bic_group_thermal_pwr);
 SET_BIC(BIC_PkgTmp, &bic_group_thermal_pwr);
 SET_BIC(BIC_PkgWatt, &bic_group_thermal_pwr);
 SET_BIC(BIC_CorWatt, &bic_group_thermal_pwr);
 SET_BIC(BIC_GFXWatt, &bic_group_thermal_pwr);
 SET_BIC(BIC_RAMWatt, &bic_group_thermal_pwr);
 SET_BIC(BIC_PKG__, &bic_group_thermal_pwr);
 SET_BIC(BIC_RAM__, &bic_group_thermal_pwr);
 SET_BIC(BIC_SysWatt, &bic_group_thermal_pwr);

 BIC_INIT(&bic_group_frequency);
 SET_BIC(BIC_Avg_MHz, &bic_group_frequency);
 SET_BIC(BIC_Busy, &bic_group_frequency);
 SET_BIC(BIC_Bzy_MHz, &bic_group_frequency);
 SET_BIC(BIC_TSC_MHz, &bic_group_frequency);
 SET_BIC(BIC_GFXMHz, &bic_group_frequency);
 SET_BIC(BIC_GFXACTMHz, &bic_group_frequency);
 SET_BIC(BIC_SAMMHz, &bic_group_frequency);
 SET_BIC(BIC_SAMACTMHz, &bic_group_frequency);
 SET_BIC(BIC_UNCORE_MHZ, &bic_group_frequency);

 BIC_INIT(&bic_group_hw_idle);
 SET_BIC(BIC_Busy, &bic_group_hw_idle);
 SET_BIC(BIC_CPU_c1, &bic_group_hw_idle);
 SET_BIC(BIC_CPU_c3, &bic_group_hw_idle);
 SET_BIC(BIC_CPU_c6, &bic_group_hw_idle);
 SET_BIC(BIC_CPU_c7, &bic_group_hw_idle);
 SET_BIC(BIC_GFX_rc6, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc2, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc3, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc6, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc7, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc8, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc9, &bic_group_hw_idle);
 SET_BIC(BIC_Pkgpc10, &bic_group_hw_idle);
 SET_BIC(BIC_CPU_LPI, &bic_group_hw_idle);
 SET_BIC(BIC_SYS_LPI, &bic_group_hw_idle);
 SET_BIC(BIC_Mod_c6, &bic_group_hw_idle);
 SET_BIC(BIC_Totl_c0, &bic_group_hw_idle);
 SET_BIC(BIC_Any_c0, &bic_group_hw_idle);
 SET_BIC(BIC_GFX_c0, &bic_group_hw_idle);
 SET_BIC(BIC_CPUGFX, &bic_group_hw_idle);
 SET_BIC(BIC_SAM_mc6, &bic_group_hw_idle);
 SET_BIC(BIC_Diec6, &bic_group_hw_idle);

 BIC_INIT(&bic_group_sw_idle);
 SET_BIC(BIC_Busy, &bic_group_sw_idle);
 SET_BIC(BIC_cpuidle, &bic_group_sw_idle);
 SET_BIC(BIC_pct_idle, &bic_group_sw_idle);

 BIC_INIT(&bic_group_idle);
 CPU_OR(&bic_group_idle, &bic_group_idle, &bic_group_hw_idle);
 SET_BIC(BIC_pct_idle, &bic_group_idle);

 BIC_INIT(&bic_group_other);
 SET_BIC(BIC_IRQ, &bic_group_other);
 SET_BIC(BIC_NMI, &bic_group_other);
 SET_BIC(BIC_SMI, &bic_group_other);
 SET_BIC(BIC_ThreadC, &bic_group_other);
 SET_BIC(BIC_CoreTmp, &bic_group_other);
 SET_BIC(BIC_IPC, &bic_group_other);

 BIC_INIT(&bic_group_disabled_by_default);
 SET_BIC(BIC_USEC, &bic_group_disabled_by_default);
 SET_BIC(BIC_TOD, &bic_group_disabled_by_default);
 SET_BIC(BIC_cpuidle, &bic_group_disabled_by_default);
 SET_BIC(BIC_APIC, &bic_group_disabled_by_default);
 SET_BIC(BIC_X2APIC, &bic_group_disabled_by_default);

 BIC_INIT(&bic_enabled);
 bic_set_all(&bic_enabled);
 bic_clear_bits(&bic_enabled, &bic_group_disabled_by_default);

 BIC_INIT(&bic_present);
 SET_BIC(BIC_USEC, &bic_present);
 SET_BIC(BIC_TOD, &bic_present);
 SET_BIC(BIC_cpuidle, &bic_present);
 SET_BIC(BIC_APIC, &bic_present);
 SET_BIC(BIC_X2APIC, &bic_present);
 SET_BIC(BIC_pct_idle, &bic_present);
}

/*
 * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:
 * If you change the values, note they are used both in comparisons
 * (>= PCL__7) and to index pkg_cstate_limit_strings[].
 */

#define PCLUKN 0  /* Unknown */
#define PCLRSV 1  /* Reserved */
#define PCL__0 2  /* PC0 */
#define PCL__1 3  /* PC1 */
#define PCL__2 4  /* PC2 */
#define PCL__3 5  /* PC3 */
#define PCL__4 6  /* PC4 */
#define PCL__6 7  /* PC6 */
#define PCL_6N 8  /* PC6 No Retention */
#define PCL_6R 9  /* PC6 Retention */
#define PCL__7 10  /* PC7 */
#define PCL_7S 11  /* PC7 Shrink */
#define PCL__8 12  /* PC8 */
#define PCL__9 13  /* PC9 */
#define PCL_10 14  /* PC10 */
#define PCLUNL 15  /* Unlimited */

struct amperf_group_fd;

char *proc_stat = "/proc/stat";
FILE *outf;
int *fd_percpu;
int *fd_instr_count_percpu;
struct timeval interval_tv = { 5, 0 };
struct timespec interval_ts = { 5, 0 };

unsigned int num_iterations;
unsigned int header_iterations;
unsigned int debug;
unsigned int quiet;
unsigned int shown;
unsigned int sums_need_wide_columns;
unsigned int rapl_joules;
unsigned int summary_only;
unsigned int list_header_only;
unsigned int dump_only;
unsigned int force_load;
unsigned int has_aperf;
unsigned int has_aperf_access;
unsigned int has_epb;
unsigned int has_turbo;
unsigned int is_hybrid;
unsigned int units = 1000000; /* MHz etc */
unsigned int genuine_intel;
unsigned int authentic_amd;
unsigned int hygon_genuine;
unsigned int max_level, max_extended_level;
unsigned int has_invariant_tsc;
unsigned int aperf_mperf_multiplier = 1;
double bclk;
double base_hz;
unsigned int has_base_hz;
double tsc_tweak = 1.0;
unsigned int show_pkg_only;
unsigned int show_core_only;
char *output_buffer, *outp;
unsigned int do_dts;
unsigned int do_ptm;
unsigned int do_ipc;
unsigned long long cpuidle_cur_cpu_lpi_us;
unsigned long long cpuidle_cur_sys_lpi_us;
unsigned int tj_max;
unsigned int tj_max_override;
double rapl_power_units, rapl_time_units;
double rapl_dram_energy_units, rapl_energy_units, rapl_psys_energy_units;
double rapl_joule_counter_range;
unsigned int crystal_hz;
unsigned long long tsc_hz;
int base_cpu;
unsigned int has_hwp;  /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
   /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
unsigned int first_counter_read = 1;

static struct timeval procsysfs_tv_begin;

int ignore_stdin;
bool no_msr;
bool no_perf;

enum gfx_sysfs_idx {
 GFX_rc6,
 GFX_MHz,
 GFX_ACTMHz,
 SAM_mc6,
 SAM_MHz,
 SAM_ACTMHz,
 GFX_MAX
};

struct gfx_sysfs_info {
 FILE *fp;
 unsigned int val;
 unsigned long long val_ull;
};

static struct gfx_sysfs_info gfx_info[GFX_MAX];

int get_msr(int cpu, off_t offset, unsigned long long *msr);
int add_counter(unsigned int msr_num, char *path, char *name,
  unsigned int width, enum counter_scope scope,
  enum counter_type type, enum counter_format format, int flags, int package_num);

/* Model specific support Start */

/* List of features that may diverge among different platforms */
struct platform_features {
 bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */
 bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */
 bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, MSR_IA32_POWER_CTL, TRL MSRs */
 bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */
 int bclk_freq;  /* CPU base clock */
 int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */
 int supported_cstates; /* Core cstates and Package cstates supported */
 int cst_limit;  /* MSR_PKG_CST_CONFIG_CONTROL */
 bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */
 bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */
 bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */
 bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */
 bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */
 bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */
 bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */
 bool has_ext_cst_msrs; /* MSR_PKG_WEIGHTED_CORE_C0_RES/MSR_PKG_ANY_CORE_C0_RES/MSR_PKG_ANY_GFXE_C0_RES/MSR_PKG_BOTH_CORE_GFXE_C0_RES */
 bool has_cst_prewake_bit; /* Cstate prewake bit in MSR_IA32_POWER_CTL */
 int trl_msrs;  /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */
 int plr_msrs;  /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */
 int rapl_msrs;  /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */
 bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */
 bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */
 bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */
 bool has_fixed_rapl_psys_unit; /* Fixed Energy Unit used for PSYS RAPL Domain */
 int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */
 int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */
 bool enable_tsc_tweak; /* Use CPU Base freq instead of TSC freq for aperf/mperf counter */
 bool need_perf_multiplier; /* mperf/aperf multiplier */
};

struct platform_data {
 unsigned int vfm;
 const struct platform_features *features;
};

/* For BCLK */
enum bclk_freq {
 BCLK_100MHZ = 1,
 BCLK_133MHZ,
 BCLK_SLV,
};

#define SLM_BCLK_FREQS 5
double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 };

double slm_bclk(void)
{
 unsigned long long msr = 3;
 unsigned int i;
 double freq;

 if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))
  fprintf(outf, "SLM BCLK: unknown\n");

 i = msr & 0xf;
 if (i >= SLM_BCLK_FREQS) {
  fprintf(outf, "SLM BCLK[%d] invalid\n", i);
  i = 3;
 }
 freq = slm_freq_table[i];

 if (!quiet)
  fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);

 return freq;
}

/* For Package cstate limit */
enum package_cstate_limit {
 CST_LIMIT_NHM = 1,
 CST_LIMIT_SNB,
 CST_LIMIT_HSW,
 CST_LIMIT_SKX,
 CST_LIMIT_ICX,
 CST_LIMIT_SLV,
 CST_LIMIT_AMT,
 CST_LIMIT_KNL,
 CST_LIMIT_GMT,
};

/* For Turbo Ratio Limit MSRs */
enum turbo_ratio_limit_msrs {
 TRL_BASE = BIT(0),
 TRL_LIMIT1 = BIT(1),
 TRL_LIMIT2 = BIT(2),
 TRL_ATOM = BIT(3),
 TRL_KNL = BIT(4),
 TRL_CORECOUNT = BIT(5),
};

/* For Perf Limit Reason MSRs */
enum perf_limit_reason_msrs {
 PLR_CORE = BIT(0),
 PLR_GFX = BIT(1),
 PLR_RING = BIT(2),
};

/* For RAPL MSRs */
enum rapl_msrs {
 RAPL_PKG_POWER_LIMIT = BIT(0), /* 0x610 MSR_PKG_POWER_LIMIT */
 RAPL_PKG_ENERGY_STATUS = BIT(1), /* 0x611 MSR_PKG_ENERGY_STATUS */
 RAPL_PKG_PERF_STATUS = BIT(2), /* 0x613 MSR_PKG_PERF_STATUS */
 RAPL_PKG_POWER_INFO = BIT(3), /* 0x614 MSR_PKG_POWER_INFO */
 RAPL_DRAM_POWER_LIMIT = BIT(4), /* 0x618 MSR_DRAM_POWER_LIMIT */
 RAPL_DRAM_ENERGY_STATUS = BIT(5), /* 0x619 MSR_DRAM_ENERGY_STATUS */
 RAPL_DRAM_PERF_STATUS = BIT(6), /* 0x61b MSR_DRAM_PERF_STATUS */
 RAPL_DRAM_POWER_INFO = BIT(7), /* 0x61c MSR_DRAM_POWER_INFO */
 RAPL_CORE_POWER_LIMIT = BIT(8), /* 0x638 MSR_PP0_POWER_LIMIT */
 RAPL_CORE_ENERGY_STATUS = BIT(9), /* 0x639 MSR_PP0_ENERGY_STATUS */
 RAPL_CORE_POLICY = BIT(10), /* 0x63a MSR_PP0_POLICY */
 RAPL_GFX_POWER_LIMIT = BIT(11), /* 0x640 MSR_PP1_POWER_LIMIT */
 RAPL_GFX_ENERGY_STATUS = BIT(12), /* 0x641 MSR_PP1_ENERGY_STATUS */
 RAPL_GFX_POLICY = BIT(13), /* 0x642 MSR_PP1_POLICY */
 RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */
 RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */
 RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */
 RAPL_PLATFORM_ENERGY_LIMIT = BIT(17), /* 0x64c MSR_PLATFORM_ENERGY_LIMIT */
 RAPL_PLATFORM_ENERGY_STATUS = BIT(18), /* 0x64d MSR_PLATFORM_ENERGY_STATUS */
};

#define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT)
#define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT)
#define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT)
#define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS)
#define RAPL_PSYS (RAPL_PLATFORM_ENERGY_STATUS | RAPL_PLATFORM_ENERGY_LIMIT)

#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)
#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)
#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY)
#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLICY)

#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT)

/* For Cstates */
enum cstates {
 CC1 = BIT(0),
 CC3 = BIT(1),
 CC6 = BIT(2),
 CC7 = BIT(3),
 PC2 = BIT(4),
 PC3 = BIT(5),
 PC6 = BIT(6),
 PC7 = BIT(7),
 PC8 = BIT(8),
 PC9 = BIT(9),
 PC10 = BIT(10),
};

static const struct platform_features nhm_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_133MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,
 .cst_limit = CST_LIMIT_NHM,
 .trl_msrs = TRL_BASE,
};

static const struct platform_features nhx_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_133MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,
 .cst_limit = CST_LIMIT_NHM,
};

static const struct platform_features snb_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_SNB,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features snx_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_SNB,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,
};

static const struct platform_features ivb_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_SNB,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features ivx_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_SNB,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE | TRL_LIMIT1,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,
};

static const struct platform_features hsw_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features hsx_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2,
 .plr_msrs = PLR_CORE | PLR_RING,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
 .has_fixed_rapl_unit = 1,
};

static const struct platform_features hswl_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features hswg_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features bdw_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features bdwg_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,
};

static const struct platform_features bdx_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .has_cst_auto_convension = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
 .has_fixed_rapl_unit = 1,
};

static const struct platform_features skl_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .crystal_freq = 24000000,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .has_ext_cst_msrs = 1,
 .trl_msrs = TRL_BASE,
 .tcc_offset_bits = 6,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS,
 .enable_tsc_tweak = 1,
};

static const struct platform_features cnl_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_HSW,
 .has_irtl_msrs = 1,
 .has_msr_core_c1_res = 1,
 .has_ext_cst_msrs = 1,
 .trl_msrs = TRL_BASE,
 .tcc_offset_bits = 6,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS,
 .enable_tsc_tweak = 1,
};

/* Copied from cnl_features, with PC7/PC9 removed */
static const struct platform_features adl_features = {
 .has_msr_misc_feature_control = cnl_features.has_msr_misc_feature_control,
 .has_msr_misc_pwr_mgmt  = cnl_features.has_msr_misc_pwr_mgmt,
 .has_nhm_msrs   = cnl_features.has_nhm_msrs,
 .has_config_tdp   = cnl_features.has_config_tdp,
 .bclk_freq   = cnl_features.bclk_freq,
 .supported_cstates  = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10,
 .cst_limit   = cnl_features.cst_limit,
 .has_irtl_msrs   = cnl_features.has_irtl_msrs,
 .has_msr_core_c1_res  = cnl_features.has_msr_core_c1_res,
 .has_ext_cst_msrs  = cnl_features.has_ext_cst_msrs,
 .trl_msrs   = cnl_features.trl_msrs,
 .tcc_offset_bits  = cnl_features.tcc_offset_bits,
 .rapl_msrs   = cnl_features.rapl_msrs,
 .enable_tsc_tweak  = cnl_features.enable_tsc_tweak,
};

/* Copied from adl_features, with PC3/PC8 removed */
static const struct platform_features lnl_features = {
 .has_msr_misc_feature_control = adl_features.has_msr_misc_feature_control,
 .has_msr_misc_pwr_mgmt  = adl_features.has_msr_misc_pwr_mgmt,
 .has_nhm_msrs   = adl_features.has_nhm_msrs,
 .has_config_tdp   = adl_features.has_config_tdp,
 .bclk_freq   = adl_features.bclk_freq,
 .supported_cstates  = CC1 | CC6 | CC7 | PC2 | PC6 | PC10,
 .cst_limit   = adl_features.cst_limit,
 .has_irtl_msrs   = adl_features.has_irtl_msrs,
 .has_msr_core_c1_res  = adl_features.has_msr_core_c1_res,
 .has_ext_cst_msrs  = adl_features.has_ext_cst_msrs,
 .trl_msrs   = adl_features.trl_msrs,
 .tcc_offset_bits  = adl_features.tcc_offset_bits,
 .rapl_msrs   = adl_features.rapl_msrs,
 .enable_tsc_tweak  = adl_features.enable_tsc_tweak,
};

static const struct platform_features skx_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | PC2 | PC6,
 .cst_limit = CST_LIMIT_SKX,
 .has_irtl_msrs = 1,
 .has_cst_auto_convension = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
 .has_fixed_rapl_unit = 1,
};

static const struct platform_features icx_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | PC2 | PC6,
 .cst_limit = CST_LIMIT_ICX,
 .has_msr_core_c1_res = 1,
 .has_irtl_msrs = 1,
 .has_cst_prewake_bit = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
 .has_fixed_rapl_unit = 1,
};

static const struct platform_features spr_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | PC2 | PC6,
 .cst_limit = CST_LIMIT_SKX,
 .has_msr_core_c1_res = 1,
 .has_irtl_msrs = 1,
 .has_cst_prewake_bit = 1,
 .has_fixed_rapl_psys_unit = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
};

static const struct platform_features dmr_features = {
 .has_msr_misc_feature_control = spr_features.has_msr_misc_feature_control,
 .has_msr_misc_pwr_mgmt  = spr_features.has_msr_misc_pwr_mgmt,
 .has_nhm_msrs   = spr_features.has_nhm_msrs,
 .bclk_freq   = spr_features.bclk_freq,
 .supported_cstates  = spr_features.supported_cstates,
 .cst_limit   = spr_features.cst_limit,
 .has_msr_core_c1_res  = spr_features.has_msr_core_c1_res,
 .has_cst_prewake_bit  = spr_features.has_cst_prewake_bit,
 .has_fixed_rapl_psys_unit = spr_features.has_fixed_rapl_psys_unit,
 .trl_msrs   = spr_features.trl_msrs,
 .has_msr_module_c6_res_ms = 1, /* DMR has Dual-Core-Module and MC6 MSR */
 .rapl_msrs   = 0, /* DMR does not have RAPL MSRs */
 .plr_msrs   = 0, /* DMR does not have PLR  MSRs */
 .has_irtl_msrs   = 0, /* DMR does not have IRTL MSRs */
 .has_config_tdp   = 0, /* DMR does not have CTDP MSRs */
};

static const struct platform_features srf_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | PC2 | PC6,
 .cst_limit = CST_LIMIT_SKX,
 .has_msr_core_c1_res = 1,
 .has_msr_module_c6_res_ms = 1,
 .has_irtl_msrs = 1,
 .has_cst_prewake_bit = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
};

static const struct platform_features grr_features = {
 .has_msr_misc_feature_control = 1,
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6,
 .cst_limit = CST_LIMIT_SKX,
 .has_msr_core_c1_res = 1,
 .has_msr_module_c6_res_ms = 1,
 .has_irtl_msrs = 1,
 .has_cst_prewake_bit = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
};

static const struct platform_features slv_features = {
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_SLV,
 .supported_cstates = CC1 | CC6 | PC6,
 .cst_limit = CST_LIMIT_SLV,
 .has_msr_core_c1_res = 1,
 .has_msr_module_c6_res_ms = 1,
 .has_msr_c6_demotion_policy_config = 1,
 .has_msr_atom_pkg_c6_residency = 1,
 .trl_msrs = TRL_ATOM,
 .rapl_msrs = RAPL_PKG | RAPL_CORE,
 .has_rapl_divisor = 1,
 .rapl_quirk_tdp = 30,
};

static const struct platform_features slvd_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_SLV,
 .supported_cstates = CC1 | CC6 | PC3 | PC6,
 .cst_limit = CST_LIMIT_SLV,
 .has_msr_atom_pkg_c6_residency = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG | RAPL_CORE,
 .rapl_quirk_tdp = 30,
};

static const struct platform_features amt_features = {
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_133MHZ,
 .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,
 .cst_limit = CST_LIMIT_AMT,
 .trl_msrs = TRL_BASE,
};

static const struct platform_features gmt_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .crystal_freq = 19200000,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_GMT,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,
};

static const struct platform_features gmtd_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .crystal_freq = 25000000,
 .supported_cstates = CC1 | CC6 | PC2 | PC6,
 .cst_limit = CST_LIMIT_GMT,
 .has_irtl_msrs = 1,
 .has_msr_core_c1_res = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS,
};

static const struct platform_features gmtp_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .crystal_freq = 19200000,
 .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_GMT,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,
};

static const struct platform_features tmt_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,
 .cst_limit = CST_LIMIT_GMT,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
 .enable_tsc_tweak = 1,
};

static const struct platform_features tmtd_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6,
 .cst_limit = CST_LIMIT_GMT,
 .has_irtl_msrs = 1,
 .trl_msrs = TRL_BASE | TRL_CORECOUNT,
 .rapl_msrs = RAPL_PKG_ALL,
};

static const struct platform_features knl_features = {
 .has_msr_misc_pwr_mgmt = 1,
 .has_nhm_msrs = 1,
 .has_config_tdp = 1,
 .bclk_freq = BCLK_100MHZ,
 .supported_cstates = CC1 | CC6 | PC3 | PC6,
 .cst_limit = CST_LIMIT_KNL,
 .has_msr_knl_core_c6_residency = 1,
 .trl_msrs = TRL_KNL,
 .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
 .has_fixed_rapl_unit = 1,
 .need_perf_multiplier = 1,
};

static const struct platform_features default_features = {
};

static const struct platform_features amd_features_with_rapl = {
 .rapl_msrs = RAPL_AMD_F17H,
 .has_per_core_rapl = 1,
 .rapl_quirk_tdp = 280, /* This is the max stock TDP of HEDT/Server Fam17h+ chips */
};

static const struct platform_data turbostat_pdata[] = {
 { INTEL_NEHALEM, &nhm_features },
 { INTEL_NEHALEM_G, &nhm_features },
 { INTEL_NEHALEM_EP, &nhm_features },
 { INTEL_NEHALEM_EX, &nhx_features },
 { INTEL_WESTMERE, &nhm_features },
 { INTEL_WESTMERE_EP, &nhm_features },
 { INTEL_WESTMERE_EX, &nhx_features },
 { INTEL_SANDYBRIDGE, &snb_features },
 { INTEL_SANDYBRIDGE_X, &snx_features },
 { INTEL_IVYBRIDGE, &ivb_features },
 { INTEL_IVYBRIDGE_X, &ivx_features },
 { INTEL_HASWELL, &hsw_features },
 { INTEL_HASWELL_X, &hsx_features },
 { INTEL_HASWELL_L, &hswl_features },
 { INTEL_HASWELL_G, &hswg_features },
 { INTEL_BROADWELL, &bdw_features },
 { INTEL_BROADWELL_G, &bdwg_features },
 { INTEL_BROADWELL_X, &bdx_features },
 { INTEL_BROADWELL_D, &bdx_features },
 { INTEL_SKYLAKE_L, &skl_features },
 { INTEL_SKYLAKE, &skl_features },
 { INTEL_SKYLAKE_X, &skx_features },
 { INTEL_KABYLAKE_L, &skl_features },
 { INTEL_KABYLAKE, &skl_features },
 { INTEL_COMETLAKE, &skl_features },
 { INTEL_COMETLAKE_L, &skl_features },
 { INTEL_CANNONLAKE_L, &cnl_features },
 { INTEL_ICELAKE_X, &icx_features },
 { INTEL_ICELAKE_D, &icx_features },
 { INTEL_ICELAKE_L, &cnl_features },
 { INTEL_ICELAKE_NNPI, &cnl_features },
 { INTEL_ROCKETLAKE, &cnl_features },
 { INTEL_TIGERLAKE_L, &cnl_features },
 { INTEL_TIGERLAKE, &cnl_features },
 { INTEL_SAPPHIRERAPIDS_X, &spr_features },
 { INTEL_EMERALDRAPIDS_X, &spr_features },
 { INTEL_GRANITERAPIDS_X, &spr_features },
 { INTEL_GRANITERAPIDS_D, &spr_features },
 { INTEL_PANTHERCOVE_X, &dmr_features },
 { INTEL_LAKEFIELD, &cnl_features },
 { INTEL_ALDERLAKE, &adl_features },
 { INTEL_ALDERLAKE_L, &adl_features },
 { INTEL_RAPTORLAKE, &adl_features },
 { INTEL_RAPTORLAKE_P, &adl_features },
 { INTEL_RAPTORLAKE_S, &adl_features },
 { INTEL_BARTLETTLAKE, &adl_features },
 { INTEL_METEORLAKE, &adl_features },
 { INTEL_METEORLAKE_L, &adl_features },
 { INTEL_ARROWLAKE_H, &adl_features },
 { INTEL_ARROWLAKE_U, &adl_features },
 { INTEL_ARROWLAKE, &adl_features },
 { INTEL_LUNARLAKE_M, &lnl_features },
 { INTEL_PANTHERLAKE_L, &lnl_features },
 { INTEL_ATOM_SILVERMONT, &slv_features },
 { INTEL_ATOM_SILVERMONT_D, &slvd_features },
 { INTEL_ATOM_AIRMONT, &amt_features },
 { INTEL_ATOM_GOLDMONT, &gmt_features },
 { INTEL_ATOM_GOLDMONT_D, &gmtd_features },
 { INTEL_ATOM_GOLDMONT_PLUS, &gmtp_features },
 { INTEL_ATOM_TREMONT_D, &tmtd_features },
 { INTEL_ATOM_TREMONT, &tmt_features },
 { INTEL_ATOM_TREMONT_L, &tmt_features },
 { INTEL_ATOM_GRACEMONT, &adl_features },
 { INTEL_ATOM_CRESTMONT_X, &srf_features },
 { INTEL_ATOM_CRESTMONT, &grr_features },
 { INTEL_ATOM_DARKMONT_X, &srf_features },
 { INTEL_XEON_PHI_KNL, &knl_features },
 { INTEL_XEON_PHI_KNM, &knl_features },
 /*
 * Missing support for
 * INTEL_ICELAKE
 * INTEL_ATOM_SILVERMONT_MID
 * INTEL_ATOM_SILVERMONT_MID2
 * INTEL_ATOM_AIRMONT_NP
 */

 { 0, NULL },
};

static const struct platform_features *platform;

void probe_platform_features(unsigned int family, unsigned int model)
{
 int i;

 if (authentic_amd || hygon_genuine) {
  /* fallback to default features on unsupported models */
  force_load++;
  if (max_extended_level >= 0x80000007) {
   unsigned int eax, ebx, ecx, edx;

   __cpuid(0x80000007, eax, ebx, ecx, edx);
   /* RAPL (Fam 17h+) */
   if ((edx & (1 << 14)) && family >= 0x17)
    platform = &amd_features_with_rapl;
  }
  goto end;
 }

 if (!genuine_intel)
  goto end;

 for (i = 0; turbostat_pdata[i].features; i++) {
  if (VFM_FAMILY(turbostat_pdata[i].vfm) == family && VFM_MODEL(turbostat_pdata[i].vfm) == model) {
   platform = turbostat_pdata[i].features;
   return;
  }
 }

end:
 if (force_load && !platform) {
  fprintf(outf, "Forced to run on unsupported platform!\n");
  platform = &default_features;
 }

 if (platform)
  return;

 fprintf(stderr, "Unsupported platform detected.\n\tSee RUN THE LATEST VERSION on turbostat(8)\n");
 exit(1);
}

/* Model specific support End */

#define TJMAX_DEFAULT 100

/* MSRs that are not yet in the kernel-provided header. */
#define MSR_RAPL_PWR_UNIT 0xc0010299
#define MSR_CORE_ENERGY_STAT 0xc001029a
#define MSR_PKG_ENERGY_STAT 0xc001029b

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int backwards_count;
char *progname;

#define CPU_SUBSET_MAXCPUS 8192 /* need to use before probe... */
cpu_set_t *cpu_present_set, *cpu_possible_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;
size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize,
    cpu_subset_size;
#define MAX_ADDED_THREAD_COUNTERS 24
#define MAX_ADDED_CORE_COUNTERS 8
#define MAX_ADDED_PACKAGE_COUNTERS 16
#define PMT_MAX_ADDED_THREAD_COUNTERS 24
#define PMT_MAX_ADDED_CORE_COUNTERS 8
#define PMT_MAX_ADDED_PACKAGE_COUNTERS 16
#define BITMASK_SIZE 32

#define ZERO_ARRAY(arr) (memset(arr, 0, sizeof(arr)) + __must_be_array(arr))

/* Indexes used to map data read from perf and MSRs into global variables */
enum rapl_rci_index {
 RAPL_RCI_INDEX_ENERGY_PKG = 0,
 RAPL_RCI_INDEX_ENERGY_CORES = 1,
 RAPL_RCI_INDEX_DRAM = 2,
 RAPL_RCI_INDEX_GFX = 3,
 RAPL_RCI_INDEX_PKG_PERF_STATUS = 4,
 RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5,
 RAPL_RCI_INDEX_CORE_ENERGY = 6,
 RAPL_RCI_INDEX_ENERGY_PLATFORM = 7,
 NUM_RAPL_COUNTERS,
};

enum rapl_unit {
 RAPL_UNIT_INVALID,
 RAPL_UNIT_JOULES,
 RAPL_UNIT_WATTS,
};

struct rapl_counter_info_t {
 unsigned long long data[NUM_RAPL_COUNTERS];
 enum counter_source source[NUM_RAPL_COUNTERS];
 unsigned long long flags[NUM_RAPL_COUNTERS];
 double scale[NUM_RAPL_COUNTERS];
 enum rapl_unit unit[NUM_RAPL_COUNTERS];
 unsigned long long msr[NUM_RAPL_COUNTERS];
 unsigned long long msr_mask[NUM_RAPL_COUNTERS];
 int msr_shift[NUM_RAPL_COUNTERS];

 int fd_perf;
};

/* struct rapl_counter_info_t for each RAPL domain */
struct rapl_counter_info_t *rapl_counter_info_perdomain;
unsigned int rapl_counter_info_perdomain_size;

#define RAPL_COUNTER_FLAG_PLATFORM_COUNTER (1u << 0)
#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1)

struct rapl_counter_arch_info {
 int feature_mask; /* Mask for testing if the counter is supported on host */
 const char *perf_subsys;
 const char *perf_name;
 unsigned long long msr;
 unsigned long long msr_mask;
 int msr_shift;  /* Positive mean shift right, negative mean shift left */
 double *platform_rapl_msr_scale; /* Scale applied to values read by MSR (platform dependent, filled at runtime) */
 unsigned int rci_index; /* Maps data from perf counters to global variables */
 unsigned int bic_number;
 double compat_scale; /* Some counters require constant scaling to be in the same range as other, similar ones */
 unsigned long long flags;
};

static const struct rapl_counter_arch_info rapl_counter_arch_infos[] = {
 {
  .feature_mask = RAPL_PKG,
  .perf_subsys = "power",
  .perf_name = "energy-pkg",
  .msr = MSR_PKG_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_PKG,
  .bic_number = BIC_PkgWatt,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_PKG,
  .perf_subsys = "power",
  .perf_name = "energy-pkg",
  .msr = MSR_PKG_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_PKG,
  .bic_number = BIC_Pkg_J,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_AMD_F17H,
  .perf_subsys = "power",
  .perf_name = "energy-pkg",
  .msr = MSR_PKG_ENERGY_STAT,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_PKG,
  .bic_number = BIC_PkgWatt,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_AMD_F17H,
  .perf_subsys = "power",
  .perf_name = "energy-pkg",
  .msr = MSR_PKG_ENERGY_STAT,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_PKG,
  .bic_number = BIC_Pkg_J,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_CORE_ENERGY_STATUS,
  .perf_subsys = "power",
  .perf_name = "energy-cores",
  .msr = MSR_PP0_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_CORES,
  .bic_number = BIC_CorWatt,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_CORE_ENERGY_STATUS,
  .perf_subsys = "power",
  .perf_name = "energy-cores",
  .msr = MSR_PP0_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_CORES,
  .bic_number = BIC_Cor_J,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_DRAM,
  .perf_subsys = "power",
  .perf_name = "energy-ram",
  .msr = MSR_DRAM_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_dram_energy_units,
  .rci_index = RAPL_RCI_INDEX_DRAM,
  .bic_number = BIC_RAMWatt,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_DRAM,
  .perf_subsys = "power",
  .perf_name = "energy-ram",
  .msr = MSR_DRAM_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_dram_energy_units,
  .rci_index = RAPL_RCI_INDEX_DRAM,
  .bic_number = BIC_RAM_J,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_GFX,
  .perf_subsys = "power",
  .perf_name = "energy-gpu",
  .msr = MSR_PP1_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_GFX,
  .bic_number = BIC_GFXWatt,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_GFX,
  .perf_subsys = "power",
  .perf_name = "energy-gpu",
  .msr = MSR_PP1_ENERGY_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_GFX,
  .bic_number = BIC_GFX_J,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_PKG_PERF_STATUS,
  .perf_subsys = NULL,
  .perf_name = NULL,
  .msr = MSR_PKG_PERF_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_time_units,
  .rci_index = RAPL_RCI_INDEX_PKG_PERF_STATUS,
  .bic_number = BIC_PKG__,
  .compat_scale = 100.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_DRAM_PERF_STATUS,
  .perf_subsys = NULL,
  .perf_name = NULL,
  .msr = MSR_DRAM_PERF_STATUS,
  .msr_mask = 0xFFFFFFFFFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_time_units,
  .rci_index = RAPL_RCI_INDEX_DRAM_PERF_STATUS,
  .bic_number = BIC_RAM__,
  .compat_scale = 100.0,
  .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_AMD_F17H,
  .perf_subsys = NULL,
  .perf_name = NULL,
  .msr = MSR_CORE_ENERGY_STAT,
  .msr_mask = 0xFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_CORE_ENERGY,
  .bic_number = BIC_CorWatt,
  .compat_scale = 1.0,
  .flags = 0,
   },
 {
  .feature_mask = RAPL_AMD_F17H,
  .perf_subsys = NULL,
  .perf_name = NULL,
  .msr = MSR_CORE_ENERGY_STAT,
  .msr_mask = 0xFFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_energy_units,
  .rci_index = RAPL_RCI_INDEX_CORE_ENERGY,
  .bic_number = BIC_Cor_J,
  .compat_scale = 1.0,
  .flags = 0,
   },
 {
  .feature_mask = RAPL_PSYS,
  .perf_subsys = "power",
  .perf_name = "energy-psys",
  .msr = MSR_PLATFORM_ENERGY_STATUS,
  .msr_mask = 0x00000000FFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_psys_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM,
  .bic_number = BIC_SysWatt,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
 {
  .feature_mask = RAPL_PSYS,
  .perf_subsys = "power",
  .perf_name = "energy-psys",
  .msr = MSR_PLATFORM_ENERGY_STATUS,
  .msr_mask = 0x00000000FFFFFFFF,
  .msr_shift = 0,
  .platform_rapl_msr_scale = &rapl_psys_energy_units,
  .rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM,
  .bic_number = BIC_Sys_J,
  .compat_scale = 1.0,
  .flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM,
   },
};

struct rapl_counter {
 unsigned long long raw_value;
 enum rapl_unit unit;
 double scale;
};

/* Indexes used to map data read from perf and MSRs into global variables */
enum ccstate_rci_index {
 CCSTATE_RCI_INDEX_C1_RESIDENCY = 0,
 CCSTATE_RCI_INDEX_C3_RESIDENCY = 1,
 CCSTATE_RCI_INDEX_C6_RESIDENCY = 2,
 CCSTATE_RCI_INDEX_C7_RESIDENCY = 3,
 PCSTATE_RCI_INDEX_C2_RESIDENCY = 4,
 PCSTATE_RCI_INDEX_C3_RESIDENCY = 5,
 PCSTATE_RCI_INDEX_C6_RESIDENCY = 6,
 PCSTATE_RCI_INDEX_C7_RESIDENCY = 7,
 PCSTATE_RCI_INDEX_C8_RESIDENCY = 8,
 PCSTATE_RCI_INDEX_C9_RESIDENCY = 9,
 PCSTATE_RCI_INDEX_C10_RESIDENCY = 10,
 NUM_CSTATE_COUNTERS,
};

struct cstate_counter_info_t {
 unsigned long long data[NUM_CSTATE_COUNTERS];
 enum counter_source source[NUM_CSTATE_COUNTERS];
 unsigned long long msr[NUM_CSTATE_COUNTERS];
 int fd_perf_core;
 int fd_perf_pkg;
};

struct cstate_counter_info_t *ccstate_counter_info;
unsigned int ccstate_counter_info_size;

#define CSTATE_COUNTER_FLAG_COLLECT_PER_CORE   (1u << 0)
#define CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD ((1u << 1) | CSTATE_COUNTER_FLAG_COLLECT_PER_CORE)
#define CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY (1u << 2)

struct cstate_counter_arch_info {
 int feature_mask; /* Mask for testing if the counter is supported on host */
 const char *perf_subsys;
 const char *perf_name;
 unsigned long long msr;
 unsigned int rci_index; /* Maps data from perf counters to global variables */
 unsigned int bic_number;
 unsigned long long flags;
 int pkg_cstate_limit;
};

static struct cstate_counter_arch_info ccstate_counter_arch_infos[] = {
 {
  .feature_mask = CC1,
  .perf_subsys = "cstate_core",
  .perf_name = "c1-residency",
  .msr = MSR_CORE_C1_RES,
  .rci_index = CCSTATE_RCI_INDEX_C1_RESIDENCY,
  .bic_number = BIC_CPU_c1,
  .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD,
  .pkg_cstate_limit = 0,
   },
 {
  .feature_mask = CC3,
  .perf_subsys = "cstate_core",
  .perf_name = "c3-residency",
  .msr = MSR_CORE_C3_RESIDENCY,
  .rci_index = CCSTATE_RCI_INDEX_C3_RESIDENCY,
  .bic_number = BIC_CPU_c3,
  .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,
  .pkg_cstate_limit = 0,
   },
 {
  .feature_mask = CC6,
  .perf_subsys = "cstate_core",
  .perf_name = "c6-residency",
  .msr = MSR_CORE_C6_RESIDENCY,
  .rci_index = CCSTATE_RCI_INDEX_C6_RESIDENCY,
  .bic_number = BIC_CPU_c6,
  .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,
  .pkg_cstate_limit = 0,
   },
 {
  .feature_mask = CC7,
  .perf_subsys = "cstate_core",
  .perf_name = "c7-residency",
  .msr = MSR_CORE_C7_RESIDENCY,
  .rci_index = CCSTATE_RCI_INDEX_C7_RESIDENCY,
  .bic_number = BIC_CPU_c7,
  .flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,
  .pkg_cstate_limit = 0,
   },
 {
  .feature_mask = PC2,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c2-residency",
  .msr = MSR_PKG_C2_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C2_RESIDENCY,
  .bic_number = BIC_Pkgpc2,
  .flags = 0,
  .pkg_cstate_limit = PCL__2,
   },
 {
  .feature_mask = PC3,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c3-residency",
  .msr = MSR_PKG_C3_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C3_RESIDENCY,
  .bic_number = BIC_Pkgpc3,
  .flags = 0,
  .pkg_cstate_limit = PCL__3,
   },
 {
  .feature_mask = PC6,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c6-residency",
  .msr = MSR_PKG_C6_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C6_RESIDENCY,
  .bic_number = BIC_Pkgpc6,
  .flags = 0,
  .pkg_cstate_limit = PCL__6,
   },
 {
  .feature_mask = PC7,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c7-residency",
  .msr = MSR_PKG_C7_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C7_RESIDENCY,
  .bic_number = BIC_Pkgpc7,
  .flags = 0,
  .pkg_cstate_limit = PCL__7,
   },
 {
  .feature_mask = PC8,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c8-residency",
  .msr = MSR_PKG_C8_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C8_RESIDENCY,
  .bic_number = BIC_Pkgpc8,
  .flags = 0,
  .pkg_cstate_limit = PCL__8,
   },
 {
  .feature_mask = PC9,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c9-residency",
  .msr = MSR_PKG_C9_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C9_RESIDENCY,
  .bic_number = BIC_Pkgpc9,
  .flags = 0,
  .pkg_cstate_limit = PCL__9,
   },
 {
  .feature_mask = PC10,
  .perf_subsys = "cstate_pkg",
  .perf_name = "c10-residency",
  .msr = MSR_PKG_C10_RESIDENCY,
  .rci_index = PCSTATE_RCI_INDEX_C10_RESIDENCY,
  .bic_number = BIC_Pkgpc10,
  .flags = 0,
  .pkg_cstate_limit = PCL_10,
   },
};

/* Indexes used to map data read from perf and MSRs into global variables */
enum msr_rci_index {
 MSR_RCI_INDEX_APERF = 0,
 MSR_RCI_INDEX_MPERF = 1,
 MSR_RCI_INDEX_SMI = 2,
 NUM_MSR_COUNTERS,
};

struct msr_counter_info_t {
 unsigned long long data[NUM_MSR_COUNTERS];
 enum counter_source source[NUM_MSR_COUNTERS];
 unsigned long long msr[NUM_MSR_COUNTERS];
 unsigned long long msr_mask[NUM_MSR_COUNTERS];
 int fd_perf;
};

struct msr_counter_info_t *msr_counter_info;
unsigned int msr_counter_info_size;

struct msr_counter_arch_info {
 const char *perf_subsys;
 const char *perf_name;
 unsigned long long msr;
 unsigned long long msr_mask;
 unsigned int rci_index; /* Maps data from perf counters to global variables */
 bool needed;
 bool present;
};

enum msr_arch_info_index {
 MSR_ARCH_INFO_APERF_INDEX = 0,
 MSR_ARCH_INFO_MPERF_INDEX = 1,
 MSR_ARCH_INFO_SMI_INDEX = 2,
};

static struct msr_counter_arch_info msr_counter_arch_infos[] = {
 [MSR_ARCH_INFO_APERF_INDEX] = {
           .perf_subsys = "msr",
           .perf_name = "aperf",
           .msr = MSR_IA32_APERF,
           .msr_mask = 0xFFFFFFFFFFFFFFFF,
           .rci_index = MSR_RCI_INDEX_APERF,
            },

 [MSR_ARCH_INFO_MPERF_INDEX] = {
           .perf_subsys = "msr",
           .perf_name = "mperf",
           .msr = MSR_IA32_MPERF,
           .msr_mask = 0xFFFFFFFFFFFFFFFF,
           .rci_index = MSR_RCI_INDEX_MPERF,
            },

 [MSR_ARCH_INFO_SMI_INDEX] = {
         .perf_subsys = "msr",
         .perf_name = "smi",
         .msr = MSR_SMI_COUNT,
         .msr_mask = 0xFFFFFFFF,
         .rci_index = MSR_RCI_INDEX_SMI,
          },
};

/* Can be redefined when compiling, useful for testing. */
#ifndef SYSFS_TELEM_PATH
#define SYSFS_TELEM_PATH "/sys/class/intel_pmt"
#endif

#define PMT_COUNTER_MTL_DC6_OFFSET 120
#define PMT_COUNTER_MTL_DC6_LSB    0
#define PMT_COUNTER_MTL_DC6_MSB    63
#define PMT_MTL_DC6_GUID           0x1a067102
#define PMT_MTL_DC6_SEQ            0

#define PMT_COUNTER_CWF_MC1E_OFFSET_BASE          20936
#define PMT_COUNTER_CWF_MC1E_OFFSET_INCREMENT     24
#define PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE 12
#define PMT_COUNTER_CWF_CPUS_PER_MODULE           4
#define PMT_COUNTER_CWF_MC1E_LSB                  0
#define PMT_COUNTER_CWF_MC1E_MSB                  63
#define PMT_CWF_MC1E_GUID                         0x14421519

unsigned long long tcore_clock_freq_hz = 800000000;

#define PMT_COUNTER_NAME_SIZE_BYTES      16
#define PMT_COUNTER_TYPE_NAME_SIZE_BYTES 32

struct pmt_mmio {
 struct pmt_mmio *next;

 unsigned int guid;
 unsigned int size;

 /* Base pointer to the mmaped memory. */
 void *mmio_base;

 /*
 * Offset to be applied to the mmio_base
 * to get the beginning of the PMT counters for given GUID.
 */

 unsigned long pmt_offset;
} *pmt_mmios;

enum pmt_datatype {
 PMT_TYPE_RAW,
 PMT_TYPE_XTAL_TIME,
 PMT_TYPE_TCORE_CLOCK,
};

struct pmt_domain_info {
 /*
 * Pointer to the MMIO obtained by applying a counter offset
 * to the mmio_base of the mmaped region for the given GUID.
 *
 * This is where to read the raw value of the counter from.
 */

 unsigned long *pcounter;
};

struct pmt_counter {
 struct pmt_counter *next;

 /* PMT metadata */
 char name[PMT_COUNTER_NAME_SIZE_BYTES];
 enum pmt_datatype type;
 enum counter_scope scope;
 unsigned int lsb;
 unsigned int msb;

 /* BIC-like metadata */
 enum counter_format format;

 unsigned int num_domains;
 struct pmt_domain_info *domains;
};

/*
 * PMT telemetry directory iterator.
 * Used to iterate telemetry files in sysfs in correct order.
 */

struct pmt_diriter_t {
 DIR *dir;
 struct dirent **namelist;
 unsigned int num_names;
 unsigned int current_name_idx;
};

int pmt_telemdir_filter(const struct dirent *e)
{
 unsigned int dummy;

 return sscanf(e->d_name, "telem%u", &dummy);
}

int pmt_telemdir_sort(const struct dirent **a, const struct dirent **b)
{
 unsigned int aidx = 0, bidx = 0;

 sscanf((*a)->d_name, "telem%u", &aidx);
 sscanf((*b)->d_name, "telem%u", &bidx);

 return (aidx > bidx) ? 1 : (aidx < bidx) ? -1 : 0;
}

const struct dirent *pmt_diriter_next(struct pmt_diriter_t *iter)
{
 const struct dirent *ret = NULL;

 if (!iter->dir)
  return NULL;

 if (iter->current_name_idx >= iter->num_names)
  return NULL;

 ret = iter->namelist[iter->current_name_idx];
 ++iter->current_name_idx;

 return ret;
}

const struct dirent *pmt_diriter_begin(struct pmt_diriter_t *iter, const char *pmt_root_path)
{
 int num_names = iter->num_names;

 if (!iter->dir) {
  iter->dir = opendir(pmt_root_path);
  if (iter->dir == NULL)
   return NULL;

  num_names = scandir(pmt_root_path, &iter->namelist, pmt_telemdir_filter, pmt_telemdir_sort);
  if (num_names == -1)
   return NULL;
 }

 iter->current_name_idx = 0;
 iter->num_names = num_names;

 return pmt_diriter_next(iter);
}

void pmt_diriter_init(struct pmt_diriter_t *iter)
{
 memset(iter, 0, sizeof(*iter));
}

void pmt_diriter_remove(struct pmt_diriter_t *iter)
{
 if (iter->namelist) {
  for (unsigned int i = 0; i < iter->num_names; i++) {
   free(iter->namelist[i]);
   iter->namelist[i] = NULL;
  }
 }

 free(iter->namelist);
 iter->namelist = NULL;
 iter->num_names = 0;
 iter->current_name_idx = 0;

 closedir(iter->dir);
 iter->dir = NULL;
}

unsigned int pmt_counter_get_width(const struct pmt_counter *p)
{
 return (p->msb - p->lsb) + 1;
}

void pmt_counter_resize_(struct pmt_counter *pcounter, unsigned int new_size)
{
 struct pmt_domain_info *new_mem;

 new_mem = (struct pmt_domain_info *)reallocarray(pcounter->domains, new_size, sizeof(*pcounter->domains));
 if (!new_mem) {
  fprintf(stderr, "%s: failed to allocate memory for PMT counters\n", __func__);
  exit(1);
 }

 /* Zero initialize just allocated memory. */
 const size_t num_new_domains = new_size - pcounter->num_domains;

 memset(&new_mem[pcounter->num_domains], 0, num_new_domains * sizeof(*pcounter->domains));

 pcounter->num_domains = new_size;
 pcounter->domains = new_mem;
}

void pmt_counter_resize(struct pmt_counter *pcounter, unsigned int new_size)
{
 /*
 * Allocate more memory ahead of time.
 *
 * Always allocate space for at least 8 elements
 * and double the size when growing.
 */

 if (new_size < 8)
  new_size = 8;
 new_size = MAX(new_size, pcounter->num_domains * 2);

 pmt_counter_resize_(pcounter, new_size);
}

struct thread_data {
 struct timeval tv_begin;
 struct timeval tv_end;
 struct timeval tv_delta;
 unsigned long long tsc;
 unsigned long long aperf;
 unsigned long long mperf;
 unsigned long long c1;
 unsigned long long instr_count;
 unsigned long long irq_count;
 unsigned long long nmi_count;
 unsigned int smi_count;
 unsigned int cpu_id;
 unsigned int apic_id;
 unsigned int x2apic_id;
 unsigned int flags;
 bool is_atom;
 unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];
 unsigned long long perf_counter[MAX_ADDED_THREAD_COUNTERS];
 unsigned long long pmt_counter[PMT_MAX_ADDED_THREAD_COUNTERS];
} *thread_even, *thread_odd;

struct core_data {
 int base_cpu;
 unsigned long long c3;
 unsigned long long c6;
 unsigned long long c7;
 unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */
 unsigned int core_temp_c;
 struct rapl_counter core_energy; /* MSR_CORE_ENERGY_STAT */
 unsigned int core_id;
 unsigned long long core_throt_cnt;
 unsigned long long counter[MAX_ADDED_CORE_COUNTERS];
 unsigned long long perf_counter[MAX_ADDED_CORE_COUNTERS];
 unsigned long long pmt_counter[PMT_MAX_ADDED_CORE_COUNTERS];
} *core_even, *core_odd;

struct pkg_data {
 int base_cpu;
 unsigned long long pc2;
 unsigned long long pc3;
 unsigned long long pc6;
 unsigned long long pc7;
 unsigned long long pc8;
 unsigned long long pc9;
 unsigned long long pc10;
 long long cpu_lpi;
 long long sys_lpi;
 unsigned long long pkg_wtd_core_c0;
 unsigned long long pkg_any_core_c0;
 unsigned long long pkg_any_gfxe_c0;
 unsigned long long pkg_both_core_gfxe_c0;
 long long gfx_rc6_ms;
 unsigned int gfx_mhz;
 unsigned int gfx_act_mhz;
 long long sam_mc6_ms;
 unsigned int sam_mhz;
 unsigned int sam_act_mhz;
 unsigned int package_id;
 struct rapl_counter energy_pkg; /* MSR_PKG_ENERGY_STATUS */
 struct rapl_counter energy_dram; /* MSR_DRAM_ENERGY_STATUS */
 struct rapl_counter energy_cores; /* MSR_PP0_ENERGY_STATUS */
 struct rapl_counter energy_gfx; /* MSR_PP1_ENERGY_STATUS */
 struct rapl_counter rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
 struct rapl_counter rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
 unsigned int pkg_temp_c;
 unsigned int uncore_mhz;
 unsigned long long die_c6;
 unsigned long long counter[MAX_ADDED_PACKAGE_COUNTERS];
 unsigned long long perf_counter[MAX_ADDED_PACKAGE_COUNTERS];
 unsigned long long pmt_counter[PMT_MAX_ADDED_PACKAGE_COUNTERS];
} *package_even, *package_odd;

#define ODD_COUNTERS thread_odd, core_odd, package_odd
#define EVEN_COUNTERS thread_even, core_even, package_even

#define GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no)       \
 ((thread_base) +            \
  ((pkg_no) *             \
   topo.nodes_per_pkg * topo.cores_per_node * topo.threads_per_core) + \
  ((node_no) * topo.cores_per_node * topo.threads_per_core) +       \
  ((core_no) * topo.threads_per_core) +          \
  (thread_no))

#define GET_CORE(core_base, core_no, node_no, pkg_no)   \
 ((core_base) +       \
  ((pkg_no) *  topo.nodes_per_pkg * topo.cores_per_node) + \
  ((node_no) * topo.cores_per_node) +    \
  (core_no))

/*
 * The accumulated sum of MSR is defined as a monotonic
 * increasing MSR, it will be accumulated periodically,
 * despite its register's bit width.
 */

enum {
 IDX_PKG_ENERGY,
 IDX_DRAM_ENERGY,
 IDX_PP0_ENERGY,
 IDX_PP1_ENERGY,
 IDX_PKG_PERF,
 IDX_DRAM_PERF,
 IDX_PSYS_ENERGY,
 IDX_COUNT,
};

int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);

struct msr_sum_array {
 /* get_msr_sum() = sum + (get_msr() - last) */
 struct {
  /*The accumulated MSR value is updated by the timer */
  unsigned long long sum;
  /*The MSR footprint recorded in last timer */
  unsigned long long last;
 } entries[IDX_COUNT];
};

/* The percpu MSR sum array.*/
struct msr_sum_array *per_cpu_msr_sum;

off_t idx_to_offset(int idx)
{
 off_t offset;

 switch (idx) {
 case IDX_PKG_ENERGY:
  if (platform->rapl_msrs & RAPL_AMD_F17H)
   offset = MSR_PKG_ENERGY_STAT;
  else
   offset = MSR_PKG_ENERGY_STATUS;
  break;
 case IDX_DRAM_ENERGY:
  offset = MSR_DRAM_ENERGY_STATUS;
  break;
 case IDX_PP0_ENERGY:
  offset = MSR_PP0_ENERGY_STATUS;
  break;
 case IDX_PP1_ENERGY:
  offset = MSR_PP1_ENERGY_STATUS;
  break;
 case IDX_PKG_PERF:
  offset = MSR_PKG_PERF_STATUS;
  break;
 case IDX_DRAM_PERF:
  offset = MSR_DRAM_PERF_STATUS;
  break;
 case IDX_PSYS_ENERGY:
  offset = MSR_PLATFORM_ENERGY_STATUS;
  break;
 default:
  offset = -1;
 }
 return offset;
}

int offset_to_idx(off_t offset)
{
 int idx;

 switch (offset) {
 case MSR_PKG_ENERGY_STATUS:
 case MSR_PKG_ENERGY_STAT:
  idx = IDX_PKG_ENERGY;
  break;
 case MSR_DRAM_ENERGY_STATUS:
  idx = IDX_DRAM_ENERGY;
  break;
 case MSR_PP0_ENERGY_STATUS:
  idx = IDX_PP0_ENERGY;
  break;
 case MSR_PP1_ENERGY_STATUS:
  idx = IDX_PP1_ENERGY;
  break;
 case MSR_PKG_PERF_STATUS:
  idx = IDX_PKG_PERF;
  break;
 case MSR_DRAM_PERF_STATUS:
  idx = IDX_DRAM_PERF;
  break;
 case MSR_PLATFORM_ENERGY_STATUS:
  idx = IDX_PSYS_ENERGY;
  break;
 default:
  idx = -1;
 }
 return idx;
}

int idx_valid(int idx)
{
 switch (idx) {
 case IDX_PKG_ENERGY:
  return platform->rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H);
 case IDX_DRAM_ENERGY:
  return platform->rapl_msrs & RAPL_DRAM;
 case IDX_PP0_ENERGY:
  return platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS;
 case IDX_PP1_ENERGY:
  return platform->rapl_msrs & RAPL_GFX;
 case IDX_PKG_PERF:
  return platform->rapl_msrs & RAPL_PKG_PERF_STATUS;
 case IDX_DRAM_PERF:
  return platform->rapl_msrs & RAPL_DRAM_PERF_STATUS;
 case IDX_PSYS_ENERGY:
  return platform->rapl_msrs & RAPL_PSYS;
 default:
  return 0;
 }
}

struct sys_counters {
 /* MSR added counters */
 unsigned int added_thread_counters;
 unsigned int added_core_counters;
 unsigned int added_package_counters;
 struct msr_counter *tp;
 struct msr_counter *cp;
 struct msr_counter *pp;

 /* perf added counters */
 unsigned int added_thread_perf_counters;
 unsigned int added_core_perf_counters;
 unsigned int added_package_perf_counters;
 struct perf_counter_info *perf_tp;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=99 G=96

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.