Path: blob/master/tools/power/x86/turbostat/turbostat.c
54337 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* turbostat -- show CPU frequency and C-state residency3* on modern Intel and AMD processors.4*5* Copyright (c) 2010 - 2026 Intel Corporation6* Len Brown <[email protected]>7*/89#define _GNU_SOURCE10#include MSRHEADER1112// copied from arch/x86/include/asm/cpu_device_id.h13#define VFM_MODEL_BIT 014#define VFM_FAMILY_BIT 815#define VFM_VENDOR_BIT 1616#define VFM_RSVD_BIT 241718#define VFM_MODEL_MASK GENMASK(VFM_FAMILY_BIT - 1, VFM_MODEL_BIT)19#define VFM_FAMILY_MASK GENMASK(VFM_VENDOR_BIT - 1, VFM_FAMILY_BIT)20#define VFM_VENDOR_MASK GENMASK(VFM_RSVD_BIT - 1, VFM_VENDOR_BIT)2122#define VFM_MODEL(vfm) (((vfm) & VFM_MODEL_MASK) >> VFM_MODEL_BIT)23#define VFM_FAMILY(vfm) (((vfm) & VFM_FAMILY_MASK) >> VFM_FAMILY_BIT)24#define VFM_VENDOR(vfm) (((vfm) & VFM_VENDOR_MASK) >> VFM_VENDOR_BIT)2526#define VFM_MAKE(_vendor, _family, _model) ( \27((_model) << VFM_MODEL_BIT) | \28((_family) << VFM_FAMILY_BIT) | \29((_vendor) << VFM_VENDOR_BIT) \30)31// end copied section3233#define CPUID_LEAF_MODEL_ID 0x1A34#define CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT 243536#define X86_VENDOR_INTEL 03738#include INTEL_FAMILY_HEADER39#include BUILD_BUG_HEADER40#include <stdarg.h>41#include <stdio.h>42#include <err.h>43#include <unistd.h>44#include <sys/types.h>45#include <sys/wait.h>46#include <sys/stat.h>47#include <sys/select.h>48#include <sys/resource.h>49#include <sys/mman.h>50#include <fcntl.h>51#include <signal.h>52#include <sys/time.h>53#include <stdlib.h>54#include <getopt.h>55#include <dirent.h>56#include <string.h>57#include <ctype.h>58#include <sched.h>59#include <time.h>60#include <cpuid.h>61#include <sys/capability.h>62#include <errno.h>63#include <math.h>64#include <linux/perf_event.h>65#include <asm/unistd.h>66#include <stdbool.h>67#include <assert.h>68#include <linux/kernel.h>69#include <limits.h>7071#define UNUSED(x) (void)(x)7273/*74* This list matches the column headers, except75* 1. built-in only, the sysfs counters are not here -- we learn of those at run-time76* 2. Core and CPU are moved to the end, we can't have strings that contain them77* matching on them for --show and --hide.78*/7980/*81* buffer size used by sscanf() for added column names82* Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters83*/84#define NAME_BYTES 2085#define PATH_BYTES 12886#define PERF_NAME_BYTES 1288788#define MAX_NOFILE 0x80008990#define COUNTER_KIND_PERF_PREFIX "perf/"91#define COUNTER_KIND_PERF_PREFIX_LEN strlen(COUNTER_KIND_PERF_PREFIX)92#define PERF_DEV_NAME_BYTES 3293#define PERF_EVT_NAME_BYTES 329495#define INTEL_ECORE_TYPE 0x2096#define INTEL_PCORE_TYPE 0x409798#define ROUND_UP_TO_PAGE_SIZE(n) (((n) + 0x1000UL-1UL) & ~(0x1000UL-1UL))99100enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };101enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M };102enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT, FORMAT_AVERAGE };103enum counter_source { COUNTER_SOURCE_NONE, COUNTER_SOURCE_PERF, COUNTER_SOURCE_MSR };104105struct perf_counter_info {106struct perf_counter_info *next;107108/* How to open the counter / What counter it is. */109char device[PERF_DEV_NAME_BYTES];110char event[PERF_EVT_NAME_BYTES];111112/* How to show/format the counter. */113char name[PERF_NAME_BYTES];114unsigned int width;115enum counter_scope scope;116enum counter_type type;117enum counter_format format;118double scale;119120/* For reading the counter. */121int *fd_perf_per_domain;122size_t num_domains;123};124125struct sysfs_path {126char path[PATH_BYTES];127int id;128struct sysfs_path *next;129};130131struct msr_counter {132unsigned int msr_num;133char name[NAME_BYTES];134struct sysfs_path *sp;135unsigned int width;136enum counter_type type;137enum counter_format format;138struct msr_counter *next;139unsigned int flags;140#define FLAGS_HIDE (1 << 0)141#define FLAGS_SHOW (1 << 1)142#define SYSFS_PERCPU (1 << 1)143};144static int use_android_msr_path;145146struct msr_counter bic[] = {147{ 0x0, "usec", NULL, 0, 0, 0, NULL, 0 },148{ 0x0, "Time_Of_Day_Seconds", NULL, 0, 0, 0, NULL, 0 },149{ 0x0, "Package", NULL, 0, 0, 0, NULL, 0 },150{ 0x0, "Node", NULL, 0, 0, 0, NULL, 0 },151{ 0x0, "Avg_MHz", NULL, 0, 0, 0, NULL, 0 },152{ 0x0, "Busy%", NULL, 0, 0, 0, NULL, 0 },153{ 0x0, "Bzy_MHz", NULL, 0, 0, 0, NULL, 0 },154{ 0x0, "TSC_MHz", NULL, 0, 0, 0, NULL, 0 },155{ 0x0, "IRQ", NULL, 0, 0, 0, NULL, 0 },156{ 0x0, "SMI", NULL, 32, 0, FORMAT_DELTA, NULL, 0 },157{ 0x0, "cpuidle", NULL, 0, 0, 0, NULL, 0 },158{ 0x0, "CPU%c1", NULL, 0, 0, 0, NULL, 0 },159{ 0x0, "CPU%c3", NULL, 0, 0, 0, NULL, 0 },160{ 0x0, "CPU%c6", NULL, 0, 0, 0, NULL, 0 },161{ 0x0, "CPU%c7", NULL, 0, 0, 0, NULL, 0 },162{ 0x0, "ThreadC", NULL, 0, 0, 0, NULL, 0 },163{ 0x0, "CoreTmp", NULL, 0, 0, 0, NULL, 0 },164{ 0x0, "CoreCnt", NULL, 0, 0, 0, NULL, 0 },165{ 0x0, "PkgTmp", NULL, 0, 0, 0, NULL, 0 },166{ 0x0, "GFX%rc6", NULL, 0, 0, 0, NULL, 0 },167{ 0x0, "GFXMHz", NULL, 0, 0, 0, NULL, 0 },168{ 0x0, "Pkg%pc2", NULL, 0, 0, 0, NULL, 0 },169{ 0x0, "Pkg%pc3", NULL, 0, 0, 0, NULL, 0 },170{ 0x0, "Pkg%pc6", NULL, 0, 0, 0, NULL, 0 },171{ 0x0, "Pkg%pc7", NULL, 0, 0, 0, NULL, 0 },172{ 0x0, "Pkg%pc8", NULL, 0, 0, 0, NULL, 0 },173{ 0x0, "Pkg%pc9", NULL, 0, 0, 0, NULL, 0 },174{ 0x0, "Pk%pc10", NULL, 0, 0, 0, NULL, 0 },175{ 0x0, "CPU%LPI", NULL, 0, 0, 0, NULL, 0 },176{ 0x0, "SYS%LPI", NULL, 0, 0, 0, NULL, 0 },177{ 0x0, "PkgWatt", NULL, 0, 0, 0, NULL, 0 },178{ 0x0, "CorWatt", NULL, 0, 0, 0, NULL, 0 },179{ 0x0, "GFXWatt", NULL, 0, 0, 0, NULL, 0 },180{ 0x0, "PkgCnt", NULL, 0, 0, 0, NULL, 0 },181{ 0x0, "RAMWatt", NULL, 0, 0, 0, NULL, 0 },182{ 0x0, "PKG_%", NULL, 0, 0, 0, NULL, 0 },183{ 0x0, "RAM_%", NULL, 0, 0, 0, NULL, 0 },184{ 0x0, "Pkg_J", NULL, 0, 0, 0, NULL, 0 },185{ 0x0, "Cor_J", NULL, 0, 0, 0, NULL, 0 },186{ 0x0, "GFX_J", NULL, 0, 0, 0, NULL, 0 },187{ 0x0, "RAM_J", NULL, 0, 0, 0, NULL, 0 },188{ 0x0, "Mod%c6", NULL, 0, 0, 0, NULL, 0 },189{ 0x0, "Totl%C0", NULL, 0, 0, 0, NULL, 0 },190{ 0x0, "Any%C0", NULL, 0, 0, 0, NULL, 0 },191{ 0x0, "GFX%C0", NULL, 0, 0, 0, NULL, 0 },192{ 0x0, "CPUGFX%", NULL, 0, 0, 0, NULL, 0 },193{ 0x0, "Core", NULL, 0, 0, 0, NULL, 0 },194{ 0x0, "CPU", NULL, 0, 0, 0, NULL, 0 },195{ 0x0, "APIC", NULL, 0, 0, 0, NULL, 0 },196{ 0x0, "X2APIC", NULL, 0, 0, 0, NULL, 0 },197{ 0x0, "Die", NULL, 0, 0, 0, NULL, 0 },198{ 0x0, "L3", NULL, 0, 0, 0, NULL, 0 },199{ 0x0, "GFXAMHz", NULL, 0, 0, 0, NULL, 0 },200{ 0x0, "IPC", NULL, 0, 0, 0, NULL, 0 },201{ 0x0, "CoreThr", NULL, 0, 0, 0, NULL, 0 },202{ 0x0, "UncMHz", NULL, 0, 0, 0, NULL, 0 },203{ 0x0, "SAM%mc6", NULL, 0, 0, 0, NULL, 0 },204{ 0x0, "SAMMHz", NULL, 0, 0, 0, NULL, 0 },205{ 0x0, "SAMAMHz", NULL, 0, 0, 0, NULL, 0 },206{ 0x0, "Die%c6", NULL, 0, 0, 0, NULL, 0 },207{ 0x0, "SysWatt", NULL, 0, 0, 0, NULL, 0 },208{ 0x0, "Sys_J", NULL, 0, 0, 0, NULL, 0 },209{ 0x0, "NMI", NULL, 0, 0, 0, NULL, 0 },210{ 0x0, "CPU%c1e", NULL, 0, 0, 0, NULL, 0 },211{ 0x0, "pct_idle", NULL, 0, 0, 0, NULL, 0 },212{ 0x0, "LLCMRPS", NULL, 0, 0, 0, NULL, 0 },213{ 0x0, "LLC%hit", NULL, 0, 0, 0, NULL, 0 },214{ 0x0, "L2MRPS", NULL, 0, 0, 0, NULL, 0 },215{ 0x0, "L2%hit", NULL, 0, 0, 0, NULL, 0 },216};217218/* n.b. bic_names must match the order in bic[], above */219enum bic_names {220BIC_USEC,221BIC_TOD,222BIC_Package,223BIC_Node,224BIC_Avg_MHz,225BIC_Busy,226BIC_Bzy_MHz,227BIC_TSC_MHz,228BIC_IRQ,229BIC_SMI,230BIC_cpuidle,231BIC_CPU_c1,232BIC_CPU_c3,233BIC_CPU_c6,234BIC_CPU_c7,235BIC_ThreadC,236BIC_CoreTmp,237BIC_CoreCnt,238BIC_PkgTmp,239BIC_GFX_rc6,240BIC_GFXMHz,241BIC_Pkgpc2,242BIC_Pkgpc3,243BIC_Pkgpc6,244BIC_Pkgpc7,245BIC_Pkgpc8,246BIC_Pkgpc9,247BIC_Pkgpc10,248BIC_CPU_LPI,249BIC_SYS_LPI,250BIC_PkgWatt,251BIC_CorWatt,252BIC_GFXWatt,253BIC_PkgCnt,254BIC_RAMWatt,255BIC_PKG__,256BIC_RAM__,257BIC_Pkg_J,258BIC_Cor_J,259BIC_GFX_J,260BIC_RAM_J,261BIC_Mod_c6,262BIC_Totl_c0,263BIC_Any_c0,264BIC_GFX_c0,265BIC_CPUGFX,266BIC_Core,267BIC_CPU,268BIC_APIC,269BIC_X2APIC,270BIC_Die,271BIC_L3,272BIC_GFXACTMHz,273BIC_IPC,274BIC_CORE_THROT_CNT,275BIC_UNCORE_MHZ,276BIC_SAM_mc6,277BIC_SAMMHz,278BIC_SAMACTMHz,279BIC_Diec6,280BIC_SysWatt,281BIC_Sys_J,282BIC_NMI,283BIC_CPU_c1e,284BIC_pct_idle,285BIC_LLC_MRPS,286BIC_LLC_HIT,287BIC_L2_MRPS,288BIC_L2_HIT,289MAX_BIC290};291292void print_bic_set(char *s, cpu_set_t *set)293{294int i;295296assert(MAX_BIC < CPU_SETSIZE);297298printf("%s:", s);299300for (i = 0; i < MAX_BIC; ++i) {301302if (CPU_ISSET(i, set))303printf(" %s", bic[i].name);304}305putchar('\n');306}307308static cpu_set_t bic_group_topology;309static cpu_set_t bic_group_thermal_pwr;310static cpu_set_t bic_group_frequency;311static cpu_set_t bic_group_hw_idle;312static cpu_set_t bic_group_sw_idle;313static cpu_set_t bic_group_idle;314static cpu_set_t bic_group_cache;315static cpu_set_t bic_group_other;316static cpu_set_t bic_group_disabled_by_default;317static cpu_set_t bic_enabled;318static cpu_set_t bic_present;319320/* modify */321#define BIC_INIT(set) CPU_ZERO(set)322323#define SET_BIC(COUNTER_NUMBER, set) CPU_SET(COUNTER_NUMBER, set)324#define CLR_BIC(COUNTER_NUMBER, set) CPU_CLR(COUNTER_NUMBER, set)325326#define BIC_PRESENT(COUNTER_NUMBER) SET_BIC(COUNTER_NUMBER, &bic_present)327#define BIC_NOT_PRESENT(COUNTER_NUMBER) CPU_CLR(COUNTER_NUMBER, &bic_present)328329/* test */330#define BIC_IS_ENABLED(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_enabled)331#define DO_BIC_READ(COUNTER_NUMBER) CPU_ISSET(COUNTER_NUMBER, &bic_present)332#define DO_BIC(COUNTER_NUMBER) (CPU_ISSET(COUNTER_NUMBER, &bic_enabled) && CPU_ISSET(COUNTER_NUMBER, &bic_present))333334static void bic_set_all(cpu_set_t *set)335{336int i;337338assert(MAX_BIC < CPU_SETSIZE);339340for (i = 0; i < MAX_BIC; ++i)341SET_BIC(i, set);342}343344/*345* bic_clear_bits()346* clear all the bits from "clr" in "dst"347*/348static void bic_clear_bits(cpu_set_t *dst, cpu_set_t *clr)349{350int i;351352assert(MAX_BIC < CPU_SETSIZE);353354for (i = 0; i < MAX_BIC; ++i)355if (CPU_ISSET(i, clr))356CLR_BIC(i, dst);357}358359static void bic_groups_init(void)360{361BIC_INIT(&bic_group_topology);362SET_BIC(BIC_Package, &bic_group_topology);363SET_BIC(BIC_Node, &bic_group_topology);364SET_BIC(BIC_CoreCnt, &bic_group_topology);365SET_BIC(BIC_PkgCnt, &bic_group_topology);366SET_BIC(BIC_Core, &bic_group_topology);367SET_BIC(BIC_CPU, &bic_group_topology);368SET_BIC(BIC_Die, &bic_group_topology);369SET_BIC(BIC_L3, &bic_group_topology);370371BIC_INIT(&bic_group_thermal_pwr);372SET_BIC(BIC_CoreTmp, &bic_group_thermal_pwr);373SET_BIC(BIC_PkgTmp, &bic_group_thermal_pwr);374SET_BIC(BIC_PkgWatt, &bic_group_thermal_pwr);375SET_BIC(BIC_CorWatt, &bic_group_thermal_pwr);376SET_BIC(BIC_GFXWatt, &bic_group_thermal_pwr);377SET_BIC(BIC_RAMWatt, &bic_group_thermal_pwr);378SET_BIC(BIC_PKG__, &bic_group_thermal_pwr);379SET_BIC(BIC_RAM__, &bic_group_thermal_pwr);380SET_BIC(BIC_SysWatt, &bic_group_thermal_pwr);381382BIC_INIT(&bic_group_frequency);383SET_BIC(BIC_Avg_MHz, &bic_group_frequency);384SET_BIC(BIC_Busy, &bic_group_frequency);385SET_BIC(BIC_Bzy_MHz, &bic_group_frequency);386SET_BIC(BIC_TSC_MHz, &bic_group_frequency);387SET_BIC(BIC_GFXMHz, &bic_group_frequency);388SET_BIC(BIC_GFXACTMHz, &bic_group_frequency);389SET_BIC(BIC_SAMMHz, &bic_group_frequency);390SET_BIC(BIC_SAMACTMHz, &bic_group_frequency);391SET_BIC(BIC_UNCORE_MHZ, &bic_group_frequency);392393BIC_INIT(&bic_group_hw_idle);394SET_BIC(BIC_Busy, &bic_group_hw_idle);395SET_BIC(BIC_CPU_c1, &bic_group_hw_idle);396SET_BIC(BIC_CPU_c3, &bic_group_hw_idle);397SET_BIC(BIC_CPU_c6, &bic_group_hw_idle);398SET_BIC(BIC_CPU_c7, &bic_group_hw_idle);399SET_BIC(BIC_GFX_rc6, &bic_group_hw_idle);400SET_BIC(BIC_Pkgpc2, &bic_group_hw_idle);401SET_BIC(BIC_Pkgpc3, &bic_group_hw_idle);402SET_BIC(BIC_Pkgpc6, &bic_group_hw_idle);403SET_BIC(BIC_Pkgpc7, &bic_group_hw_idle);404SET_BIC(BIC_Pkgpc8, &bic_group_hw_idle);405SET_BIC(BIC_Pkgpc9, &bic_group_hw_idle);406SET_BIC(BIC_Pkgpc10, &bic_group_hw_idle);407SET_BIC(BIC_CPU_LPI, &bic_group_hw_idle);408SET_BIC(BIC_SYS_LPI, &bic_group_hw_idle);409SET_BIC(BIC_Mod_c6, &bic_group_hw_idle);410SET_BIC(BIC_Totl_c0, &bic_group_hw_idle);411SET_BIC(BIC_Any_c0, &bic_group_hw_idle);412SET_BIC(BIC_GFX_c0, &bic_group_hw_idle);413SET_BIC(BIC_CPUGFX, &bic_group_hw_idle);414SET_BIC(BIC_SAM_mc6, &bic_group_hw_idle);415SET_BIC(BIC_Diec6, &bic_group_hw_idle);416417BIC_INIT(&bic_group_sw_idle);418SET_BIC(BIC_Busy, &bic_group_sw_idle);419SET_BIC(BIC_cpuidle, &bic_group_sw_idle);420SET_BIC(BIC_pct_idle, &bic_group_sw_idle);421422BIC_INIT(&bic_group_idle);423424CPU_OR(&bic_group_idle, &bic_group_idle, &bic_group_hw_idle);425SET_BIC(BIC_pct_idle, &bic_group_idle);426427BIC_INIT(&bic_group_cache);428SET_BIC(BIC_LLC_MRPS, &bic_group_cache);429SET_BIC(BIC_LLC_HIT, &bic_group_cache);430SET_BIC(BIC_L2_MRPS, &bic_group_cache);431SET_BIC(BIC_L2_HIT, &bic_group_cache);432433BIC_INIT(&bic_group_other);434SET_BIC(BIC_IRQ, &bic_group_other);435SET_BIC(BIC_NMI, &bic_group_other);436SET_BIC(BIC_SMI, &bic_group_other);437SET_BIC(BIC_ThreadC, &bic_group_other);438SET_BIC(BIC_CoreTmp, &bic_group_other);439SET_BIC(BIC_IPC, &bic_group_other);440441BIC_INIT(&bic_group_disabled_by_default);442SET_BIC(BIC_USEC, &bic_group_disabled_by_default);443SET_BIC(BIC_TOD, &bic_group_disabled_by_default);444SET_BIC(BIC_cpuidle, &bic_group_disabled_by_default);445SET_BIC(BIC_APIC, &bic_group_disabled_by_default);446SET_BIC(BIC_X2APIC, &bic_group_disabled_by_default);447448BIC_INIT(&bic_enabled);449bic_set_all(&bic_enabled);450bic_clear_bits(&bic_enabled, &bic_group_disabled_by_default);451452BIC_INIT(&bic_present);453SET_BIC(BIC_USEC, &bic_present);454SET_BIC(BIC_TOD, &bic_present);455SET_BIC(BIC_cpuidle, &bic_present);456SET_BIC(BIC_APIC, &bic_present);457SET_BIC(BIC_X2APIC, &bic_present);458SET_BIC(BIC_pct_idle, &bic_present);459}460461/*462* MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit:463* If you change the values, note they are used both in comparisons464* (>= PCL__7) and to index pkg_cstate_limit_strings[].465*/466#define PCLUKN 0 /* Unknown */467#define PCLRSV 1 /* Reserved */468#define PCL__0 2 /* PC0 */469#define PCL__1 3 /* PC1 */470#define PCL__2 4 /* PC2 */471#define PCL__3 5 /* PC3 */472#define PCL__4 6 /* PC4 */473#define PCL__6 7 /* PC6 */474#define PCL_6N 8 /* PC6 No Retention */475#define PCL_6R 9 /* PC6 Retention */476#define PCL__7 10 /* PC7 */477#define PCL_7S 11 /* PC7 Shrink */478#define PCL__8 12 /* PC8 */479#define PCL__9 13 /* PC9 */480#define PCL_10 14 /* PC10 */481#define PCLUNL 15 /* Unlimited */482483char *proc_stat = "/proc/stat";484FILE *outf;485int *fd_percpu;486int *fd_instr_count_percpu;487int *fd_llc_percpu;488int *fd_l2_percpu;489struct timeval interval_tv = { 5, 0 };490struct timespec interval_ts = { 5, 0 };491492unsigned int num_iterations;493unsigned int header_iterations;494unsigned int debug;495unsigned int quiet;496unsigned int shown;497unsigned int sums_need_wide_columns;498unsigned int rapl_joules;499unsigned int valid_rapl_msrs;500unsigned int summary_only;501unsigned int list_header_only;502unsigned int dump_only;503unsigned int force_load;504unsigned int cpuid_has_aperf_mperf;505unsigned int cpuid_has_hv;506unsigned int has_aperf_access;507unsigned int has_epb;508unsigned int has_turbo;509unsigned int is_hybrid;510unsigned int units = 1000000; /* MHz etc */511unsigned int genuine_intel;512unsigned int authentic_amd;513unsigned int hygon_genuine;514unsigned int max_level, max_extended_level;515unsigned int has_invariant_tsc;516unsigned int aperf_mperf_multiplier = 1;517double bclk;518double base_hz;519unsigned int has_base_hz;520double tsc_tweak = 1.0;521unsigned int show_pkg_only;522unsigned int show_core_only;523char *output_buffer, *outp;524unsigned int do_dts;525unsigned int do_ptm;526unsigned int do_ipc;527unsigned long long cpuidle_cur_cpu_lpi_us;528unsigned long long cpuidle_cur_sys_lpi_us;529unsigned int tj_max;530unsigned int tj_max_override;531double rapl_power_units, rapl_time_units;532double rapl_dram_energy_units, rapl_energy_units, rapl_psys_energy_units;533double rapl_joule_counter_range;534unsigned int crystal_hz;535unsigned long long tsc_hz;536int master_cpu;537unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */538/* IA32_HWP_REQUEST, IA32_HWP_STATUS */539unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */540unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */541unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */542unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */543unsigned int first_counter_read = 1;544545static struct timeval procsysfs_tv_begin;546547int ignore_stdin;548bool no_msr;549bool no_perf;550551enum gfx_sysfs_idx {552GFX_rc6,553GFX_MHz,554GFX_ACTMHz,555SAM_mc6,556SAM_MHz,557SAM_ACTMHz,558GFX_MAX559};560561struct gfx_sysfs_info {562FILE *fp;563unsigned int val;564unsigned long long val_ull;565};566567static struct gfx_sysfs_info gfx_info[GFX_MAX];568569int get_msr(int cpu, off_t offset, unsigned long long *msr);570int add_counter(unsigned int msr_num, char *path, char *name,571unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int package_num);572573/* Model specific support Start */574575/* List of features that may diverge among different platforms */576struct platform_features {577bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */578bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */579bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, MSR_IA32_POWER_CTL, TRL MSRs */580bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */581int bclk_freq; /* CPU base clock */582int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */583int supported_cstates; /* Core cstates and Package cstates supported */584int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */585bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */586bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */587bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */588bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */589bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */590bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */591bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */592bool 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 */593bool has_cst_prewake_bit; /* Cstate prewake bit in MSR_IA32_POWER_CTL */594int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */595int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */596int plat_rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */597bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */598bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */599bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */600bool has_fixed_rapl_psys_unit; /* Fixed Energy Unit used for PSYS RAPL Domain */601int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */602int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */603bool enable_tsc_tweak; /* Use CPU Base freq instead of TSC freq for aperf/mperf counter */604bool need_perf_multiplier; /* mperf/aperf multiplier */605};606607struct platform_data {608unsigned int vfm;609const struct platform_features *features;610};611612/* For BCLK */613enum bclk_freq {614BCLK_100MHZ = 1,615BCLK_133MHZ,616BCLK_SLV,617};618619#define SLM_BCLK_FREQS 5620double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 };621622double slm_bclk(void)623{624unsigned long long msr = 3;625unsigned int i;626double freq;627628if (get_msr(master_cpu, MSR_FSB_FREQ, &msr))629fprintf(outf, "SLM BCLK: unknown\n");630631i = msr & 0xf;632if (i >= SLM_BCLK_FREQS) {633fprintf(outf, "SLM BCLK[%d] invalid\n", i);634i = 3;635}636freq = slm_freq_table[i];637638if (!quiet)639fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);640641return freq;642}643644/* For Package cstate limit */645enum package_cstate_limit {646CST_LIMIT_NHM = 1,647CST_LIMIT_SNB,648CST_LIMIT_HSW,649CST_LIMIT_SKX,650CST_LIMIT_ICX,651CST_LIMIT_SLV,652CST_LIMIT_AMT,653CST_LIMIT_KNL,654CST_LIMIT_GMT,655};656657/* For Turbo Ratio Limit MSRs */658enum turbo_ratio_limit_msrs {659TRL_BASE = BIT(0),660TRL_LIMIT1 = BIT(1),661TRL_LIMIT2 = BIT(2),662TRL_ATOM = BIT(3),663TRL_KNL = BIT(4),664TRL_CORECOUNT = BIT(5),665};666667/* For Perf Limit Reason MSRs */668enum perf_limit_reason_msrs {669PLR_CORE = BIT(0),670PLR_GFX = BIT(1),671PLR_RING = BIT(2),672};673674/* For RAPL MSRs */675enum rapl_msrs {676RAPL_PKG_POWER_LIMIT = BIT(0), /* 0x610 MSR_PKG_POWER_LIMIT */677RAPL_PKG_ENERGY_STATUS = BIT(1), /* 0x611 MSR_PKG_ENERGY_STATUS */678RAPL_PKG_PERF_STATUS = BIT(2), /* 0x613 MSR_PKG_PERF_STATUS */679RAPL_PKG_POWER_INFO = BIT(3), /* 0x614 MSR_PKG_POWER_INFO */680RAPL_DRAM_POWER_LIMIT = BIT(4), /* 0x618 MSR_DRAM_POWER_LIMIT */681RAPL_DRAM_ENERGY_STATUS = BIT(5), /* 0x619 MSR_DRAM_ENERGY_STATUS */682RAPL_DRAM_PERF_STATUS = BIT(6), /* 0x61b MSR_DRAM_PERF_STATUS */683RAPL_DRAM_POWER_INFO = BIT(7), /* 0x61c MSR_DRAM_POWER_INFO */684RAPL_CORE_POWER_LIMIT = BIT(8), /* 0x638 MSR_PP0_POWER_LIMIT */685RAPL_CORE_ENERGY_STATUS = BIT(9), /* 0x639 MSR_PP0_ENERGY_STATUS */686RAPL_CORE_POLICY = BIT(10), /* 0x63a MSR_PP0_POLICY */687RAPL_GFX_POWER_LIMIT = BIT(11), /* 0x640 MSR_PP1_POWER_LIMIT */688RAPL_GFX_ENERGY_STATUS = BIT(12), /* 0x641 MSR_PP1_ENERGY_STATUS */689RAPL_GFX_POLICY = BIT(13), /* 0x642 MSR_PP1_POLICY */690RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */691RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */692RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */693RAPL_PLATFORM_ENERGY_LIMIT = BIT(17), /* 0x64c MSR_PLATFORM_ENERGY_LIMIT */694RAPL_PLATFORM_ENERGY_STATUS = BIT(18), /* 0x64d MSR_PLATFORM_ENERGY_STATUS */695};696697#define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT)698#define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT)699#define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT)700#define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS)701#define RAPL_PSYS (RAPL_PLATFORM_ENERGY_STATUS | RAPL_PLATFORM_ENERGY_LIMIT)702703#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)704#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)705#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY)706#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLICY)707708#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT)709710/* For Cstates */711enum cstates {712CC1 = BIT(0),713CC3 = BIT(1),714CC6 = BIT(2),715CC7 = BIT(3),716PC2 = BIT(4),717PC3 = BIT(5),718PC6 = BIT(6),719PC7 = BIT(7),720PC8 = BIT(8),721PC9 = BIT(9),722PC10 = BIT(10),723};724725static const struct platform_features nhm_features = {726.has_msr_misc_pwr_mgmt = 1,727.has_nhm_msrs = 1,728.bclk_freq = BCLK_133MHZ,729.supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,730.cst_limit = CST_LIMIT_NHM,731.trl_msrs = TRL_BASE,732};733734static const struct platform_features nhx_features = {735.has_msr_misc_pwr_mgmt = 1,736.has_nhm_msrs = 1,737.bclk_freq = BCLK_133MHZ,738.supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,739.cst_limit = CST_LIMIT_NHM,740};741742static const struct platform_features snb_features = {743.has_msr_misc_feature_control = 1,744.has_msr_misc_pwr_mgmt = 1,745.has_nhm_msrs = 1,746.bclk_freq = BCLK_100MHZ,747.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,748.cst_limit = CST_LIMIT_SNB,749.has_irtl_msrs = 1,750.trl_msrs = TRL_BASE,751.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,752};753754static const struct platform_features snx_features = {755.has_msr_misc_feature_control = 1,756.has_msr_misc_pwr_mgmt = 1,757.has_nhm_msrs = 1,758.bclk_freq = BCLK_100MHZ,759.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,760.cst_limit = CST_LIMIT_SNB,761.has_irtl_msrs = 1,762.trl_msrs = TRL_BASE,763.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,764};765766static const struct platform_features ivb_features = {767.has_msr_misc_feature_control = 1,768.has_msr_misc_pwr_mgmt = 1,769.has_nhm_msrs = 1,770.has_config_tdp = 1,771.bclk_freq = BCLK_100MHZ,772.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,773.cst_limit = CST_LIMIT_SNB,774.has_irtl_msrs = 1,775.trl_msrs = TRL_BASE,776.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,777};778779static const struct platform_features ivx_features = {780.has_msr_misc_feature_control = 1,781.has_msr_misc_pwr_mgmt = 1,782.has_nhm_msrs = 1,783.bclk_freq = BCLK_100MHZ,784.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,785.cst_limit = CST_LIMIT_SNB,786.has_irtl_msrs = 1,787.trl_msrs = TRL_BASE | TRL_LIMIT1,788.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL,789};790791static const struct platform_features hsw_features = {792.has_msr_misc_feature_control = 1,793.has_msr_misc_pwr_mgmt = 1,794.has_nhm_msrs = 1,795.has_config_tdp = 1,796.bclk_freq = BCLK_100MHZ,797.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,798.cst_limit = CST_LIMIT_HSW,799.has_irtl_msrs = 1,800.trl_msrs = TRL_BASE,801.plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,802.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,803};804805static const struct platform_features hsx_features = {806.has_msr_misc_feature_control = 1,807.has_msr_misc_pwr_mgmt = 1,808.has_nhm_msrs = 1,809.has_config_tdp = 1,810.bclk_freq = BCLK_100MHZ,811.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,812.cst_limit = CST_LIMIT_HSW,813.has_irtl_msrs = 1,814.trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2,815.plr_msrs = PLR_CORE | PLR_RING,816.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,817.has_fixed_rapl_unit = 1,818};819820static const struct platform_features hswl_features = {821.has_msr_misc_feature_control = 1,822.has_msr_misc_pwr_mgmt = 1,823.has_nhm_msrs = 1,824.has_config_tdp = 1,825.bclk_freq = BCLK_100MHZ,826.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,827.cst_limit = CST_LIMIT_HSW,828.has_irtl_msrs = 1,829.trl_msrs = TRL_BASE,830.plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,831.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,832};833834static const struct platform_features hswg_features = {835.has_msr_misc_feature_control = 1,836.has_msr_misc_pwr_mgmt = 1,837.has_nhm_msrs = 1,838.has_config_tdp = 1,839.bclk_freq = BCLK_100MHZ,840.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,841.cst_limit = CST_LIMIT_HSW,842.has_irtl_msrs = 1,843.trl_msrs = TRL_BASE,844.plr_msrs = PLR_CORE | PLR_GFX | PLR_RING,845.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,846};847848static const struct platform_features bdw_features = {849.has_msr_misc_feature_control = 1,850.has_msr_misc_pwr_mgmt = 1,851.has_nhm_msrs = 1,852.has_config_tdp = 1,853.bclk_freq = BCLK_100MHZ,854.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,855.cst_limit = CST_LIMIT_HSW,856.has_irtl_msrs = 1,857.trl_msrs = TRL_BASE,858.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,859};860861static const struct platform_features bdwg_features = {862.has_msr_misc_feature_control = 1,863.has_msr_misc_pwr_mgmt = 1,864.has_nhm_msrs = 1,865.has_config_tdp = 1,866.bclk_freq = BCLK_100MHZ,867.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7,868.cst_limit = CST_LIMIT_HSW,869.has_irtl_msrs = 1,870.trl_msrs = TRL_BASE,871.plat_rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO,872};873874static const struct platform_features bdx_features = {875.has_msr_misc_feature_control = 1,876.has_msr_misc_pwr_mgmt = 1,877.has_nhm_msrs = 1,878.has_config_tdp = 1,879.bclk_freq = BCLK_100MHZ,880.supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6,881.cst_limit = CST_LIMIT_HSW,882.has_irtl_msrs = 1,883.has_cst_auto_convension = 1,884.trl_msrs = TRL_BASE,885.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,886.has_fixed_rapl_unit = 1,887};888889static const struct platform_features skl_features = {890.has_msr_misc_feature_control = 1,891.has_msr_misc_pwr_mgmt = 1,892.has_nhm_msrs = 1,893.has_config_tdp = 1,894.bclk_freq = BCLK_100MHZ,895.crystal_freq = 24000000,896.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,897.cst_limit = CST_LIMIT_HSW,898.has_irtl_msrs = 1,899.has_ext_cst_msrs = 1,900.trl_msrs = TRL_BASE,901.tcc_offset_bits = 6,902.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS,903.enable_tsc_tweak = 1,904};905906static const struct platform_features cnl_features = {907.has_msr_misc_feature_control = 1,908.has_msr_misc_pwr_mgmt = 1,909.has_nhm_msrs = 1,910.has_config_tdp = 1,911.bclk_freq = BCLK_100MHZ,912.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,913.cst_limit = CST_LIMIT_HSW,914.has_irtl_msrs = 1,915.has_msr_core_c1_res = 1,916.has_ext_cst_msrs = 1,917.trl_msrs = TRL_BASE,918.tcc_offset_bits = 6,919.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS,920.enable_tsc_tweak = 1,921};922923/* Copied from cnl_features, with PC7/PC9 removed */924static const struct platform_features adl_features = {925.has_msr_misc_feature_control = cnl_features.has_msr_misc_feature_control,926.has_msr_misc_pwr_mgmt = cnl_features.has_msr_misc_pwr_mgmt,927.has_nhm_msrs = cnl_features.has_nhm_msrs,928.has_config_tdp = cnl_features.has_config_tdp,929.bclk_freq = cnl_features.bclk_freq,930.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10,931.cst_limit = cnl_features.cst_limit,932.has_irtl_msrs = cnl_features.has_irtl_msrs,933.has_msr_core_c1_res = cnl_features.has_msr_core_c1_res,934.has_ext_cst_msrs = cnl_features.has_ext_cst_msrs,935.trl_msrs = cnl_features.trl_msrs,936.tcc_offset_bits = cnl_features.tcc_offset_bits,937.plat_rapl_msrs = cnl_features.plat_rapl_msrs,938.enable_tsc_tweak = cnl_features.enable_tsc_tweak,939};940941/* Copied from adl_features, with PC3/PC8 removed */942static const struct platform_features lnl_features = {943.has_msr_misc_feature_control = adl_features.has_msr_misc_feature_control,944.has_msr_misc_pwr_mgmt = adl_features.has_msr_misc_pwr_mgmt,945.has_nhm_msrs = adl_features.has_nhm_msrs,946.has_config_tdp = adl_features.has_config_tdp,947.bclk_freq = adl_features.bclk_freq,948.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC6 | PC10,949.cst_limit = adl_features.cst_limit,950.has_irtl_msrs = adl_features.has_irtl_msrs,951.has_msr_core_c1_res = adl_features.has_msr_core_c1_res,952.has_ext_cst_msrs = adl_features.has_ext_cst_msrs,953.trl_msrs = adl_features.trl_msrs,954.tcc_offset_bits = adl_features.tcc_offset_bits,955.plat_rapl_msrs = adl_features.plat_rapl_msrs,956.enable_tsc_tweak = adl_features.enable_tsc_tweak,957};958959static const struct platform_features skx_features = {960.has_msr_misc_feature_control = 1,961.has_msr_misc_pwr_mgmt = 1,962.has_nhm_msrs = 1,963.has_config_tdp = 1,964.bclk_freq = BCLK_100MHZ,965.supported_cstates = CC1 | CC6 | PC2 | PC6,966.cst_limit = CST_LIMIT_SKX,967.has_irtl_msrs = 1,968.has_cst_auto_convension = 1,969.trl_msrs = TRL_BASE | TRL_CORECOUNT,970.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,971.has_fixed_rapl_unit = 1,972};973974static const struct platform_features icx_features = {975.has_msr_misc_feature_control = 1,976.has_msr_misc_pwr_mgmt = 1,977.has_nhm_msrs = 1,978.has_config_tdp = 1,979.bclk_freq = BCLK_100MHZ,980.supported_cstates = CC1 | CC6 | PC2 | PC6,981.cst_limit = CST_LIMIT_ICX,982.has_msr_core_c1_res = 1,983.has_irtl_msrs = 1,984.has_cst_prewake_bit = 1,985.trl_msrs = TRL_BASE | TRL_CORECOUNT,986.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,987.has_fixed_rapl_unit = 1,988};989990static const struct platform_features spr_features = {991.has_msr_misc_feature_control = 1,992.has_msr_misc_pwr_mgmt = 1,993.has_nhm_msrs = 1,994.has_config_tdp = 1,995.bclk_freq = BCLK_100MHZ,996.supported_cstates = CC1 | CC6 | PC2 | PC6,997.cst_limit = CST_LIMIT_SKX,998.has_msr_core_c1_res = 1,999.has_irtl_msrs = 1,1000.has_cst_prewake_bit = 1,1001.has_fixed_rapl_psys_unit = 1,1002.trl_msrs = TRL_BASE | TRL_CORECOUNT,1003.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,1004};10051006static const struct platform_features dmr_features = {1007.has_msr_misc_feature_control = spr_features.has_msr_misc_feature_control,1008.has_msr_misc_pwr_mgmt = spr_features.has_msr_misc_pwr_mgmt,1009.has_nhm_msrs = spr_features.has_nhm_msrs,1010.bclk_freq = spr_features.bclk_freq,1011.supported_cstates = spr_features.supported_cstates,1012.cst_limit = spr_features.cst_limit,1013.has_msr_core_c1_res = spr_features.has_msr_core_c1_res,1014.has_cst_prewake_bit = spr_features.has_cst_prewake_bit,1015.has_fixed_rapl_psys_unit = spr_features.has_fixed_rapl_psys_unit,1016.trl_msrs = spr_features.trl_msrs,1017.has_msr_module_c6_res_ms = 1, /* DMR has Dual-Core-Module and MC6 MSR */1018.plat_rapl_msrs = 0, /* DMR does not have RAPL MSRs */1019.plr_msrs = 0, /* DMR does not have PLR MSRs */1020.has_irtl_msrs = 0, /* DMR does not have IRTL MSRs */1021.has_config_tdp = 0, /* DMR does not have CTDP MSRs */1022};10231024static const struct platform_features srf_features = {1025.has_msr_misc_feature_control = 1,1026.has_msr_misc_pwr_mgmt = 1,1027.has_nhm_msrs = 1,1028.has_config_tdp = 1,1029.bclk_freq = BCLK_100MHZ,1030.supported_cstates = CC1 | CC6 | PC2 | PC6,1031.cst_limit = CST_LIMIT_SKX,1032.has_msr_core_c1_res = 1,1033.has_msr_module_c6_res_ms = 1,1034.has_irtl_msrs = 1,1035.has_cst_prewake_bit = 1,1036.trl_msrs = TRL_BASE | TRL_CORECOUNT,1037.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,1038};10391040static const struct platform_features grr_features = {1041.has_msr_misc_feature_control = 1,1042.has_msr_misc_pwr_mgmt = 1,1043.has_nhm_msrs = 1,1044.has_config_tdp = 1,1045.bclk_freq = BCLK_100MHZ,1046.supported_cstates = CC1 | CC6,1047.cst_limit = CST_LIMIT_SKX,1048.has_msr_core_c1_res = 1,1049.has_msr_module_c6_res_ms = 1,1050.has_irtl_msrs = 1,1051.has_cst_prewake_bit = 1,1052.trl_msrs = TRL_BASE | TRL_CORECOUNT,1053.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,1054};10551056static const struct platform_features slv_features = {1057.has_nhm_msrs = 1,1058.bclk_freq = BCLK_SLV,1059.supported_cstates = CC1 | CC6 | PC6,1060.cst_limit = CST_LIMIT_SLV,1061.has_msr_core_c1_res = 1,1062.has_msr_module_c6_res_ms = 1,1063.has_msr_c6_demotion_policy_config = 1,1064.has_msr_atom_pkg_c6_residency = 1,1065.trl_msrs = TRL_ATOM,1066.plat_rapl_msrs = RAPL_PKG | RAPL_CORE,1067.has_rapl_divisor = 1,1068.rapl_quirk_tdp = 30,1069};10701071static const struct platform_features slvd_features = {1072.has_msr_misc_pwr_mgmt = 1,1073.has_nhm_msrs = 1,1074.bclk_freq = BCLK_SLV,1075.supported_cstates = CC1 | CC6 | PC3 | PC6,1076.cst_limit = CST_LIMIT_SLV,1077.has_msr_atom_pkg_c6_residency = 1,1078.trl_msrs = TRL_BASE,1079.plat_rapl_msrs = RAPL_PKG | RAPL_CORE,1080.rapl_quirk_tdp = 30,1081};10821083static const struct platform_features amt_features = {1084.has_nhm_msrs = 1,1085.bclk_freq = BCLK_133MHZ,1086.supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6,1087.cst_limit = CST_LIMIT_AMT,1088.trl_msrs = TRL_BASE,1089};10901091static const struct platform_features gmt_features = {1092.has_msr_misc_pwr_mgmt = 1,1093.has_nhm_msrs = 1,1094.bclk_freq = BCLK_100MHZ,1095.crystal_freq = 19200000,1096.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,1097.cst_limit = CST_LIMIT_GMT,1098.has_irtl_msrs = 1,1099.trl_msrs = TRL_BASE | TRL_CORECOUNT,1100.plat_rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,1101};11021103static const struct platform_features gmtd_features = {1104.has_msr_misc_pwr_mgmt = 1,1105.has_nhm_msrs = 1,1106.bclk_freq = BCLK_100MHZ,1107.crystal_freq = 25000000,1108.supported_cstates = CC1 | CC6 | PC2 | PC6,1109.cst_limit = CST_LIMIT_GMT,1110.has_irtl_msrs = 1,1111.has_msr_core_c1_res = 1,1112.trl_msrs = TRL_BASE | TRL_CORECOUNT,1113.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS,1114};11151116static const struct platform_features gmtp_features = {1117.has_msr_misc_pwr_mgmt = 1,1118.has_nhm_msrs = 1,1119.bclk_freq = BCLK_100MHZ,1120.crystal_freq = 19200000,1121.supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,1122.cst_limit = CST_LIMIT_GMT,1123.has_irtl_msrs = 1,1124.trl_msrs = TRL_BASE,1125.plat_rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO,1126};11271128static const struct platform_features tmt_features = {1129.has_msr_misc_pwr_mgmt = 1,1130.has_nhm_msrs = 1,1131.bclk_freq = BCLK_100MHZ,1132.supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10,1133.cst_limit = CST_LIMIT_GMT,1134.has_irtl_msrs = 1,1135.trl_msrs = TRL_BASE,1136.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,1137.enable_tsc_tweak = 1,1138};11391140static const struct platform_features tmtd_features = {1141.has_msr_misc_pwr_mgmt = 1,1142.has_nhm_msrs = 1,1143.bclk_freq = BCLK_100MHZ,1144.supported_cstates = CC1 | CC6,1145.cst_limit = CST_LIMIT_GMT,1146.has_irtl_msrs = 1,1147.trl_msrs = TRL_BASE | TRL_CORECOUNT,1148.plat_rapl_msrs = RAPL_PKG_ALL,1149};11501151static const struct platform_features knl_features = {1152.has_msr_misc_pwr_mgmt = 1,1153.has_nhm_msrs = 1,1154.has_config_tdp = 1,1155.bclk_freq = BCLK_100MHZ,1156.supported_cstates = CC1 | CC6 | PC3 | PC6,1157.cst_limit = CST_LIMIT_KNL,1158.has_msr_knl_core_c6_residency = 1,1159.trl_msrs = TRL_KNL,1160.plat_rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,1161.has_fixed_rapl_unit = 1,1162.need_perf_multiplier = 1,1163};11641165static const struct platform_features default_features = {1166};11671168static const struct platform_features amd_features_with_rapl = {1169.plat_rapl_msrs = RAPL_AMD_F17H,1170.has_per_core_rapl = 1,1171.rapl_quirk_tdp = 280, /* This is the max stock TDP of HEDT/Server Fam17h+ chips */1172};11731174static const struct platform_data turbostat_pdata[] = {1175{ INTEL_NEHALEM, &nhm_features },1176{ INTEL_NEHALEM_G, &nhm_features },1177{ INTEL_NEHALEM_EP, &nhm_features },1178{ INTEL_NEHALEM_EX, &nhx_features },1179{ INTEL_WESTMERE, &nhm_features },1180{ INTEL_WESTMERE_EP, &nhm_features },1181{ INTEL_WESTMERE_EX, &nhx_features },1182{ INTEL_SANDYBRIDGE, &snb_features },1183{ INTEL_SANDYBRIDGE_X, &snx_features },1184{ INTEL_IVYBRIDGE, &ivb_features },1185{ INTEL_IVYBRIDGE_X, &ivx_features },1186{ INTEL_HASWELL, &hsw_features },1187{ INTEL_HASWELL_X, &hsx_features },1188{ INTEL_HASWELL_L, &hswl_features },1189{ INTEL_HASWELL_G, &hswg_features },1190{ INTEL_BROADWELL, &bdw_features },1191{ INTEL_BROADWELL_G, &bdwg_features },1192{ INTEL_BROADWELL_X, &bdx_features },1193{ INTEL_BROADWELL_D, &bdx_features },1194{ INTEL_SKYLAKE_L, &skl_features },1195{ INTEL_SKYLAKE, &skl_features },1196{ INTEL_SKYLAKE_X, &skx_features },1197{ INTEL_KABYLAKE_L, &skl_features },1198{ INTEL_KABYLAKE, &skl_features },1199{ INTEL_COMETLAKE, &skl_features },1200{ INTEL_COMETLAKE_L, &skl_features },1201{ INTEL_CANNONLAKE_L, &cnl_features },1202{ INTEL_ICELAKE_X, &icx_features },1203{ INTEL_ICELAKE_D, &icx_features },1204{ INTEL_ICELAKE_L, &cnl_features },1205{ INTEL_ICELAKE_NNPI, &cnl_features },1206{ INTEL_ROCKETLAKE, &cnl_features },1207{ INTEL_TIGERLAKE_L, &cnl_features },1208{ INTEL_TIGERLAKE, &cnl_features },1209{ INTEL_SAPPHIRERAPIDS_X, &spr_features },1210{ INTEL_EMERALDRAPIDS_X, &spr_features },1211{ INTEL_GRANITERAPIDS_X, &spr_features },1212{ INTEL_GRANITERAPIDS_D, &spr_features },1213{ INTEL_DIAMONDRAPIDS_X, &dmr_features },1214{ INTEL_LAKEFIELD, &cnl_features },1215{ INTEL_ALDERLAKE, &adl_features },1216{ INTEL_ALDERLAKE_L, &adl_features },1217{ INTEL_RAPTORLAKE, &adl_features },1218{ INTEL_RAPTORLAKE_P, &adl_features },1219{ INTEL_RAPTORLAKE_S, &adl_features },1220{ INTEL_BARTLETTLAKE, &adl_features },1221{ INTEL_METEORLAKE, &adl_features },1222{ INTEL_METEORLAKE_L, &adl_features },1223{ INTEL_ARROWLAKE_H, &adl_features },1224{ INTEL_ARROWLAKE_U, &adl_features },1225{ INTEL_ARROWLAKE, &adl_features },1226{ INTEL_LUNARLAKE_M, &lnl_features },1227{ INTEL_PANTHERLAKE_L, &lnl_features },1228{ INTEL_NOVALAKE, &lnl_features },1229{ INTEL_NOVALAKE_L, &lnl_features },1230{ INTEL_WILDCATLAKE_L, &lnl_features },1231{ INTEL_ATOM_SILVERMONT, &slv_features },1232{ INTEL_ATOM_SILVERMONT_D, &slvd_features },1233{ INTEL_ATOM_AIRMONT, &amt_features },1234{ INTEL_ATOM_GOLDMONT, &gmt_features },1235{ INTEL_ATOM_GOLDMONT_D, &gmtd_features },1236{ INTEL_ATOM_GOLDMONT_PLUS, &gmtp_features },1237{ INTEL_ATOM_TREMONT_D, &tmtd_features },1238{ INTEL_ATOM_TREMONT, &tmt_features },1239{ INTEL_ATOM_TREMONT_L, &tmt_features },1240{ INTEL_ATOM_GRACEMONT, &adl_features },1241{ INTEL_ATOM_CRESTMONT_X, &srf_features },1242{ INTEL_ATOM_CRESTMONT, &grr_features },1243{ INTEL_ATOM_DARKMONT_X, &srf_features },1244{ INTEL_XEON_PHI_KNL, &knl_features },1245{ INTEL_XEON_PHI_KNM, &knl_features },1246/*1247* Missing support for1248* INTEL_ICELAKE1249* INTEL_ATOM_SILVERMONT_MID1250* INTEL_ATOM_SILVERMONT_MID21251* INTEL_ATOM_AIRMONT_NP1252*/1253{ 0, NULL },1254};12551256struct {1257unsigned int uniform;1258unsigned int pcore;1259unsigned int ecore;1260unsigned int lcore;1261} perf_pmu_types;12621263/*1264* Events are enumerated in https://github.com/intel/perfmon1265* and tools/perf/pmu-events/arch/x86/.../cache.json1266*/1267struct perf_l2_events {1268unsigned long long refs; /* L2_REQUEST.ALL */1269unsigned long long hits; /* L2_REQUEST.HIT */1270};12711272struct perf_model_support {1273unsigned int vfm;1274struct perf_l2_events first;1275struct perf_l2_events second;1276struct perf_l2_events third;1277} *perf_model_support;12781279/* Perf Cache Events */1280#define PCE(ext_umask, umask) (((unsigned long long) ext_umask) << 40 | umask << 8 | 0x24)12811282/*1283* Enumerate up to three perf CPU PMU's in a system.1284* The first, second, and third columns are populated without skipping, describing1285* pcore, ecore, lcore PMUs, in order, if present. (The associated PMU "type" field is1286* read from sysfs in all cases.) Eg.1287*1288* non-hybrid:1289* GNR: pcore, {}, {}1290* ADL-N: ecore, {}, {}1291* hybrid:1292* MTL: pcore, ecore, {}%1293* ARL-H: pcore, ecore, lcore1294* LNL: ecore, ecore%%, {}1295*1296* % MTL physical lcore share architecture and PMU with ecore, and are thus not enumerated separately.1297* %% LNL physical lcore is enumerated by perf as ecore1298*/1299static struct perf_model_support turbostat_perf_model_support[] = {1300{ INTEL_SAPPHIRERAPIDS_X, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, {}, {} },1301{ INTEL_EMERALDRAPIDS_X, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, {}, {} },1302{ INTEL_GRANITERAPIDS_X, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, {}, {} },1303{ INTEL_GRANITERAPIDS_D, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, {}, {} },1304{ INTEL_DIAMONDRAPIDS_X, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, {}, {} },13051306{ INTEL_ATOM_GRACEMONT, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {}, {} }, /* ADL-N */1307{ INTEL_ATOM_CRESTMONT_X, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {}, {} }, /* SRF */1308{ INTEL_ATOM_CRESTMONT, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {}, {} }, /* GRR */1309{ INTEL_ATOM_DARKMONT_X, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {}, {} }, /* CWF */13101311{ INTEL_ALDERLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1312{ INTEL_ALDERLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1313{ INTEL_ALDERLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1314{ INTEL_RAPTORLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1315{ INTEL_RAPTORLAKE_P, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1316{ INTEL_RAPTORLAKE_S, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1317{ INTEL_METEORLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1318{ INTEL_METEORLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },1319{ INTEL_ARROWLAKE_U, { PCE(0x00, 0xFF), PCE(0x00, 0xDF)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)}, {} },13201321{ INTEL_LUNARLAKE_M, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x00, 0x07), PCE(0x00, 0x02)}, {} },1322{ INTEL_ARROWLAKE_H, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x00, 0x07), PCE(0x00, 0x02)}, { PCE(0x00, 0x00), PCE(0x00, 0x02)} },1323{ INTEL_ARROWLAKE, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x00, 0x07), PCE(0x00, 0x02)}, {} },13241325{ INTEL_PANTHERLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} },1326{ INTEL_WILDCATLAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} },13271328{ INTEL_NOVALAKE, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} },1329{ INTEL_NOVALAKE_L, { PCE(0x00, 0xFF), PCE(0x00, 0x5F)}, { PCE(0x01, 0xFF), PCE(0x01, 0xBF)}, {} },13301331{ 0, {}, {}, {} }1332};13331334static const struct platform_features *platform;13351336void probe_platform_features(unsigned int family, unsigned int model)1337{1338int i;13391340if (authentic_amd || hygon_genuine) {1341/* fallback to default features on unsupported models */1342force_load++;1343if (max_extended_level >= 0x80000007) {1344unsigned int eax, ebx, ecx, edx;13451346__cpuid(0x80000007, eax, ebx, ecx, edx);1347/* RAPL (Fam 17h+) */1348if ((edx & (1 << 14)) && family >= 0x17)1349platform = &amd_features_with_rapl;1350}1351goto end;1352}13531354if (!genuine_intel)1355goto end;13561357for (i = 0; turbostat_pdata[i].features; i++) {1358if (VFM_FAMILY(turbostat_pdata[i].vfm) == family && VFM_MODEL(turbostat_pdata[i].vfm) == model) {1359platform = turbostat_pdata[i].features;1360return;1361}1362}13631364end:1365if (force_load && !platform) {1366fprintf(outf, "Forced to run on unsupported platform!\n");1367platform = &default_features;1368}13691370if (platform)1371return;13721373fprintf(stderr, "Unsupported platform detected.\n\tSee RUN THE LATEST VERSION on turbostat(8)\n");1374exit(1);1375}13761377void init_perf_model_support(unsigned int family, unsigned int model)1378{1379int i;13801381if (!genuine_intel)1382return;13831384for (i = 0; turbostat_perf_model_support[i].vfm; i++) {1385if (VFM_FAMILY(turbostat_perf_model_support[i].vfm) == family && VFM_MODEL(turbostat_perf_model_support[i].vfm) == model) {1386perf_model_support = &turbostat_perf_model_support[i];1387return;1388}1389}1390}13911392/* Model specific support End */13931394#define TJMAX_DEFAULT 10013951396/* MSRs that are not yet in the kernel-provided header. */1397#define MSR_RAPL_PWR_UNIT 0xc00102991398#define MSR_CORE_ENERGY_STAT 0xc001029a1399#define MSR_PKG_ENERGY_STAT 0xc001029b14001401#define MAX(a, b) ((a) > (b) ? (a) : (b))14021403int backwards_count;1404char *progname;14051406#define CPU_SUBSET_MAXCPUS 8192 /* need to use before probe... */1407cpu_set_t *cpu_present_set, *cpu_possible_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;1408cpu_set_t *perf_pcore_set, *perf_ecore_set, *perf_lcore_set;1409size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size;1410#define MAX_ADDED_THREAD_COUNTERS 241411#define MAX_ADDED_CORE_COUNTERS 81412#define MAX_ADDED_PACKAGE_COUNTERS 161413#define PMT_MAX_ADDED_THREAD_COUNTERS 241414#define PMT_MAX_ADDED_CORE_COUNTERS 81415#define PMT_MAX_ADDED_PACKAGE_COUNTERS 161416#define BITMASK_SIZE 3214171418#define ZERO_ARRAY(arr) (memset(arr, 0, sizeof(arr)) + __must_be_array(arr))14191420/* Indexes used to map data read from perf and MSRs into global variables */1421enum rapl_rci_index {1422RAPL_RCI_INDEX_ENERGY_PKG = 0,1423RAPL_RCI_INDEX_ENERGY_CORES = 1,1424RAPL_RCI_INDEX_DRAM = 2,1425RAPL_RCI_INDEX_GFX = 3,1426RAPL_RCI_INDEX_PKG_PERF_STATUS = 4,1427RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5,1428RAPL_RCI_INDEX_CORE_ENERGY = 6,1429RAPL_RCI_INDEX_ENERGY_PLATFORM = 7,1430NUM_RAPL_COUNTERS,1431};14321433enum rapl_unit {1434RAPL_UNIT_INVALID,1435RAPL_UNIT_JOULES,1436RAPL_UNIT_WATTS,1437};14381439struct rapl_counter_info_t {1440unsigned long long data[NUM_RAPL_COUNTERS];1441enum counter_source source[NUM_RAPL_COUNTERS];1442unsigned long long flags[NUM_RAPL_COUNTERS];1443double scale[NUM_RAPL_COUNTERS];1444enum rapl_unit unit[NUM_RAPL_COUNTERS];1445unsigned long long msr[NUM_RAPL_COUNTERS];1446unsigned long long msr_mask[NUM_RAPL_COUNTERS];1447int msr_shift[NUM_RAPL_COUNTERS];14481449int fd_perf;1450};14511452/* struct rapl_counter_info_t for each RAPL domain */1453struct rapl_counter_info_t *rapl_counter_info_perdomain;1454unsigned int rapl_counter_info_perdomain_size;14551456#define RAPL_COUNTER_FLAG_PLATFORM_COUNTER (1u << 0)1457#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1)14581459struct rapl_counter_arch_info {1460int feature_mask; /* Mask for testing if the counter is supported on host */1461const char *perf_subsys;1462const char *perf_name;1463unsigned long long msr;1464unsigned long long msr_mask;1465int msr_shift; /* Positive mean shift right, negative mean shift left */1466double *platform_rapl_msr_scale; /* Scale applied to values read by MSR (platform dependent, filled at runtime) */1467unsigned int rci_index; /* Maps data from perf counters to global variables */1468unsigned int bic_number;1469double compat_scale; /* Some counters require constant scaling to be in the same range as other, similar ones */1470unsigned long long flags;1471};14721473static const struct rapl_counter_arch_info rapl_counter_arch_infos[] = {1474{1475.feature_mask = RAPL_PKG,1476.perf_subsys = "power",1477.perf_name = "energy-pkg",1478.msr = MSR_PKG_ENERGY_STATUS,1479.msr_mask = 0xFFFFFFFFFFFFFFFF,1480.msr_shift = 0,1481.platform_rapl_msr_scale = &rapl_energy_units,1482.rci_index = RAPL_RCI_INDEX_ENERGY_PKG,1483.bic_number = BIC_PkgWatt,1484.compat_scale = 1.0,1485.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1486},1487{1488.feature_mask = RAPL_PKG,1489.perf_subsys = "power",1490.perf_name = "energy-pkg",1491.msr = MSR_PKG_ENERGY_STATUS,1492.msr_mask = 0xFFFFFFFFFFFFFFFF,1493.msr_shift = 0,1494.platform_rapl_msr_scale = &rapl_energy_units,1495.rci_index = RAPL_RCI_INDEX_ENERGY_PKG,1496.bic_number = BIC_Pkg_J,1497.compat_scale = 1.0,1498.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1499},1500{1501.feature_mask = RAPL_AMD_F17H,1502.perf_subsys = "power",1503.perf_name = "energy-pkg",1504.msr = MSR_PKG_ENERGY_STAT,1505.msr_mask = 0xFFFFFFFFFFFFFFFF,1506.msr_shift = 0,1507.platform_rapl_msr_scale = &rapl_energy_units,1508.rci_index = RAPL_RCI_INDEX_ENERGY_PKG,1509.bic_number = BIC_PkgWatt,1510.compat_scale = 1.0,1511.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1512},1513{1514.feature_mask = RAPL_AMD_F17H,1515.perf_subsys = "power",1516.perf_name = "energy-pkg",1517.msr = MSR_PKG_ENERGY_STAT,1518.msr_mask = 0xFFFFFFFFFFFFFFFF,1519.msr_shift = 0,1520.platform_rapl_msr_scale = &rapl_energy_units,1521.rci_index = RAPL_RCI_INDEX_ENERGY_PKG,1522.bic_number = BIC_Pkg_J,1523.compat_scale = 1.0,1524.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1525},1526{1527.feature_mask = RAPL_CORE_ENERGY_STATUS,1528.perf_subsys = "power",1529.perf_name = "energy-cores",1530.msr = MSR_PP0_ENERGY_STATUS,1531.msr_mask = 0xFFFFFFFFFFFFFFFF,1532.msr_shift = 0,1533.platform_rapl_msr_scale = &rapl_energy_units,1534.rci_index = RAPL_RCI_INDEX_ENERGY_CORES,1535.bic_number = BIC_CorWatt,1536.compat_scale = 1.0,1537.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1538},1539{1540.feature_mask = RAPL_CORE_ENERGY_STATUS,1541.perf_subsys = "power",1542.perf_name = "energy-cores",1543.msr = MSR_PP0_ENERGY_STATUS,1544.msr_mask = 0xFFFFFFFFFFFFFFFF,1545.msr_shift = 0,1546.platform_rapl_msr_scale = &rapl_energy_units,1547.rci_index = RAPL_RCI_INDEX_ENERGY_CORES,1548.bic_number = BIC_Cor_J,1549.compat_scale = 1.0,1550.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1551},1552{1553.feature_mask = RAPL_DRAM,1554.perf_subsys = "power",1555.perf_name = "energy-ram",1556.msr = MSR_DRAM_ENERGY_STATUS,1557.msr_mask = 0xFFFFFFFFFFFFFFFF,1558.msr_shift = 0,1559.platform_rapl_msr_scale = &rapl_dram_energy_units,1560.rci_index = RAPL_RCI_INDEX_DRAM,1561.bic_number = BIC_RAMWatt,1562.compat_scale = 1.0,1563.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1564},1565{1566.feature_mask = RAPL_DRAM,1567.perf_subsys = "power",1568.perf_name = "energy-ram",1569.msr = MSR_DRAM_ENERGY_STATUS,1570.msr_mask = 0xFFFFFFFFFFFFFFFF,1571.msr_shift = 0,1572.platform_rapl_msr_scale = &rapl_dram_energy_units,1573.rci_index = RAPL_RCI_INDEX_DRAM,1574.bic_number = BIC_RAM_J,1575.compat_scale = 1.0,1576.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1577},1578{1579.feature_mask = RAPL_GFX,1580.perf_subsys = "power",1581.perf_name = "energy-gpu",1582.msr = MSR_PP1_ENERGY_STATUS,1583.msr_mask = 0xFFFFFFFFFFFFFFFF,1584.msr_shift = 0,1585.platform_rapl_msr_scale = &rapl_energy_units,1586.rci_index = RAPL_RCI_INDEX_GFX,1587.bic_number = BIC_GFXWatt,1588.compat_scale = 1.0,1589.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1590},1591{1592.feature_mask = RAPL_GFX,1593.perf_subsys = "power",1594.perf_name = "energy-gpu",1595.msr = MSR_PP1_ENERGY_STATUS,1596.msr_mask = 0xFFFFFFFFFFFFFFFF,1597.msr_shift = 0,1598.platform_rapl_msr_scale = &rapl_energy_units,1599.rci_index = RAPL_RCI_INDEX_GFX,1600.bic_number = BIC_GFX_J,1601.compat_scale = 1.0,1602.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1603},1604{1605.feature_mask = RAPL_PKG_PERF_STATUS,1606.perf_subsys = NULL,1607.perf_name = NULL,1608.msr = MSR_PKG_PERF_STATUS,1609.msr_mask = 0xFFFFFFFFFFFFFFFF,1610.msr_shift = 0,1611.platform_rapl_msr_scale = &rapl_time_units,1612.rci_index = RAPL_RCI_INDEX_PKG_PERF_STATUS,1613.bic_number = BIC_PKG__,1614.compat_scale = 100.0,1615.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1616},1617{1618.feature_mask = RAPL_DRAM_PERF_STATUS,1619.perf_subsys = NULL,1620.perf_name = NULL,1621.msr = MSR_DRAM_PERF_STATUS,1622.msr_mask = 0xFFFFFFFFFFFFFFFF,1623.msr_shift = 0,1624.platform_rapl_msr_scale = &rapl_time_units,1625.rci_index = RAPL_RCI_INDEX_DRAM_PERF_STATUS,1626.bic_number = BIC_RAM__,1627.compat_scale = 100.0,1628.flags = RAPL_COUNTER_FLAG_USE_MSR_SUM,1629},1630{1631.feature_mask = RAPL_AMD_F17H,1632.perf_subsys = NULL,1633.perf_name = NULL,1634.msr = MSR_CORE_ENERGY_STAT,1635.msr_mask = 0xFFFFFFFF,1636.msr_shift = 0,1637.platform_rapl_msr_scale = &rapl_energy_units,1638.rci_index = RAPL_RCI_INDEX_CORE_ENERGY,1639.bic_number = BIC_CorWatt,1640.compat_scale = 1.0,1641.flags = 0,1642},1643{1644.feature_mask = RAPL_AMD_F17H,1645.perf_subsys = NULL,1646.perf_name = NULL,1647.msr = MSR_CORE_ENERGY_STAT,1648.msr_mask = 0xFFFFFFFF,1649.msr_shift = 0,1650.platform_rapl_msr_scale = &rapl_energy_units,1651.rci_index = RAPL_RCI_INDEX_CORE_ENERGY,1652.bic_number = BIC_Cor_J,1653.compat_scale = 1.0,1654.flags = 0,1655},1656{1657.feature_mask = RAPL_PSYS,1658.perf_subsys = "power",1659.perf_name = "energy-psys",1660.msr = MSR_PLATFORM_ENERGY_STATUS,1661.msr_mask = 0x00000000FFFFFFFF,1662.msr_shift = 0,1663.platform_rapl_msr_scale = &rapl_psys_energy_units,1664.rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM,1665.bic_number = BIC_SysWatt,1666.compat_scale = 1.0,1667.flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM,1668},1669{1670.feature_mask = RAPL_PSYS,1671.perf_subsys = "power",1672.perf_name = "energy-psys",1673.msr = MSR_PLATFORM_ENERGY_STATUS,1674.msr_mask = 0x00000000FFFFFFFF,1675.msr_shift = 0,1676.platform_rapl_msr_scale = &rapl_psys_energy_units,1677.rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM,1678.bic_number = BIC_Sys_J,1679.compat_scale = 1.0,1680.flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM,1681},1682};16831684struct rapl_counter {1685unsigned long long raw_value;1686enum rapl_unit unit;1687double scale;1688};16891690/* Indexes used to map data read from perf and MSRs into global variables */1691enum ccstate_rci_index {1692CCSTATE_RCI_INDEX_C1_RESIDENCY = 0,1693CCSTATE_RCI_INDEX_C3_RESIDENCY = 1,1694CCSTATE_RCI_INDEX_C6_RESIDENCY = 2,1695CCSTATE_RCI_INDEX_C7_RESIDENCY = 3,1696PCSTATE_RCI_INDEX_C2_RESIDENCY = 4,1697PCSTATE_RCI_INDEX_C3_RESIDENCY = 5,1698PCSTATE_RCI_INDEX_C6_RESIDENCY = 6,1699PCSTATE_RCI_INDEX_C7_RESIDENCY = 7,1700PCSTATE_RCI_INDEX_C8_RESIDENCY = 8,1701PCSTATE_RCI_INDEX_C9_RESIDENCY = 9,1702PCSTATE_RCI_INDEX_C10_RESIDENCY = 10,1703NUM_CSTATE_COUNTERS,1704};17051706struct cstate_counter_info_t {1707unsigned long long data[NUM_CSTATE_COUNTERS];1708enum counter_source source[NUM_CSTATE_COUNTERS];1709unsigned long long msr[NUM_CSTATE_COUNTERS];1710int fd_perf_core;1711int fd_perf_pkg;1712};17131714struct cstate_counter_info_t *ccstate_counter_info;1715unsigned int ccstate_counter_info_size;17161717#define CSTATE_COUNTER_FLAG_COLLECT_PER_CORE (1u << 0)1718#define CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD ((1u << 1) | CSTATE_COUNTER_FLAG_COLLECT_PER_CORE)1719#define CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY (1u << 2)17201721struct cstate_counter_arch_info {1722int feature_mask; /* Mask for testing if the counter is supported on host */1723const char *perf_subsys;1724const char *perf_name;1725unsigned long long msr;1726unsigned int rci_index; /* Maps data from perf counters to global variables */1727unsigned int bic_number;1728unsigned long long flags;1729int pkg_cstate_limit;1730};17311732static struct cstate_counter_arch_info ccstate_counter_arch_infos[] = {1733{1734.feature_mask = CC1,1735.perf_subsys = "cstate_core",1736.perf_name = "c1-residency",1737.msr = MSR_CORE_C1_RES,1738.rci_index = CCSTATE_RCI_INDEX_C1_RESIDENCY,1739.bic_number = BIC_CPU_c1,1740.flags = CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD,1741.pkg_cstate_limit = 0,1742},1743{1744.feature_mask = CC3,1745.perf_subsys = "cstate_core",1746.perf_name = "c3-residency",1747.msr = MSR_CORE_C3_RESIDENCY,1748.rci_index = CCSTATE_RCI_INDEX_C3_RESIDENCY,1749.bic_number = BIC_CPU_c3,1750.flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,1751.pkg_cstate_limit = 0,1752},1753{1754.feature_mask = CC6,1755.perf_subsys = "cstate_core",1756.perf_name = "c6-residency",1757.msr = MSR_CORE_C6_RESIDENCY,1758.rci_index = CCSTATE_RCI_INDEX_C6_RESIDENCY,1759.bic_number = BIC_CPU_c6,1760.flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,1761.pkg_cstate_limit = 0,1762},1763{1764.feature_mask = CC7,1765.perf_subsys = "cstate_core",1766.perf_name = "c7-residency",1767.msr = MSR_CORE_C7_RESIDENCY,1768.rci_index = CCSTATE_RCI_INDEX_C7_RESIDENCY,1769.bic_number = BIC_CPU_c7,1770.flags = CSTATE_COUNTER_FLAG_COLLECT_PER_CORE | CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY,1771.pkg_cstate_limit = 0,1772},1773{1774.feature_mask = PC2,1775.perf_subsys = "cstate_pkg",1776.perf_name = "c2-residency",1777.msr = MSR_PKG_C2_RESIDENCY,1778.rci_index = PCSTATE_RCI_INDEX_C2_RESIDENCY,1779.bic_number = BIC_Pkgpc2,1780.flags = 0,1781.pkg_cstate_limit = PCL__2,1782},1783{1784.feature_mask = PC3,1785.perf_subsys = "cstate_pkg",1786.perf_name = "c3-residency",1787.msr = MSR_PKG_C3_RESIDENCY,1788.rci_index = PCSTATE_RCI_INDEX_C3_RESIDENCY,1789.bic_number = BIC_Pkgpc3,1790.flags = 0,1791.pkg_cstate_limit = PCL__3,1792},1793{1794.feature_mask = PC6,1795.perf_subsys = "cstate_pkg",1796.perf_name = "c6-residency",1797.msr = MSR_PKG_C6_RESIDENCY,1798.rci_index = PCSTATE_RCI_INDEX_C6_RESIDENCY,1799.bic_number = BIC_Pkgpc6,1800.flags = 0,1801.pkg_cstate_limit = PCL__6,1802},1803{1804.feature_mask = PC7,1805.perf_subsys = "cstate_pkg",1806.perf_name = "c7-residency",1807.msr = MSR_PKG_C7_RESIDENCY,1808.rci_index = PCSTATE_RCI_INDEX_C7_RESIDENCY,1809.bic_number = BIC_Pkgpc7,1810.flags = 0,1811.pkg_cstate_limit = PCL__7,1812},1813{1814.feature_mask = PC8,1815.perf_subsys = "cstate_pkg",1816.perf_name = "c8-residency",1817.msr = MSR_PKG_C8_RESIDENCY,1818.rci_index = PCSTATE_RCI_INDEX_C8_RESIDENCY,1819.bic_number = BIC_Pkgpc8,1820.flags = 0,1821.pkg_cstate_limit = PCL__8,1822},1823{1824.feature_mask = PC9,1825.perf_subsys = "cstate_pkg",1826.perf_name = "c9-residency",1827.msr = MSR_PKG_C9_RESIDENCY,1828.rci_index = PCSTATE_RCI_INDEX_C9_RESIDENCY,1829.bic_number = BIC_Pkgpc9,1830.flags = 0,1831.pkg_cstate_limit = PCL__9,1832},1833{1834.feature_mask = PC10,1835.perf_subsys = "cstate_pkg",1836.perf_name = "c10-residency",1837.msr = MSR_PKG_C10_RESIDENCY,1838.rci_index = PCSTATE_RCI_INDEX_C10_RESIDENCY,1839.bic_number = BIC_Pkgpc10,1840.flags = 0,1841.pkg_cstate_limit = PCL_10,1842},1843};18441845/* Indexes used to map data read from perf and MSRs into global variables */1846enum msr_rci_index {1847MSR_RCI_INDEX_APERF = 0,1848MSR_RCI_INDEX_MPERF = 1,1849MSR_RCI_INDEX_SMI = 2,1850NUM_MSR_COUNTERS,1851};18521853struct msr_counter_info_t {1854unsigned long long data[NUM_MSR_COUNTERS];1855enum counter_source source[NUM_MSR_COUNTERS];1856unsigned long long msr[NUM_MSR_COUNTERS];1857unsigned long long msr_mask[NUM_MSR_COUNTERS];1858int fd_perf;1859};18601861struct msr_counter_info_t *msr_counter_info;1862unsigned int msr_counter_info_size;18631864struct msr_counter_arch_info {1865const char *perf_subsys;1866const char *perf_name;1867unsigned long long msr;1868unsigned long long msr_mask;1869unsigned int rci_index; /* Maps data from perf counters to global variables */1870bool needed;1871bool present;1872};18731874enum msr_arch_info_index {1875MSR_ARCH_INFO_APERF_INDEX = 0,1876MSR_ARCH_INFO_MPERF_INDEX = 1,1877MSR_ARCH_INFO_SMI_INDEX = 2,1878};18791880static struct msr_counter_arch_info msr_counter_arch_infos[] = {1881[MSR_ARCH_INFO_APERF_INDEX] = {1882.perf_subsys = "msr",1883.perf_name = "aperf",1884.msr = MSR_IA32_APERF,1885.msr_mask = 0xFFFFFFFFFFFFFFFF,1886.rci_index = MSR_RCI_INDEX_APERF,1887},18881889[MSR_ARCH_INFO_MPERF_INDEX] = {1890.perf_subsys = "msr",1891.perf_name = "mperf",1892.msr = MSR_IA32_MPERF,1893.msr_mask = 0xFFFFFFFFFFFFFFFF,1894.rci_index = MSR_RCI_INDEX_MPERF,1895},18961897[MSR_ARCH_INFO_SMI_INDEX] = {1898.perf_subsys = "msr",1899.perf_name = "smi",1900.msr = MSR_SMI_COUNT,1901.msr_mask = 0xFFFFFFFF,1902.rci_index = MSR_RCI_INDEX_SMI,1903},1904};19051906/* Can be redefined when compiling, useful for testing. */1907#ifndef SYSFS_TELEM_PATH1908#define SYSFS_TELEM_PATH "/sys/class/intel_pmt"1909#endif19101911#define PMT_COUNTER_MTL_DC6_OFFSET 1201912#define PMT_COUNTER_MTL_DC6_LSB 01913#define PMT_COUNTER_MTL_DC6_MSB 631914#define PMT_MTL_DC6_GUID 0x1a0671021915#define PMT_MTL_DC6_SEQ 019161917#define PMT_COUNTER_CWF_MC1E_OFFSET_BASE 209361918#define PMT_COUNTER_CWF_MC1E_OFFSET_INCREMENT 241919#define PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE 121920#define PMT_COUNTER_CWF_CPUS_PER_MODULE 41921#define PMT_COUNTER_CWF_MC1E_LSB 01922#define PMT_COUNTER_CWF_MC1E_MSB 631923#define PMT_CWF_MC1E_GUID 0x1442151919241925unsigned long long tcore_clock_freq_hz = 800000000;19261927#define PMT_COUNTER_NAME_SIZE_BYTES 161928#define PMT_COUNTER_TYPE_NAME_SIZE_BYTES 3219291930struct pmt_mmio {1931struct pmt_mmio *next;19321933unsigned int guid;1934unsigned int size;19351936/* Base pointer to the mmaped memory. */1937void *mmio_base;19381939/*1940* Offset to be applied to the mmio_base1941* to get the beginning of the PMT counters for given GUID.1942*/1943unsigned long pmt_offset;1944} *pmt_mmios;19451946enum pmt_datatype {1947PMT_TYPE_RAW,1948PMT_TYPE_XTAL_TIME,1949PMT_TYPE_TCORE_CLOCK,1950};19511952struct pmt_domain_info {1953/*1954* Pointer to the MMIO obtained by applying a counter offset1955* to the mmio_base of the mmaped region for the given GUID.1956*1957* This is where to read the raw value of the counter from.1958*/1959unsigned long *pcounter;1960};19611962struct pmt_counter {1963struct pmt_counter *next;19641965/* PMT metadata */1966char name[PMT_COUNTER_NAME_SIZE_BYTES];1967enum pmt_datatype type;1968enum counter_scope scope;1969unsigned int lsb;1970unsigned int msb;19711972/* BIC-like metadata */1973enum counter_format format;19741975unsigned int num_domains;1976struct pmt_domain_info *domains;1977};19781979/*1980* PMT telemetry directory iterator.1981* Used to iterate telemetry files in sysfs in correct order.1982*/1983struct pmt_diriter_t {1984DIR *dir;1985struct dirent **namelist;1986unsigned int num_names;1987unsigned int current_name_idx;1988};19891990int pmt_telemdir_filter(const struct dirent *e)1991{1992unsigned int dummy;19931994return sscanf(e->d_name, "telem%u", &dummy);1995}19961997int pmt_telemdir_sort(const struct dirent **a, const struct dirent **b)1998{1999unsigned int aidx = 0, bidx = 0;20002001sscanf((*a)->d_name, "telem%u", &aidx);2002sscanf((*b)->d_name, "telem%u", &bidx);20032004return (aidx > bidx) ? 1 : (aidx < bidx) ? -1 : 0;2005}20062007const struct dirent *pmt_diriter_next(struct pmt_diriter_t *iter)2008{2009const struct dirent *ret = NULL;20102011if (!iter->dir)2012return NULL;20132014if (iter->current_name_idx >= iter->num_names)2015return NULL;20162017ret = iter->namelist[iter->current_name_idx];2018++iter->current_name_idx;20192020return ret;2021}20222023const struct dirent *pmt_diriter_begin(struct pmt_diriter_t *iter, const char *pmt_root_path)2024{2025int num_names = iter->num_names;20262027if (!iter->dir) {2028iter->dir = opendir(pmt_root_path);2029if (iter->dir == NULL)2030return NULL;20312032num_names = scandir(pmt_root_path, &iter->namelist, pmt_telemdir_filter, pmt_telemdir_sort);2033if (num_names == -1)2034return NULL;2035}20362037iter->current_name_idx = 0;2038iter->num_names = num_names;20392040return pmt_diriter_next(iter);2041}20422043void pmt_diriter_init(struct pmt_diriter_t *iter)2044{2045memset(iter, 0, sizeof(*iter));2046}20472048void pmt_diriter_remove(struct pmt_diriter_t *iter)2049{2050if (iter->namelist) {2051for (unsigned int i = 0; i < iter->num_names; i++) {2052free(iter->namelist[i]);2053iter->namelist[i] = NULL;2054}2055}20562057free(iter->namelist);2058iter->namelist = NULL;2059iter->num_names = 0;2060iter->current_name_idx = 0;20612062closedir(iter->dir);2063iter->dir = NULL;2064}20652066unsigned int pmt_counter_get_width(const struct pmt_counter *p)2067{2068return (p->msb - p->lsb) + 1;2069}20702071void pmt_counter_resize_(struct pmt_counter *pcounter, unsigned int new_size)2072{2073struct pmt_domain_info *new_mem;20742075new_mem = (struct pmt_domain_info *)reallocarray(pcounter->domains, new_size, sizeof(*pcounter->domains));2076if (!new_mem) {2077fprintf(stderr, "%s: failed to allocate memory for PMT counters\n", __func__);2078exit(1);2079}20802081/* Zero initialize just allocated memory. */2082const size_t num_new_domains = new_size - pcounter->num_domains;20832084memset(&new_mem[pcounter->num_domains], 0, num_new_domains * sizeof(*pcounter->domains));20852086pcounter->num_domains = new_size;2087pcounter->domains = new_mem;2088}20892090void pmt_counter_resize(struct pmt_counter *pcounter, unsigned int new_size)2091{2092/*2093* Allocate more memory ahead of time.2094*2095* Always allocate space for at least 8 elements2096* and double the size when growing.2097*/2098if (new_size < 8)2099new_size = 8;2100new_size = MAX(new_size, pcounter->num_domains * 2);21012102pmt_counter_resize_(pcounter, new_size);2103}21042105struct llc_stats {2106unsigned long long references;2107unsigned long long misses;2108};2109struct l2_stats {2110unsigned long long references;2111unsigned long long hits;2112};2113struct thread_data {2114struct timeval tv_begin;2115struct timeval tv_end;2116struct timeval tv_delta;2117unsigned long long tsc;2118unsigned long long aperf;2119unsigned long long mperf;2120unsigned long long c1;2121unsigned long long instr_count;2122unsigned long long irq_count;2123unsigned long long nmi_count;2124unsigned int smi_count;2125struct llc_stats llc;2126struct l2_stats l2;2127unsigned int cpu_id;2128unsigned int apic_id;2129unsigned int x2apic_id;2130unsigned int flags;2131bool is_atom;2132unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];2133unsigned long long perf_counter[MAX_ADDED_THREAD_COUNTERS];2134unsigned long long pmt_counter[PMT_MAX_ADDED_THREAD_COUNTERS];2135};21362137struct core_data {2138int first_cpu;2139unsigned long long c3;2140unsigned long long c6;2141unsigned long long c7;2142unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */2143unsigned int core_temp_c;2144struct rapl_counter core_energy; /* MSR_CORE_ENERGY_STAT */2145unsigned long long core_throt_cnt;2146unsigned long long counter[MAX_ADDED_CORE_COUNTERS];2147unsigned long long perf_counter[MAX_ADDED_CORE_COUNTERS];2148unsigned long long pmt_counter[PMT_MAX_ADDED_CORE_COUNTERS];2149};21502151struct pkg_data {2152int first_cpu;2153unsigned long long pc2;2154unsigned long long pc3;2155unsigned long long pc6;2156unsigned long long pc7;2157unsigned long long pc8;2158unsigned long long pc9;2159unsigned long long pc10;2160long long cpu_lpi;2161long long sys_lpi;2162unsigned long long pkg_wtd_core_c0;2163unsigned long long pkg_any_core_c0;2164unsigned long long pkg_any_gfxe_c0;2165unsigned long long pkg_both_core_gfxe_c0;2166long long gfx_rc6_ms;2167unsigned int gfx_mhz;2168unsigned int gfx_act_mhz;2169long long sam_mc6_ms;2170unsigned int sam_mhz;2171unsigned int sam_act_mhz;2172struct rapl_counter energy_pkg; /* MSR_PKG_ENERGY_STATUS */2173struct rapl_counter energy_dram; /* MSR_DRAM_ENERGY_STATUS */2174struct rapl_counter energy_cores; /* MSR_PP0_ENERGY_STATUS */2175struct rapl_counter energy_gfx; /* MSR_PP1_ENERGY_STATUS */2176struct rapl_counter rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */2177struct rapl_counter rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */2178unsigned int pkg_temp_c;2179unsigned int uncore_mhz;2180unsigned long long die_c6;2181unsigned long long counter[MAX_ADDED_PACKAGE_COUNTERS];2182unsigned long long perf_counter[MAX_ADDED_PACKAGE_COUNTERS];2183unsigned long long pmt_counter[PMT_MAX_ADDED_PACKAGE_COUNTERS];2184};21852186#define ODD_COUNTERS odd.threads, odd.cores, odd.packages2187#define EVEN_COUNTERS even.threads, even.cores, even.packages21882189/*2190* The accumulated sum of MSR is defined as a monotonic2191* increasing MSR, it will be accumulated periodically,2192* despite its register's bit width.2193*/2194enum {2195IDX_PKG_ENERGY,2196IDX_DRAM_ENERGY,2197IDX_PP0_ENERGY,2198IDX_PP1_ENERGY,2199IDX_PKG_PERF,2200IDX_DRAM_PERF,2201IDX_PSYS_ENERGY,2202IDX_COUNT,2203};22042205int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);22062207struct msr_sum_array {2208/* get_msr_sum() = sum + (get_msr() - last) */2209struct {2210/*The accumulated MSR value is updated by the timer */2211unsigned long long sum;2212/*The MSR footprint recorded in last timer */2213unsigned long long last;2214} entries[IDX_COUNT];2215};22162217/* The percpu MSR sum array.*/2218struct msr_sum_array *per_cpu_msr_sum;22192220off_t idx_to_offset(int idx)2221{2222off_t offset;22232224switch (idx) {2225case IDX_PKG_ENERGY:2226if (platform->plat_rapl_msrs & RAPL_AMD_F17H)2227offset = MSR_PKG_ENERGY_STAT;2228else2229offset = MSR_PKG_ENERGY_STATUS;2230break;2231case IDX_DRAM_ENERGY:2232offset = MSR_DRAM_ENERGY_STATUS;2233break;2234case IDX_PP0_ENERGY:2235offset = MSR_PP0_ENERGY_STATUS;2236break;2237case IDX_PP1_ENERGY:2238offset = MSR_PP1_ENERGY_STATUS;2239break;2240case IDX_PKG_PERF:2241offset = MSR_PKG_PERF_STATUS;2242break;2243case IDX_DRAM_PERF:2244offset = MSR_DRAM_PERF_STATUS;2245break;2246case IDX_PSYS_ENERGY:2247offset = MSR_PLATFORM_ENERGY_STATUS;2248break;2249default:2250offset = -1;2251}2252return offset;2253}22542255int offset_to_idx(off_t offset)2256{2257int idx;22582259switch (offset) {2260case MSR_PKG_ENERGY_STATUS:2261case MSR_PKG_ENERGY_STAT:2262idx = IDX_PKG_ENERGY;2263break;2264case MSR_DRAM_ENERGY_STATUS:2265idx = IDX_DRAM_ENERGY;2266break;2267case MSR_PP0_ENERGY_STATUS:2268idx = IDX_PP0_ENERGY;2269break;2270case MSR_PP1_ENERGY_STATUS:2271idx = IDX_PP1_ENERGY;2272break;2273case MSR_PKG_PERF_STATUS:2274idx = IDX_PKG_PERF;2275break;2276case MSR_DRAM_PERF_STATUS:2277idx = IDX_DRAM_PERF;2278break;2279case MSR_PLATFORM_ENERGY_STATUS:2280idx = IDX_PSYS_ENERGY;2281break;2282default:2283idx = -1;2284}2285return idx;2286}22872288int idx_valid(int idx)2289{2290switch (idx) {2291case IDX_PKG_ENERGY:2292return valid_rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H);2293case IDX_DRAM_ENERGY:2294return valid_rapl_msrs & RAPL_DRAM;2295case IDX_PP0_ENERGY:2296return valid_rapl_msrs & RAPL_CORE_ENERGY_STATUS;2297case IDX_PP1_ENERGY:2298return valid_rapl_msrs & RAPL_GFX;2299case IDX_PKG_PERF:2300return valid_rapl_msrs & RAPL_PKG_PERF_STATUS;2301case IDX_DRAM_PERF:2302return valid_rapl_msrs & RAPL_DRAM_PERF_STATUS;2303case IDX_PSYS_ENERGY:2304return valid_rapl_msrs & RAPL_PSYS;2305default:2306return 0;2307}2308}23092310struct sys_counters {2311/* MSR added counters */2312unsigned int added_thread_counters;2313unsigned int added_core_counters;2314unsigned int added_package_counters;2315struct msr_counter *tp;2316struct msr_counter *cp;2317struct msr_counter *pp;23182319/* perf added counters */2320unsigned int added_thread_perf_counters;2321unsigned int added_core_perf_counters;2322unsigned int added_package_perf_counters;2323struct perf_counter_info *perf_tp;2324struct perf_counter_info *perf_cp;2325struct perf_counter_info *perf_pp;23262327struct pmt_counter *pmt_tp;2328struct pmt_counter *pmt_cp;2329struct pmt_counter *pmt_pp;2330} sys;23312332static size_t free_msr_counters_(struct msr_counter **pp)2333{2334struct msr_counter *p = NULL;2335size_t num_freed = 0;23362337while (*pp) {2338p = *pp;23392340if (p->msr_num != 0) {2341*pp = p->next;23422343free(p);2344++num_freed;23452346continue;2347}23482349pp = &p->next;2350}23512352return num_freed;2353}23542355/*2356* Free all added counters accessed via msr.2357*/2358static void free_sys_msr_counters(void)2359{2360/* Thread counters */2361sys.added_thread_counters -= free_msr_counters_(&sys.tp);23622363/* Core counters */2364sys.added_core_counters -= free_msr_counters_(&sys.cp);23652366/* Package counters */2367sys.added_package_counters -= free_msr_counters_(&sys.pp);2368}23692370struct counters {2371struct thread_data *threads;2372struct core_data *cores;2373struct pkg_data *packages;2374} average, even, odd;23752376struct platform_counters {2377struct rapl_counter energy_psys; /* MSR_PLATFORM_ENERGY_STATUS */2378} platform_counters_odd, platform_counters_even;23792380#define MAX_HT_ID 3 /* support SMT-4 */23812382struct cpu_topology {2383int cpu_id;2384int core_id; /* unique within a package */2385int package_id;2386int die_id;2387int l3_id;2388int physical_node_id;2389int logical_node_id; /* 0-based count within the package */2390int ht_id; /* unique within a core */2391int ht_sibling_cpu_id[MAX_HT_ID + 1];2392int type;2393cpu_set_t *put_ids; /* Processing Unit/Thread IDs */2394} *cpus;23952396struct topo_params {2397int num_packages;2398int num_die;2399int num_cpus;2400int num_cores; /* system wide */2401int allowed_packages;2402int allowed_cpus;2403int allowed_cores;2404int max_cpu_num;2405int max_core_id; /* within a package */2406int max_package_id;2407int max_die_id;2408int max_l3_id;2409int max_node_num;2410int nodes_per_pkg;2411int cores_per_node;2412int threads_per_core;2413} topo;24142415struct timeval tv_even, tv_odd, tv_delta;24162417int *irq_column_2_cpu; /* /proc/interrupts column numbers */2418int *irqs_per_cpu; /* indexed by cpu_num */2419int *nmi_per_cpu; /* indexed by cpu_num */24202421void setup_all_buffers(bool startup);24222423char *sys_lpi_file;2424char *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us";2425char *sys_lpi_file_debugfs = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec";24262427int cpu_is_not_present(int cpu)2428{2429return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);2430}24312432int cpu_is_not_allowed(int cpu)2433{2434return !CPU_ISSET_S(cpu, cpu_allowed_setsize, cpu_allowed_set);2435}24362437#define GLOBAL_CORE_ID(core_id, pkg_id) (core_id + pkg_id * (topo.max_core_id + 1))2438/*2439* run func(thread, core, package) in topology order2440* skip non-present cpus2441*/24422443#define PER_THREAD_PARAMS struct thread_data *t, struct core_data *c, struct pkg_data *p24442445int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *),2446struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)2447{2448int cpu, retval;24492450retval = 0;24512452for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {2453struct thread_data *t;2454struct core_data *c;2455struct pkg_data *p;24562457int pkg_id = cpus[cpu].package_id;24582459if (cpu_is_not_allowed(cpu))2460continue;24612462if (cpus[cpu].ht_id > 0) /* skip HT sibling */2463continue;24642465t = &thread_base[cpu];2466c = &core_base[GLOBAL_CORE_ID(cpus[cpu].core_id, pkg_id)];2467p = &pkg_base[pkg_id];24682469retval |= func(t, c, p);24702471/* Handle HT sibling now */2472int i;24732474for (i = MAX_HT_ID; i > 0; --i) { /* ht_id 0 is self */2475if (cpus[cpu].ht_sibling_cpu_id[i] <= 0)2476continue;2477t = &thread_base[cpus[cpu].ht_sibling_cpu_id[i]];24782479retval |= func(t, c, p);2480}2481}2482return retval;2483}24842485int is_cpu_first_thread_in_core(struct thread_data *t, struct core_data *c)2486{2487return ((int)t->cpu_id == c->first_cpu || c->first_cpu < 0);2488}24892490int is_cpu_first_core_in_package(struct thread_data *t, struct pkg_data *p)2491{2492return ((int)t->cpu_id == p->first_cpu || p->first_cpu < 0);2493}24942495int is_cpu_first_thread_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p)2496{2497return is_cpu_first_thread_in_core(t, c) && is_cpu_first_core_in_package(t, p);2498}24992500int cpu_migrate(int cpu)2501{2502CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);2503CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);2504if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1)2505return -1;2506else2507return 0;2508}25092510int get_msr_fd(int cpu)2511{2512char pathname[32];2513int fd;25142515fd = fd_percpu[cpu];25162517if (fd)2518return fd;2519sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", cpu);2520fd = open(pathname, O_RDONLY);2521if (fd < 0)2522err(-1, "%s open failed, try chown or chmod +r %s, "2523"or run with --no-msr, or run as root", pathname, use_android_msr_path ? "/dev/msr*" : "/dev/cpu/*/msr");2524fd_percpu[cpu] = fd;25252526return fd;2527}25282529static void bic_disable_msr_access(void)2530{2531CLR_BIC(BIC_Mod_c6, &bic_enabled);2532CLR_BIC(BIC_CoreTmp, &bic_enabled);2533CLR_BIC(BIC_Totl_c0, &bic_enabled);2534CLR_BIC(BIC_Any_c0, &bic_enabled);2535CLR_BIC(BIC_GFX_c0, &bic_enabled);2536CLR_BIC(BIC_CPUGFX, &bic_enabled);2537CLR_BIC(BIC_PkgTmp, &bic_enabled);25382539free_sys_msr_counters();2540}25412542static void bic_disable_perf_access(void)2543{2544CLR_BIC(BIC_IPC, &bic_enabled);2545CLR_BIC(BIC_LLC_MRPS, &bic_enabled);2546CLR_BIC(BIC_LLC_HIT, &bic_enabled);2547CLR_BIC(BIC_L2_MRPS, &bic_enabled);2548CLR_BIC(BIC_L2_HIT, &bic_enabled);2549}25502551static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)2552{2553assert(!no_perf);25542555return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);2556}25572558static long open_perf_counter(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format)2559{2560struct perf_event_attr attr;2561const pid_t pid = -1;2562const unsigned long flags = 0;25632564assert(!no_perf);25652566memset(&attr, 0, sizeof(struct perf_event_attr));25672568attr.type = type;2569attr.size = sizeof(struct perf_event_attr);2570attr.config = config;2571attr.disabled = 0;2572attr.sample_type = PERF_SAMPLE_IDENTIFIER;2573attr.read_format = read_format;25742575const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags);25762577return fd;2578}25792580int get_instr_count_fd(int cpu)2581{2582if (fd_instr_count_percpu[cpu])2583return fd_instr_count_percpu[cpu];25842585fd_instr_count_percpu[cpu] = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0);25862587return fd_instr_count_percpu[cpu];2588}25892590int get_msr(int cpu, off_t offset, unsigned long long *msr)2591{2592ssize_t retval;25932594assert(!no_msr);25952596retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);25972598if (retval != sizeof *msr)2599err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);26002601return 0;2602}26032604int add_msr_counter(int cpu, off_t offset)2605{2606ssize_t retval;2607unsigned long long value;26082609if (no_msr)2610return -1;26112612if (!offset)2613return -1;26142615retval = pread(get_msr_fd(cpu), &value, sizeof(value), offset);26162617/* if the read failed, the probe fails */2618if (retval != sizeof(value))2619return -1;26202621if (value == 0)2622return 0;26232624return 1;2625}26262627int add_rapl_msr_counter(int cpu, const struct rapl_counter_arch_info *cai)2628{2629int ret;26302631if (!(valid_rapl_msrs & cai->feature_mask))2632return -1;26332634ret = add_msr_counter(cpu, cai->msr);2635if (ret < 0)2636return -1;26372638switch (cai->rci_index) {2639case RAPL_RCI_INDEX_ENERGY_PKG:2640case RAPL_RCI_INDEX_ENERGY_CORES:2641case RAPL_RCI_INDEX_DRAM:2642case RAPL_RCI_INDEX_GFX:2643case RAPL_RCI_INDEX_ENERGY_PLATFORM:2644if (ret == 0)2645return 1;2646}26472648/* PKG,DRAM_PERF_STATUS MSRs, can return any value */2649return 1;2650}26512652/* Convert CPU ID to domain ID for given added perf counter. */2653unsigned int cpu_to_domain(const struct perf_counter_info *pc, int cpu)2654{2655switch (pc->scope) {2656case SCOPE_CPU:2657return cpu;26582659case SCOPE_CORE:2660return cpus[cpu].core_id;26612662case SCOPE_PACKAGE:2663return cpus[cpu].package_id;2664}26652666__builtin_unreachable();2667}26682669#define MAX_DEFERRED 162670char *deferred_add_names[MAX_DEFERRED];2671char *deferred_skip_names[MAX_DEFERRED];2672int deferred_add_index;2673int deferred_skip_index;2674unsigned int deferred_add_consumed;2675unsigned int deferred_skip_consumed;26762677/*2678* HIDE_LIST - hide this list of counters, show the rest [default]2679* SHOW_LIST - show this list of counters, hide the rest2680*/2681enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;26822683void help(void)2684{2685fprintf(outf,2686"Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"2687"\n"2688"Turbostat forks the specified COMMAND and prints statistics\n"2689"when COMMAND completes.\n"2690"If no COMMAND is specified, turbostat wakes every 5-seconds\n"2691"to print statistics, until interrupted.\n"2692" -a, --add counter\n"2693" add a counter\n"2694" eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"2695" eg. --add perf/cstate_pkg/c2-residency,package,delta,percent,perfPC2\n"2696" eg. --add pmt,name=XTAL,type=raw,domain=package0,offset=0,lsb=0,msb=63,guid=0x1a067102\n"2697" -c, --cpu cpu-set\n"2698" limit output to summary plus cpu-set:\n"2699" {core | package | j,k,l..m,n-p }\n"2700" -d, --debug\n"2701" displays usec, Time_Of_Day_Seconds and more debugging\n"2702" debug messages are printed to stderr\n"2703" -D, --Dump\n"2704" displays the raw counter values\n"2705" -e, --enable [all | column]\n"2706" shows all or the specified disabled column\n"2707" -f, --force\n"2708" force load turbostat with minimum default features on unsupported platforms.\n"2709" -H, --hide [column | column,column,...]\n"2710" hide the specified column(s)\n"2711" -i, --interval sec.subsec\n"2712" override default 5-second measurement interval\n"2713" -J, --Joules\n"2714" displays energy in Joules instead of Watts\n"2715" -l, --list\n"2716" list column headers only\n"2717" -M, --no-msr\n"2718" disable all uses of the MSR driver\n"2719" -P, --no-perf\n"2720" disable all uses of the perf API\n"2721" -n, --num_iterations num\n"2722" number of the measurement iterations\n"2723" -N, --header_iterations num\n"2724" print header every num iterations\n"2725" -o, --out file\n"2726" create or truncate \"file\" for all output\n"2727" -q, --quiet\n"2728" skip decoding system configuration header\n"2729" -s, --show [column | column,column,...]\n"2730" show only the specified column(s)\n"2731" -S, --Summary\n"2732" limits output to 1-line system summary per interval\n"2733" -T, --TCC temperature\n"2734" sets the Thermal Control Circuit temperature in\n"2735" degrees Celsius\n"2736" -h, --help\n"2737" print this help message\n -v, --version\n\t\tprint version information\n\nFor more help, run \"man turbostat\"\n");2738}27392740/*2741* bic_lookup2742* for all the strings in comma separate name_list,2743* set the approprate bit in return value.2744*/2745void bic_lookup(cpu_set_t *ret_set, char *name_list, enum show_hide_mode mode)2746{2747unsigned int i;27482749while (name_list) {2750char *comma;27512752comma = strchr(name_list, ',');27532754if (comma)2755*comma = '\0';27562757for (i = 0; i < MAX_BIC; ++i) {2758if (!strcmp(name_list, bic[i].name)) {2759SET_BIC(i, ret_set);2760break;2761}2762if (!strcmp(name_list, "all")) {2763bic_set_all(ret_set);2764break;2765} else if (!strcmp(name_list, "topology")) {2766CPU_OR(ret_set, ret_set, &bic_group_topology);2767break;2768} else if (!strcmp(name_list, "power")) {2769CPU_OR(ret_set, ret_set, &bic_group_thermal_pwr);2770break;2771} else if (!strcmp(name_list, "idle")) {2772CPU_OR(ret_set, ret_set, &bic_group_idle);2773break;2774} else if (!strcmp(name_list, "cache")) {2775CPU_OR(ret_set, ret_set, &bic_group_cache);2776break;2777} else if (!strcmp(name_list, "llc")) {2778CPU_OR(ret_set, ret_set, &bic_group_cache);2779break;2780} else if (!strcmp(name_list, "swidle")) {2781CPU_OR(ret_set, ret_set, &bic_group_sw_idle);2782break;2783} else if (!strcmp(name_list, "sysfs")) { /* legacy compatibility */2784CPU_OR(ret_set, ret_set, &bic_group_sw_idle);2785break;2786} else if (!strcmp(name_list, "hwidle")) {2787CPU_OR(ret_set, ret_set, &bic_group_hw_idle);2788break;2789} else if (!strcmp(name_list, "frequency")) {2790CPU_OR(ret_set, ret_set, &bic_group_frequency);2791break;2792} else if (!strcmp(name_list, "other")) {2793CPU_OR(ret_set, ret_set, &bic_group_other);2794break;2795}2796}2797if (i == MAX_BIC) {2798if (mode == SHOW_LIST) {2799deferred_add_names[deferred_add_index++] = name_list;2800if (deferred_add_index >= MAX_DEFERRED) {2801fprintf(stderr, "More than max %d un-recognized --add options '%s'\n", MAX_DEFERRED, name_list);2802help();2803exit(1);2804}2805} else {2806deferred_skip_names[deferred_skip_index++] = name_list;2807if (debug)2808fprintf(stderr, "deferred \"%s\"\n", name_list);2809if (deferred_skip_index >= MAX_DEFERRED) {2810fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n", MAX_DEFERRED, name_list);2811help();2812exit(1);2813}2814}2815}28162817name_list = comma;2818if (name_list)2819name_list++;28202821}2822}28232824/*2825* print_name()2826* Print column header name for raw 64-bit counter in 16 columns (at least 8-char plus a tab)2827* Otherwise, allow the name + tab to fit within 8-coumn tab-stop.2828* In both cases, left justififed, just like other turbostat columns,2829* to allow the column values to consume the tab.2830*2831* Yes, 32-bit counters can overflow 8-columns, and2832* 64-bit counters can overflow 16-columns, but that is uncommon.2833*/2834static inline int print_name(int width, int *printed, char *delim, char *name, enum counter_type type, enum counter_format format)2835{2836UNUSED(type);28372838if (format == FORMAT_RAW && width >= 64)2839return (sprintf(outp, "%s%-8s", (*printed++ ? delim : ""), name));2840else2841return (sprintf(outp, "%s%s", (*printed++ ? delim : ""), name));2842}28432844static inline int print_hex_value(int width, int *printed, char *delim, unsigned long long value)2845{2846if (width <= 32)2847return (sprintf(outp, "%s%08x", (*printed++ ? delim : ""), (unsigned int)value));2848else2849return (sprintf(outp, "%s%016llx", (*printed++ ? delim : ""), value));2850}28512852static inline int print_decimal_value(int width, int *printed, char *delim, unsigned long long value)2853{2854if (width <= 32)2855return (sprintf(outp, "%s%d", (*printed++ ? delim : ""), (unsigned int)value));2856else2857return (sprintf(outp, "%s%-8lld", (*printed++ ? delim : ""), value));2858}28592860static inline int print_float_value(int *printed, char *delim, double value)2861{2862return (sprintf(outp, "%s%0.2f", (*printed++ ? delim : ""), value));2863}28642865void print_header(char *delim)2866{2867struct msr_counter *mp;2868struct perf_counter_info *pp;2869struct pmt_counter *ppmt;2870int printed = 0;28712872if (DO_BIC(BIC_USEC))2873outp += sprintf(outp, "%susec", (printed++ ? delim : ""));2874if (DO_BIC(BIC_TOD))2875outp += sprintf(outp, "%sTime_Of_Day_Seconds", (printed++ ? delim : ""));2876if (DO_BIC(BIC_Package))2877outp += sprintf(outp, "%sPackage", (printed++ ? delim : ""));2878if (DO_BIC(BIC_Die))2879outp += sprintf(outp, "%sDie", (printed++ ? delim : ""));2880if (DO_BIC(BIC_L3))2881outp += sprintf(outp, "%sL3", (printed++ ? delim : ""));2882if (DO_BIC(BIC_Node))2883outp += sprintf(outp, "%sNode", (printed++ ? delim : ""));2884if (DO_BIC(BIC_Core))2885outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));2886if (DO_BIC(BIC_CPU))2887outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));2888if (DO_BIC(BIC_APIC))2889outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));2890if (DO_BIC(BIC_X2APIC))2891outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));2892if (DO_BIC(BIC_Avg_MHz))2893outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));2894if (DO_BIC(BIC_Busy))2895outp += sprintf(outp, "%sBusy%%", (printed++ ? delim : ""));2896if (DO_BIC(BIC_Bzy_MHz))2897outp += sprintf(outp, "%sBzy_MHz", (printed++ ? delim : ""));2898if (DO_BIC(BIC_TSC_MHz))2899outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));29002901if (DO_BIC(BIC_IPC))2902outp += sprintf(outp, "%sIPC", (printed++ ? delim : ""));29032904if (DO_BIC(BIC_IRQ)) {2905if (sums_need_wide_columns)2906outp += sprintf(outp, "%s IRQ", (printed++ ? delim : ""));2907else2908outp += sprintf(outp, "%sIRQ", (printed++ ? delim : ""));2909}2910if (DO_BIC(BIC_NMI)) {2911if (sums_need_wide_columns)2912outp += sprintf(outp, "%s NMI", (printed++ ? delim : ""));2913else2914outp += sprintf(outp, "%sNMI", (printed++ ? delim : ""));2915}29162917if (DO_BIC(BIC_SMI))2918outp += sprintf(outp, "%sSMI", (printed++ ? delim : ""));29192920if (DO_BIC(BIC_LLC_MRPS))2921outp += sprintf(outp, "%sLLCMRPS", (printed++ ? delim : ""));29222923if (DO_BIC(BIC_LLC_HIT))2924outp += sprintf(outp, "%sLLC%%hit", (printed++ ? delim : ""));29252926if (DO_BIC(BIC_L2_MRPS))2927outp += sprintf(outp, "%sL2MRPS", (printed++ ? delim : ""));29282929if (DO_BIC(BIC_L2_HIT))2930outp += sprintf(outp, "%sL2%%hit", (printed++ ? delim : ""));29312932for (mp = sys.tp; mp; mp = mp->next)2933outp += print_name(mp->width, &printed, delim, mp->name, mp->type, mp->format);29342935for (pp = sys.perf_tp; pp; pp = pp->next)2936outp += print_name(pp->width, &printed, delim, pp->name, pp->type, pp->format);29372938ppmt = sys.pmt_tp;2939while (ppmt) {2940switch (ppmt->type) {2941case PMT_TYPE_RAW:2942outp += print_name(pmt_counter_get_width(ppmt), &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format);2943break;29442945case PMT_TYPE_XTAL_TIME:2946case PMT_TYPE_TCORE_CLOCK:2947outp += print_name(32, &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format);2948break;2949}29502951ppmt = ppmt->next;2952}29532954if (DO_BIC(BIC_CPU_c1))2955outp += sprintf(outp, "%sCPU%%c1", (printed++ ? delim : ""));2956if (DO_BIC(BIC_CPU_c3))2957outp += sprintf(outp, "%sCPU%%c3", (printed++ ? delim : ""));2958if (DO_BIC(BIC_CPU_c6))2959outp += sprintf(outp, "%sCPU%%c6", (printed++ ? delim : ""));2960if (DO_BIC(BIC_CPU_c7))2961outp += sprintf(outp, "%sCPU%%c7", (printed++ ? delim : ""));29622963if (DO_BIC(BIC_Mod_c6))2964outp += sprintf(outp, "%sMod%%c6", (printed++ ? delim : ""));29652966if (DO_BIC(BIC_CoreTmp))2967outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));29682969if (DO_BIC(BIC_CORE_THROT_CNT))2970outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : ""));29712972if (valid_rapl_msrs && !rapl_joules) {2973if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl)2974outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));2975} else if (valid_rapl_msrs && rapl_joules) {2976if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl)2977outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));2978}29792980for (mp = sys.cp; mp; mp = mp->next)2981outp += print_name(mp->width, &printed, delim, mp->name, mp->type, mp->format);29822983for (pp = sys.perf_cp; pp; pp = pp->next)2984outp += print_name(pp->width, &printed, delim, pp->name, pp->type, pp->format);29852986ppmt = sys.pmt_cp;2987while (ppmt) {2988switch (ppmt->type) {2989case PMT_TYPE_RAW:2990outp += print_name(pmt_counter_get_width(ppmt), &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format);29912992break;29932994case PMT_TYPE_XTAL_TIME:2995case PMT_TYPE_TCORE_CLOCK:2996outp += print_name(32, &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format);2997break;2998}29993000ppmt = ppmt->next;3001}3002if (DO_BIC(BIC_PkgTmp))3003outp += sprintf(outp, "%sPkgTmp", (printed++ ? delim : ""));30043005if (DO_BIC(BIC_GFX_rc6))3006outp += sprintf(outp, "%sGFX%%rc6", (printed++ ? delim : ""));30073008if (DO_BIC(BIC_GFXMHz))3009outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));30103011if (DO_BIC(BIC_GFXACTMHz))3012outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));30133014if (DO_BIC(BIC_SAM_mc6))3015outp += sprintf(outp, "%sSAM%%mc6", (printed++ ? delim : ""));30163017if (DO_BIC(BIC_SAMMHz))3018outp += sprintf(outp, "%sSAMMHz", (printed++ ? delim : ""));30193020if (DO_BIC(BIC_SAMACTMHz))3021outp += sprintf(outp, "%sSAMAMHz", (printed++ ? delim : ""));30223023if (DO_BIC(BIC_Totl_c0))3024outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));3025if (DO_BIC(BIC_Any_c0))3026outp += sprintf(outp, "%sAny%%C0", (printed++ ? delim : ""));3027if (DO_BIC(BIC_GFX_c0))3028outp += sprintf(outp, "%sGFX%%C0", (printed++ ? delim : ""));3029if (DO_BIC(BIC_CPUGFX))3030outp += sprintf(outp, "%sCPUGFX%%", (printed++ ? delim : ""));30313032if (DO_BIC(BIC_Pkgpc2))3033outp += sprintf(outp, "%sPkg%%pc2", (printed++ ? delim : ""));3034if (DO_BIC(BIC_Pkgpc3))3035outp += sprintf(outp, "%sPkg%%pc3", (printed++ ? delim : ""));3036if (DO_BIC(BIC_Pkgpc6))3037outp += sprintf(outp, "%sPkg%%pc6", (printed++ ? delim : ""));3038if (DO_BIC(BIC_Pkgpc7))3039outp += sprintf(outp, "%sPkg%%pc7", (printed++ ? delim : ""));3040if (DO_BIC(BIC_Pkgpc8))3041outp += sprintf(outp, "%sPkg%%pc8", (printed++ ? delim : ""));3042if (DO_BIC(BIC_Pkgpc9))3043outp += sprintf(outp, "%sPkg%%pc9", (printed++ ? delim : ""));3044if (DO_BIC(BIC_Pkgpc10))3045outp += sprintf(outp, "%sPk%%pc10", (printed++ ? delim : ""));3046if (DO_BIC(BIC_Diec6))3047outp += sprintf(outp, "%sDie%%c6", (printed++ ? delim : ""));3048if (DO_BIC(BIC_CPU_LPI))3049outp += sprintf(outp, "%sCPU%%LPI", (printed++ ? delim : ""));3050if (DO_BIC(BIC_SYS_LPI))3051outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : ""));30523053if (!rapl_joules) {3054if (DO_BIC(BIC_PkgWatt))3055outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : ""));3056if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)3057outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));3058if (DO_BIC(BIC_GFXWatt))3059outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : ""));3060if (DO_BIC(BIC_RAMWatt))3061outp += sprintf(outp, "%sRAMWatt", (printed++ ? delim : ""));3062if (DO_BIC(BIC_PKG__))3063outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));3064if (DO_BIC(BIC_RAM__))3065outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));3066} else {3067if (DO_BIC(BIC_Pkg_J))3068outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : ""));3069if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)3070outp += sprintf(outp, "%sCor_J", (printed++ ? delim : ""));3071if (DO_BIC(BIC_GFX_J))3072outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : ""));3073if (DO_BIC(BIC_RAM_J))3074outp += sprintf(outp, "%sRAM_J", (printed++ ? delim : ""));3075if (DO_BIC(BIC_PKG__))3076outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : ""));3077if (DO_BIC(BIC_RAM__))3078outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));3079}3080if (DO_BIC(BIC_UNCORE_MHZ))3081outp += sprintf(outp, "%sUncMHz", (printed++ ? delim : ""));30823083for (mp = sys.pp; mp; mp = mp->next)3084outp += print_name(mp->width, &printed, delim, mp->name, mp->type, mp->format);30853086for (pp = sys.perf_pp; pp; pp = pp->next)3087outp += print_name(pp->width, &printed, delim, pp->name, pp->type, pp->format);30883089ppmt = sys.pmt_pp;3090while (ppmt) {3091switch (ppmt->type) {3092case PMT_TYPE_RAW:3093outp += print_name(pmt_counter_get_width(ppmt), &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format);3094break;30953096case PMT_TYPE_XTAL_TIME:3097case PMT_TYPE_TCORE_CLOCK:3098outp += print_name(32, &printed, delim, ppmt->name, COUNTER_ITEMS, ppmt->format);3099break;3100}31013102ppmt = ppmt->next;3103}31043105if (DO_BIC(BIC_SysWatt))3106outp += sprintf(outp, "%sSysWatt", (printed++ ? delim : ""));3107if (DO_BIC(BIC_Sys_J))3108outp += sprintf(outp, "%sSys_J", (printed++ ? delim : ""));31093110outp += sprintf(outp, "\n");3111}31123113/*3114* pct(numerator, denominator)3115*3116* Return sanity checked percentage (100.0 * numerator/denominotor)3117*3118* n < 0: nan3119* d <= 0: nan3120* n/d > 1.1: nan3121*/3122double pct(double numerator, double denominator)3123{3124double retval;31253126if (numerator < 0)3127return nan("");31283129if (denominator <= 0)3130return nan("");31313132retval = 100.0 * numerator / denominator;31333134if (retval > 110.0)3135return nan("");31363137return retval;3138}31393140int dump_counters(PER_THREAD_PARAMS)3141{3142int i;3143struct msr_counter *mp;3144struct platform_counters *pplat_cnt = p == odd.packages ? &platform_counters_odd : &platform_counters_even;31453146outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);31473148if (t) {3149outp += sprintf(outp, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags);3150outp += sprintf(outp, "TSC: %016llX\n", t->tsc);3151outp += sprintf(outp, "aperf: %016llX\n", t->aperf);3152outp += sprintf(outp, "mperf: %016llX\n", t->mperf);3153outp += sprintf(outp, "c1: %016llX\n", t->c1);31543155if (DO_BIC(BIC_IPC))3156outp += sprintf(outp, "IPC: %lld\n", t->instr_count);31573158if (DO_BIC(BIC_IRQ))3159outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);3160if (DO_BIC(BIC_NMI))3161outp += sprintf(outp, "IRQ: %lld\n", t->nmi_count);3162if (DO_BIC(BIC_SMI))3163outp += sprintf(outp, "SMI: %d\n", t->smi_count);31643165outp += sprintf(outp, "LLC refs: %lld", t->llc.references);3166outp += sprintf(outp, "LLC miss: %lld", t->llc.misses);3167outp += sprintf(outp, "LLC Hit%%: %.2f", pct((t->llc.references - t->llc.misses), t->llc.references));31683169outp += sprintf(outp, "L2 refs: %lld", t->l2.references);3170outp += sprintf(outp, "L2 hits: %lld", t->l2.hits);3171outp += sprintf(outp, "L2 Hit%%: %.2f", pct(t->l2.hits, t->l2.references));31723173for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {3174outp += sprintf(outp, "tADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, t->counter[i], mp->sp->path);3175}3176}31773178if (c && is_cpu_first_thread_in_core(t, c)) {3179outp += sprintf(outp, "core: %d\n", cpus[t->cpu_id].core_id);3180outp += sprintf(outp, "c3: %016llX\n", c->c3);3181outp += sprintf(outp, "c6: %016llX\n", c->c6);3182outp += sprintf(outp, "c7: %016llX\n", c->c7);3183outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c);3184outp += sprintf(outp, "cpu_throt_count: %016llX\n", c->core_throt_cnt);31853186const unsigned long long energy_value = c->core_energy.raw_value * c->core_energy.scale;3187const double energy_scale = c->core_energy.scale;31883189if (c->core_energy.unit == RAPL_UNIT_JOULES)3190outp += sprintf(outp, "Joules: %0llX (scale: %lf)\n", energy_value, energy_scale);31913192for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {3193outp += sprintf(outp, "cADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, c->counter[i], mp->sp->path);3194}3195outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);3196}31973198if (p && is_cpu_first_core_in_package(t, p)) {3199outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0);3200outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0);3201outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0);3202outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);32033204outp += sprintf(outp, "pc2: %016llX\n", p->pc2);3205if (DO_BIC(BIC_Pkgpc3))3206outp += sprintf(outp, "pc3: %016llX\n", p->pc3);3207if (DO_BIC(BIC_Pkgpc6))3208outp += sprintf(outp, "pc6: %016llX\n", p->pc6);3209if (DO_BIC(BIC_Pkgpc7))3210outp += sprintf(outp, "pc7: %016llX\n", p->pc7);3211outp += sprintf(outp, "pc8: %016llX\n", p->pc8);3212outp += sprintf(outp, "pc9: %016llX\n", p->pc9);3213outp += sprintf(outp, "pc10: %016llX\n", p->pc10);3214outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);3215outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);3216outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg.raw_value);3217outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores.raw_value);3218outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx.raw_value);3219outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram.raw_value);3220outp += sprintf(outp, "Joules PSYS: %0llX\n", pplat_cnt->energy_psys.raw_value);3221outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status.raw_value);3222outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status.raw_value);3223outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);32243225for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3226outp += sprintf(outp, "pADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, p->counter[i], mp->sp->path);3227}3228}32293230outp += sprintf(outp, "\n");32313232return 0;3233}32343235double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desired_unit, double interval)3236{3237assert(desired_unit != RAPL_UNIT_INVALID);32383239/*3240* For now we don't expect anything other than joules,3241* so just simplify the logic.3242*/3243assert(c->unit == RAPL_UNIT_JOULES);32443245const double scaled = c->raw_value * c->scale;32463247if (desired_unit == RAPL_UNIT_WATTS)3248return scaled / interval;3249return scaled;3250}32513252void get_perf_llc_stats(int cpu, struct llc_stats *llc)3253{3254struct read_format {3255unsigned long long num_read;3256struct llc_stats llc;3257} r;3258const ssize_t expected_read_size = sizeof(r);3259ssize_t actual_read_size;32603261actual_read_size = read(fd_llc_percpu[cpu], &r, expected_read_size);32623263if (actual_read_size == -1)3264err(-1, "%s(cpu%d,) %d,,%ld", __func__, cpu, fd_llc_percpu[cpu], expected_read_size);32653266llc->references = r.llc.references;3267llc->misses = r.llc.misses;3268if (actual_read_size != expected_read_size)3269warn("%s: failed to read perf_data (req %zu act %zu)", __func__, expected_read_size, actual_read_size);3270}32713272void get_perf_l2_stats(int cpu, struct l2_stats *l2)3273{3274struct read_format {3275unsigned long long num_read;3276struct l2_stats l2;3277} r;3278const ssize_t expected_read_size = sizeof(r);3279ssize_t actual_read_size;32803281actual_read_size = read(fd_l2_percpu[cpu], &r, expected_read_size);32823283if (actual_read_size == -1)3284err(-1, "%s(cpu%d,) %d,,%ld", __func__, cpu, fd_l2_percpu[cpu], expected_read_size);32853286l2->references = r.l2.references;3287l2->hits = r.l2.hits;3288if (actual_read_size != expected_read_size)3289warn("%s: cpu%d: failed to read(%d) perf_data (req %zu act %zu)", __func__, cpu, fd_l2_percpu[cpu], expected_read_size, actual_read_size);3290}32913292/*3293* column formatting convention & formats3294*/3295int format_counters(PER_THREAD_PARAMS)3296{3297static int count;32983299struct platform_counters *pplat_cnt = NULL;3300double interval_float, tsc;3301char *fmt8 = "%s%.2f";33023303int i;3304struct msr_counter *mp;3305struct perf_counter_info *pp;3306struct pmt_counter *ppmt;3307char *delim = "\t";3308int printed = 0;33093310if (t == average.threads) {3311pplat_cnt = count & 1 ? &platform_counters_odd : &platform_counters_even;3312++count;3313}33143315/* if showing only 1st thread in core and this isn't one, bail out */3316if (show_core_only && !is_cpu_first_thread_in_core(t, c))3317return 0;33183319/* if showing only 1st thread in pkg and this isn't one, bail out */3320if (show_pkg_only && !is_cpu_first_core_in_package(t, p))3321return 0;33223323/*if not summary line and --cpu is used */3324if ((t != average.threads) && (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))3325return 0;33263327if (DO_BIC(BIC_USEC)) {3328/* on each row, print how many usec each timestamp took to gather */3329struct timeval tv;33303331timersub(&t->tv_end, &t->tv_begin, &tv);3332outp += sprintf(outp, "%5ld\t", tv.tv_sec * 1000000 + tv.tv_usec);3333}33343335/* Time_Of_Day_Seconds: on each row, print sec.usec last timestamp taken */3336if (DO_BIC(BIC_TOD))3337outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);33383339interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec / 1000000.0;33403341tsc = t->tsc * tsc_tweak;33423343/* topo columns, print blanks on 1st (average) line */3344if (t == average.threads) {3345if (DO_BIC(BIC_Package))3346outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3347if (DO_BIC(BIC_Die))3348outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3349if (DO_BIC(BIC_L3))3350outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3351if (DO_BIC(BIC_Node))3352outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3353if (DO_BIC(BIC_Core))3354outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3355if (DO_BIC(BIC_CPU))3356outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3357if (DO_BIC(BIC_APIC))3358outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3359if (DO_BIC(BIC_X2APIC))3360outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3361} else {3362if (DO_BIC(BIC_Package)) {3363if (p)3364outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].package_id);3365else3366outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3367}3368if (DO_BIC(BIC_Die)) {3369if (c)3370outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].die_id);3371else3372outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3373}3374if (DO_BIC(BIC_L3)) {3375if (c)3376outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].l3_id);3377else3378outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3379}3380if (DO_BIC(BIC_Node)) {3381if (t)3382outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].physical_node_id);3383else3384outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3385}3386if (DO_BIC(BIC_Core)) {3387if (c)3388outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), cpus[t->cpu_id].core_id);3389else3390outp += sprintf(outp, "%s-", (printed++ ? delim : ""));3391}3392if (DO_BIC(BIC_CPU))3393outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);3394if (DO_BIC(BIC_APIC))3395outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);3396if (DO_BIC(BIC_X2APIC))3397outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);3398}33993400if (DO_BIC(BIC_Avg_MHz))3401outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 / units * t->aperf / interval_float);34023403if (DO_BIC(BIC_Busy))3404outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->mperf, tsc));34053406if (DO_BIC(BIC_Bzy_MHz)) {3407if (has_base_hz)3408outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);3409else3410outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), tsc / units * t->aperf / t->mperf / interval_float);3411}34123413if (DO_BIC(BIC_TSC_MHz))3414outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc / units / interval_float);34153416if (DO_BIC(BIC_IPC))3417outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 1.0 * t->instr_count / t->aperf);34183419/* IRQ */3420if (DO_BIC(BIC_IRQ)) {3421if (sums_need_wide_columns)3422outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->irq_count);3423else3424outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->irq_count);3425}34263427/* NMI */3428if (DO_BIC(BIC_NMI)) {3429if (sums_need_wide_columns)3430outp += sprintf(outp, "%s%8lld", (printed++ ? delim : ""), t->nmi_count);3431else3432outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->nmi_count);3433}34343435/* SMI */3436if (DO_BIC(BIC_SMI))3437outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->smi_count);34383439/* LLC Stats */3440if (DO_BIC(BIC_LLC_MRPS))3441outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), t->llc.references / interval_float / 1000000);34423443if (DO_BIC(BIC_LLC_HIT))3444outp += sprintf(outp, fmt8, (printed++ ? delim : ""), pct((t->llc.references - t->llc.misses), t->llc.references));34453446/* L2 Stats */3447if (DO_BIC(BIC_L2_MRPS))3448outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), t->l2.references / interval_float / 1000000);34493450if (DO_BIC(BIC_L2_HIT))3451outp += sprintf(outp, fmt8, (printed++ ? delim : ""), pct(t->l2.hits, t->l2.references));34523453/* Added Thread Counters */3454for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {3455if (mp->format == FORMAT_RAW)3456outp += print_hex_value(mp->width, &printed, delim, t->counter[i]);3457else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)3458outp += print_decimal_value(mp->width, &printed, delim, t->counter[i]);3459else if (mp->format == FORMAT_PERCENT) {3460if (mp->type == COUNTER_USEC)3461outp += print_float_value(&printed, delim, t->counter[i] / interval_float / 10000);3462else3463outp += print_float_value(&printed, delim, pct(t->counter[i], tsc));3464}3465}34663467/* Added perf Thread Counters */3468for (i = 0, pp = sys.perf_tp; pp; ++i, pp = pp->next) {3469if (pp->format == FORMAT_RAW)3470outp += print_hex_value(pp->width, &printed, delim, t->perf_counter[i]);3471else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)3472outp += print_decimal_value(pp->width, &printed, delim, t->perf_counter[i]);3473else if (pp->format == FORMAT_PERCENT) {3474if (pp->type == COUNTER_USEC)3475outp += print_float_value(&printed, delim, t->perf_counter[i] / interval_float / 10000);3476else3477outp += print_float_value(&printed, delim, pct(t->perf_counter[i], tsc));3478}3479}34803481/* Added PMT Thread Counters */3482for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {3483const unsigned long value_raw = t->pmt_counter[i];3484double value_converted;3485switch (ppmt->type) {3486case PMT_TYPE_RAW:3487outp += print_hex_value(pmt_counter_get_width(ppmt), &printed, delim, t->pmt_counter[i]);3488break;34893490case PMT_TYPE_XTAL_TIME:3491value_converted = pct(value_raw / crystal_hz, interval_float);3492outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);3493break;34943495case PMT_TYPE_TCORE_CLOCK:3496value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);3497outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);3498}3499}35003501/* C1 */3502if (DO_BIC(BIC_CPU_c1))3503outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->c1, tsc));35043505/* print per-core data only for 1st thread in core */3506if (!is_cpu_first_thread_in_core(t, c))3507goto done;35083509if (DO_BIC(BIC_CPU_c3))3510outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c3, tsc));3511if (DO_BIC(BIC_CPU_c6))3512outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c6, tsc));3513if (DO_BIC(BIC_CPU_c7))3514outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c7, tsc));35153516/* Mod%c6 */3517if (DO_BIC(BIC_Mod_c6))3518outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->mc6_us, tsc));35193520if (DO_BIC(BIC_CoreTmp))3521outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);35223523/* Core throttle count */3524if (DO_BIC(BIC_CORE_THROT_CNT))3525outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->core_throt_cnt);35263527/* Added Core Counters */3528for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {3529if (mp->format == FORMAT_RAW)3530outp += print_hex_value(mp->width, &printed, delim, c->counter[i]);3531else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)3532outp += print_decimal_value(mp->width, &printed, delim, c->counter[i]);3533else if (mp->format == FORMAT_PERCENT)3534outp += print_float_value(&printed, delim, pct(c->counter[i], tsc));3535}35363537/* Added perf Core counters */3538for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {3539if (pp->format == FORMAT_RAW)3540outp += print_hex_value(pp->width, &printed, delim, c->perf_counter[i]);3541else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)3542outp += print_decimal_value(pp->width, &printed, delim, c->perf_counter[i]);3543else if (pp->format == FORMAT_PERCENT)3544outp += print_float_value(&printed, delim, pct(c->perf_counter[i], tsc));3545}35463547/* Added PMT Core counters */3548for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {3549const unsigned long value_raw = c->pmt_counter[i];3550double value_converted;3551switch (ppmt->type) {3552case PMT_TYPE_RAW:3553outp += print_hex_value(pmt_counter_get_width(ppmt), &printed, delim, c->pmt_counter[i]);3554break;35553556case PMT_TYPE_XTAL_TIME:3557value_converted = pct(value_raw / crystal_hz, interval_float);3558outp += print_float_value(&printed, delim, value_converted);3559break;35603561case PMT_TYPE_TCORE_CLOCK:3562value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);3563outp += print_float_value(&printed, delim, value_converted);3564}3565}35663567if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl)3568outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&c->core_energy, RAPL_UNIT_WATTS, interval_float));3569if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl)3570outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&c->core_energy, RAPL_UNIT_JOULES, interval_float));35713572/* print per-package data only for 1st core in package */3573if (!is_cpu_first_core_in_package(t, p))3574goto done;35753576/* PkgTmp */3577if (DO_BIC(BIC_PkgTmp))3578outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->pkg_temp_c);35793580/* GFXrc6 */3581if (DO_BIC(BIC_GFX_rc6)) {3582if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */3583outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));3584} else {3585outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->gfx_rc6_ms / 10.0 / interval_float);3586}3587}35883589/* GFXMHz */3590if (DO_BIC(BIC_GFXMHz))3591outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);35923593/* GFXACTMHz */3594if (DO_BIC(BIC_GFXACTMHz))3595outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);35963597/* SAMmc6 */3598if (DO_BIC(BIC_SAM_mc6)) {3599if (p->sam_mc6_ms == -1) { /* detect GFX counter reset */3600outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));3601} else {3602outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->sam_mc6_ms / 10.0 / interval_float);3603}3604}36053606/* SAMMHz */3607if (DO_BIC(BIC_SAMMHz))3608outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_mhz);36093610/* SAMACTMHz */3611if (DO_BIC(BIC_SAMACTMHz))3612outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_act_mhz);36133614/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */3615if (DO_BIC(BIC_Totl_c0))3616outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100 * p->pkg_wtd_core_c0 / tsc); /* can exceed 100% */3617if (DO_BIC(BIC_Any_c0))3618outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_core_c0, tsc));3619if (DO_BIC(BIC_GFX_c0))3620outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_gfxe_c0, tsc));3621if (DO_BIC(BIC_CPUGFX))3622outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_both_core_gfxe_c0, tsc));36233624if (DO_BIC(BIC_Pkgpc2))3625outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc2, tsc));3626if (DO_BIC(BIC_Pkgpc3))3627outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc3, tsc));3628if (DO_BIC(BIC_Pkgpc6))3629outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc6, tsc));3630if (DO_BIC(BIC_Pkgpc7))3631outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc7, tsc));3632if (DO_BIC(BIC_Pkgpc8))3633outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc8, tsc));3634if (DO_BIC(BIC_Pkgpc9))3635outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc9, tsc));3636if (DO_BIC(BIC_Pkgpc10))3637outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc10, tsc));36383639if (DO_BIC(BIC_Diec6))3640outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->die_c6 / crystal_hz, interval_float));36413642if (DO_BIC(BIC_CPU_LPI)) {3643if (p->cpu_lpi >= 0)3644outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->cpu_lpi / 1000000.0, interval_float));3645else3646outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));3647}3648if (DO_BIC(BIC_SYS_LPI)) {3649if (p->sys_lpi >= 0)3650outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->sys_lpi / 1000000.0, interval_float));3651else3652outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));3653}36543655if (DO_BIC(BIC_PkgWatt))3656outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_WATTS, interval_float));3657if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl)3658outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_WATTS, interval_float));3659if (DO_BIC(BIC_GFXWatt))3660outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_WATTS, interval_float));3661if (DO_BIC(BIC_RAMWatt))3662outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_WATTS, interval_float));3663if (DO_BIC(BIC_Pkg_J))3664outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_JOULES, interval_float));3665if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl)3666outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_JOULES, interval_float));3667if (DO_BIC(BIC_GFX_J))3668outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_JOULES, interval_float));3669if (DO_BIC(BIC_RAM_J))3670outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_JOULES, interval_float));3671if (DO_BIC(BIC_PKG__))3672outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->rapl_pkg_perf_status, RAPL_UNIT_WATTS, interval_float));3673if (DO_BIC(BIC_RAM__))3674outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&p->rapl_dram_perf_status, RAPL_UNIT_WATTS, interval_float));3675/* UncMHz */3676if (DO_BIC(BIC_UNCORE_MHZ))3677outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->uncore_mhz);36783679/* Added Package Counters */3680for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3681if (mp->format == FORMAT_RAW)3682outp += print_hex_value(mp->width, &printed, delim, p->counter[i]);3683else if (mp->type == COUNTER_K2M)3684outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->counter[i] / 1000);3685else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)3686outp += print_decimal_value(mp->width, &printed, delim, p->counter[i]);3687else if (mp->format == FORMAT_PERCENT)3688outp += print_float_value(&printed, delim, pct(p->counter[i], tsc));3689}36903691/* Added perf Package Counters */3692for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {3693if (pp->format == FORMAT_RAW)3694outp += print_hex_value(pp->width, &printed, delim, p->perf_counter[i]);3695else if (pp->type == COUNTER_K2M)3696outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->perf_counter[i] / 1000);3697else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)3698outp += print_decimal_value(pp->width, &printed, delim, p->perf_counter[i]);3699else if (pp->format == FORMAT_PERCENT)3700outp += print_float_value(&printed, delim, pct(p->perf_counter[i], tsc));3701}37023703/* Added PMT Package Counters */3704for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {3705const unsigned long value_raw = p->pmt_counter[i];3706double value_converted;3707switch (ppmt->type) {3708case PMT_TYPE_RAW:3709outp += print_hex_value(pmt_counter_get_width(ppmt), &printed, delim, p->pmt_counter[i]);3710break;37113712case PMT_TYPE_XTAL_TIME:3713value_converted = pct(value_raw / crystal_hz, interval_float);3714outp += print_float_value(&printed, delim, value_converted);3715break;37163717case PMT_TYPE_TCORE_CLOCK:3718value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);3719outp += print_float_value(&printed, delim, value_converted);3720}3721}37223723if (DO_BIC(BIC_SysWatt) && (t == average.threads))3724outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_WATTS, interval_float));3725if (DO_BIC(BIC_Sys_J) && (t == average.threads))3726outp += sprintf(outp, fmt8, (printed++ ? delim : ""), rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_JOULES, interval_float));37273728done:3729if (*(outp - 1) != '\n')3730outp += sprintf(outp, "\n");37313732return 0;3733}37343735void flush_output_stdout(void)3736{3737FILE *filep;37383739if (outf == stderr)3740filep = stdout;3741else3742filep = outf;37433744fputs(output_buffer, filep);3745fflush(filep);37463747outp = output_buffer;3748}37493750void flush_output_stderr(void)3751{3752fputs(output_buffer, outf);3753fflush(outf);3754outp = output_buffer;3755}37563757void format_all_counters(PER_THREAD_PARAMS)3758{3759static int count;37603761if ((!count || (header_iterations && !(count % header_iterations))) || !summary_only)3762print_header("\t");37633764format_counters(average.threads, average.cores, average.packages);37653766count++;37673768if (summary_only)3769return;37703771for_all_cpus(format_counters, t, c, p);3772}37733774#define DELTA_WRAP32(new, old) \3775old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);37763777int delta_package(struct pkg_data *new, struct pkg_data *old)3778{3779int i;3780struct msr_counter *mp;3781struct perf_counter_info *pp;3782struct pmt_counter *ppmt;37833784if (DO_BIC(BIC_Totl_c0))3785old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;3786if (DO_BIC(BIC_Any_c0))3787old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;3788if (DO_BIC(BIC_GFX_c0))3789old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;3790if (DO_BIC(BIC_CPUGFX))3791old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;37923793old->pc2 = new->pc2 - old->pc2;3794if (DO_BIC(BIC_Pkgpc3))3795old->pc3 = new->pc3 - old->pc3;3796if (DO_BIC(BIC_Pkgpc6))3797old->pc6 = new->pc6 - old->pc6;3798if (DO_BIC(BIC_Pkgpc7))3799old->pc7 = new->pc7 - old->pc7;3800old->pc8 = new->pc8 - old->pc8;3801old->pc9 = new->pc9 - old->pc9;3802old->pc10 = new->pc10 - old->pc10;3803old->die_c6 = new->die_c6 - old->die_c6;3804old->cpu_lpi = new->cpu_lpi - old->cpu_lpi;3805old->sys_lpi = new->sys_lpi - old->sys_lpi;3806old->pkg_temp_c = new->pkg_temp_c;38073808/* flag an error when rc6 counter resets/wraps */3809if (old->gfx_rc6_ms > new->gfx_rc6_ms)3810old->gfx_rc6_ms = -1;3811else3812old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;38133814old->uncore_mhz = new->uncore_mhz;3815old->gfx_mhz = new->gfx_mhz;3816old->gfx_act_mhz = new->gfx_act_mhz;38173818/* flag an error when mc6 counter resets/wraps */3819if (old->sam_mc6_ms > new->sam_mc6_ms)3820old->sam_mc6_ms = -1;3821else3822old->sam_mc6_ms = new->sam_mc6_ms - old->sam_mc6_ms;38233824old->sam_mhz = new->sam_mhz;3825old->sam_act_mhz = new->sam_act_mhz;38263827old->energy_pkg.raw_value = new->energy_pkg.raw_value - old->energy_pkg.raw_value;3828old->energy_cores.raw_value = new->energy_cores.raw_value - old->energy_cores.raw_value;3829old->energy_gfx.raw_value = new->energy_gfx.raw_value - old->energy_gfx.raw_value;3830old->energy_dram.raw_value = new->energy_dram.raw_value - old->energy_dram.raw_value;3831old->rapl_pkg_perf_status.raw_value = new->rapl_pkg_perf_status.raw_value - old->rapl_pkg_perf_status.raw_value;3832old->rapl_dram_perf_status.raw_value = new->rapl_dram_perf_status.raw_value - old->rapl_dram_perf_status.raw_value;38333834for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {3835if (mp->format == FORMAT_RAW)3836old->counter[i] = new->counter[i];3837else if (mp->format == FORMAT_AVERAGE)3838old->counter[i] = new->counter[i];3839else3840old->counter[i] = new->counter[i] - old->counter[i];3841}38423843for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {3844if (pp->format == FORMAT_RAW)3845old->perf_counter[i] = new->perf_counter[i];3846else if (pp->format == FORMAT_AVERAGE)3847old->perf_counter[i] = new->perf_counter[i];3848else3849old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i];3850}38513852for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {3853if (ppmt->format == FORMAT_RAW)3854old->pmt_counter[i] = new->pmt_counter[i];3855else3856old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i];3857}38583859return 0;3860}38613862void delta_core(struct core_data *new, struct core_data *old)3863{3864int i;3865struct msr_counter *mp;3866struct perf_counter_info *pp;3867struct pmt_counter *ppmt;38683869old->c3 = new->c3 - old->c3;3870old->c6 = new->c6 - old->c6;3871old->c7 = new->c7 - old->c7;3872old->core_temp_c = new->core_temp_c;3873old->core_throt_cnt = new->core_throt_cnt - old->core_throt_cnt;3874old->mc6_us = new->mc6_us - old->mc6_us;38753876DELTA_WRAP32(new->core_energy.raw_value, old->core_energy.raw_value);38773878for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {3879if (mp->format == FORMAT_RAW || mp->format == FORMAT_AVERAGE)3880old->counter[i] = new->counter[i];3881else3882old->counter[i] = new->counter[i] - old->counter[i];3883}38843885for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {3886if (pp->format == FORMAT_RAW)3887old->perf_counter[i] = new->perf_counter[i];3888else3889old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i];3890}38913892for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {3893if (ppmt->format == FORMAT_RAW)3894old->pmt_counter[i] = new->pmt_counter[i];3895else3896old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i];3897}3898}38993900int soft_c1_residency_display(int bic)3901{3902if (!DO_BIC(BIC_CPU_c1) || platform->has_msr_core_c1_res)3903return 0;39043905return DO_BIC_READ(bic);3906}39073908/*3909* old = new - old3910*/3911int delta_thread(struct thread_data *new, struct thread_data *old, struct core_data *core_delta)3912{3913int i;3914struct msr_counter *mp;3915struct perf_counter_info *pp;3916struct pmt_counter *ppmt;39173918/* we run cpuid just the 1st time, copy the results */3919if (DO_BIC(BIC_APIC))3920new->apic_id = old->apic_id;3921if (DO_BIC(BIC_X2APIC))3922new->x2apic_id = old->x2apic_id;39233924/*3925* the timestamps from start of measurement interval are in "old"3926* the timestamp from end of measurement interval are in "new"3927* over-write old w/ new so we can print end of interval values3928*/39293930timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);3931old->tv_begin = new->tv_begin;3932old->tv_end = new->tv_end;39333934old->tsc = new->tsc - old->tsc;39353936/* check for TSC < 1 Mcycles over interval */3937if (old->tsc < (1000 * 1000))3938errx(-3, "Insanely slow TSC rate, TSC stops in idle?\n"3939"You can disable all c-states by booting with \"idle=poll\"\nor just the deep ones with \"processor.max_cstate=1\"");39403941old->c1 = new->c1 - old->c1;39423943if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || DO_BIC(BIC_IPC)3944|| soft_c1_residency_display(BIC_Avg_MHz)) {3945if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {3946old->aperf = new->aperf - old->aperf;3947old->mperf = new->mperf - old->mperf;3948} else {3949return -1;3950}3951}39523953if (platform->has_msr_core_c1_res) {3954/*3955* Some models have a dedicated C1 residency MSR,3956* which should be more accurate than the derivation below.3957*/3958} else {3959/*3960* As counter collection is not atomic,3961* it is possible for mperf's non-halted cycles + idle states3962* to exceed TSC's all cycles: show c1 = 0% in that case.3963*/3964if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > (old->tsc * tsc_tweak))3965old->c1 = 0;3966else {3967/* normal case, derive c1 */3968old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3 - core_delta->c6 - core_delta->c7;3969}3970}39713972if (old->mperf == 0) {3973if (debug > 1)3974fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);3975old->mperf = 1; /* divide by 0 protection */3976}39773978if (DO_BIC(BIC_IPC))3979old->instr_count = new->instr_count - old->instr_count;39803981if (DO_BIC(BIC_IRQ))3982old->irq_count = new->irq_count - old->irq_count;39833984if (DO_BIC(BIC_NMI))3985old->nmi_count = new->nmi_count - old->nmi_count;39863987if (DO_BIC(BIC_SMI))3988old->smi_count = new->smi_count - old->smi_count;39893990if (DO_BIC(BIC_LLC_MRPS) || DO_BIC(BIC_LLC_HIT))3991old->llc.references = new->llc.references - old->llc.references;39923993if (DO_BIC(BIC_LLC_HIT))3994old->llc.misses = new->llc.misses - old->llc.misses;39953996if (DO_BIC(BIC_L2_MRPS) || DO_BIC(BIC_L2_HIT))3997old->l2.references = new->l2.references - old->l2.references;39983999if (DO_BIC(BIC_L2_HIT))4000old->l2.hits = new->l2.hits - old->l2.hits;40014002for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {4003if (mp->format == FORMAT_RAW || mp->format == FORMAT_AVERAGE)4004old->counter[i] = new->counter[i];4005else4006old->counter[i] = new->counter[i] - old->counter[i];4007}40084009for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) {4010if (pp->format == FORMAT_RAW)4011old->perf_counter[i] = new->perf_counter[i];4012else4013old->perf_counter[i] = new->perf_counter[i] - old->perf_counter[i];4014}40154016for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {4017if (ppmt->format == FORMAT_RAW)4018old->pmt_counter[i] = new->pmt_counter[i];4019else4020old->pmt_counter[i] = new->pmt_counter[i] - old->pmt_counter[i];4021}40224023return 0;4024}40254026int delta_cpu(struct thread_data *t, struct core_data *c, struct pkg_data *p, struct thread_data *t2, struct core_data *c2, struct pkg_data *p2)4027{4028int retval = 0;40294030/* calculate core delta only for 1st thread in core */4031if (is_cpu_first_thread_in_core(t, c))4032delta_core(c, c2);40334034/* always calculate thread delta */4035retval = delta_thread(t, t2, c2); /* c2 is core delta */40364037/* calculate package delta only for 1st core in package */4038if (is_cpu_first_core_in_package(t, p))4039retval |= delta_package(p, p2);40404041return retval;4042}40434044void delta_platform(struct platform_counters *new, struct platform_counters *old)4045{4046old->energy_psys.raw_value = new->energy_psys.raw_value - old->energy_psys.raw_value;4047}40484049void rapl_counter_clear(struct rapl_counter *c)4050{4051c->raw_value = 0;4052c->scale = 0.0;4053c->unit = RAPL_UNIT_INVALID;4054}40554056void clear_counters(PER_THREAD_PARAMS)4057{4058int i;4059struct msr_counter *mp;40604061t->tv_begin.tv_sec = 0;4062t->tv_begin.tv_usec = 0;4063t->tv_end.tv_sec = 0;4064t->tv_end.tv_usec = 0;4065t->tv_delta.tv_sec = 0;4066t->tv_delta.tv_usec = 0;40674068t->tsc = 0;4069t->aperf = 0;4070t->mperf = 0;4071t->c1 = 0;40724073t->instr_count = 0;40744075t->irq_count = 0;4076t->nmi_count = 0;4077t->smi_count = 0;40784079t->llc.references = 0;4080t->llc.misses = 0;40814082t->l2.references = 0;4083t->l2.hits = 0;40844085c->c3 = 0;4086c->c6 = 0;4087c->c7 = 0;4088c->mc6_us = 0;4089c->core_temp_c = 0;4090rapl_counter_clear(&c->core_energy);4091c->core_throt_cnt = 0;40924093p->pkg_wtd_core_c0 = 0;4094p->pkg_any_core_c0 = 0;4095p->pkg_any_gfxe_c0 = 0;4096p->pkg_both_core_gfxe_c0 = 0;40974098p->pc2 = 0;4099if (DO_BIC(BIC_Pkgpc3))4100p->pc3 = 0;4101if (DO_BIC(BIC_Pkgpc6))4102p->pc6 = 0;4103if (DO_BIC(BIC_Pkgpc7))4104p->pc7 = 0;4105p->pc8 = 0;4106p->pc9 = 0;4107p->pc10 = 0;4108p->die_c6 = 0;4109p->cpu_lpi = 0;4110p->sys_lpi = 0;41114112rapl_counter_clear(&p->energy_pkg);4113rapl_counter_clear(&p->energy_dram);4114rapl_counter_clear(&p->energy_cores);4115rapl_counter_clear(&p->energy_gfx);4116rapl_counter_clear(&p->rapl_pkg_perf_status);4117rapl_counter_clear(&p->rapl_dram_perf_status);4118p->pkg_temp_c = 0;41194120p->gfx_rc6_ms = 0;4121p->uncore_mhz = 0;4122p->gfx_mhz = 0;4123p->gfx_act_mhz = 0;4124p->sam_mc6_ms = 0;4125p->sam_mhz = 0;4126p->sam_act_mhz = 0;4127for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)4128t->counter[i] = 0;41294130for (i = 0, mp = sys.cp; mp; i++, mp = mp->next)4131c->counter[i] = 0;41324133for (i = 0, mp = sys.pp; mp; i++, mp = mp->next)4134p->counter[i] = 0;41354136memset(&t->perf_counter[0], 0, sizeof(t->perf_counter));4137memset(&c->perf_counter[0], 0, sizeof(c->perf_counter));4138memset(&p->perf_counter[0], 0, sizeof(p->perf_counter));41394140memset(&t->pmt_counter[0], 0, ARRAY_SIZE(t->pmt_counter));4141memset(&c->pmt_counter[0], 0, ARRAY_SIZE(c->pmt_counter));4142memset(&p->pmt_counter[0], 0, ARRAY_SIZE(p->pmt_counter));4143}41444145void rapl_counter_accumulate(struct rapl_counter *dst, const struct rapl_counter *src)4146{4147/* Copy unit and scale from src if dst is not initialized */4148if (dst->unit == RAPL_UNIT_INVALID) {4149dst->unit = src->unit;4150dst->scale = src->scale;4151}41524153assert(dst->unit == src->unit);4154assert(dst->scale == src->scale);41554156dst->raw_value += src->raw_value;4157}41584159int sum_counters(PER_THREAD_PARAMS)4160{4161int i;4162struct msr_counter *mp;4163struct perf_counter_info *pp;4164struct pmt_counter *ppmt;41654166/* copy un-changing apic_id's */4167if (DO_BIC(BIC_APIC))4168average.threads->apic_id = t->apic_id;4169if (DO_BIC(BIC_X2APIC))4170average.threads->x2apic_id = t->x2apic_id;41714172/* remember first tv_begin */4173if (average.threads->tv_begin.tv_sec == 0)4174average.threads->tv_begin = procsysfs_tv_begin;41754176/* remember last tv_end */4177average.threads->tv_end = t->tv_end;41784179average.threads->tsc += t->tsc;4180average.threads->aperf += t->aperf;4181average.threads->mperf += t->mperf;4182average.threads->c1 += t->c1;41834184average.threads->instr_count += t->instr_count;41854186average.threads->irq_count += t->irq_count;4187average.threads->nmi_count += t->nmi_count;4188average.threads->smi_count += t->smi_count;41894190average.threads->llc.references += t->llc.references;4191average.threads->llc.misses += t->llc.misses;41924193average.threads->l2.references += t->l2.references;4194average.threads->l2.hits += t->l2.hits;41954196for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {4197if (mp->format == FORMAT_RAW)4198continue;4199average.threads->counter[i] += t->counter[i];4200}42014202for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) {4203if (pp->format == FORMAT_RAW)4204continue;4205average.threads->perf_counter[i] += t->perf_counter[i];4206}42074208for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {4209average.threads->pmt_counter[i] += t->pmt_counter[i];4210}42114212/* sum per-core values only for 1st thread in core */4213if (!is_cpu_first_thread_in_core(t, c))4214return 0;42154216average.cores->c3 += c->c3;4217average.cores->c6 += c->c6;4218average.cores->c7 += c->c7;4219average.cores->mc6_us += c->mc6_us;42204221average.cores->core_temp_c = MAX(average.cores->core_temp_c, c->core_temp_c);4222average.cores->core_throt_cnt = MAX(average.cores->core_throt_cnt, c->core_throt_cnt);42234224rapl_counter_accumulate(&average.cores->core_energy, &c->core_energy);42254226for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {4227if (mp->format == FORMAT_RAW)4228continue;4229average.cores->counter[i] += c->counter[i];4230}42314232for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {4233if (pp->format == FORMAT_RAW)4234continue;4235average.cores->perf_counter[i] += c->perf_counter[i];4236}42374238for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {4239average.cores->pmt_counter[i] += c->pmt_counter[i];4240}42414242/* sum per-pkg values only for 1st core in pkg */4243if (!is_cpu_first_core_in_package(t, p))4244return 0;42454246if (DO_BIC(BIC_Totl_c0))4247average.packages->pkg_wtd_core_c0 += p->pkg_wtd_core_c0;4248if (DO_BIC(BIC_Any_c0))4249average.packages->pkg_any_core_c0 += p->pkg_any_core_c0;4250if (DO_BIC(BIC_GFX_c0))4251average.packages->pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;4252if (DO_BIC(BIC_CPUGFX))4253average.packages->pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;42544255average.packages->pc2 += p->pc2;4256if (DO_BIC(BIC_Pkgpc3))4257average.packages->pc3 += p->pc3;4258if (DO_BIC(BIC_Pkgpc6))4259average.packages->pc6 += p->pc6;4260if (DO_BIC(BIC_Pkgpc7))4261average.packages->pc7 += p->pc7;4262average.packages->pc8 += p->pc8;4263average.packages->pc9 += p->pc9;4264average.packages->pc10 += p->pc10;4265average.packages->die_c6 += p->die_c6;42664267average.packages->cpu_lpi = p->cpu_lpi;4268average.packages->sys_lpi = p->sys_lpi;42694270rapl_counter_accumulate(&average.packages->energy_pkg, &p->energy_pkg);4271rapl_counter_accumulate(&average.packages->energy_dram, &p->energy_dram);4272rapl_counter_accumulate(&average.packages->energy_cores, &p->energy_cores);4273rapl_counter_accumulate(&average.packages->energy_gfx, &p->energy_gfx);42744275average.packages->gfx_rc6_ms = p->gfx_rc6_ms;4276average.packages->uncore_mhz = p->uncore_mhz;4277average.packages->gfx_mhz = p->gfx_mhz;4278average.packages->gfx_act_mhz = p->gfx_act_mhz;4279average.packages->sam_mc6_ms = p->sam_mc6_ms;4280average.packages->sam_mhz = p->sam_mhz;4281average.packages->sam_act_mhz = p->sam_act_mhz;42824283average.packages->pkg_temp_c = MAX(average.packages->pkg_temp_c, p->pkg_temp_c);42844285rapl_counter_accumulate(&average.packages->rapl_pkg_perf_status, &p->rapl_pkg_perf_status);4286rapl_counter_accumulate(&average.packages->rapl_dram_perf_status, &p->rapl_dram_perf_status);42874288for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {4289if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0))4290average.packages->counter[i] = p->counter[i];4291else4292average.packages->counter[i] += p->counter[i];4293}42944295for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {4296if ((pp->format == FORMAT_RAW) && (topo.num_packages == 0))4297average.packages->perf_counter[i] = p->perf_counter[i];4298else4299average.packages->perf_counter[i] += p->perf_counter[i];4300}43014302for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {4303average.packages->pmt_counter[i] += p->pmt_counter[i];4304}43054306return 0;4307}43084309/*4310* sum the counters for all cpus in the system4311* compute the weighted average4312*/4313void compute_average(PER_THREAD_PARAMS)4314{4315int i;4316struct msr_counter *mp;4317struct perf_counter_info *pp;4318struct pmt_counter *ppmt;43194320clear_counters(average.threads, average.cores, average.packages);43214322for_all_cpus(sum_counters, t, c, p);43234324/* Use the global time delta for the average. */4325average.threads->tv_delta = tv_delta;43264327average.threads->tsc /= topo.allowed_cpus;4328average.threads->aperf /= topo.allowed_cpus;4329average.threads->mperf /= topo.allowed_cpus;4330average.threads->instr_count /= topo.allowed_cpus;4331average.threads->c1 /= topo.allowed_cpus;43324333if (average.threads->irq_count > 9999999)4334sums_need_wide_columns = 1;4335if (average.threads->nmi_count > 9999999)4336sums_need_wide_columns = 1;43374338average.cores->c3 /= topo.allowed_cores;4339average.cores->c6 /= topo.allowed_cores;4340average.cores->c7 /= topo.allowed_cores;4341average.cores->mc6_us /= topo.allowed_cores;43424343if (DO_BIC(BIC_Totl_c0))4344average.packages->pkg_wtd_core_c0 /= topo.allowed_packages;4345if (DO_BIC(BIC_Any_c0))4346average.packages->pkg_any_core_c0 /= topo.allowed_packages;4347if (DO_BIC(BIC_GFX_c0))4348average.packages->pkg_any_gfxe_c0 /= topo.allowed_packages;4349if (DO_BIC(BIC_CPUGFX))4350average.packages->pkg_both_core_gfxe_c0 /= topo.allowed_packages;43514352average.packages->pc2 /= topo.allowed_packages;4353if (DO_BIC(BIC_Pkgpc3))4354average.packages->pc3 /= topo.allowed_packages;4355if (DO_BIC(BIC_Pkgpc6))4356average.packages->pc6 /= topo.allowed_packages;4357if (DO_BIC(BIC_Pkgpc7))4358average.packages->pc7 /= topo.allowed_packages;43594360average.packages->pc8 /= topo.allowed_packages;4361average.packages->pc9 /= topo.allowed_packages;4362average.packages->pc10 /= topo.allowed_packages;4363average.packages->die_c6 /= topo.allowed_packages;43644365for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {4366if (mp->format == FORMAT_RAW)4367continue;4368if (mp->type == COUNTER_ITEMS) {4369if (average.threads->counter[i] > 9999999)4370sums_need_wide_columns = 1;4371continue;4372}4373average.threads->counter[i] /= topo.allowed_cpus;4374}4375for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {4376if (mp->format == FORMAT_RAW)4377continue;4378if (mp->type == COUNTER_ITEMS) {4379if (average.cores->counter[i] > 9999999)4380sums_need_wide_columns = 1;4381}4382average.cores->counter[i] /= topo.allowed_cores;4383}4384for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {4385if (mp->format == FORMAT_RAW)4386continue;4387if (mp->type == COUNTER_ITEMS) {4388if (average.packages->counter[i] > 9999999)4389sums_need_wide_columns = 1;4390}4391average.packages->counter[i] /= topo.allowed_packages;4392}43934394for (i = 0, pp = sys.perf_tp; pp; i++, pp = pp->next) {4395if (pp->format == FORMAT_RAW)4396continue;4397if (pp->type == COUNTER_ITEMS) {4398if (average.threads->perf_counter[i] > 9999999)4399sums_need_wide_columns = 1;4400continue;4401}4402average.threads->perf_counter[i] /= topo.allowed_cpus;4403}4404for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {4405if (pp->format == FORMAT_RAW)4406continue;4407if (pp->type == COUNTER_ITEMS) {4408if (average.cores->perf_counter[i] > 9999999)4409sums_need_wide_columns = 1;4410}4411average.cores->perf_counter[i] /= topo.allowed_cores;4412}4413for (i = 0, pp = sys.perf_pp; pp; i++, pp = pp->next) {4414if (pp->format == FORMAT_RAW)4415continue;4416if (pp->type == COUNTER_ITEMS) {4417if (average.packages->perf_counter[i] > 9999999)4418sums_need_wide_columns = 1;4419}4420average.packages->perf_counter[i] /= topo.allowed_packages;4421}44224423for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {4424average.threads->pmt_counter[i] /= topo.allowed_cpus;4425}4426for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {4427average.cores->pmt_counter[i] /= topo.allowed_cores;4428}4429for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {4430average.packages->pmt_counter[i] /= topo.allowed_packages;4431}4432}44334434static unsigned long long rdtsc(void)4435{4436unsigned int low, high;44374438asm volatile ("rdtsc":"=a" (low), "=d"(high));44394440return low | ((unsigned long long)high) << 32;4441}44424443/*4444* Open a file, and exit on failure4445*/4446FILE *fopen_or_die(const char *path, const char *mode)4447{4448FILE *filep = fopen(path, mode);44494450if (!filep)4451err(1, "%s: open failed", path);4452return filep;4453}44544455/*4456* snapshot_sysfs_counter()4457*4458* return snapshot of given counter4459*/4460unsigned long long snapshot_sysfs_counter(char *path)4461{4462FILE *fp;4463int retval;4464unsigned long long counter;44654466fp = fopen_or_die(path, "r");44674468retval = fscanf(fp, "%lld", &counter);4469if (retval != 1)4470err(1, "snapshot_sysfs_counter(%s)", path);44714472fclose(fp);44734474return counter;4475}44764477int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp, char *counter_path)4478{4479if (mp->msr_num != 0) {4480assert(!no_msr);4481if (get_msr(cpu, mp->msr_num, counterp))4482return -1;4483} else {4484char path[128 + PATH_BYTES];44854486if (mp->flags & SYSFS_PERCPU) {4487sprintf(path, "/sys/devices/system/cpu/cpu%d/%s", cpu, mp->sp->path);44884489*counterp = snapshot_sysfs_counter(path);4490} else {4491*counterp = snapshot_sysfs_counter(counter_path);4492}4493}44944495return 0;4496}44974498unsigned long long get_legacy_uncore_mhz(int package)4499{4500char path[128];4501int die;4502static int warn_once;45034504/*4505* for this package, use the first die_id that exists4506*/4507for (die = 0; die <= topo.max_die_id; ++die) {45084509sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/current_freq_khz", package, die);45104511if (access(path, R_OK) == 0)4512return (snapshot_sysfs_counter(path) / 1000);4513}4514if (!warn_once) {4515warnx("BUG: %s: No %s", __func__, path);4516warn_once = 1;4517}45184519return 0;4520}45214522int get_epb(int cpu)4523{4524char path[128 + PATH_BYTES];4525unsigned long long msr;4526int ret, epb = -1;4527FILE *fp;45284529sprintf(path, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", cpu);45304531fp = fopen(path, "r");4532if (!fp)4533goto msr_fallback;45344535ret = fscanf(fp, "%d", &epb);4536if (ret != 1)4537err(1, "%s(%s)", __func__, path);45384539fclose(fp);45404541return epb;45424543msr_fallback:4544if (no_msr)4545return -1;45464547get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);45484549return msr & 0xf;4550}45514552void get_apic_id(struct thread_data *t)4553{4554unsigned int eax, ebx, ecx, edx;45554556if (DO_BIC(BIC_APIC)) {4557eax = ebx = ecx = edx = 0;4558__cpuid(1, eax, ebx, ecx, edx);45594560t->apic_id = (ebx >> 24) & 0xff;4561}45624563if (!DO_BIC(BIC_X2APIC))4564return;45654566if (authentic_amd || hygon_genuine) {4567unsigned int topology_extensions;45684569if (max_extended_level < 0x8000001e)4570return;45714572eax = ebx = ecx = edx = 0;4573__cpuid(0x80000001, eax, ebx, ecx, edx);4574topology_extensions = ecx & (1 << 22);45754576if (topology_extensions == 0)4577return;45784579eax = ebx = ecx = edx = 0;4580__cpuid(0x8000001e, eax, ebx, ecx, edx);45814582t->x2apic_id = eax;4583return;4584}45854586if (!genuine_intel)4587return;45884589if (max_level < 0xb)4590return;45914592ecx = 0;4593__cpuid(0xb, eax, ebx, ecx, edx);4594t->x2apic_id = edx;45954596if (debug && (t->apic_id != (t->x2apic_id & 0xff)))4597fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id);4598}45994600int get_core_throt_cnt(int cpu, unsigned long long *cnt)4601{4602char path[128 + PATH_BYTES];4603unsigned long long tmp;4604FILE *fp;4605int ret;46064607sprintf(path, "/sys/devices/system/cpu/cpu%d/thermal_throttle/core_throttle_count", cpu);4608fp = fopen(path, "r");4609if (!fp)4610return -1;4611ret = fscanf(fp, "%lld", &tmp);4612fclose(fp);4613if (ret != 1)4614return -1;4615*cnt = tmp;46164617return 0;4618}46194620static int read_perf_counter_info(const char *const path, const char *const parse_format, void *value_ptr)4621{4622int fdmt;4623int bytes_read;4624char buf[64];4625int ret = -1;46264627fdmt = open(path, O_RDONLY, 0);4628if (fdmt == -1) {4629if (debug)4630fprintf(stderr, "Failed to parse perf counter info %s\n", path);4631ret = -1;4632goto cleanup_and_exit;4633}46344635bytes_read = read(fdmt, buf, sizeof(buf) - 1);4636if (bytes_read <= 0 || bytes_read >= (int)sizeof(buf)) {4637if (debug)4638fprintf(stderr, "Failed to parse perf counter info %s\n", path);4639ret = -1;4640goto cleanup_and_exit;4641}46424643buf[bytes_read] = '\0';46444645if (sscanf(buf, parse_format, value_ptr) != 1) {4646if (debug)4647fprintf(stderr, "Failed to parse perf counter info %s\n", path);4648ret = -1;4649goto cleanup_and_exit;4650}46514652ret = 0;46534654cleanup_and_exit:4655close(fdmt);4656return ret;4657}46584659static unsigned int read_perf_counter_info_n(const char *const path, const char *const parse_format)4660{4661unsigned int v;4662int status;46634664status = read_perf_counter_info(path, parse_format, &v);4665if (status)4666v = -1;46674668return v;4669}46704671static unsigned int read_perf_type(const char *subsys)4672{4673const char *const path_format = "/sys/bus/event_source/devices/%s/type";4674const char *const format = "%u";4675char path[128];46764677snprintf(path, sizeof(path), path_format, subsys);46784679return read_perf_counter_info_n(path, format);4680}46814682static unsigned int read_perf_config(const char *subsys, const char *event_name)4683{4684const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s";4685FILE *fconfig = NULL;4686char path[128];4687char config_str[64];4688unsigned int config;4689unsigned int umask;4690bool has_config = false;4691bool has_umask = false;4692unsigned int ret = -1;46934694snprintf(path, sizeof(path), path_format, subsys, event_name);46954696fconfig = fopen(path, "r");4697if (!fconfig)4698return -1;46994700if (fgets(config_str, ARRAY_SIZE(config_str), fconfig) != config_str)4701goto cleanup_and_exit;47024703for (char *pconfig_str = &config_str[0]; pconfig_str;) {4704if (sscanf(pconfig_str, "event=%x", &config) == 1) {4705has_config = true;4706goto next;4707}47084709if (sscanf(pconfig_str, "umask=%x", &umask) == 1) {4710has_umask = true;4711goto next;4712}47134714next:4715pconfig_str = strchr(pconfig_str, ',');4716if (pconfig_str) {4717*pconfig_str = '\0';4718++pconfig_str;4719}4720}47214722if (!has_umask)4723umask = 0;47244725if (has_config)4726ret = (umask << 8) | config;47274728cleanup_and_exit:4729fclose(fconfig);4730return ret;4731}47324733static unsigned int read_perf_rapl_unit(const char *subsys, const char *event_name)4734{4735const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.unit";4736const char *const format = "%s";4737char path[128];4738char unit_buffer[16];47394740snprintf(path, sizeof(path), path_format, subsys, event_name);47414742read_perf_counter_info(path, format, &unit_buffer);4743if (strcmp("Joules", unit_buffer) == 0)4744return RAPL_UNIT_JOULES;47454746return RAPL_UNIT_INVALID;4747}47484749static double read_perf_scale(const char *subsys, const char *event_name)4750{4751const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.scale";4752const char *const format = "%lf";4753char path[128];4754double scale;47554756snprintf(path, sizeof(path), path_format, subsys, event_name);47574758if (read_perf_counter_info(path, format, &scale))4759return 0.0;47604761return scale;4762}47634764size_t rapl_counter_info_count_perf(const struct rapl_counter_info_t *rci)4765{4766size_t ret = 0;47674768for (int i = 0; i < NUM_RAPL_COUNTERS; ++i)4769if (rci->source[i] == COUNTER_SOURCE_PERF)4770++ret;47714772return ret;4773}47744775static size_t cstate_counter_info_count_perf(const struct cstate_counter_info_t *cci)4776{4777size_t ret = 0;47784779for (int i = 0; i < NUM_CSTATE_COUNTERS; ++i)4780if (cci->source[i] == COUNTER_SOURCE_PERF)4781++ret;47824783return ret;4784}47854786void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx)4787{4788if (rci->source[idx] == COUNTER_SOURCE_NONE)4789return;47904791rc->raw_value = rci->data[idx];4792rc->unit = rci->unit[idx];4793rc->scale = rci->scale[idx];4794}47954796int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p)4797{4798struct platform_counters *pplat_cnt = p == odd.packages ? &platform_counters_odd : &platform_counters_even;4799unsigned long long perf_data[NUM_RAPL_COUNTERS + 1];4800struct rapl_counter_info_t *rci;48014802if (debug >= 2)4803fprintf(stderr, "%s: cpu%d domain%d\n", __func__, cpu, domain);48044805assert(rapl_counter_info_perdomain);4806assert(domain < rapl_counter_info_perdomain_size);48074808rci = &rapl_counter_info_perdomain[domain];48094810/*4811* If we have any perf counters to read, read them all now, in bulk4812*/4813if (rci->fd_perf != -1) {4814size_t num_perf_counters = rapl_counter_info_count_perf(rci);4815const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long);4816const ssize_t actual_read_size = read(rci->fd_perf, &perf_data[0], sizeof(perf_data));48174818if (actual_read_size != expected_read_size)4819err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size);4820}48214822for (unsigned int i = 0, pi = 1; i < NUM_RAPL_COUNTERS; ++i) {4823switch (rci->source[i]) {4824case COUNTER_SOURCE_NONE:4825rci->data[i] = 0;4826break;48274828case COUNTER_SOURCE_PERF:4829assert(pi < ARRAY_SIZE(perf_data));4830assert(rci->fd_perf != -1);48314832if (debug >= 2)4833fprintf(stderr, "Reading rapl counter via perf at %u (%llu %e %lf)\n",4834i, perf_data[pi], rci->scale[i], perf_data[pi] * rci->scale[i]);48354836rci->data[i] = perf_data[pi];48374838++pi;4839break;48404841case COUNTER_SOURCE_MSR:4842if (debug >= 2)4843fprintf(stderr, "Reading rapl counter via msr at %u\n", i);48444845assert(!no_msr);4846if (rci->flags[i] & RAPL_COUNTER_FLAG_USE_MSR_SUM) {4847if (get_msr_sum(cpu, rci->msr[i], &rci->data[i]))4848return -13 - i;4849} else {4850if (get_msr(cpu, rci->msr[i], &rci->data[i]))4851return -13 - i;4852}48534854rci->data[i] &= rci->msr_mask[i];4855if (rci->msr_shift[i] >= 0)4856rci->data[i] >>= abs(rci->msr_shift[i]);4857else4858rci->data[i] <<= abs(rci->msr_shift[i]);48594860break;4861}4862}48634864BUILD_BUG_ON(NUM_RAPL_COUNTERS != 8);4865write_rapl_counter(&p->energy_pkg, rci, RAPL_RCI_INDEX_ENERGY_PKG);4866write_rapl_counter(&p->energy_cores, rci, RAPL_RCI_INDEX_ENERGY_CORES);4867write_rapl_counter(&p->energy_dram, rci, RAPL_RCI_INDEX_DRAM);4868write_rapl_counter(&p->energy_gfx, rci, RAPL_RCI_INDEX_GFX);4869write_rapl_counter(&p->rapl_pkg_perf_status, rci, RAPL_RCI_INDEX_PKG_PERF_STATUS);4870write_rapl_counter(&p->rapl_dram_perf_status, rci, RAPL_RCI_INDEX_DRAM_PERF_STATUS);4871write_rapl_counter(&c->core_energy, rci, RAPL_RCI_INDEX_CORE_ENERGY);4872write_rapl_counter(&pplat_cnt->energy_psys, rci, RAPL_RCI_INDEX_ENERGY_PLATFORM);48734874return 0;4875}48764877char *find_sysfs_path_by_id(struct sysfs_path *sp, int id)4878{4879while (sp) {4880if (sp->id == id)4881return (sp->path);4882sp = sp->next;4883}4884if (debug)4885warnx("%s: id%d not found", __func__, id);4886return NULL;4887}48884889int get_cstate_counters(unsigned int cpu, PER_THREAD_PARAMS)4890{4891/*4892* Overcommit memory a little bit here,4893* but skip calculating exact sizes for the buffers.4894*/4895unsigned long long perf_data[NUM_CSTATE_COUNTERS];4896unsigned long long perf_data_core[NUM_CSTATE_COUNTERS + 1];4897unsigned long long perf_data_pkg[NUM_CSTATE_COUNTERS + 1];48984899struct cstate_counter_info_t *cci;49004901if (debug >= 2)4902fprintf(stderr, "%s: cpu%d\n", __func__, cpu);49034904assert(ccstate_counter_info);4905assert(cpu <= ccstate_counter_info_size);49064907ZERO_ARRAY(perf_data);4908ZERO_ARRAY(perf_data_core);4909ZERO_ARRAY(perf_data_pkg);49104911cci = &ccstate_counter_info[cpu];49124913/*4914* If we have any perf counters to read, read them all now, in bulk4915*/4916const size_t num_perf_counters = cstate_counter_info_count_perf(cci);4917ssize_t expected_read_size = num_perf_counters * sizeof(unsigned long long);4918ssize_t actual_read_size_core = 0, actual_read_size_pkg = 0;49194920if (cci->fd_perf_core != -1) {4921/* Each descriptor read begins with number of counters read. */4922expected_read_size += sizeof(unsigned long long);49234924actual_read_size_core = read(cci->fd_perf_core, &perf_data_core[0], sizeof(perf_data_core));49254926if (actual_read_size_core <= 0)4927err(-1, "%s: read perf %s: %ld", __func__, "core", actual_read_size_core);4928}49294930if (cci->fd_perf_pkg != -1) {4931/* Each descriptor read begins with number of counters read. */4932expected_read_size += sizeof(unsigned long long);49334934actual_read_size_pkg = read(cci->fd_perf_pkg, &perf_data_pkg[0], sizeof(perf_data_pkg));49354936if (actual_read_size_pkg <= 0)4937err(-1, "%s: read perf %s: %ld", __func__, "pkg", actual_read_size_pkg);4938}49394940const ssize_t actual_read_size_total = actual_read_size_core + actual_read_size_pkg;49414942if (actual_read_size_total != expected_read_size)4943err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size_total);49444945/*4946* Copy ccstate and pcstate data into unified buffer.4947*4948* Skip first element from core and pkg buffers.4949* Kernel puts there how many counters were read.4950*/4951const size_t num_core_counters = perf_data_core[0];4952const size_t num_pkg_counters = perf_data_pkg[0];49534954assert(num_perf_counters == num_core_counters + num_pkg_counters);49554956/* Copy ccstate perf data */4957memcpy(&perf_data[0], &perf_data_core[1], num_core_counters * sizeof(unsigned long long));49584959/* Copy pcstate perf data */4960memcpy(&perf_data[num_core_counters], &perf_data_pkg[1], num_pkg_counters * sizeof(unsigned long long));49614962for (unsigned int i = 0, pi = 0; i < NUM_CSTATE_COUNTERS; ++i) {4963switch (cci->source[i]) {4964case COUNTER_SOURCE_NONE:4965break;49664967case COUNTER_SOURCE_PERF:4968assert(pi < ARRAY_SIZE(perf_data));4969assert(cci->fd_perf_core != -1 || cci->fd_perf_pkg != -1);49704971if (debug >= 2)4972fprintf(stderr, "cstate via %s %u: %llu\n", "perf", i, perf_data[pi]);49734974cci->data[i] = perf_data[pi];49754976++pi;4977break;49784979case COUNTER_SOURCE_MSR:4980assert(!no_msr);4981if (get_msr(cpu, cci->msr[i], &cci->data[i]))4982return -13 - i;49834984if (debug >= 2)4985fprintf(stderr, "cstate via %s0x%llx %u: %llu\n", "msr", cci->msr[i], i, cci->data[i]);49864987break;4988}4989}49904991/*4992* Helper to write the data only if the source of4993* the counter for the current cpu is not none.4994*4995* Otherwise we would overwrite core data with 0 (default value),4996* when invoked for the thread sibling.4997*/4998#define PERF_COUNTER_WRITE_DATA(out_counter, index) do { \4999if (cci->source[index] != COUNTER_SOURCE_NONE) \5000out_counter = cci->data[index]; \5001} while (0)50025003BUILD_BUG_ON(NUM_CSTATE_COUNTERS != 11);50045005PERF_COUNTER_WRITE_DATA(t->c1, CCSTATE_RCI_INDEX_C1_RESIDENCY);5006PERF_COUNTER_WRITE_DATA(c->c3, CCSTATE_RCI_INDEX_C3_RESIDENCY);5007PERF_COUNTER_WRITE_DATA(c->c6, CCSTATE_RCI_INDEX_C6_RESIDENCY);5008PERF_COUNTER_WRITE_DATA(c->c7, CCSTATE_RCI_INDEX_C7_RESIDENCY);50095010PERF_COUNTER_WRITE_DATA(p->pc2, PCSTATE_RCI_INDEX_C2_RESIDENCY);5011PERF_COUNTER_WRITE_DATA(p->pc3, PCSTATE_RCI_INDEX_C3_RESIDENCY);5012PERF_COUNTER_WRITE_DATA(p->pc6, PCSTATE_RCI_INDEX_C6_RESIDENCY);5013PERF_COUNTER_WRITE_DATA(p->pc7, PCSTATE_RCI_INDEX_C7_RESIDENCY);5014PERF_COUNTER_WRITE_DATA(p->pc8, PCSTATE_RCI_INDEX_C8_RESIDENCY);5015PERF_COUNTER_WRITE_DATA(p->pc9, PCSTATE_RCI_INDEX_C9_RESIDENCY);5016PERF_COUNTER_WRITE_DATA(p->pc10, PCSTATE_RCI_INDEX_C10_RESIDENCY);50175018#undef PERF_COUNTER_WRITE_DATA50195020return 0;5021}50225023size_t msr_counter_info_count_perf(const struct msr_counter_info_t *mci)5024{5025size_t ret = 0;50265027for (int i = 0; i < NUM_MSR_COUNTERS; ++i)5028if (mci->source[i] == COUNTER_SOURCE_PERF)5029++ret;50305031return ret;5032}50335034int get_smi_aperf_mperf(unsigned int cpu, struct thread_data *t)5035{5036unsigned long long perf_data[NUM_MSR_COUNTERS + 1];50375038struct msr_counter_info_t *mci;50395040if (debug >= 2)5041fprintf(stderr, "%s: cpu%d\n", __func__, cpu);50425043assert(msr_counter_info);5044assert(cpu <= msr_counter_info_size);50455046mci = &msr_counter_info[cpu];50475048ZERO_ARRAY(perf_data);5049ZERO_ARRAY(mci->data);50505051if (mci->fd_perf != -1) {5052const size_t num_perf_counters = msr_counter_info_count_perf(mci);5053const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long);5054const ssize_t actual_read_size = read(mci->fd_perf, &perf_data[0], sizeof(perf_data));50555056if (actual_read_size != expected_read_size)5057err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size);5058}50595060for (unsigned int i = 0, pi = 1; i < NUM_MSR_COUNTERS; ++i) {5061switch (mci->source[i]) {5062case COUNTER_SOURCE_NONE:5063break;50645065case COUNTER_SOURCE_PERF:5066assert(pi < ARRAY_SIZE(perf_data));5067assert(mci->fd_perf != -1);50685069if (debug >= 2)5070fprintf(stderr, "Reading msr counter via perf at %u: %llu\n", i, perf_data[pi]);50715072mci->data[i] = perf_data[pi];50735074++pi;5075break;50765077case COUNTER_SOURCE_MSR:5078assert(!no_msr);50795080if (get_msr(cpu, mci->msr[i], &mci->data[i]))5081return -2 - i;50825083mci->data[i] &= mci->msr_mask[i];50845085if (debug >= 2)5086fprintf(stderr, "Reading msr counter via msr at %u: %llu\n", i, mci->data[i]);50875088break;5089}5090}50915092BUILD_BUG_ON(NUM_MSR_COUNTERS != 3);5093t->aperf = mci->data[MSR_RCI_INDEX_APERF];5094t->mperf = mci->data[MSR_RCI_INDEX_MPERF];5095t->smi_count = mci->data[MSR_RCI_INDEX_SMI];50965097return 0;5098}50995100int perf_counter_info_read_values(struct perf_counter_info *pp, int cpu, unsigned long long *out, size_t out_size)5101{5102unsigned int domain;5103unsigned long long value;5104int fd_counter;51055106for (size_t i = 0; pp; ++i, pp = pp->next) {5107domain = cpu_to_domain(pp, cpu);5108assert(domain < pp->num_domains);51095110fd_counter = pp->fd_perf_per_domain[domain];51115112if (fd_counter == -1)5113continue;51145115if (read(fd_counter, &value, sizeof(value)) != sizeof(value))5116return 1;51175118assert(i < out_size);5119out[i] = value * pp->scale;5120}51215122return 0;5123}51245125unsigned long pmt_gen_value_mask(unsigned int lsb, unsigned int msb)5126{5127unsigned long mask;51285129if (msb == 63)5130mask = 0xffffffffffffffff;5131else5132mask = ((1 << (msb + 1)) - 1);51335134mask -= (1 << lsb) - 1;51355136return mask;5137}51385139unsigned long pmt_read_counter(struct pmt_counter *ppmt, unsigned int domain_id)5140{5141if (domain_id >= ppmt->num_domains)5142return 0;51435144const unsigned long *pmmio = ppmt->domains[domain_id].pcounter;5145const unsigned long value = pmmio ? *pmmio : 0;5146const unsigned long value_mask = pmt_gen_value_mask(ppmt->lsb, ppmt->msb);5147const unsigned long value_shift = ppmt->lsb;51485149return (value & value_mask) >> value_shift;5150}51515152/* Rapl domain enumeration helpers */5153static inline int get_rapl_num_domains(void)5154{5155if (!platform->has_per_core_rapl)5156return topo.num_packages;51575158return topo.num_cores;5159}51605161static inline int get_rapl_domain_id(int cpu)5162{5163if (!platform->has_per_core_rapl)5164return cpus[cpu].package_id;51655166return GLOBAL_CORE_ID(cpus[cpu].core_id, cpus[cpu].package_id);5167}51685169/*5170* get_counters(...)5171* migrate to cpu5172* acquire and record local counters for that cpu5173*/5174int get_counters(PER_THREAD_PARAMS)5175{5176int cpu = t->cpu_id;5177unsigned long long msr;5178struct msr_counter *mp;5179struct pmt_counter *pp;5180int i;5181int status;51825183if (cpu_migrate(cpu)) {5184fprintf(outf, "%s: Could not migrate to CPU %d\n", __func__, cpu);5185return -1;5186}51875188gettimeofday(&t->tv_begin, (struct timezone *)NULL);51895190if (first_counter_read)5191get_apic_id(t);51925193t->tsc = rdtsc(); /* we are running on local CPU of interest */51945195get_smi_aperf_mperf(cpu, t);51965197if (DO_BIC(BIC_LLC_MRPS) || DO_BIC(BIC_LLC_HIT))5198get_perf_llc_stats(cpu, &t->llc);51995200if (DO_BIC(BIC_L2_MRPS) || DO_BIC(BIC_L2_HIT))5201get_perf_l2_stats(cpu, &t->l2);52025203if (DO_BIC(BIC_IPC))5204if (read(get_instr_count_fd(cpu), &t->instr_count, sizeof(long long)) != sizeof(long long))5205return -4;52065207if (DO_BIC(BIC_IRQ))5208t->irq_count = irqs_per_cpu[cpu];5209if (DO_BIC(BIC_NMI))5210t->nmi_count = nmi_per_cpu[cpu];52115212get_cstate_counters(cpu, t, c, p);52135214for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {5215if (get_mp(cpu, mp, &t->counter[i], mp->sp->path))5216return -10;5217}52185219if (perf_counter_info_read_values(sys.perf_tp, cpu, t->perf_counter, MAX_ADDED_THREAD_COUNTERS))5220return -10;52215222for (i = 0, pp = sys.pmt_tp; pp; i++, pp = pp->next)5223t->pmt_counter[i] = pmt_read_counter(pp, t->cpu_id);52245225/* collect core counters only for 1st thread in core */5226if (!is_cpu_first_thread_in_core(t, c))5227goto done;52285229if (platform->has_per_core_rapl) {5230status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p);5231if (status != 0)5232return status;5233}52345235if (DO_BIC(BIC_CPU_c7) && t->is_atom) {5236/*5237* For Atom CPUs that has core cstate deeper than c6,5238* MSR_CORE_C6_RESIDENCY returns residency of cc6 and deeper.5239* Minus CC7 (and deeper cstates) residency to get5240* accturate cc6 residency.5241*/5242c->c6 -= c->c7;5243}52445245if (DO_BIC(BIC_Mod_c6))5246if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))5247return -8;52485249if (DO_BIC(BIC_CoreTmp)) {5250if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))5251return -9;5252c->core_temp_c = tj_max - ((msr >> 16) & 0x7F);5253}52545255if (DO_BIC(BIC_CORE_THROT_CNT))5256get_core_throt_cnt(cpu, &c->core_throt_cnt);52575258for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {5259if (get_mp(cpu, mp, &c->counter[i], mp->sp->path))5260return -10;5261}52625263if (perf_counter_info_read_values(sys.perf_cp, cpu, c->perf_counter, MAX_ADDED_CORE_COUNTERS))5264return -10;52655266for (i = 0, pp = sys.pmt_cp; pp; i++, pp = pp->next)5267c->pmt_counter[i] = pmt_read_counter(pp, cpus[t->cpu_id].core_id);52685269/* collect package counters only for 1st core in package */5270if (!is_cpu_first_core_in_package(t, p))5271goto done;52725273if (DO_BIC(BIC_Totl_c0)) {5274if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))5275return -10;5276}5277if (DO_BIC(BIC_Any_c0)) {5278if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))5279return -11;5280}5281if (DO_BIC(BIC_GFX_c0)) {5282if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))5283return -12;5284}5285if (DO_BIC(BIC_CPUGFX)) {5286if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))5287return -13;5288}52895290if (DO_BIC(BIC_CPU_LPI))5291p->cpu_lpi = cpuidle_cur_cpu_lpi_us;5292if (DO_BIC(BIC_SYS_LPI))5293p->sys_lpi = cpuidle_cur_sys_lpi_us;52945295if (!platform->has_per_core_rapl) {5296status = get_rapl_counters(cpu, get_rapl_domain_id(cpu), c, p);5297if (status != 0)5298return status;5299}53005301if (DO_BIC(BIC_PkgTmp)) {5302if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))5303return -17;5304p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F);5305}53065307if (DO_BIC(BIC_UNCORE_MHZ))5308p->uncore_mhz = get_legacy_uncore_mhz(cpus[t->cpu_id].package_id);53095310if (DO_BIC(BIC_GFX_rc6))5311p->gfx_rc6_ms = gfx_info[GFX_rc6].val_ull;53125313if (DO_BIC(BIC_GFXMHz))5314p->gfx_mhz = gfx_info[GFX_MHz].val;53155316if (DO_BIC(BIC_GFXACTMHz))5317p->gfx_act_mhz = gfx_info[GFX_ACTMHz].val;53185319if (DO_BIC(BIC_SAM_mc6))5320p->sam_mc6_ms = gfx_info[SAM_mc6].val_ull;53215322if (DO_BIC(BIC_SAMMHz))5323p->sam_mhz = gfx_info[SAM_MHz].val;53245325if (DO_BIC(BIC_SAMACTMHz))5326p->sam_act_mhz = gfx_info[SAM_ACTMHz].val;53275328for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {5329char *path = NULL;53305331if (mp->msr_num == 0) {5332path = find_sysfs_path_by_id(mp->sp, cpus[t->cpu_id].package_id);5333if (path == NULL) {5334warnx("%s: package_id %d not found", __func__, cpus[t->cpu_id].package_id);5335return -10;5336}5337}5338if (get_mp(cpu, mp, &p->counter[i], path))5339return -10;5340}53415342if (perf_counter_info_read_values(sys.perf_pp, cpu, p->perf_counter, MAX_ADDED_PACKAGE_COUNTERS))5343return -10;53445345for (i = 0, pp = sys.pmt_pp; pp; i++, pp = pp->next)5346p->pmt_counter[i] = pmt_read_counter(pp, cpus[t->cpu_id].package_id);53475348done:5349gettimeofday(&t->tv_end, (struct timezone *)NULL);53505351return 0;5352}53535354int pkg_cstate_limit = PCLUKN;5355char *pkg_cstate_limit_strings[] = { "unknown", "reserved", "pc0", "pc1", "pc2",5356"pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"5357};53585359int nhm_pkg_cstate_limits[16] = { PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,5360PCLRSV, PCLRSV5361};53625363int 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,5364PCLRSV, PCLRSV5365};53665367int 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,5368PCLRSV, PCLRSV5369};53705371int slv_pkg_cstate_limits[16] = { PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,5372PCL__6, PCL__75373};53745375int amt_pkg_cstate_limits[16] = { PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,5376PCLRSV, PCLRSV5377};53785379int phi_pkg_cstate_limits[16] = { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,5380PCLRSV, PCLRSV5381};53825383int 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,5384PCLRSV, PCLRSV5385};53865387int skx_pkg_cstate_limits[16] = { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,5388PCLRSV, PCLRSV5389};53905391int icx_pkg_cstate_limits[16] = { PCL__0, PCL__2, PCL__6, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,5392PCLRSV, PCLRSV5393};53945395void probe_cst_limit(void)5396{5397unsigned long long msr;5398int *pkg_cstate_limits;53995400if (!platform->has_nhm_msrs || no_msr)5401return;54025403switch (platform->cst_limit) {5404case CST_LIMIT_NHM:5405pkg_cstate_limits = nhm_pkg_cstate_limits;5406break;5407case CST_LIMIT_SNB:5408pkg_cstate_limits = snb_pkg_cstate_limits;5409break;5410case CST_LIMIT_HSW:5411pkg_cstate_limits = hsw_pkg_cstate_limits;5412break;5413case CST_LIMIT_SKX:5414pkg_cstate_limits = skx_pkg_cstate_limits;5415break;5416case CST_LIMIT_ICX:5417pkg_cstate_limits = icx_pkg_cstate_limits;5418break;5419case CST_LIMIT_SLV:5420pkg_cstate_limits = slv_pkg_cstate_limits;5421break;5422case CST_LIMIT_AMT:5423pkg_cstate_limits = amt_pkg_cstate_limits;5424break;5425case CST_LIMIT_KNL:5426pkg_cstate_limits = phi_pkg_cstate_limits;5427break;5428case CST_LIMIT_GMT:5429pkg_cstate_limits = glm_pkg_cstate_limits;5430break;5431default:5432return;5433}54345435get_msr(master_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);5436pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];5437}54385439static void dump_platform_info(void)5440{5441unsigned long long msr;5442unsigned int ratio;54435444if (!platform->has_nhm_msrs || no_msr)5445return;54465447get_msr(master_cpu, MSR_PLATFORM_INFO, &msr);54485449fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", master_cpu, msr);54505451ratio = (msr >> 40) & 0xFF;5452fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n", ratio, bclk, ratio * bclk);54535454ratio = (msr >> 8) & 0xFF;5455fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);5456}54575458static void dump_power_ctl(void)5459{5460unsigned long long msr;54615462if (!platform->has_nhm_msrs || no_msr)5463return;54645465get_msr(master_cpu, MSR_IA32_POWER_CTL, &msr);5466fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", master_cpu, msr, msr & 0x2 ? "EN" : "DIS");54675468/* C-state Pre-wake Disable (CSTATE_PREWAKE_DISABLE) */5469if (platform->has_cst_prewake_bit)5470fprintf(outf, "C-state Pre-wake: %sabled\n", msr & 0x40000000 ? "DIS" : "EN");54715472return;5473}54745475static void dump_turbo_ratio_limit2(void)5476{5477unsigned long long msr;5478unsigned int ratio;54795480get_msr(master_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);54815482fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", master_cpu, msr);54835484ratio = (msr >> 8) & 0xFF;5485if (ratio)5486fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n", ratio, bclk, ratio * bclk);54875488ratio = (msr >> 0) & 0xFF;5489if (ratio)5490fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n", ratio, bclk, ratio * bclk);5491return;5492}54935494static void dump_turbo_ratio_limit1(void)5495{5496unsigned long long msr;5497unsigned int ratio;54985499get_msr(master_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);55005501fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", master_cpu, msr);55025503ratio = (msr >> 56) & 0xFF;5504if (ratio)5505fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n", ratio, bclk, ratio * bclk);55065507ratio = (msr >> 48) & 0xFF;5508if (ratio)5509fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n", ratio, bclk, ratio * bclk);55105511ratio = (msr >> 40) & 0xFF;5512if (ratio)5513fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n", ratio, bclk, ratio * bclk);55145515ratio = (msr >> 32) & 0xFF;5516if (ratio)5517fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n", ratio, bclk, ratio * bclk);55185519ratio = (msr >> 24) & 0xFF;5520if (ratio)5521fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n", ratio, bclk, ratio * bclk);55225523ratio = (msr >> 16) & 0xFF;5524if (ratio)5525fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n", ratio, bclk, ratio * bclk);55265527ratio = (msr >> 8) & 0xFF;5528if (ratio)5529fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n", ratio, bclk, ratio * bclk);55305531ratio = (msr >> 0) & 0xFF;5532if (ratio)5533fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n", ratio, bclk, ratio * bclk);5534return;5535}55365537static void dump_turbo_ratio_limits(int trl_msr_offset)5538{5539unsigned long long msr, core_counts;5540int shift;55415542get_msr(master_cpu, trl_msr_offset, &msr);5543fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n", master_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr);55445545if (platform->trl_msrs & TRL_CORECOUNT) {5546get_msr(master_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);5547fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", master_cpu, core_counts);5548} else {5549core_counts = 0x0807060504030201;5550}55515552for (shift = 56; shift >= 0; shift -= 8) {5553unsigned int ratio, group_size;55545555ratio = (msr >> shift) & 0xFF;5556group_size = (core_counts >> shift) & 0xFF;5557if (ratio)5558fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n", ratio, bclk, ratio * bclk, group_size);5559}55605561return;5562}55635564static void dump_atom_turbo_ratio_limits(void)5565{5566unsigned long long msr;5567unsigned int ratio;55685569get_msr(master_cpu, MSR_ATOM_CORE_RATIOS, &msr);5570fprintf(outf, "cpu%d: MSR_ATOM_CORE_RATIOS: 0x%08llx\n", master_cpu, msr & 0xFFFFFFFF);55715572ratio = (msr >> 0) & 0x3F;5573if (ratio)5574fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n", ratio, bclk, ratio * bclk);55755576ratio = (msr >> 8) & 0x3F;5577if (ratio)5578fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n", ratio, bclk, ratio * bclk);55795580ratio = (msr >> 16) & 0x3F;5581if (ratio)5582fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);55835584get_msr(master_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);5585fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", master_cpu, msr & 0xFFFFFFFF);55865587ratio = (msr >> 24) & 0x3F;5588if (ratio)5589fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n", ratio, bclk, ratio * bclk);55905591ratio = (msr >> 16) & 0x3F;5592if (ratio)5593fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n", ratio, bclk, ratio * bclk);55945595ratio = (msr >> 8) & 0x3F;5596if (ratio)5597fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n", ratio, bclk, ratio * bclk);55985599ratio = (msr >> 0) & 0x3F;5600if (ratio)5601fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n", ratio, bclk, ratio * bclk);5602}56035604static void dump_knl_turbo_ratio_limits(void)5605{5606const unsigned int buckets_no = 7;56075608unsigned long long msr;5609int delta_cores, delta_ratio;5610int i, b_nr;5611unsigned int cores[buckets_no];5612unsigned int ratio[buckets_no];56135614get_msr(master_cpu, MSR_TURBO_RATIO_LIMIT, &msr);56155616fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", master_cpu, msr);56175618/*5619* Turbo encoding in KNL is as follows:5620* [0] -- Reserved5621* [7:1] -- Base value of number of active cores of bucket 1.5622* [15:8] -- Base value of freq ratio of bucket 1.5623* [20:16] -- +ve delta of number of active cores of bucket 2.5624* i.e. active cores of bucket 2 =5625* active cores of bucket 1 + delta5626* [23:21] -- Negative delta of freq ratio of bucket 2.5627* i.e. freq ratio of bucket 2 =5628* freq ratio of bucket 1 - delta5629* [28:24]-- +ve delta of number of active cores of bucket 3.5630* [31:29]-- -ve delta of freq ratio of bucket 3.5631* [36:32]-- +ve delta of number of active cores of bucket 4.5632* [39:37]-- -ve delta of freq ratio of bucket 4.5633* [44:40]-- +ve delta of number of active cores of bucket 5.5634* [47:45]-- -ve delta of freq ratio of bucket 5.5635* [52:48]-- +ve delta of number of active cores of bucket 6.5636* [55:53]-- -ve delta of freq ratio of bucket 6.5637* [60:56]-- +ve delta of number of active cores of bucket 7.5638* [63:61]-- -ve delta of freq ratio of bucket 7.5639*/56405641b_nr = 0;5642cores[b_nr] = (msr & 0xFF) >> 1;5643ratio[b_nr] = (msr >> 8) & 0xFF;56445645for (i = 16; i < 64; i += 8) {5646delta_cores = (msr >> i) & 0x1F;5647delta_ratio = (msr >> (i + 5)) & 0x7;56485649cores[b_nr + 1] = cores[b_nr] + delta_cores;5650ratio[b_nr + 1] = ratio[b_nr] - delta_ratio;5651b_nr++;5652}56535654for (i = buckets_no - 1; i >= 0; i--)5655if (i > 0 ? ratio[i] != ratio[i - 1] : 1)5656fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n", ratio[i], bclk, ratio[i] * bclk, cores[i]);5657}56585659static void dump_cst_cfg(void)5660{5661unsigned long long msr;56625663if (!platform->has_nhm_msrs || no_msr)5664return;56655666get_msr(master_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr);56675668fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", master_cpu, msr);56695670fprintf(outf, " (%s%s%s%s%slocked, pkg-cstate-limit=%d (%s)",5671(msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",5672(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",5673(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",5674(msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",5675(msr & (1 << 15)) ? "" : "UN", (unsigned int)msr & 0xF, pkg_cstate_limit_strings[pkg_cstate_limit]);56765677#define AUTOMATIC_CSTATE_CONVERSION (1UL << 16)5678if (platform->has_cst_auto_convension) {5679fprintf(outf, ", automatic c-state conversion=%s", (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");5680}56815682fprintf(outf, ")\n");56835684return;5685}56865687static void dump_config_tdp(void)5688{5689unsigned long long msr;56905691get_msr(master_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);5692fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", master_cpu, msr);5693fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);56945695get_msr(master_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);5696fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", master_cpu, msr);5697if (msr) {5698fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);5699fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);5700fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);5701fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);5702}5703fprintf(outf, ")\n");57045705get_msr(master_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);5706fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", master_cpu, msr);5707if (msr) {5708fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);5709fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);5710fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);5711fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);5712}5713fprintf(outf, ")\n");57145715get_msr(master_cpu, MSR_CONFIG_TDP_CONTROL, &msr);5716fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", master_cpu, msr);5717if ((msr) & 0x3)5718fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);5719fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);5720fprintf(outf, ")\n");57215722get_msr(master_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);5723fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", master_cpu, msr);5724fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);5725fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);5726fprintf(outf, ")\n");5727}57285729unsigned int irtl_time_units[] = { 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };57305731void print_irtl(void)5732{5733unsigned long long msr;57345735if (!platform->has_irtl_msrs || no_msr)5736return;57375738if (platform->supported_cstates & PC3) {5739get_msr(master_cpu, MSR_PKGC3_IRTL, &msr);5740fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", master_cpu, msr);5741fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5742}57435744if (platform->supported_cstates & PC6) {5745get_msr(master_cpu, MSR_PKGC6_IRTL, &msr);5746fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", master_cpu, msr);5747fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5748}57495750if (platform->supported_cstates & PC7) {5751get_msr(master_cpu, MSR_PKGC7_IRTL, &msr);5752fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", master_cpu, msr);5753fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5754}57555756if (platform->supported_cstates & PC8) {5757get_msr(master_cpu, MSR_PKGC8_IRTL, &msr);5758fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", master_cpu, msr);5759fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5760}57615762if (platform->supported_cstates & PC9) {5763get_msr(master_cpu, MSR_PKGC9_IRTL, &msr);5764fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", master_cpu, msr);5765fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5766}57675768if (platform->supported_cstates & PC10) {5769get_msr(master_cpu, MSR_PKGC10_IRTL, &msr);5770fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", master_cpu, msr);5771fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);5772}5773}57745775void free_fd_percpu(void)5776{5777int i;57785779if (!fd_percpu)5780return;57815782for (i = 0; i < topo.max_cpu_num + 1; ++i) {5783if (fd_percpu[i] != 0)5784close(fd_percpu[i]);5785}57865787free(fd_percpu);5788fd_percpu = NULL;5789}57905791void free_fd_instr_count_percpu(void)5792{5793if (!fd_instr_count_percpu)5794return;57955796for (int i = 0; i < topo.max_cpu_num + 1; ++i) {5797if (fd_instr_count_percpu[i] != 0)5798close(fd_instr_count_percpu[i]);5799}58005801free(fd_instr_count_percpu);5802fd_instr_count_percpu = NULL;5803}58045805void free_fd_llc_percpu(void)5806{5807if (!fd_llc_percpu)5808return;58095810for (int i = 0; i < topo.max_cpu_num + 1; ++i) {5811if (fd_llc_percpu[i] != 0)5812close(fd_llc_percpu[i]);5813}58145815free(fd_llc_percpu);5816fd_llc_percpu = NULL;58175818BIC_NOT_PRESENT(BIC_LLC_MRPS);5819BIC_NOT_PRESENT(BIC_LLC_HIT);5820}58215822void free_fd_l2_percpu(void)5823{5824if (!fd_l2_percpu)5825return;58265827for (int i = 0; i < topo.max_cpu_num + 1; ++i) {5828if (fd_l2_percpu[i] != 0)5829close(fd_l2_percpu[i]);5830}58315832free(fd_l2_percpu);5833fd_l2_percpu = NULL;58345835BIC_NOT_PRESENT(BIC_L2_MRPS);5836BIC_NOT_PRESENT(BIC_L2_HIT);5837}58385839void free_fd_cstate(void)5840{5841if (!ccstate_counter_info)5842return;58435844const int counter_info_num = ccstate_counter_info_size;58455846for (int counter_id = 0; counter_id < counter_info_num; ++counter_id) {5847if (ccstate_counter_info[counter_id].fd_perf_core != -1)5848close(ccstate_counter_info[counter_id].fd_perf_core);58495850if (ccstate_counter_info[counter_id].fd_perf_pkg != -1)5851close(ccstate_counter_info[counter_id].fd_perf_pkg);5852}58535854free(ccstate_counter_info);5855ccstate_counter_info = NULL;5856ccstate_counter_info_size = 0;5857}58585859void free_fd_msr(void)5860{5861if (!msr_counter_info)5862return;58635864for (int cpu = 0; cpu < topo.max_cpu_num; ++cpu) {5865if (msr_counter_info[cpu].fd_perf != -1)5866close(msr_counter_info[cpu].fd_perf);5867}58685869free(msr_counter_info);5870msr_counter_info = NULL;5871msr_counter_info_size = 0;5872}58735874void free_fd_rapl_percpu(void)5875{5876if (!rapl_counter_info_perdomain)5877return;58785879const int num_domains = rapl_counter_info_perdomain_size;58805881for (int domain_id = 0; domain_id < num_domains; ++domain_id) {5882if (rapl_counter_info_perdomain[domain_id].fd_perf != -1)5883close(rapl_counter_info_perdomain[domain_id].fd_perf);5884}58855886free(rapl_counter_info_perdomain);5887rapl_counter_info_perdomain = NULL;5888rapl_counter_info_perdomain_size = 0;5889}58905891void free_fd_added_perf_counters_(struct perf_counter_info *pp)5892{5893if (!pp)5894return;58955896if (!pp->fd_perf_per_domain)5897return;58985899while (pp) {5900for (size_t domain = 0; domain < pp->num_domains; ++domain) {5901if (pp->fd_perf_per_domain[domain] != -1) {5902close(pp->fd_perf_per_domain[domain]);5903pp->fd_perf_per_domain[domain] = -1;5904}5905}59065907free(pp->fd_perf_per_domain);5908pp->fd_perf_per_domain = NULL;59095910pp = pp->next;5911}5912}59135914void free_fd_added_perf_counters(void)5915{5916free_fd_added_perf_counters_(sys.perf_tp);5917free_fd_added_perf_counters_(sys.perf_cp);5918free_fd_added_perf_counters_(sys.perf_pp);5919}59205921void free_all_buffers(void)5922{5923int i;59245925CPU_FREE(cpu_present_set);5926cpu_present_set = NULL;5927cpu_present_setsize = 0;59285929CPU_FREE(cpu_effective_set);5930cpu_effective_set = NULL;5931cpu_effective_setsize = 0;59325933CPU_FREE(cpu_allowed_set);5934cpu_allowed_set = NULL;5935cpu_allowed_setsize = 0;59365937CPU_FREE(cpu_affinity_set);5938cpu_affinity_set = NULL;5939cpu_affinity_setsize = 0;59405941if (perf_pcore_set) {5942CPU_FREE(perf_pcore_set);5943perf_pcore_set = NULL;5944}59455946if (perf_ecore_set) {5947CPU_FREE(perf_ecore_set);5948perf_ecore_set = NULL;5949}59505951if (perf_lcore_set) {5952CPU_FREE(perf_lcore_set);5953perf_lcore_set = NULL;5954}59555956free(even.threads);5957free(even.cores);5958free(even.packages);59595960even.threads = NULL;5961even.cores = NULL;5962even.packages = NULL;59635964free(odd.threads);5965free(odd.cores);5966free(odd.packages);59675968odd.threads = NULL;5969odd.cores = NULL;5970odd.packages = NULL;59715972free(output_buffer);5973output_buffer = NULL;5974outp = NULL;59755976free_fd_percpu();5977free_fd_instr_count_percpu();5978free_fd_llc_percpu();5979free_fd_l2_percpu();5980free_fd_msr();5981free_fd_rapl_percpu();5982free_fd_cstate();5983free_fd_added_perf_counters();59845985free(irq_column_2_cpu);5986free(irqs_per_cpu);5987free(nmi_per_cpu);59885989for (i = 0; i <= topo.max_cpu_num; ++i) {5990if (cpus[i].put_ids)5991CPU_FREE(cpus[i].put_ids);5992}5993free(cpus);5994}59955996/*5997* Parse a file containing a single int.5998* Return 0 if file can not be opened5999* Exit if file can be opened, but can not be parsed6000*/6001int parse_int_file(const char *fmt, ...)6002{6003va_list args;6004char path[PATH_MAX];6005FILE *filep;6006int value;60076008va_start(args, fmt);6009vsnprintf(path, sizeof(path), fmt, args);6010va_end(args);6011filep = fopen(path, "r");6012if (!filep)6013return 0;6014if (fscanf(filep, "%d", &value) != 1)6015err(1, "%s: failed to parse number from file", path);6016fclose(filep);6017return value;6018}60196020/*6021* cpu_is_first_core_in_package(cpu)6022* return 1 if given CPU is 1st core in package6023*/6024int cpu_is_first_core_in_package(int cpu)6025{6026return cpu == parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", cpu);6027}60286029int get_package_id(int cpu)6030{6031return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);6032}60336034int get_die_id(int cpu)6035{6036return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/die_id", cpu);6037}60386039int get_l3_id(int cpu)6040{6041return parse_int_file("/sys/devices/system/cpu/cpu%d/cache/index3/id", cpu);6042}60436044int get_core_id(int cpu)6045{6046return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);6047}60486049void set_node_data(void)6050{6051int pkg, node, lnode, cpu, cpux;6052int cpu_count;60536054/* initialize logical_node_id */6055for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu)6056cpus[cpu].logical_node_id = -1;60576058cpu_count = 0;6059for (pkg = 0; pkg < topo.num_packages; pkg++) {6060lnode = 0;6061for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {6062if (cpus[cpu].package_id != pkg)6063continue;6064/* find a cpu with an unset logical_node_id */6065if (cpus[cpu].logical_node_id != -1)6066continue;6067cpus[cpu].logical_node_id = lnode;6068node = cpus[cpu].physical_node_id;6069cpu_count++;6070/*6071* find all matching cpus on this pkg and set6072* the logical_node_id6073*/6074for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) {6075if ((cpus[cpux].package_id == pkg) && (cpus[cpux].physical_node_id == node)) {6076cpus[cpux].logical_node_id = lnode;6077cpu_count++;6078}6079}6080lnode++;6081if (lnode > topo.nodes_per_pkg)6082topo.nodes_per_pkg = lnode;6083}6084if (cpu_count >= topo.max_cpu_num)6085break;6086}6087}60886089int get_physical_node_id(struct cpu_topology *thiscpu)6090{6091char path[80];6092FILE *filep;6093int i;6094int cpu = thiscpu->cpu_id;60956096for (i = 0; i <= topo.max_cpu_num; i++) {6097sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist", cpu, i);6098filep = fopen(path, "r");6099if (!filep)6100continue;6101fclose(filep);6102return i;6103}6104return -1;6105}61066107static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size)6108{6109unsigned int start, end;6110char *next = cpu_str;61116112while (next && *next) {61136114if (*next == '-') /* no negative cpu numbers */6115return 1;61166117if (*next == '\0' || *next == '\n')6118break;61196120start = strtoul(next, &next, 10);61216122if (start >= CPU_SUBSET_MAXCPUS)6123return 1;6124CPU_SET_S(start, cpu_set_size, cpu_set);61256126if (*next == '\0' || *next == '\n')6127break;61286129if (*next == ',') {6130next += 1;6131continue;6132}61336134if (*next == '-') {6135next += 1; /* start range */6136} else if (*next == '.') {6137next += 1;6138if (*next == '.')6139next += 1; /* start range */6140else6141return 1;6142}61436144end = strtoul(next, &next, 10);6145if (end <= start)6146return 1;61476148while (++start <= end) {6149if (start >= CPU_SUBSET_MAXCPUS)6150return 1;6151CPU_SET_S(start, cpu_set_size, cpu_set);6152}61536154if (*next == ',')6155next += 1;6156else if (*next != '\0' && *next != '\n')6157return 1;6158}61596160return 0;6161}61626163int set_thread_siblings(struct cpu_topology *thiscpu)6164{6165char path[80], character;6166FILE *filep;6167unsigned long map;6168int so, shift, sib_core;6169int cpu = thiscpu->cpu_id;6170int offset = topo.max_cpu_num + 1;6171size_t size;6172int thread_id = 0;61736174thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1));6175if (thiscpu->ht_id < 0)6176thiscpu->ht_id = thread_id++;6177if (!thiscpu->put_ids)6178return -1;61796180size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));6181CPU_ZERO_S(size, thiscpu->put_ids);61826183sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);6184filep = fopen(path, "r");61856186if (!filep) {6187warnx("%s: open failed", path);6188return -1;6189}6190do {6191offset -= BITMASK_SIZE;6192if (fscanf(filep, "%lx%c", &map, &character) != 2)6193err(1, "%s: failed to parse file", path);6194for (shift = 0; shift < BITMASK_SIZE; shift++) {6195if ((map >> shift) & 0x1) {6196so = shift + offset;6197sib_core = get_core_id(so);6198if (sib_core == thiscpu->core_id) {6199CPU_SET_S(so, size, thiscpu->put_ids);6200if ((so != cpu) && (cpus[so].ht_id < 0)) {6201cpus[so].ht_id = thread_id;6202cpus[cpu].ht_sibling_cpu_id[thread_id] = so;6203if (debug)6204fprintf(stderr, "%s: cpu%d.ht_sibling_cpu_id[%d] = %d\n", __func__, cpu, thread_id, so);6205thread_id += 1;6206}6207}6208}6209}6210} while (character == ',');6211fclose(filep);62126213return CPU_COUNT_S(size, thiscpu->put_ids);6214}62156216/*6217* run func(thread, core, package) in topology order6218* skip non-present cpus6219*/62206221int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *,6222struct pkg_data *, struct thread_data *, struct core_data *,6223struct pkg_data *), struct thread_data *thread_base,6224struct core_data *core_base, struct pkg_data *pkg_base,6225struct thread_data *thread_base2, struct core_data *core_base2, struct pkg_data *pkg_base2)6226{6227int cpu, retval;62286229retval = 0;62306231for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {6232struct thread_data *t, *t2;6233struct core_data *c, *c2;6234struct pkg_data *p, *p2;62356236if (cpu_is_not_allowed(cpu))6237continue;62386239if (cpus[cpu].ht_id > 0) /* skip HT sibling */6240continue;62416242t = &thread_base[cpu];6243t2 = &thread_base2[cpu];6244c = &core_base[GLOBAL_CORE_ID(cpus[cpu].core_id, cpus[cpu].package_id)];6245c2 = &core_base2[GLOBAL_CORE_ID(cpus[cpu].core_id, cpus[cpu].package_id)];6246p = &pkg_base[cpus[cpu].package_id];6247p2 = &pkg_base2[cpus[cpu].package_id];62486249retval |= func(t, c, p, t2, c2, p2);62506251/* Handle HT sibling now */6252int i;62536254for (i = MAX_HT_ID; i > 0; --i) { /* ht_id 0 is self */6255if (cpus[cpu].ht_sibling_cpu_id[i] <= 0)6256continue;6257t = &thread_base[cpus[cpu].ht_sibling_cpu_id[i]];6258t2 = &thread_base2[cpus[cpu].ht_sibling_cpu_id[i]];62596260retval |= func(t, c, p, t2, c2, p2);6261}6262}6263return retval;6264}62656266/*6267* run func(cpu) on every cpu in /proc/stat6268* return max_cpu number6269*/6270int for_all_proc_cpus(int (func) (int))6271{6272FILE *fp;6273int cpu_num;6274int retval;62756276fp = fopen_or_die(proc_stat, "r");62776278retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");6279if (retval != 0)6280err(1, "%s: failed to parse format", proc_stat);62816282while (1) {6283retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);6284if (retval != 1)6285break;62866287retval = func(cpu_num);6288if (retval) {6289fclose(fp);6290return (retval);6291}6292}6293fclose(fp);6294return 0;6295}62966297#define PATH_EFFECTIVE_CPUS "/sys/fs/cgroup/cpuset.cpus.effective"62986299static char cpu_effective_str[1024];63006301static int update_effective_str(bool startup)6302{6303FILE *fp;6304char *pos;6305char buf[1024];6306int ret;63076308if (cpu_effective_str[0] == '\0' && !startup)6309return 0;63106311fp = fopen(PATH_EFFECTIVE_CPUS, "r");6312if (!fp)6313return 0;63146315pos = fgets(buf, 1024, fp);6316if (!pos)6317err(1, "%s: file read failed", PATH_EFFECTIVE_CPUS);63186319fclose(fp);63206321ret = strncmp(cpu_effective_str, buf, 1024);6322if (!ret)6323return 0;63246325strncpy(cpu_effective_str, buf, 1024);6326return 1;6327}63286329static void update_effective_set(bool startup)6330{6331update_effective_str(startup);63326333if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_effective_setsize))6334err(1, "%s: cpu str malformat %s", PATH_EFFECTIVE_CPUS, cpu_effective_str);6335}63366337void linux_perf_init(void);6338void msr_perf_init(void);6339void rapl_perf_init(void);6340void cstate_perf_init(void);6341void perf_llc_init(void);6342void perf_l2_init(void);6343void added_perf_counters_init(void);6344void pmt_init(void);63456346void re_initialize(void)6347{6348free_all_buffers();6349setup_all_buffers(false);6350linux_perf_init();6351msr_perf_init();6352rapl_perf_init();6353cstate_perf_init();6354perf_llc_init();6355perf_l2_init();6356added_perf_counters_init();6357pmt_init();6358fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus);6359}63606361void set_max_cpu_num(void)6362{6363FILE *filep;6364int current_cpu;6365unsigned long dummy;6366char pathname[64];63676368current_cpu = sched_getcpu();6369if (current_cpu < 0)6370err(1, "cannot find calling cpu ID");6371sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", current_cpu);63726373filep = fopen_or_die(pathname, "r");6374topo.max_cpu_num = 0;6375while (fscanf(filep, "%lx,", &dummy) == 1)6376topo.max_cpu_num += BITMASK_SIZE;6377fclose(filep);6378topo.max_cpu_num--; /* 0 based */6379}63806381/*6382* count_cpus()6383* remember the last one seen, it will be the max6384*/6385int count_cpus(int cpu)6386{6387UNUSED(cpu);63886389topo.num_cpus++;6390return 0;6391}63926393int mark_cpu_present(int cpu)6394{6395CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);6396return 0;6397}63986399int clear_ht_id(int cpu)6400{6401int i;64026403cpus[cpu].ht_id = -1;6404for (i = 0; i <= MAX_HT_ID; ++i)6405cpus[cpu].ht_sibling_cpu_id[i] = -1;6406return 0;6407}64086409int set_my_cpu_type(void)6410{6411unsigned int eax, ebx, ecx, edx;6412unsigned int max_level;64136414__cpuid(0, max_level, ebx, ecx, edx);64156416if (max_level < CPUID_LEAF_MODEL_ID)6417return 0;64186419__cpuid(CPUID_LEAF_MODEL_ID, eax, ebx, ecx, edx);64206421return (eax >> CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT);6422}64236424int set_cpu_hybrid_type(int cpu)6425{6426if (cpu_migrate(cpu))6427return -1;64286429int type = set_my_cpu_type();64306431cpus[cpu].type = type;6432return 0;6433}64346435/*6436* snapshot_proc_interrupts()6437*6438* read and record summary of /proc/interrupts6439*6440* return 1 if config change requires a restart, else return 06441*/6442int snapshot_proc_interrupts(void)6443{6444static FILE *fp;6445int column, retval;64466447if (fp == NULL)6448fp = fopen_or_die("/proc/interrupts", "r");6449else6450rewind(fp);64516452/* read 1st line of /proc/interrupts to get cpu* name for each column */6453for (column = 0; column < topo.num_cpus; ++column) {6454int cpu_number;64556456retval = fscanf(fp, " CPU%d", &cpu_number);6457if (retval != 1)6458break;64596460if (cpu_number > topo.max_cpu_num) {6461warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);6462return 1;6463}64646465irq_column_2_cpu[column] = cpu_number;6466irqs_per_cpu[cpu_number] = 0;6467nmi_per_cpu[cpu_number] = 0;6468}64696470/* read /proc/interrupt count lines and sum up irqs per cpu */6471while (1) {6472int column;6473char buf[64];6474int this_row_is_nmi = 0;64756476retval = fscanf(fp, " %s:", buf); /* irq# "N:" */6477if (retval != 1)6478break;64796480if (strncmp(buf, "NMI", strlen("NMI")) == 0)6481this_row_is_nmi = 1;64826483/* read the count per cpu */6484for (column = 0; column < topo.num_cpus; ++column) {64856486int cpu_number, irq_count;64876488retval = fscanf(fp, " %d", &irq_count);64896490if (retval != 1)6491break;64926493cpu_number = irq_column_2_cpu[column];6494irqs_per_cpu[cpu_number] += irq_count;6495if (this_row_is_nmi)6496nmi_per_cpu[cpu_number] += irq_count;6497}6498while (getc(fp) != '\n') ; /* flush interrupt description */64996500}6501return 0;6502}65036504/*6505* snapshot_graphics()6506*6507* record snapshot of specified graphics sysfs knob6508*6509* return 1 if config change requires a restart, else return 06510*/6511int snapshot_graphics(int idx)6512{6513int retval;65146515rewind(gfx_info[idx].fp);6516fflush(gfx_info[idx].fp);65176518switch (idx) {6519case GFX_rc6:6520case SAM_mc6:6521retval = fscanf(gfx_info[idx].fp, "%lld", &gfx_info[idx].val_ull);6522if (retval != 1)6523err(1, "rc6");6524return 0;6525case GFX_MHz:6526case GFX_ACTMHz:6527case SAM_MHz:6528case SAM_ACTMHz:6529retval = fscanf(gfx_info[idx].fp, "%d", &gfx_info[idx].val);6530if (retval != 1)6531err(1, "MHz");6532return 0;6533default:6534return -EINVAL;6535}6536}65376538/*6539* snapshot_cpu_lpi()6540*6541* record snapshot of6542* /sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us6543*/6544int snapshot_cpu_lpi_us(void)6545{6546FILE *fp;6547int retval;65486549fp = fopen_or_die("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", "r");65506551retval = fscanf(fp, "%lld", &cpuidle_cur_cpu_lpi_us);6552if (retval != 1) {6553fprintf(stderr, "Disabling Low Power Idle CPU output\n");6554BIC_NOT_PRESENT(BIC_CPU_LPI);6555fclose(fp);6556return -1;6557}65586559fclose(fp);65606561return 0;6562}65636564/*6565* snapshot_sys_lpi()6566*6567* record snapshot of sys_lpi_file6568*/6569int snapshot_sys_lpi_us(void)6570{6571FILE *fp;6572int retval;65736574fp = fopen_or_die(sys_lpi_file, "r");65756576retval = fscanf(fp, "%lld", &cpuidle_cur_sys_lpi_us);6577if (retval != 1) {6578fprintf(stderr, "Disabling Low Power Idle System output\n");6579BIC_NOT_PRESENT(BIC_SYS_LPI);6580fclose(fp);6581return -1;6582}6583fclose(fp);65846585return 0;6586}65876588/*6589* snapshot /proc and /sys files6590*6591* return 1 if configuration restart needed, else return 06592*/6593int snapshot_proc_sysfs_files(void)6594{6595gettimeofday(&procsysfs_tv_begin, (struct timezone *)NULL);65966597if (DO_BIC(BIC_IRQ) || DO_BIC(BIC_NMI))6598if (snapshot_proc_interrupts())6599return 1;66006601if (DO_BIC(BIC_GFX_rc6))6602snapshot_graphics(GFX_rc6);66036604if (DO_BIC(BIC_GFXMHz))6605snapshot_graphics(GFX_MHz);66066607if (DO_BIC(BIC_GFXACTMHz))6608snapshot_graphics(GFX_ACTMHz);66096610if (DO_BIC(BIC_SAM_mc6))6611snapshot_graphics(SAM_mc6);66126613if (DO_BIC(BIC_SAMMHz))6614snapshot_graphics(SAM_MHz);66156616if (DO_BIC(BIC_SAMACTMHz))6617snapshot_graphics(SAM_ACTMHz);66186619if (DO_BIC(BIC_CPU_LPI))6620snapshot_cpu_lpi_us();66216622if (DO_BIC(BIC_SYS_LPI))6623snapshot_sys_lpi_us();66246625return 0;6626}66276628int exit_requested;66296630static void signal_handler(int signal)6631{6632switch (signal) {6633case SIGINT:6634exit_requested = 1;6635if (debug)6636fprintf(stderr, " SIGINT\n");6637break;6638case SIGUSR1:6639if (debug > 1)6640fprintf(stderr, "SIGUSR1\n");6641break;6642}6643}66446645void setup_signal_handler(void)6646{6647struct sigaction sa;66486649memset(&sa, 0, sizeof(sa));66506651sa.sa_handler = &signal_handler;66526653if (sigaction(SIGINT, &sa, NULL) < 0)6654err(1, "sigaction SIGINT");6655if (sigaction(SIGUSR1, &sa, NULL) < 0)6656err(1, "sigaction SIGUSR1");6657}66586659void do_sleep(void)6660{6661struct timeval tout;6662struct timespec rest;6663fd_set readfds;6664int retval;66656666FD_ZERO(&readfds);6667FD_SET(0, &readfds);66686669if (ignore_stdin) {6670nanosleep(&interval_ts, NULL);6671return;6672}66736674tout = interval_tv;6675retval = select(1, &readfds, NULL, NULL, &tout);66766677if (retval == 1) {6678switch (getc(stdin)) {6679case 'q':6680exit_requested = 1;6681break;6682case EOF:6683/*6684* 'stdin' is a pipe closed on the other end. There6685* won't be any further input.6686*/6687ignore_stdin = 1;6688/* Sleep the rest of the time */6689rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);6690rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;6691nanosleep(&rest, NULL);6692}6693}6694}66956696int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)6697{6698int ret, idx;6699unsigned long long msr_cur, msr_last;67006701assert(!no_msr);67026703if (!per_cpu_msr_sum)6704return 1;67056706idx = offset_to_idx(offset);6707if (idx < 0)6708return idx;6709/* get_msr_sum() = sum + (get_msr() - last) */6710ret = get_msr(cpu, offset, &msr_cur);6711if (ret)6712return ret;6713msr_last = per_cpu_msr_sum[cpu].entries[idx].last;6714DELTA_WRAP32(msr_cur, msr_last);6715*msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;67166717return 0;6718}67196720timer_t timerid;67216722/* Timer callback, update the sum of MSRs periodically. */6723static int update_msr_sum(PER_THREAD_PARAMS)6724{6725int i, ret;6726int cpu = t->cpu_id;67276728UNUSED(c);6729UNUSED(p);67306731assert(!no_msr);67326733for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {6734unsigned long long msr_cur, msr_last;6735off_t offset;67366737if (!idx_valid(i))6738continue;6739offset = idx_to_offset(i);6740if (offset < 0)6741continue;6742ret = get_msr(cpu, offset, &msr_cur);6743if (ret) {6744fprintf(outf, "Can not update msr(0x%llx)\n", (unsigned long long)offset);6745continue;6746}67476748msr_last = per_cpu_msr_sum[cpu].entries[i].last;6749per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;67506751DELTA_WRAP32(msr_cur, msr_last);6752per_cpu_msr_sum[cpu].entries[i].sum += msr_last;6753}6754return 0;6755}67566757static void msr_record_handler(union sigval v)6758{6759UNUSED(v);67606761for_all_cpus(update_msr_sum, EVEN_COUNTERS);6762}67636764void msr_sum_record(void)6765{6766struct itimerspec its;6767struct sigevent sev;67686769per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));6770if (!per_cpu_msr_sum) {6771fprintf(outf, "Can not allocate memory for long time MSR.\n");6772return;6773}6774/*6775* Signal handler might be restricted, so use thread notifier instead.6776*/6777memset(&sev, 0, sizeof(struct sigevent));6778sev.sigev_notify = SIGEV_THREAD;6779sev.sigev_notify_function = msr_record_handler;67806781sev.sigev_value.sival_ptr = &timerid;6782if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {6783fprintf(outf, "Can not create timer.\n");6784goto release_msr;6785}67866787its.it_value.tv_sec = 0;6788its.it_value.tv_nsec = 1;6789/*6790* A wraparound time has been calculated early.6791* Some sources state that the peak power for a6792* microprocessor is usually 1.5 times the TDP rating,6793* use 2 * TDP for safety.6794*/6795its.it_interval.tv_sec = rapl_joule_counter_range / 2;6796its.it_interval.tv_nsec = 0;67976798if (timer_settime(timerid, 0, &its, NULL) == -1) {6799fprintf(outf, "Can not set timer.\n");6800goto release_timer;6801}6802return;68036804release_timer:6805timer_delete(timerid);6806release_msr:6807free(per_cpu_msr_sum);6808per_cpu_msr_sum = NULL;6809}68106811/*6812* set_my_sched_priority(pri)6813* return previous priority on success6814* return value < -20 on failure6815*/6816int set_my_sched_priority(int priority)6817{6818int retval;6819int original_priority;68206821errno = 0;6822original_priority = getpriority(PRIO_PROCESS, 0);6823if (errno && (original_priority == -1))6824return -21;68256826retval = setpriority(PRIO_PROCESS, 0, priority);6827if (retval)6828return -21;68296830errno = 0;6831retval = getpriority(PRIO_PROCESS, 0);6832if (retval != priority)6833return -21;68346835return original_priority;6836}68376838void turbostat_loop()6839{6840int retval;6841int restarted = 0;6842unsigned int done_iters = 0;68436844setup_signal_handler();68456846/*6847* elevate own priority for interval mode6848*6849* ignore on error - we probably don't have permission to set it, but6850* it's not a big deal6851*/6852set_my_sched_priority(-20);68536854restart:6855restarted++;68566857snapshot_proc_sysfs_files();6858retval = for_all_cpus(get_counters, EVEN_COUNTERS);6859first_counter_read = 0;6860if (retval < -1) {6861exit(retval);6862} else if (retval == -1) {6863if (restarted > 10) {6864exit(retval);6865}6866re_initialize();6867goto restart;6868}6869restarted = 0;6870done_iters = 0;6871gettimeofday(&tv_even, (struct timezone *)NULL);68726873while (1) {6874if (for_all_proc_cpus(cpu_is_not_present)) {6875re_initialize();6876goto restart;6877}6878if (update_effective_str(false)) {6879re_initialize();6880goto restart;6881}6882do_sleep();6883if (snapshot_proc_sysfs_files())6884goto restart;6885retval = for_all_cpus(get_counters, ODD_COUNTERS);6886if (retval < -1) {6887exit(retval);6888} else if (retval == -1) {6889re_initialize();6890goto restart;6891}6892gettimeofday(&tv_odd, (struct timezone *)NULL);6893timersub(&tv_odd, &tv_even, &tv_delta);6894if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) {6895re_initialize();6896goto restart;6897}6898delta_platform(&platform_counters_odd, &platform_counters_even);6899compute_average(EVEN_COUNTERS);6900format_all_counters(EVEN_COUNTERS);6901flush_output_stdout();6902if (exit_requested)6903break;6904if (num_iterations && ++done_iters >= num_iterations)6905break;6906do_sleep();6907if (snapshot_proc_sysfs_files())6908goto restart;6909retval = for_all_cpus(get_counters, EVEN_COUNTERS);6910if (retval < -1) {6911exit(retval);6912} else if (retval == -1) {6913re_initialize();6914goto restart;6915}6916gettimeofday(&tv_even, (struct timezone *)NULL);6917timersub(&tv_even, &tv_odd, &tv_delta);6918if (for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS)) {6919re_initialize();6920goto restart;6921}6922delta_platform(&platform_counters_even, &platform_counters_odd);6923compute_average(ODD_COUNTERS);6924format_all_counters(ODD_COUNTERS);6925flush_output_stdout();6926if (exit_requested)6927break;6928if (num_iterations && ++done_iters >= num_iterations)6929break;6930}6931}69326933int probe_dev_msr(void)6934{6935struct stat sb;6936char pathname[32];69376938sprintf(pathname, "/dev/msr%d", master_cpu);6939return !stat(pathname, &sb);6940}69416942int probe_dev_cpu_msr(void)6943{6944struct stat sb;6945char pathname[32];69466947sprintf(pathname, "/dev/cpu/%d/msr", master_cpu);6948return !stat(pathname, &sb);6949}69506951int probe_msr_driver(void)6952{6953if (probe_dev_msr()) {6954use_android_msr_path = 1;6955return 1;6956}6957return probe_dev_cpu_msr();6958}69596960void check_msr_driver(void)6961{6962if (probe_msr_driver())6963return;69646965if (system("/sbin/modprobe msr > /dev/null 2>&1"))6966no_msr = 1;69676968if (!probe_msr_driver())6969no_msr = 1;6970}69716972/*6973* check for CAP_SYS_RAWIO6974* return 0 on success6975* return 1 on fail6976*/6977int check_for_cap_sys_rawio(void)6978{6979cap_t caps;6980cap_flag_value_t cap_flag_value;6981int ret = 0;69826983caps = cap_get_proc();6984if (caps == NULL) {6985/*6986* CONFIG_MULTIUSER=n kernels have no cap_get_proc()6987* Allow them to continue and attempt to access MSRs6988*/6989if (errno == ENOSYS)6990return 0;69916992return 1;6993}69946995if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value)) {6996ret = 1;6997goto free_and_exit;6998}69997000if (cap_flag_value != CAP_SET) {7001ret = 1;7002goto free_and_exit;7003}70047005free_and_exit:7006if (cap_free(caps) == -1)7007err(-6, "cap_free");70087009return ret;7010}70117012void check_msr_permission(void)7013{7014int failed = 0;7015char pathname[32];70167017if (no_msr)7018return;70197020/* check for CAP_SYS_RAWIO */7021failed += check_for_cap_sys_rawio();70227023/* test file permissions */7024sprintf(pathname, use_android_msr_path ? "/dev/msr%d" : "/dev/cpu/%d/msr", master_cpu);7025if (euidaccess(pathname, R_OK)) {7026failed++;7027}70287029if (failed) {7030warnx("Failed to access %s. Some of the counters may not be available\n"7031"\tRun as root to enable them or use %s to disable the access explicitly", pathname, "--no-msr");7032no_msr = 1;7033}7034}70357036void probe_bclk(void)7037{7038unsigned long long msr;7039unsigned int base_ratio;70407041if (!platform->has_nhm_msrs || no_msr)7042return;70437044if (platform->bclk_freq == BCLK_100MHZ)7045bclk = 100.00;7046else if (platform->bclk_freq == BCLK_133MHZ)7047bclk = 133.33;7048else if (platform->bclk_freq == BCLK_SLV)7049bclk = slm_bclk();7050else7051return;70527053get_msr(master_cpu, MSR_PLATFORM_INFO, &msr);7054base_ratio = (msr >> 8) & 0xFF;70557056base_hz = base_ratio * bclk * 1000000;7057has_base_hz = 1;70587059if (platform->enable_tsc_tweak)7060tsc_tweak = base_hz / tsc_hz;7061}70627063static void remove_underbar(char *s)7064{7065char *to = s;70667067while (*s) {7068if (*s != '_')7069*to++ = *s;7070s++;7071}70727073*to = 0;7074}70757076static void dump_turbo_ratio_info(void)7077{7078if (!has_turbo)7079return;70807081if (!platform->has_nhm_msrs || no_msr)7082return;70837084if (platform->trl_msrs & TRL_LIMIT2)7085dump_turbo_ratio_limit2();70867087if (platform->trl_msrs & TRL_LIMIT1)7088dump_turbo_ratio_limit1();70897090if (platform->trl_msrs & TRL_BASE) {7091dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT);70927093if (is_hybrid)7094dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT);7095}70967097if (platform->trl_msrs & TRL_ATOM)7098dump_atom_turbo_ratio_limits();70997100if (platform->trl_msrs & TRL_KNL)7101dump_knl_turbo_ratio_limits();71027103if (platform->has_config_tdp)7104dump_config_tdp();7105}71067107static int read_sysfs_int(char *path)7108{7109FILE *input;7110int retval = -1;71117112input = fopen(path, "r");7113if (input == NULL) {7114if (debug)7115fprintf(outf, "NSFOD %s\n", path);7116return (-1);7117}7118if (fscanf(input, "%d", &retval) != 1)7119err(1, "%s: failed to read int from file", path);7120fclose(input);71217122return (retval);7123}71247125static void dump_sysfs_file(char *path)7126{7127FILE *input;7128char cpuidle_buf[64];71297130input = fopen(path, "r");7131if (input == NULL) {7132if (debug)7133fprintf(outf, "NSFOD %s\n", path);7134return;7135}7136if (!fgets(cpuidle_buf, sizeof(cpuidle_buf), input))7137err(1, "%s: failed to read file", path);7138fclose(input);71397140fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);7141}71427143static void probe_intel_uncore_frequency_legacy(void)7144{7145int i, j;7146char path[256];71477148for (i = 0; i < topo.num_packages; ++i) {7149for (j = 0; j <= topo.max_die_id; ++j) {7150int k, l;7151char path_base[128];71527153sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d", i, j);71547155sprintf(path, "%s/current_freq_khz", path_base);7156if (access(path, R_OK))7157continue;71587159BIC_PRESENT(BIC_UNCORE_MHZ);71607161if (quiet)7162return;71637164sprintf(path, "%s/min_freq_khz", path_base);7165k = read_sysfs_int(path);7166sprintf(path, "%s/max_freq_khz", path_base);7167l = read_sysfs_int(path);7168fprintf(outf, "Uncore Frequency package%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000);71697170sprintf(path, "%s/initial_min_freq_khz", path_base);7171k = read_sysfs_int(path);7172sprintf(path, "%s/initial_max_freq_khz", path_base);7173l = read_sysfs_int(path);7174fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000);71757176sprintf(path, "%s/current_freq_khz", path_base);7177k = read_sysfs_int(path);7178fprintf(outf, " %d MHz\n", k / 1000);7179}7180}7181}71827183static void probe_intel_uncore_frequency_cluster(void)7184{7185int i, uncore_max_id;7186char path[256];7187char path_base[128];71887189if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00/current_freq_khz", R_OK))7190return;71917192for (uncore_max_id = 0;; ++uncore_max_id) {71937194sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", uncore_max_id);71957196/* uncore## start at 00 and skips no numbers, so stop upon first missing */7197if (access(path_base, R_OK)) {7198uncore_max_id -= 1;7199break;7200}7201}7202for (i = uncore_max_id; i >= 0; --i) {7203int k, l;7204int unc_pkg_id, domain_id, cluster_id;7205char name_buf[16];72067207sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", i);72087209if (access(path_base, R_OK))7210err(1, "%s: %s", __func__, path_base);72117212sprintf(path, "%s/package_id", path_base);7213unc_pkg_id = read_sysfs_int(path);72147215sprintf(path, "%s/domain_id", path_base);7216domain_id = read_sysfs_int(path);72177218sprintf(path, "%s/fabric_cluster_id", path_base);7219cluster_id = read_sysfs_int(path);72207221sprintf(path, "%s/current_freq_khz", path_base);7222sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id);72237224/*7225* Once add_couter() is called, that counter is always read7226* and reported -- So it is effectively (enabled & present).7227* Only call add_counter() here if legacy BIC_UNCORE_MHZ (UncMHz)7228* is (enabled). Since we are in this routine, we7229* know we will not probe and set (present) the legacy counter.7230*7231* This allows "--show/--hide UncMHz" to be effective for7232* the clustered MHz counters, as a group.7233*/7234if BIC_IS_ENABLED7235(BIC_UNCORE_MHZ)7236add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, unc_pkg_id);72377238if (quiet)7239continue;72407241sprintf(path, "%s/min_freq_khz", path_base);7242k = read_sysfs_int(path);7243sprintf(path, "%s/max_freq_khz", path_base);7244l = read_sysfs_int(path);7245fprintf(outf, "Uncore Frequency package%d domain%d cluster%d: %d - %d MHz ", unc_pkg_id, domain_id, cluster_id, k / 1000, l / 1000);72467247sprintf(path, "%s/initial_min_freq_khz", path_base);7248k = read_sysfs_int(path);7249sprintf(path, "%s/initial_max_freq_khz", path_base);7250l = read_sysfs_int(path);7251fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000);72527253sprintf(path, "%s/current_freq_khz", path_base);7254k = read_sysfs_int(path);7255fprintf(outf, " %d MHz\n", k / 1000);7256}7257}72587259static void probe_intel_uncore_frequency(void)7260{7261if (!genuine_intel)7262return;72637264if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK) == 0)7265probe_intel_uncore_frequency_cluster();7266else7267probe_intel_uncore_frequency_legacy();7268}72697270static void set_graphics_fp(char *path, int idx)7271{7272if (!access(path, R_OK))7273gfx_info[idx].fp = fopen_or_die(path, "r");7274}72757276/* Enlarge this if there are /sys/class/drm/card2 ... */7277#define GFX_MAX_CARDS 272787279static void probe_graphics(void)7280{7281char path[PATH_MAX];7282int i;72837284/* Xe graphics sysfs knobs */7285if (!access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) {7286FILE *fp;7287char buf[8];7288bool gt0_is_gt;72897290fp = fopen("/sys/class/drm/card0/device/tile0/gt0/gtidle/name", "r");7291if (!fp)7292goto next;72937294if (!fread(buf, sizeof(char), 7, fp)) {7295fclose(fp);7296goto next;7297}7298fclose(fp);72997300if (!strncmp(buf, "gt0-rc", strlen("gt0-rc")))7301gt0_is_gt = true;7302else if (!strncmp(buf, "gt0-mc", strlen("gt0-mc")))7303gt0_is_gt = false;7304else7305goto next;73067307set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", gt0_is_gt ? GFX_rc6 : SAM_mc6);73087309set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", gt0_is_gt ? GFX_MHz : SAM_MHz);73107311set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz);73127313set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", gt0_is_gt ? SAM_mc6 : GFX_rc6);73147315set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", gt0_is_gt ? SAM_MHz : GFX_MHz);73167317set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz);73187319goto end;7320}73217322next:7323/* New i915 graphics sysfs knobs */7324for (i = 0; i < GFX_MAX_CARDS; i++) {7325snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i);7326if (!access(path, R_OK))7327break;7328}73297330if (i == GFX_MAX_CARDS)7331goto legacy_i915;73327333snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i);7334set_graphics_fp(path, GFX_rc6);73357336snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_cur_freq_mhz", i);7337set_graphics_fp(path, GFX_MHz);73387339snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_act_freq_mhz", i);7340set_graphics_fp(path, GFX_ACTMHz);73417342snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rc6_residency_ms", i);7343set_graphics_fp(path, SAM_mc6);73447345snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_cur_freq_mhz", i);7346set_graphics_fp(path, SAM_MHz);73477348snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_act_freq_mhz", i);7349set_graphics_fp(path, SAM_ACTMHz);73507351goto end;73527353legacy_i915:7354/* Fall back to traditional i915 graphics sysfs knobs */7355set_graphics_fp("/sys/class/drm/card0/power/rc6_residency_ms", GFX_rc6);73567357set_graphics_fp("/sys/class/drm/card0/gt_cur_freq_mhz", GFX_MHz);7358if (!gfx_info[GFX_MHz].fp)7359set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", GFX_MHz);73607361set_graphics_fp("/sys/class/drm/card0/gt_act_freq_mhz", GFX_ACTMHz);7362if (!gfx_info[GFX_ACTMHz].fp)7363set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", GFX_ACTMHz);73647365end:7366if (gfx_info[GFX_rc6].fp)7367BIC_PRESENT(BIC_GFX_rc6);7368if (gfx_info[GFX_MHz].fp)7369BIC_PRESENT(BIC_GFXMHz);7370if (gfx_info[GFX_ACTMHz].fp)7371BIC_PRESENT(BIC_GFXACTMHz);7372if (gfx_info[SAM_mc6].fp)7373BIC_PRESENT(BIC_SAM_mc6);7374if (gfx_info[SAM_MHz].fp)7375BIC_PRESENT(BIC_SAMMHz);7376if (gfx_info[SAM_ACTMHz].fp)7377BIC_PRESENT(BIC_SAMACTMHz);7378}73797380static void dump_sysfs_cstate_config(void)7381{7382char path[64];7383char name_buf[16];7384char desc[64];7385FILE *input;7386int state;7387char *sp;73887389if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {7390fprintf(outf, "cpuidle not loaded\n");7391return;7392}73937394dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_driver");7395dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor");7396dump_sysfs_file("/sys/devices/system/cpu/cpuidle/current_governor_ro");73977398for (state = 0; state < 10; ++state) {73997400sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", master_cpu, state);7401input = fopen(path, "r");7402if (input == NULL)7403continue;7404if (!fgets(name_buf, sizeof(name_buf), input))7405err(1, "%s: failed to read file", path);74067407/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */7408sp = strchr(name_buf, '-');7409if (!sp)7410sp = strchrnul(name_buf, '\n');7411*sp = '\0';7412fclose(input);74137414remove_underbar(name_buf);74157416sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc", master_cpu, state);7417input = fopen(path, "r");7418if (input == NULL)7419continue;7420if (!fgets(desc, sizeof(desc), input))7421err(1, "%s: failed to read file", path);74227423fprintf(outf, "cpu%d: %s: %s", master_cpu, name_buf, desc);7424fclose(input);7425}7426}74277428static void dump_sysfs_pstate_config(void)7429{7430char path[64];7431char driver_buf[64];7432char governor_buf[64];7433FILE *input;7434int turbo;74357436sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", master_cpu);7437input = fopen(path, "r");7438if (input == NULL) {7439fprintf(outf, "NSFOD %s\n", path);7440return;7441}7442if (!fgets(driver_buf, sizeof(driver_buf), input))7443err(1, "%s: failed to read file", path);7444fclose(input);74457446sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", master_cpu);7447input = fopen(path, "r");7448if (input == NULL) {7449fprintf(outf, "NSFOD %s\n", path);7450return;7451}7452if (!fgets(governor_buf, sizeof(governor_buf), input))7453err(1, "%s: failed to read file", path);7454fclose(input);74557456fprintf(outf, "cpu%d: cpufreq driver: %s", master_cpu, driver_buf);7457fprintf(outf, "cpu%d: cpufreq governor: %s", master_cpu, governor_buf);74587459sprintf(path, "/sys/devices/system/cpu/cpufreq/boost");7460input = fopen(path, "r");7461if (input != NULL) {7462if (fscanf(input, "%d", &turbo) != 1)7463err(1, "%s: failed to parse number from file", path);7464fprintf(outf, "cpufreq boost: %d\n", turbo);7465fclose(input);7466}74677468sprintf(path, "/sys/devices/system/cpu/intel_pstate/no_turbo");7469input = fopen(path, "r");7470if (input != NULL) {7471if (fscanf(input, "%d", &turbo) != 1)7472err(1, "%s: failed to parse number from file", path);7473fprintf(outf, "cpufreq intel_pstate no_turbo: %d\n", turbo);7474fclose(input);7475}7476}74777478/*7479* print_epb()7480* Decode the ENERGY_PERF_BIAS MSR7481*/7482int print_epb(PER_THREAD_PARAMS)7483{7484char *epb_string;7485int cpu, epb;74867487UNUSED(c);7488UNUSED(p);74897490if (!has_epb)7491return 0;74927493cpu = t->cpu_id;74947495/* EPB is per-package */7496if (!is_cpu_first_thread_in_package(t, c, p))7497return 0;74987499if (cpu_migrate(cpu)) {7500fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);7501return -1;7502}75037504epb = get_epb(cpu);7505if (epb < 0)7506return 0;75077508switch (epb) {7509case ENERGY_PERF_BIAS_PERFORMANCE:7510epb_string = "performance";7511break;7512case ENERGY_PERF_BIAS_NORMAL:7513epb_string = "balanced";7514break;7515case ENERGY_PERF_BIAS_POWERSAVE:7516epb_string = "powersave";7517break;7518default:7519epb_string = "custom";7520break;7521}7522fprintf(outf, "cpu%d: EPB: %d (%s)\n", cpu, epb, epb_string);75237524return 0;7525}75267527/*7528* print_hwp()7529* Decode the MSR_HWP_CAPABILITIES7530*/7531int print_hwp(PER_THREAD_PARAMS)7532{7533unsigned long long msr;7534int cpu;75357536UNUSED(c);7537UNUSED(p);75387539if (no_msr)7540return 0;75417542if (!has_hwp)7543return 0;75447545cpu = t->cpu_id;75467547/* MSR_HWP_CAPABILITIES is per-package */7548if (!is_cpu_first_thread_in_package(t, c, p))7549return 0;75507551if (cpu_migrate(cpu)) {7552fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);7553return -1;7554}75557556if (get_msr(cpu, MSR_PM_ENABLE, &msr))7557return 0;75587559fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", cpu, msr, (msr & (1 << 0)) ? "" : "No-");75607561/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */7562if ((msr & (1 << 0)) == 0)7563return 0;75647565if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))7566return 0;75677568fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "7569"(high %d guar %d eff %d low %d)\n",7570cpu, msr,7571(unsigned int)HWP_HIGHEST_PERF(msr),7572(unsigned int)HWP_GUARANTEED_PERF(msr), (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), (unsigned int)HWP_LOWEST_PERF(msr));75737574if (get_msr(cpu, MSR_HWP_REQUEST, &msr))7575return 0;75767577fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "7578"(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",7579cpu, msr,7580(unsigned int)(((msr) >> 0) & 0xff),7581(unsigned int)(((msr) >> 8) & 0xff),7582(unsigned int)(((msr) >> 16) & 0xff),7583(unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3), (unsigned int)(((msr) >> 42) & 0x1));75847585if (has_hwp_pkg) {7586if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))7587return 0;75887589fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "7590"(min %d max %d des %d epp 0x%x window 0x%x)\n",7591cpu, msr,7592(unsigned int)(((msr) >> 0) & 0xff),7593(unsigned int)(((msr) >> 8) & 0xff),7594(unsigned int)(((msr) >> 16) & 0xff), (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3));7595}7596if (has_hwp_notify) {7597if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))7598return 0;75997600fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "7601"(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n", cpu, msr, ((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x2) ? "EN" : "Dis");7602}7603if (get_msr(cpu, MSR_HWP_STATUS, &msr))7604return 0;76057606fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "7607"(%sGuaranteed_Perf_Change, %sExcursion_Min)\n", cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-");76087609return 0;7610}76117612/*7613* print_perf_limit()7614*/7615int print_perf_limit(PER_THREAD_PARAMS)7616{7617unsigned long long msr;7618int cpu;76197620UNUSED(c);7621UNUSED(p);76227623if (no_msr)7624return 0;76257626cpu = t->cpu_id;76277628/* per-package */7629if (!is_cpu_first_thread_in_package(t, c, p))7630return 0;76317632if (cpu_migrate(cpu)) {7633fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);7634return -1;7635}76367637if (platform->plr_msrs & PLR_CORE) {7638get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);7639fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);7640fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",7641(msr & 1 << 15) ? "bit15, " : "",7642(msr & 1 << 14) ? "bit14, " : "",7643(msr & 1 << 13) ? "Transitions, " : "",7644(msr & 1 << 12) ? "MultiCoreTurbo, " : "",7645(msr & 1 << 11) ? "PkgPwrL2, " : "",7646(msr & 1 << 10) ? "PkgPwrL1, " : "",7647(msr & 1 << 9) ? "CorePwr, " : "",7648(msr & 1 << 8) ? "Amps, " : "",7649(msr & 1 << 6) ? "VR-Therm, " : "",7650(msr & 1 << 5) ? "Auto-HWP, " : "",7651(msr & 1 << 4) ? "Graphics, " : "",7652(msr & 1 << 2) ? "bit2, " : "", (msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 0) ? "PROCHOT, " : "");7653fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",7654(msr & 1 << 31) ? "bit31, " : "",7655(msr & 1 << 30) ? "bit30, " : "",7656(msr & 1 << 29) ? "Transitions, " : "",7657(msr & 1 << 28) ? "MultiCoreTurbo, " : "",7658(msr & 1 << 27) ? "PkgPwrL2, " : "",7659(msr & 1 << 26) ? "PkgPwrL1, " : "",7660(msr & 1 << 25) ? "CorePwr, " : "",7661(msr & 1 << 24) ? "Amps, " : "",7662(msr & 1 << 22) ? "VR-Therm, " : "",7663(msr & 1 << 21) ? "Auto-HWP, " : "",7664(msr & 1 << 20) ? "Graphics, " : "",7665(msr & 1 << 18) ? "bit18, " : "", (msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 16) ? "PROCHOT, " : "");76667667}7668if (platform->plr_msrs & PLR_GFX) {7669get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);7670fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);7671fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",7672(msr & 1 << 0) ? "PROCHOT, " : "",7673(msr & 1 << 1) ? "ThermStatus, " : "",7674(msr & 1 << 4) ? "Graphics, " : "",7675(msr & 1 << 6) ? "VR-Therm, " : "",7676(msr & 1 << 8) ? "Amps, " : "",7677(msr & 1 << 9) ? "GFXPwr, " : "", (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");7678fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",7679(msr & 1 << 16) ? "PROCHOT, " : "",7680(msr & 1 << 17) ? "ThermStatus, " : "",7681(msr & 1 << 20) ? "Graphics, " : "",7682(msr & 1 << 22) ? "VR-Therm, " : "",7683(msr & 1 << 24) ? "Amps, " : "",7684(msr & 1 << 25) ? "GFXPwr, " : "", (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");7685}7686if (platform->plr_msrs & PLR_RING) {7687get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);7688fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);7689fprintf(outf, " (Active: %s%s%s%s%s%s)",7690(msr & 1 << 0) ? "PROCHOT, " : "",7691(msr & 1 << 1) ? "ThermStatus, " : "",7692(msr & 1 << 6) ? "VR-Therm, " : "",7693(msr & 1 << 8) ? "Amps, " : "", (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");7694fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",7695(msr & 1 << 16) ? "PROCHOT, " : "",7696(msr & 1 << 17) ? "ThermStatus, " : "",7697(msr & 1 << 22) ? "VR-Therm, " : "",7698(msr & 1 << 24) ? "Amps, " : "", (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");7699}7700return 0;7701}77027703#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */7704#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */77057706double get_quirk_tdp(void)7707{7708if (platform->rapl_quirk_tdp)7709return platform->rapl_quirk_tdp;77107711return 135.0;7712}77137714double get_tdp_intel(void)7715{7716unsigned long long msr;77177718if (valid_rapl_msrs & RAPL_PKG_POWER_INFO)7719if (!get_msr(master_cpu, MSR_PKG_POWER_INFO, &msr))7720return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;7721return get_quirk_tdp();7722}77237724double get_tdp_amd(void)7725{7726return get_quirk_tdp();7727}77287729void rapl_probe_intel(void)7730{7731unsigned long long msr;7732unsigned int time_unit;7733double tdp;77347735if (rapl_joules) {7736CLR_BIC(BIC_SysWatt, &bic_enabled);7737CLR_BIC(BIC_PkgWatt, &bic_enabled);7738CLR_BIC(BIC_CorWatt, &bic_enabled);7739CLR_BIC(BIC_RAMWatt, &bic_enabled);7740CLR_BIC(BIC_GFXWatt, &bic_enabled);7741} else {7742CLR_BIC(BIC_Sys_J, &bic_enabled);7743CLR_BIC(BIC_Pkg_J, &bic_enabled);7744CLR_BIC(BIC_Cor_J, &bic_enabled);7745CLR_BIC(BIC_RAM_J, &bic_enabled);7746CLR_BIC(BIC_GFX_J, &bic_enabled);7747}77487749if (!valid_rapl_msrs || no_msr)7750return;77517752if (!(valid_rapl_msrs & RAPL_PKG_PERF_STATUS))7753CLR_BIC(BIC_PKG__, &bic_enabled);7754if (!(valid_rapl_msrs & RAPL_DRAM_PERF_STATUS))7755CLR_BIC(BIC_RAM__, &bic_enabled);77567757/* units on package 0, verify later other packages match */7758if (get_msr(master_cpu, MSR_RAPL_POWER_UNIT, &msr))7759return;77607761rapl_power_units = 1.0 / (1 << (msr & 0xF));7762if (platform->has_rapl_divisor)7763rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;7764else7765rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));77667767if (platform->has_fixed_rapl_unit)7768rapl_dram_energy_units = (15.3 / 1000000);7769else7770rapl_dram_energy_units = rapl_energy_units;77717772if (platform->has_fixed_rapl_psys_unit)7773rapl_psys_energy_units = 1.0;7774else7775rapl_psys_energy_units = rapl_energy_units;77767777time_unit = msr >> 16 & 0xF;7778if (time_unit == 0)7779time_unit = 0xA;77807781rapl_time_units = 1.0 / (1 << (time_unit));77827783tdp = get_tdp_intel();77847785rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;7786if (!quiet)7787fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);7788}77897790void rapl_probe_amd(void)7791{7792unsigned long long msr;7793double tdp;77947795if (rapl_joules) {7796CLR_BIC(BIC_SysWatt, &bic_enabled);7797CLR_BIC(BIC_CorWatt, &bic_enabled);7798} else {7799CLR_BIC(BIC_Pkg_J, &bic_enabled);7800CLR_BIC(BIC_Cor_J, &bic_enabled);7801}78027803if (!valid_rapl_msrs || no_msr)7804return;78057806if (get_msr(master_cpu, MSR_RAPL_PWR_UNIT, &msr))7807return;78087809rapl_time_units = ldexp(1.0, -(msr >> 16 & 0xf));7810rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));7811rapl_power_units = ldexp(1.0, -(msr & 0xf));78127813tdp = get_tdp_amd();78147815rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;7816if (!quiet)7817fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);7818}78197820void print_power_limit_msr(int cpu, unsigned long long msr, char *label)7821{7822fprintf(outf, "cpu%d: %s: %sabled (%0.3f Watts, %f sec, clamp %sabled)\n",7823cpu, label,7824((msr >> 15) & 1) ? "EN" : "DIS",7825((msr >> 0) & 0x7FFF) * rapl_power_units,7826(1.0 + (((msr >> 22) & 0x3) / 4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units, (((msr >> 16) & 1) ? "EN" : "DIS"));78277828return;7829}78307831static int fread_int(char *path, int *val)7832{7833FILE *filep;7834int ret;78357836filep = fopen(path, "r");7837if (!filep)7838return -1;78397840ret = fscanf(filep, "%d", val);7841fclose(filep);7842return ret;7843}78447845static int fread_ull(char *path, unsigned long long *val)7846{7847FILE *filep;7848int ret;78497850filep = fopen(path, "r");7851if (!filep)7852return -1;78537854ret = fscanf(filep, "%llu", val);7855fclose(filep);7856return ret;7857}78587859static int fread_str(char *path, char *buf, int size)7860{7861FILE *filep;7862int ret;7863char *cp;78647865filep = fopen(path, "r");7866if (!filep)7867return -1;78687869ret = fread(buf, 1, size, filep);7870fclose(filep);78717872/* replace '\n' with '\0' */7873cp = strchr(buf, '\n');7874if (cp != NULL)7875*cp = '\0';78767877return ret;7878}78797880#define PATH_RAPL_SYSFS "/sys/class/powercap"78817882static int dump_one_domain(char *domain_path)7883{7884char path[PATH_MAX];7885char str[PATH_MAX];7886unsigned long long val;7887int constraint;7888int enable;7889int ret;78907891snprintf(path, PATH_MAX, "%s/name", domain_path);7892ret = fread_str(path, str, PATH_MAX);7893if (ret <= 0)7894return -1;78957896fprintf(outf, "%s: %s", domain_path + strlen(PATH_RAPL_SYSFS) + 1, str);78977898snprintf(path, PATH_MAX, "%s/enabled", domain_path);7899ret = fread_int(path, &enable);7900if (ret <= 0)7901return -1;79027903if (!enable) {7904fputs(" disabled\n", outf);7905return 0;7906}79077908for (constraint = 0;; constraint++) {7909snprintf(path, PATH_MAX, "%s/constraint_%d_time_window_us", domain_path, constraint);7910ret = fread_ull(path, &val);7911if (ret <= 0)7912break;79137914if (val > 1000000)7915fprintf(outf, " %0.1fs", (double)val / 1000000);7916else if (val > 1000)7917fprintf(outf, " %0.1fms", (double)val / 1000);7918else7919fprintf(outf, " %0.1fus", (double)val);79207921snprintf(path, PATH_MAX, "%s/constraint_%d_power_limit_uw", domain_path, constraint);7922ret = fread_ull(path, &val);7923if (ret > 0 && val)7924fprintf(outf, ":%lluW", val / 1000000);79257926snprintf(path, PATH_MAX, "%s/constraint_%d_max_power_uw", domain_path, constraint);7927ret = fread_ull(path, &val);7928if (ret > 0 && val)7929fprintf(outf, ",max:%lluW", val / 1000000);7930}7931fputc('\n', outf);79327933return 0;7934}79357936static int print_rapl_sysfs(void)7937{7938DIR *dir, *cdir;7939struct dirent *entry, *centry;7940char path[PATH_MAX];7941char str[PATH_MAX];79427943if ((dir = opendir(PATH_RAPL_SYSFS)) == NULL) {7944warn("open %s failed", PATH_RAPL_SYSFS);7945return 1;7946}79477948while ((entry = readdir(dir)) != NULL) {7949if (strlen(entry->d_name) > 100)7950continue;79517952if (strncmp(entry->d_name, "intel-rapl", strlen("intel-rapl")))7953continue;79547955snprintf(path, PATH_MAX, "%s/%s/name", PATH_RAPL_SYSFS, entry->d_name);79567957/* Parse top level domains first, including package and psys */7958fread_str(path, str, PATH_MAX);7959if (strncmp(str, "package", strlen("package")) && strncmp(str, "psys", strlen("psys")))7960continue;79617962snprintf(path, PATH_MAX, "%s/%s", PATH_RAPL_SYSFS, entry->d_name);7963if ((cdir = opendir(path)) == NULL) {7964perror("opendir() error");7965return 1;7966}79677968dump_one_domain(path);79697970while ((centry = readdir(cdir)) != NULL) {7971if (strncmp(centry->d_name, "intel-rapl", strlen("intel-rapl")))7972continue;7973snprintf(path, PATH_MAX, "%s/%s/%s", PATH_RAPL_SYSFS, entry->d_name, centry->d_name);7974dump_one_domain(path);7975}7976closedir(cdir);7977}79787979closedir(dir);7980return 0;7981}79827983int print_rapl(PER_THREAD_PARAMS)7984{7985unsigned long long msr;7986const char *msr_name;7987int cpu;79887989UNUSED(c);7990UNUSED(p);79917992if (!valid_rapl_msrs)7993return 0;79947995/* RAPL counters are per package, so print only for 1st thread/package */7996if (!is_cpu_first_thread_in_package(t, c, p))7997return 0;79987999cpu = t->cpu_id;8000if (cpu_migrate(cpu)) {8001fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);8002return -1;8003}80048005if (valid_rapl_msrs & RAPL_AMD_F17H) {8006msr_name = "MSR_RAPL_PWR_UNIT";8007if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr))8008return -1;8009} else {8010msr_name = "MSR_RAPL_POWER_UNIT";8011if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr))8012return -1;8013}80148015fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr, rapl_power_units, rapl_energy_units, rapl_time_units);80168017if (valid_rapl_msrs & RAPL_PKG_POWER_INFO) {80188019if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))8020return -5;80218022fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",8023cpu, msr,8024((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,8025((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,8026((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);80278028}8029if (valid_rapl_msrs & RAPL_PKG) {80308031if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))8032return -9;80338034fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 63) & 1 ? "" : "UN");80358036print_power_limit_msr(cpu, msr, "PKG Limit #1");8037fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%0.3f Watts, %f* sec, clamp %sabled)\n",8038cpu,8039((msr >> 47) & 1) ? "EN" : "DIS",8040((msr >> 32) & 0x7FFF) * rapl_power_units,8041(1.0 + (((msr >> 54) & 0x3) / 4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units, ((msr >> 48) & 1) ? "EN" : "DIS");80428043if (get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr))8044return -9;80458046fprintf(outf, "cpu%d: MSR_VR_CURRENT_CONFIG: 0x%08llx\n", cpu, msr);8047fprintf(outf, "cpu%d: PKG Limit #4: %f Watts (%slocked)\n", cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN");8048}80498050if (valid_rapl_msrs & RAPL_DRAM_POWER_INFO) {8051if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))8052return -6;80538054fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",8055cpu, msr,8056((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,8057((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,8058((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);8059}8060if (valid_rapl_msrs & RAPL_DRAM) {8061if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))8062return -9;8063fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN");80648065print_power_limit_msr(cpu, msr, "DRAM Limit");8066}8067if (valid_rapl_msrs & RAPL_CORE_POLICY) {8068if (get_msr(cpu, MSR_PP0_POLICY, &msr))8069return -7;80708071fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);8072}8073if (valid_rapl_msrs & RAPL_CORE_POWER_LIMIT) {8074if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))8075return -9;8076fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN");8077print_power_limit_msr(cpu, msr, "Cores Limit");8078}8079if (valid_rapl_msrs & RAPL_GFX) {8080if (get_msr(cpu, MSR_PP1_POLICY, &msr))8081return -8;80828083fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);80848085if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))8086return -9;8087fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN");8088print_power_limit_msr(cpu, msr, "GFX Limit");8089}8090return 0;8091}80928093/*8094* probe_rapl_msrs8095*8096* initialize global valid_rapl_msrs to platform->plat_rapl_msrs8097* only if PKG_ENERGY counter is enumerated and reads non-zero8098*/8099void probe_rapl_msrs(void)8100{8101int ret;8102off_t offset;8103unsigned long long msr_value;81048105if (no_msr)8106return;81078108if ((platform->plat_rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H)) == 0)8109return;81108111offset = idx_to_offset(IDX_PKG_ENERGY);8112if (offset < 0)8113return;81148115ret = get_msr(master_cpu, offset, &msr_value);8116if (ret) {8117if (debug)8118fprintf(outf, "Can not read RAPL_PKG_ENERGY MSR(0x%llx)\n", (unsigned long long)offset);8119return;8120}8121if (msr_value == 0) {8122if (debug)8123fprintf(outf, "RAPL_PKG_ENERGY MSR(0x%llx) == ZERO: disabling all RAPL MSRs\n", (unsigned long long)offset);8124return;8125}81268127valid_rapl_msrs = platform->plat_rapl_msrs; /* success */8128}81298130/*8131* probe_rapl()8132*8133* sets rapl_power_units, rapl_energy_units, rapl_time_units8134*/8135void probe_rapl(void)8136{8137probe_rapl_msrs();81388139if (genuine_intel)8140rapl_probe_intel();8141if (authentic_amd || hygon_genuine)8142rapl_probe_amd();81438144if (quiet)8145return;81468147print_rapl_sysfs();81488149if (!valid_rapl_msrs || no_msr)8150return;81518152for_all_cpus(print_rapl, ODD_COUNTERS);8153}81548155/*8156* MSR_IA32_TEMPERATURE_TARGET indicates the temperature where8157* the Thermal Control Circuit (TCC) activates.8158* This is usually equal to tjMax.8159*8160* Older processors do not have this MSR, so there we guess,8161* but also allow cmdline over-ride with -T.8162*8163* Several MSR temperature values are in units of degrees-C8164* below this value, including the Digital Thermal Sensor (DTS),8165* Package Thermal Management Sensor (PTM), and thermal event thresholds.8166*/8167int set_temperature_target(PER_THREAD_PARAMS)8168{8169unsigned long long msr;8170unsigned int tcc_default, tcc_offset;8171int cpu;81728173UNUSED(c);8174UNUSED(p);81758176/* tj_max is used only for dts or ptm */8177if (!(do_dts || do_ptm))8178return 0;81798180/* this is a per-package concept */8181if (!is_cpu_first_thread_in_package(t, c, p))8182return 0;81838184cpu = t->cpu_id;8185if (cpu_migrate(cpu)) {8186fprintf(outf, "Could not migrate to CPU %d\n", cpu);8187return -1;8188}81898190if (tj_max_override != 0) {8191tj_max = tj_max_override;8192fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", cpu, tj_max);8193return 0;8194}81958196/* Temperature Target MSR is Nehalem and newer only */8197if (!platform->has_nhm_msrs || no_msr)8198goto guess;81998200if (get_msr(master_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))8201goto guess;82028203tcc_default = (msr >> 16) & 0xFF;82048205if (!quiet) {8206int bits = platform->tcc_offset_bits;8207unsigned long long enabled = 0;82088209if (bits && !get_msr(master_cpu, MSR_PLATFORM_INFO, &enabled))8210enabled = (enabled >> 30) & 1;82118212if (bits && enabled) {8213tcc_offset = (msr >> 24) & GENMASK(bits - 1, 0);8214fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n",8215cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset);8216} else {8217fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, tcc_default);8218}8219}82208221if (!tcc_default)8222goto guess;82238224tj_max = tcc_default;82258226return 0;82278228guess:8229tj_max = TJMAX_DEFAULT;8230fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", cpu, tj_max);82318232return 0;8233}82348235int print_thermal(PER_THREAD_PARAMS)8236{8237unsigned long long msr;8238unsigned int dts, dts2;8239int cpu;82408241UNUSED(c);8242UNUSED(p);82438244if (no_msr)8245return 0;82468247if (!(do_dts || do_ptm))8248return 0;82498250cpu = t->cpu_id;82518252/* DTS is per-core, no need to print for each thread */8253if (!is_cpu_first_thread_in_core(t, c))8254return 0;82558256if (cpu_migrate(cpu)) {8257fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);8258return -1;8259}82608261if (do_ptm && is_cpu_first_core_in_package(t, p)) {8262if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))8263return 0;82648265dts = (msr >> 16) & 0x7F;8266fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts);82678268if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr))8269return 0;82708271dts = (msr >> 16) & 0x7F;8272dts2 = (msr >> 8) & 0x7F;8273fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", cpu, msr, tj_max - dts, tj_max - dts2);8274}82758276if (do_dts && debug) {8277unsigned int resolution;82788279if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))8280return 0;82818282dts = (msr >> 16) & 0x7F;8283resolution = (msr >> 27) & 0xF;8284fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", cpu, msr, tj_max - dts, resolution);82858286if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr))8287return 0;82888289dts = (msr >> 16) & 0x7F;8290dts2 = (msr >> 8) & 0x7F;8291fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", cpu, msr, tj_max - dts, tj_max - dts2);8292}82938294return 0;8295}82968297void probe_thermal(void)8298{8299if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK))8300BIC_PRESENT(BIC_CORE_THROT_CNT);8301else8302BIC_NOT_PRESENT(BIC_CORE_THROT_CNT);83038304for_all_cpus(set_temperature_target, ODD_COUNTERS);83058306if (quiet)8307return;83088309for_all_cpus(print_thermal, ODD_COUNTERS);8310}83118312int get_cpu_type(PER_THREAD_PARAMS)8313{8314unsigned int eax, ebx, ecx, edx;83158316UNUSED(c);8317UNUSED(p);83188319if (!genuine_intel)8320return 0;83218322if (cpu_migrate(t->cpu_id)) {8323fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id);8324return -1;8325}83268327if (max_level < 0x1a)8328return 0;83298330__cpuid(0x1a, eax, ebx, ecx, edx);8331eax = (eax >> 24) & 0xFF;8332if (eax == 0x20)8333t->is_atom = true;8334return 0;8335}83368337void decode_feature_control_msr(void)8338{8339unsigned long long msr;83408341if (no_msr)8342return;83438344if (quiet)8345return;83468347if (!get_msr(master_cpu, MSR_IA32_FEAT_CTL, &msr))8348fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",8349master_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : "");8350}83518352void decode_misc_enable_msr(void)8353{8354unsigned long long msr;83558356if (no_msr)8357return;83588359if (!genuine_intel)8360return;83618362if (!get_msr(master_cpu, MSR_IA32_MISC_ENABLE, &msr))8363fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%sTCC %sEIST %sMWAIT %sPREFETCH %sTURBO)\n",8364master_cpu, msr,8365msr & MSR_IA32_MISC_ENABLE_TM1 ? "" : "No-",8366msr & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP ? "" : "No-",8367msr & MSR_IA32_MISC_ENABLE_MWAIT ? "" : "No-",8368msr & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE ? "No-" : "", msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ? "No-" : "");8369}83708371void decode_misc_feature_control(void)8372{8373unsigned long long msr;83748375if (no_msr)8376return;83778378if (!platform->has_msr_misc_feature_control)8379return;83808381if (!get_msr(master_cpu, MSR_MISC_FEATURE_CONTROL, &msr))8382fprintf(outf,8383"cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",8384master_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "", msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : "");8385}83868387/*8388* Decode MSR_MISC_PWR_MGMT8389*8390* Decode the bits according to the Nehalem documentation8391* bit[0] seems to continue to have same meaning going forward8392* bit[1] less so...8393*/8394void decode_misc_pwr_mgmt_msr(void)8395{8396unsigned long long msr;83978398if (no_msr)8399return;84008401if (!platform->has_msr_misc_pwr_mgmt)8402return;84038404if (!get_msr(master_cpu, MSR_MISC_PWR_MGMT, &msr))8405fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",8406master_cpu, msr, msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS");8407}84088409/*8410* Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG8411*8412* This MSRs are present on Silvermont processors,8413* Intel Atom processor E3000 series (Baytrail), and friends.8414*/8415void decode_c6_demotion_policy_msr(void)8416{8417unsigned long long msr;84188419if (no_msr)8420return;84218422if (!platform->has_msr_c6_demotion_policy_config)8423return;84248425if (!get_msr(master_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr))8426fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n", master_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");84278428if (!get_msr(master_cpu, MSR_MC6_DEMOTION_POLICY_CONFIG, &msr))8429fprintf(outf, "cpu%d: MSR_MC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-MC6-Demotion)\n", master_cpu, msr, msr & (1 << 0) ? "EN" : "DIS");8430}84318432void print_dev_latency(void)8433{8434char *path = "/dev/cpu_dma_latency";8435int fd;8436int value;8437int retval;84388439fd = open(path, O_RDONLY);8440if (fd < 0) {8441if (debug)8442warnx("Read %s failed", path);8443return;8444}84458446retval = read(fd, (void *)&value, sizeof(int));8447if (retval != sizeof(int)) {8448warn("read failed %s", path);8449close(fd);8450return;8451}8452fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n", value, value == 2000000000 ? "default" : "constrained");84538454close(fd);8455}84568457static int has_perf_instr_count_access(void)8458{8459int fd;84608461if (no_perf)8462return 0;84638464fd = open_perf_counter(master_cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0);8465if (fd != -1)8466close(fd);84678468if (fd == -1)8469warnx("Failed to access %s. Some of the counters may not be available\n"8470"\tRun as root to enable them or use %s to disable the access explicitly", "perf instructions retired counter",8471"'--hide IPC' or '--no-perf'");84728473return (fd != -1);8474}84758476int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai, double *scale_, enum rapl_unit *unit_)8477{8478int ret = -1;84798480if (no_perf)8481return -1;84828483if (!cai->perf_name)8484return -1;84858486const double scale = read_perf_scale(cai->perf_subsys, cai->perf_name);84878488if (scale == 0.0)8489goto end;84908491const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name);84928493if (unit == RAPL_UNIT_INVALID)8494goto end;84958496const unsigned int rapl_type = read_perf_type(cai->perf_subsys);8497const unsigned int rapl_energy_pkg_config = read_perf_config(cai->perf_subsys, cai->perf_name);84988499ret = open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP);8500if (ret == -1)8501goto end;85028503/* If it's the first counter opened, make it a group descriptor */8504if (rci->fd_perf == -1)8505rci->fd_perf = ret;85068507*scale_ = scale;8508*unit_ = unit;85098510end:8511if (debug >= 2)8512fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);85138514return ret;8515}85168517char cpuset_buf[1024];8518int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, char *sysfs_path, char *sysfs_file)8519{8520FILE *fp;8521char path[128];85228523if (snprintf(path, 128, "%s/%s", sysfs_path, sysfs_file) > 128)8524err(-1, "%s %s", sysfs_path, sysfs_file);85258526fp = fopen(path, "r");8527if (!fp) {8528warn("open %s", path);8529return -1;8530}8531if (fread(cpuset_buf, sizeof(char), 1024, fp) == 0) {8532warn("read %s", sysfs_path);8533goto err;8534}8535if (parse_cpu_str(cpuset_buf, cpu_set, cpu_possible_setsize)) {8536warnx("%s: cpu str malformat %s\n", sysfs_path, cpu_effective_str);8537goto err;8538}8539return 0;85408541err:8542fclose(fp);8543return -1;8544}85458546void print_cpu_set(char *s, cpu_set_t *set)8547{8548int i;85498550assert(MAX_BIC < CPU_SETSIZE);85518552printf("%s:", s);85538554for (i = 0; i <= topo.max_cpu_num; ++i)8555if (CPU_ISSET(i, set))8556printf(" %d", i);8557putchar('\n');8558}85598560void linux_perf_init_hybrid_cpus(void)8561{8562char *perf_cpu_pcore_path = "/sys/devices/cpu_core";8563char *perf_cpu_ecore_path = "/sys/devices/cpu_atom";8564char *perf_cpu_lcore_path = "/sys/devices/cpu_lowpower";8565char path[128];85668567if (!access(perf_cpu_pcore_path, F_OK)) {8568perf_pcore_set = CPU_ALLOC((topo.max_cpu_num + 1));8569if (perf_pcore_set == NULL)8570err(3, "CPU_ALLOC");8571CPU_ZERO_S(cpu_possible_setsize, perf_pcore_set);8572initialize_cpu_set_from_sysfs(perf_pcore_set, perf_cpu_pcore_path, "cpus");8573if (debug)8574print_cpu_set("perf pcores", perf_pcore_set);8575sprintf(path, "%s/%s", perf_cpu_pcore_path, "type");8576perf_pmu_types.pcore = snapshot_sysfs_counter(path);8577}85788579if (!access(perf_cpu_ecore_path, F_OK)) {8580perf_ecore_set = CPU_ALLOC((topo.max_cpu_num + 1));8581if (perf_ecore_set == NULL)8582err(3, "CPU_ALLOC");8583CPU_ZERO_S(cpu_possible_setsize, perf_ecore_set);8584initialize_cpu_set_from_sysfs(perf_ecore_set, perf_cpu_ecore_path, "cpus");8585if (debug)8586print_cpu_set("perf ecores", perf_ecore_set);8587sprintf(path, "%s/%s", perf_cpu_ecore_path, "type");8588perf_pmu_types.ecore = snapshot_sysfs_counter(path);8589}85908591if (!access(perf_cpu_lcore_path, F_OK)) {8592perf_lcore_set = CPU_ALLOC((topo.max_cpu_num + 1));8593if (perf_lcore_set == NULL)8594err(3, "CPU_ALLOC");8595CPU_ZERO_S(cpu_possible_setsize, perf_lcore_set);8596initialize_cpu_set_from_sysfs(perf_lcore_set, perf_cpu_lcore_path, "cpus");8597if (debug)8598print_cpu_set("perf lcores", perf_lcore_set);8599sprintf(path, "%s/%s", perf_cpu_lcore_path, "type");8600perf_pmu_types.lcore = snapshot_sysfs_counter(path);8601}8602}86038604/*8605* Linux-perf related initialization8606*/8607void linux_perf_init(void)8608{8609char path[128];8610char *perf_cpu_path = "/sys/devices/cpu";86118612if (access("/proc/sys/kernel/perf_event_paranoid", F_OK))8613return;86148615if (!access(perf_cpu_path, F_OK)) {8616sprintf(path, "%s/%s", perf_cpu_path, "type");8617perf_pmu_types.uniform = snapshot_sysfs_counter(path);8618} else {8619linux_perf_init_hybrid_cpus();8620}86218622if (BIC_IS_ENABLED(BIC_IPC) && cpuid_has_aperf_mperf) {8623fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));8624if (fd_instr_count_percpu == NULL)8625err(-1, "calloc fd_instr_count_percpu");8626}8627if (BIC_IS_ENABLED(BIC_LLC_MRPS) || BIC_IS_ENABLED(BIC_LLC_HIT)) {8628fd_llc_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));8629if (fd_llc_percpu == NULL)8630err(-1, "calloc fd_llc_percpu");8631}8632if (BIC_IS_ENABLED(BIC_L2_MRPS) || BIC_IS_ENABLED(BIC_L2_HIT)) {8633fd_l2_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));8634if (fd_l2_percpu == NULL)8635err(-1, "calloc fd_l2_percpu");8636}8637}86388639void rapl_perf_init(void)8640{8641const unsigned int num_domains = get_rapl_num_domains();8642bool *domain_visited = calloc(num_domains, sizeof(bool));86438644rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain));8645if (rapl_counter_info_perdomain == NULL)8646err(-1, "calloc rapl_counter_info_percpu");8647rapl_counter_info_perdomain_size = num_domains;86488649/*8650* Initialize rapl_counter_info_percpu8651*/8652for (unsigned int domain_id = 0; domain_id < num_domains; ++domain_id) {8653struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id];86548655rci->fd_perf = -1;8656for (size_t i = 0; i < NUM_RAPL_COUNTERS; ++i) {8657rci->data[i] = 0;8658rci->source[i] = COUNTER_SOURCE_NONE;8659}8660}86618662/*8663* Open/probe the counters8664* If can't get it via perf, fallback to MSR8665*/8666for (size_t i = 0; i < ARRAY_SIZE(rapl_counter_arch_infos); ++i) {86678668const struct rapl_counter_arch_info *const cai = &rapl_counter_arch_infos[i];8669bool has_counter = 0;8670double scale;8671enum rapl_unit unit;8672unsigned int next_domain;86738674if (!BIC_IS_ENABLED(cai->bic_number))8675continue;86768677memset(domain_visited, 0, num_domains * sizeof(*domain_visited));86788679for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) {86808681if (cpu_is_not_allowed(cpu))8682continue;86838684/* Skip already seen and handled RAPL domains */8685next_domain = get_rapl_domain_id(cpu);86868687assert(next_domain < num_domains);86888689if (domain_visited[next_domain])8690continue;86918692domain_visited[next_domain] = 1;86938694if ((cai->flags & RAPL_COUNTER_FLAG_PLATFORM_COUNTER) && (cpu != master_cpu))8695continue;86968697struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain];86988699/*8700* rapl_counter_arch_infos[] can have multiple entries describing the same8701* counter, due to the difference from different platforms/Vendors.8702* E.g. rapl_counter_arch_infos[0] and rapl_counter_arch_infos[1] share the8703* same perf_subsys and perf_name, but with different MSR address.8704* rapl_counter_arch_infos[0] is for Intel and rapl_counter_arch_infos[1]8705* is for AMD.8706* In this case, it is possible that multiple rapl_counter_arch_infos[]8707* entries are probed just because their perf/msr is duplicate and valid.8708*8709* Thus need a check to avoid re-probe the same counters.8710*/8711if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE)8712break;87138714/* Use perf API for this counter */8715if (add_rapl_perf_counter(cpu, rci, cai, &scale, &unit) != -1) {8716rci->source[cai->rci_index] = COUNTER_SOURCE_PERF;8717rci->scale[cai->rci_index] = scale * cai->compat_scale;8718rci->unit[cai->rci_index] = unit;8719rci->flags[cai->rci_index] = cai->flags;87208721/* Use MSR for this counter */8722} else if (add_rapl_msr_counter(cpu, cai) >= 0) {8723rci->source[cai->rci_index] = COUNTER_SOURCE_MSR;8724rci->msr[cai->rci_index] = cai->msr;8725rci->msr_mask[cai->rci_index] = cai->msr_mask;8726rci->msr_shift[cai->rci_index] = cai->msr_shift;8727rci->unit[cai->rci_index] = RAPL_UNIT_JOULES;8728rci->scale[cai->rci_index] = *cai->platform_rapl_msr_scale * cai->compat_scale;8729rci->flags[cai->rci_index] = cai->flags;8730}87318732if (rci->source[cai->rci_index] != COUNTER_SOURCE_NONE)8733has_counter = 1;8734}87358736/* If any CPU has access to the counter, make it present */8737if (has_counter)8738BIC_PRESENT(cai->bic_number);8739}87408741free(domain_visited);8742}87438744/* Assumes msr_counter_info is populated */8745static int has_amperf_access(void)8746{8747return cpuid_has_aperf_mperf && msr_counter_arch_infos[MSR_ARCH_INFO_APERF_INDEX].present && msr_counter_arch_infos[MSR_ARCH_INFO_MPERF_INDEX].present;8748}87498750int *get_cstate_perf_group_fd(struct cstate_counter_info_t *cci, const char *group_name)8751{8752if (strcmp(group_name, "cstate_core") == 0)8753return &cci->fd_perf_core;87548755if (strcmp(group_name, "cstate_pkg") == 0)8756return &cci->fd_perf_pkg;87578758return NULL;8759}87608761int add_cstate_perf_counter(int cpu, struct cstate_counter_info_t *cci, const struct cstate_counter_arch_info *cai)8762{8763int ret = -1;87648765if (no_perf)8766return -1;87678768if (!cai->perf_name)8769return -1;87708771int *pfd_group = get_cstate_perf_group_fd(cci, cai->perf_subsys);87728773if (pfd_group == NULL)8774goto end;87758776const unsigned int type = read_perf_type(cai->perf_subsys);8777const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);87788779ret = open_perf_counter(cpu, type, config, *pfd_group, PERF_FORMAT_GROUP);87808781if (ret == -1)8782goto end;87838784/* If it's the first counter opened, make it a group descriptor */8785if (*pfd_group == -1)8786*pfd_group = ret;87878788end:8789if (debug >= 2)8790fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu);87918792return ret;8793}87948795int add_msr_perf_counter(int cpu, struct msr_counter_info_t *cci, const struct msr_counter_arch_info *cai)8796{8797int ret = -1;87988799if (no_perf)8800return -1;88018802if (!cai->perf_name)8803return -1;88048805const unsigned int type = read_perf_type(cai->perf_subsys);8806const unsigned int config = read_perf_config(cai->perf_subsys, cai->perf_name);88078808ret = open_perf_counter(cpu, type, config, cci->fd_perf, PERF_FORMAT_GROUP);88098810if (ret == -1)8811goto end;88128813/* If it's the first counter opened, make it a group descriptor */8814if (cci->fd_perf == -1)8815cci->fd_perf = ret;88168817end:8818if (debug)8819fprintf(stderr, "%s: %s/%s: %d (cpu: %d)\n", __func__, cai->perf_subsys, cai->perf_name, ret, cpu);88208821return ret;8822}88238824void msr_perf_init_(void)8825{8826const int mci_num = topo.max_cpu_num + 1;88278828msr_counter_info = calloc(mci_num, sizeof(*msr_counter_info));8829if (!msr_counter_info)8830err(1, "calloc msr_counter_info");8831msr_counter_info_size = mci_num;88328833for (int cpu = 0; cpu < mci_num; ++cpu)8834msr_counter_info[cpu].fd_perf = -1;88358836for (int cidx = 0; cidx < NUM_MSR_COUNTERS; ++cidx) {88378838struct msr_counter_arch_info *cai = &msr_counter_arch_infos[cidx];88398840cai->present = false;88418842for (int cpu = 0; cpu < mci_num; ++cpu) {88438844struct msr_counter_info_t *const cci = &msr_counter_info[cpu];88458846if (cpu_is_not_allowed(cpu))8847continue;88488849if (cai->needed) {8850/* Use perf API for this counter */8851if (add_msr_perf_counter(cpu, cci, cai) != -1) {8852cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;8853cai->present = true;88548855/* User MSR for this counter */8856} else if (add_msr_counter(cpu, cai->msr) >= 0) {8857cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;8858cci->msr[cai->rci_index] = cai->msr;8859cci->msr_mask[cai->rci_index] = cai->msr_mask;8860cai->present = true;8861}8862}8863}8864}8865}88668867/* Initialize data for reading perf counters from the MSR group. */8868void msr_perf_init(void)8869{8870bool need_amperf = false, need_smi = false;8871const bool need_soft_c1 = (!platform->has_msr_core_c1_res) && (platform->supported_cstates & CC1);88728873need_amperf = BIC_IS_ENABLED(BIC_Avg_MHz) || BIC_IS_ENABLED(BIC_Busy) || BIC_IS_ENABLED(BIC_Bzy_MHz)8874|| BIC_IS_ENABLED(BIC_IPC) || need_soft_c1;88758876if (BIC_IS_ENABLED(BIC_SMI))8877need_smi = true;88788879/* Enable needed counters */8880msr_counter_arch_infos[MSR_ARCH_INFO_APERF_INDEX].needed = need_amperf;8881msr_counter_arch_infos[MSR_ARCH_INFO_MPERF_INDEX].needed = need_amperf;8882msr_counter_arch_infos[MSR_ARCH_INFO_SMI_INDEX].needed = need_smi;88838884msr_perf_init_();88858886const bool has_amperf = has_amperf_access();8887const bool has_smi = msr_counter_arch_infos[MSR_ARCH_INFO_SMI_INDEX].present;88888889has_aperf_access = has_amperf;88908891if (has_amperf) {8892BIC_PRESENT(BIC_Avg_MHz);8893BIC_PRESENT(BIC_Busy);8894BIC_PRESENT(BIC_Bzy_MHz);8895BIC_PRESENT(BIC_SMI);8896}88978898if (has_smi)8899BIC_PRESENT(BIC_SMI);8900}89018902void cstate_perf_init_(bool soft_c1)8903{8904bool has_counter;8905bool *cores_visited = NULL, *pkg_visited = NULL;8906const int cores_visited_elems = topo.max_core_id + 1;8907const int pkg_visited_elems = topo.max_package_id + 1;8908const int cci_num = topo.max_cpu_num + 1;89098910ccstate_counter_info = calloc(cci_num, sizeof(*ccstate_counter_info));8911if (!ccstate_counter_info)8912err(1, "calloc ccstate_counter_arch_info");8913ccstate_counter_info_size = cci_num;89148915cores_visited = calloc(cores_visited_elems, sizeof(*cores_visited));8916if (!cores_visited)8917err(1, "calloc cores_visited");89188919pkg_visited = calloc(pkg_visited_elems, sizeof(*pkg_visited));8920if (!pkg_visited)8921err(1, "calloc pkg_visited");89228923/* Initialize cstate_counter_info_percpu */8924for (int cpu = 0; cpu < cci_num; ++cpu) {8925ccstate_counter_info[cpu].fd_perf_core = -1;8926ccstate_counter_info[cpu].fd_perf_pkg = -1;8927}89288929for (int cidx = 0; cidx < NUM_CSTATE_COUNTERS; ++cidx) {8930has_counter = false;8931memset(cores_visited, 0, cores_visited_elems * sizeof(*cores_visited));8932memset(pkg_visited, 0, pkg_visited_elems * sizeof(*pkg_visited));89338934const struct cstate_counter_arch_info *cai = &ccstate_counter_arch_infos[cidx];89358936for (int cpu = 0; cpu < cci_num; ++cpu) {89378938struct cstate_counter_info_t *const cci = &ccstate_counter_info[cpu];89398940if (cpu_is_not_allowed(cpu))8941continue;89428943const int core_id = cpus[cpu].core_id;8944const int pkg_id = cpus[cpu].package_id;89458946assert(core_id < cores_visited_elems);8947assert(pkg_id < pkg_visited_elems);89488949const bool per_thread = cai->flags & CSTATE_COUNTER_FLAG_COLLECT_PER_THREAD;8950const bool per_core = cai->flags & CSTATE_COUNTER_FLAG_COLLECT_PER_CORE;89518952if (!per_thread && cores_visited[core_id])8953continue;89548955if (!per_core && pkg_visited[pkg_id])8956continue;89578958const bool counter_needed = BIC_IS_ENABLED(cai->bic_number) || (soft_c1 && (cai->flags & CSTATE_COUNTER_FLAG_SOFT_C1_DEPENDENCY));8959const bool counter_supported = (platform->supported_cstates & cai->feature_mask);89608961if (counter_needed && counter_supported) {8962/* Use perf API for this counter */8963if (add_cstate_perf_counter(cpu, cci, cai) != -1) {89648965cci->source[cai->rci_index] = COUNTER_SOURCE_PERF;89668967/* User MSR for this counter */8968} else if (pkg_cstate_limit >= cai->pkg_cstate_limit && add_msr_counter(cpu, cai->msr) >= 0) {8969cci->source[cai->rci_index] = COUNTER_SOURCE_MSR;8970cci->msr[cai->rci_index] = cai->msr;8971}8972}89738974if (cci->source[cai->rci_index] != COUNTER_SOURCE_NONE) {8975has_counter = true;8976cores_visited[core_id] = true;8977pkg_visited[pkg_id] = true;8978}8979}89808981/* If any CPU has access to the counter, make it present */8982if (has_counter)8983BIC_PRESENT(cai->bic_number);8984}89858986free(cores_visited);8987free(pkg_visited);8988}89898990void cstate_perf_init(void)8991{8992/*8993* If we don't have a C1 residency MSR, we calculate it "in software",8994* but we need APERF, MPERF too.8995*/8996const bool soft_c1 = !platform->has_msr_core_c1_res && has_amperf_access()8997&& platform->supported_cstates & CC1;89988999if (soft_c1)9000BIC_PRESENT(BIC_CPU_c1);90019002cstate_perf_init_(soft_c1);9003}90049005void probe_cstates(void)9006{9007probe_cst_limit();90089009if (platform->has_msr_module_c6_res_ms)9010BIC_PRESENT(BIC_Mod_c6);90119012if (platform->has_ext_cst_msrs && !no_msr) {9013BIC_PRESENT(BIC_Totl_c0);9014BIC_PRESENT(BIC_Any_c0);9015BIC_PRESENT(BIC_GFX_c0);9016BIC_PRESENT(BIC_CPUGFX);9017}90189019if (quiet)9020return;90219022dump_power_ctl();9023dump_cst_cfg();9024decode_c6_demotion_policy_msr();9025print_dev_latency();9026dump_sysfs_cstate_config();9027print_irtl();9028}90299030void probe_lpi(void)9031{9032if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))9033BIC_PRESENT(BIC_CPU_LPI);9034else9035BIC_NOT_PRESENT(BIC_CPU_LPI);90369037if (!access(sys_lpi_file_sysfs, R_OK)) {9038sys_lpi_file = sys_lpi_file_sysfs;9039BIC_PRESENT(BIC_SYS_LPI);9040} else if (!access(sys_lpi_file_debugfs, R_OK)) {9041sys_lpi_file = sys_lpi_file_debugfs;9042BIC_PRESENT(BIC_SYS_LPI);9043} else {9044sys_lpi_file_sysfs = NULL;9045BIC_NOT_PRESENT(BIC_SYS_LPI);9046}90479048}90499050void probe_pstates(void)9051{9052probe_bclk();90539054if (quiet)9055return;90569057dump_platform_info();9058dump_turbo_ratio_info();9059dump_sysfs_pstate_config();9060decode_misc_pwr_mgmt_msr();90619062for_all_cpus(print_hwp, ODD_COUNTERS);9063for_all_cpus(print_epb, ODD_COUNTERS);9064for_all_cpus(print_perf_limit, ODD_COUNTERS);9065}90669067void dump_word_chars(unsigned int word)9068{9069int i;90709071for (i = 0; i < 4; ++i)9072fprintf(outf, "%c", (word >> (i * 8)) & 0xFF);9073}90749075void dump_cpuid_hypervisor(void)9076{9077unsigned int ebx = 0;9078unsigned int ecx = 0;9079unsigned int edx = 0;90809081__cpuid(0x40000000, max_extended_level, ebx, ecx, edx);90829083fprintf(outf, "Hypervisor: ");9084dump_word_chars(ebx);9085dump_word_chars(ecx);9086dump_word_chars(edx);9087fprintf(outf, "\n");9088}90899090void process_cpuid()9091{9092unsigned int eax, ebx, ecx, edx;9093unsigned int fms, family, model, stepping, ecx_flags, edx_flags;9094unsigned long long ucode_patch = 0;9095bool ucode_patch_valid = false;90969097eax = ebx = ecx = edx = 0;90989099__cpuid(0, max_level, ebx, ecx, edx);91009101if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)9102genuine_intel = 1;9103else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)9104authentic_amd = 1;9105else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)9106hygon_genuine = 1;91079108if (!quiet)9109fprintf(outf, "CPUID(0): %.4s%.4s%.4s 0x%x CPUID levels\n", (char *)&ebx, (char *)&edx, (char *)&ecx, max_level);91109111__cpuid(1, fms, ebx, ecx, edx);9112family = (fms >> 8) & 0xf;9113model = (fms >> 4) & 0xf;9114stepping = fms & 0xf;9115if (family == 0xf)9116family += (fms >> 20) & 0xff;9117if (family >= 6)9118model += ((fms >> 16) & 0xf) << 4;9119ecx_flags = ecx;9120edx_flags = edx;9121cpuid_has_hv = ecx_flags & (1 << 31);91229123if (!no_msr) {9124if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))9125warnx("get_msr(UCODE)");9126else9127ucode_patch_valid = true;9128}91299130/*9131* check max extended function levels of CPUID.9132* This is needed to check for invariant TSC.9133* This check is valid for both Intel and AMD.9134*/9135ebx = ecx = edx = 0;9136__cpuid(0x80000000, max_extended_level, ebx, ecx, edx);91379138if (!quiet) {9139fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", family, model, stepping, family, model, stepping);9140if (ucode_patch_valid)9141fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));9142fputc('\n', outf);91439144fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);9145fprintf(outf, "CPUID(1): %sSSE3 %sMONITOR %sSMX %sEIST %sTM2 %sHV %sTSC %sMSR %sACPI-TM %sHT %sTM\n",9146ecx_flags & (1 << 0) ? "" : "No-",9147ecx_flags & (1 << 3) ? "" : "No-",9148ecx_flags & (1 << 6) ? "" : "No-",9149ecx_flags & (1 << 7) ? "" : "No-",9150ecx_flags & (1 << 8) ? "" : "No-",9151cpuid_has_hv ? "" : "No-",9152edx_flags & (1 << 4) ? "" : "No-",9153edx_flags & (1 << 5) ? "" : "No-",9154edx_flags & (1 << 22) ? "" : "No-", edx_flags & (1 << 28) ? "" : "No-", edx_flags & (1 << 29) ? "" : "No-");9155}9156if (!quiet && cpuid_has_hv)9157dump_cpuid_hypervisor();91589159probe_platform_features(family, model);9160init_perf_model_support(family, model);91619162if (!(edx_flags & (1 << 5)))9163errx(1, "CPUID: no MSR");91649165if (max_extended_level >= 0x80000007) {91669167/*9168* Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit89169* this check is valid for both Intel and AMD9170*/9171__cpuid(0x80000007, eax, ebx, ecx, edx);9172has_invariant_tsc = edx & (1 << 8);9173}91749175/*9176* APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit09177* this check is valid for both Intel and AMD9178*/91799180__cpuid(0x6, eax, ebx, ecx, edx);9181cpuid_has_aperf_mperf = ecx & (1 << 0);9182do_dts = eax & (1 << 0);9183if (do_dts)9184BIC_PRESENT(BIC_CoreTmp);9185has_turbo = eax & (1 << 1);9186do_ptm = eax & (1 << 6);9187if (do_ptm)9188BIC_PRESENT(BIC_PkgTmp);9189has_hwp = eax & (1 << 7);9190has_hwp_notify = eax & (1 << 8);9191has_hwp_activity_window = eax & (1 << 9);9192has_hwp_epp = eax & (1 << 10);9193has_hwp_pkg = eax & (1 << 11);9194has_epb = ecx & (1 << 3);91959196if (!quiet)9197fprintf(outf, "CPUID(6): %sAPERF, %sTURBO, %sDTS, %sPTM, %sHWP, "9198"%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",9199cpuid_has_aperf_mperf ? "" : "No-",9200has_turbo ? "" : "No-",9201do_dts ? "" : "No-",9202do_ptm ? "" : "No-",9203has_hwp ? "" : "No-",9204has_hwp_notify ? "" : "No-",9205has_hwp_activity_window ? "" : "No-", has_hwp_epp ? "" : "No-", has_hwp_pkg ? "" : "No-", has_epb ? "" : "No-");92069207if (!quiet)9208decode_misc_enable_msr();92099210if (max_level >= 0x7) {9211int has_sgx;92129213ecx = 0;92149215__cpuid_count(0x7, 0, eax, ebx, ecx, edx);92169217has_sgx = ebx & (1 << 2);92189219is_hybrid = !!(edx & (1 << 15));92209221if (!quiet)9222fprintf(outf, "CPUID(7): %sSGX %sHybrid\n", has_sgx ? "" : "No-", is_hybrid ? "" : "No-");92239224if (has_sgx)9225decode_feature_control_msr();9226}92279228if (max_level >= 0x15) {9229unsigned int eax_crystal;9230unsigned int ebx_tsc;92319232/*9233* CPUID 15H TSC/Crystal ratio, possibly Crystal Hz9234*/9235eax_crystal = ebx_tsc = crystal_hz = edx = 0;9236__cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);92379238if (ebx_tsc != 0) {9239if (!quiet && (ebx != 0))9240fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", eax_crystal, ebx_tsc, crystal_hz);92419242if (crystal_hz == 0)9243crystal_hz = platform->crystal_freq;92449245if (crystal_hz) {9246tsc_hz = (unsigned long long)crystal_hz *ebx_tsc / eax_crystal;9247if (!quiet)9248fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n", tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);9249}9250}9251}9252if (max_level >= 0x16) {9253unsigned int base_mhz, max_mhz, bus_mhz, edx;92549255/*9256* CPUID 16H Base MHz, Max MHz, Bus MHz9257*/9258base_mhz = max_mhz = bus_mhz = edx = 0;92599260__cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);92619262bclk = bus_mhz;92639264base_hz = base_mhz * 1000000;9265has_base_hz = 1;92669267if (platform->enable_tsc_tweak)9268tsc_tweak = base_hz / tsc_hz;92699270if (!quiet)9271fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", base_mhz, max_mhz, bus_mhz);9272}92739274if (cpuid_has_aperf_mperf)9275aperf_mperf_multiplier = platform->need_perf_multiplier ? 1024 : 1;92769277BIC_PRESENT(BIC_IRQ);9278BIC_PRESENT(BIC_NMI);9279BIC_PRESENT(BIC_TSC_MHz);9280}92819282static void counter_info_init(void)9283{9284for (int i = 0; i < NUM_CSTATE_COUNTERS; ++i) {9285struct cstate_counter_arch_info *const cai = &ccstate_counter_arch_infos[i];92869287if (platform->has_msr_knl_core_c6_residency && cai->msr == MSR_CORE_C6_RESIDENCY)9288cai->msr = MSR_KNL_CORE_C6_RESIDENCY;92899290if (!platform->has_msr_core_c1_res && cai->msr == MSR_CORE_C1_RES)9291cai->msr = 0;92929293if (platform->has_msr_atom_pkg_c6_residency && cai->msr == MSR_PKG_C6_RESIDENCY)9294cai->msr = MSR_ATOM_PKG_C6_RESIDENCY;9295}92969297for (int i = 0; i < NUM_MSR_COUNTERS; ++i) {9298msr_counter_arch_infos[i].present = false;9299msr_counter_arch_infos[i].needed = false;9300}9301}93029303void probe_pm_features(void)9304{9305probe_pstates();93069307probe_cstates();93089309probe_lpi();93109311probe_intel_uncore_frequency();93129313probe_graphics();93149315probe_rapl();93169317probe_thermal();93189319if (platform->has_nhm_msrs && !no_msr)9320BIC_PRESENT(BIC_SMI);93219322if (!quiet)9323decode_misc_feature_control();9324}93259326/*9327* has_perf_llc_access()9328*9329* return 1 on success, else 09330*/9331int has_perf_llc_access(void)9332{9333int fd;93349335if (no_perf)9336return 0;93379338fd = open_perf_counter(master_cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, -1, PERF_FORMAT_GROUP);9339if (fd != -1)9340close(fd);93419342if (fd == -1)9343warnx("Failed to access %s. Some of the counters may not be available\n"9344"\tRun as root to enable them or use %s to disable the access explicitly", "perf LLC counters", "'--hide LLC' or '--no-perf'");93459346return (fd != -1);9347}93489349void perf_llc_init(void)9350{9351int cpu;9352int retval;93539354if (no_perf)9355return;9356if (!(BIC_IS_ENABLED(BIC_LLC_MRPS) || BIC_IS_ENABLED(BIC_LLC_HIT)))9357return;93589359assert(fd_llc_percpu != 0);93609361for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {93629363if (cpu_is_not_allowed(cpu))9364continue;93659366fd_llc_percpu[cpu] = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, -1, PERF_FORMAT_GROUP);9367if (fd_llc_percpu[cpu] == -1) {9368warnx("%s: perf REFS: failed to open counter on cpu%d", __func__, cpu);9369free_fd_llc_percpu();9370return;9371}9372retval = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, fd_llc_percpu[cpu], PERF_FORMAT_GROUP);9373if (retval == -1) {9374warnx("%s: perf MISS: failed to open counter on cpu%d", __func__, cpu);9375free_fd_llc_percpu();9376return;9377}9378}9379BIC_PRESENT(BIC_LLC_MRPS);9380BIC_PRESENT(BIC_LLC_HIT);9381}93829383void perf_l2_init(void)9384{9385int cpu;9386int retval;93879388if (no_perf)9389return;9390if (!(BIC_IS_ENABLED(BIC_L2_MRPS) || BIC_IS_ENABLED(BIC_L2_HIT)))9391return;9392if (perf_model_support == NULL)9393return;93949395assert(fd_l2_percpu != 0);93969397for (cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {93989399if (cpu_is_not_allowed(cpu))9400continue;94019402if (!is_hybrid) {9403fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP);9404if (fd_l2_percpu[cpu] == -1) {9405err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs);9406free_fd_l2_percpu();9407return;9408}9409retval = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);9410if (retval == -1) {9411err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits);9412free_fd_l2_percpu();9413return;9414}9415continue;9416}9417if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_pcore_set)) {9418fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP);9419if (fd_l2_percpu[cpu] == -1) {9420err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs);9421free_fd_l2_percpu();9422return;9423}9424retval = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);9425if (retval == -1) {9426err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits);9427free_fd_l2_percpu();9428return;9429}9430} else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_ecore_set)) {9431fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.refs, -1, PERF_FORMAT_GROUP);9432if (fd_l2_percpu[cpu] == -1) {9433err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.refs);9434free_fd_l2_percpu();9435return;9436}9437retval = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);9438if (retval == -1) {9439err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.hits);9440free_fd_l2_percpu();9441return;9442}9443} else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_lcore_set)) {9444fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.refs, -1, PERF_FORMAT_GROUP);9445if (fd_l2_percpu[cpu] == -1) {9446err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.refs);9447free_fd_l2_percpu();9448return;9449}9450retval = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);9451if (retval == -1) {9452err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.hits);9453free_fd_l2_percpu();9454return;9455}9456} else9457err(-1, "%s: cpu%d: type %d", __func__, cpu, cpus[cpu].type);9458}9459BIC_PRESENT(BIC_L2_MRPS);9460BIC_PRESENT(BIC_L2_HIT);9461}94629463/*9464* in /dev/cpu/ return success for names that are numbers9465* ie. filter out ".", "..", "microcode".9466*/9467int dir_filter(const struct dirent *dirp)9468{9469if (isdigit(dirp->d_name[0]))9470return 1;9471else9472return 0;9473}94749475void topology_probe(bool startup)9476{9477int i;9478int max_core_id = 0;9479int max_package_id = 0;9480int max_siblings = 0;94819482/* Initialize num_cpus, max_cpu_num */9483set_max_cpu_num();9484topo.num_cpus = 0;9485for_all_proc_cpus(count_cpus);9486if (!summary_only)9487BIC_PRESENT(BIC_CPU);94889489if (debug > 1)9490fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);94919492cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));9493if (cpus == NULL)9494err(1, "calloc cpus");94959496/*9497* Allocate and initialize cpu_present_set9498*/9499cpu_present_set = CPU_ALLOC((topo.max_cpu_num + 1));9500if (cpu_present_set == NULL)9501err(3, "CPU_ALLOC");9502cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));9503CPU_ZERO_S(cpu_present_setsize, cpu_present_set);9504for_all_proc_cpus(mark_cpu_present);95059506/*9507* Allocate and initialize cpu_possible_set9508*/9509cpu_possible_set = CPU_ALLOC((topo.max_cpu_num + 1));9510if (cpu_possible_set == NULL)9511err(3, "CPU_ALLOC");9512cpu_possible_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));9513CPU_ZERO_S(cpu_possible_setsize, cpu_possible_set);9514initialize_cpu_set_from_sysfs(cpu_possible_set, "/sys/devices/system/cpu", "possible");95159516/*9517* Allocate and initialize cpu_effective_set9518*/9519cpu_effective_set = CPU_ALLOC((topo.max_cpu_num + 1));9520if (cpu_effective_set == NULL)9521err(3, "CPU_ALLOC");9522cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));9523CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set);9524update_effective_set(startup);95259526/*9527* Allocate and initialize cpu_allowed_set9528*/9529cpu_allowed_set = CPU_ALLOC((topo.max_cpu_num + 1));9530if (cpu_allowed_set == NULL)9531err(3, "CPU_ALLOC");9532cpu_allowed_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));9533CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set);95349535/*9536* Validate and update cpu_allowed_set.9537*9538* Make sure all cpus in cpu_subset are also in cpu_present_set during startup.9539* Give a warning when cpus in cpu_subset become unavailable at runtime.9540* Give a warning when cpus are not effective because of cgroup setting.9541*9542* cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpu_subset.9543*/9544for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {9545if (cpu_subset && !CPU_ISSET_S(i, cpu_subset_size, cpu_subset))9546continue;95479548if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) {9549if (cpu_subset) {9550/* cpus in cpu_subset must be in cpu_present_set during startup */9551if (startup)9552err(1, "cpu%d not present", i);9553else9554fprintf(stderr, "cpu%d not present\n", i);9555}9556continue;9557}95589559if (CPU_COUNT_S(cpu_effective_setsize, cpu_effective_set)) {9560if (!CPU_ISSET_S(i, cpu_effective_setsize, cpu_effective_set)) {9561fprintf(stderr, "cpu%d not effective\n", i);9562continue;9563}9564}95659566CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set);9567}95689569if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set))9570err(-ENODEV, "No valid cpus found");9571sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set);95729573/*9574* Allocate and initialize cpu_affinity_set9575*/9576cpu_affinity_set = CPU_ALLOC((topo.max_cpu_num + 1));9577if (cpu_affinity_set == NULL)9578err(3, "CPU_ALLOC");9579cpu_affinity_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));9580CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);95819582for_all_proc_cpus(clear_ht_id);95839584for_all_proc_cpus(set_cpu_hybrid_type);95859586/*9587* For online cpus9588* find max_core_id, max_package_id, num_cores (per system)9589*/9590for (i = 0; i <= topo.max_cpu_num; ++i) {9591int siblings;95929593if (cpu_is_not_present(i)) {9594if (debug > 1)9595fprintf(outf, "cpu%d NOT PRESENT\n", i);9596continue;9597}95989599cpus[i].cpu_id = i;96009601/* get package information */9602cpus[i].package_id = get_package_id(i);9603if (cpus[i].package_id > max_package_id)9604max_package_id = cpus[i].package_id;96059606/* get die information */9607cpus[i].die_id = get_die_id(i);9608if (cpus[i].die_id > topo.max_die_id)9609topo.max_die_id = cpus[i].die_id;96109611/* get l3 information */9612cpus[i].l3_id = get_l3_id(i);9613if (cpus[i].l3_id > topo.max_l3_id)9614topo.max_l3_id = cpus[i].l3_id;96159616/* get numa node information */9617cpus[i].physical_node_id = get_physical_node_id(&cpus[i]);9618if (cpus[i].physical_node_id > topo.max_node_num)9619topo.max_node_num = cpus[i].physical_node_id;96209621/* get core information */9622cpus[i].core_id = get_core_id(i);9623if (cpus[i].core_id > max_core_id)9624max_core_id = cpus[i].core_id;96259626/* get thread information */9627siblings = set_thread_siblings(&cpus[i]);9628if (siblings > max_siblings)9629max_siblings = siblings;9630if (cpus[i].ht_id == 0)9631topo.num_cores++;9632}9633topo.max_core_id = max_core_id; /* within a package */9634topo.max_package_id = max_package_id;96359636topo.cores_per_node = max_core_id + 1;9637if (debug > 1)9638fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node);9639if (!summary_only)9640BIC_PRESENT(BIC_Core);96419642topo.num_die = topo.max_die_id + 1;9643if (debug > 1)9644fprintf(outf, "max_die_id %d, sizing for %d die\n", topo.max_die_id, topo.num_die);9645if (!summary_only && topo.num_die > 1)9646BIC_PRESENT(BIC_Die);96479648if (!summary_only && topo.max_l3_id > 0)9649BIC_PRESENT(BIC_L3);96509651topo.num_packages = max_package_id + 1;9652if (debug > 1)9653fprintf(outf, "max_package_id %d, sizing for %d packages\n", max_package_id, topo.num_packages);9654if (!summary_only && topo.num_packages > 1)9655BIC_PRESENT(BIC_Package);96569657set_node_data();9658if (debug > 1)9659fprintf(outf, "nodes_per_pkg %d\n", topo.nodes_per_pkg);9660if (!summary_only && topo.nodes_per_pkg > 1)9661BIC_PRESENT(BIC_Node);96629663topo.threads_per_core = max_siblings;9664if (debug > 1)9665fprintf(outf, "max_siblings %d\n", max_siblings);96669667if (debug < 1)9668return;96699670for (i = 0; i <= topo.max_cpu_num; ++i) {9671if (cpu_is_not_present(i))9672continue;9673fprintf(outf,9674"cpu %d pkg %d die %d l3 %d node %d lnode %d core %d thread %d\n",9675i, cpus[i].package_id, cpus[i].die_id, cpus[i].l3_id,9676cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].core_id, cpus[i].ht_id);9677}96789679}96809681void allocate_counters_1(struct counters *counters)9682{9683counters->threads = calloc(1, sizeof(struct thread_data));9684if (counters->threads == NULL)9685goto error;96869687counters->cores = calloc(1, sizeof(struct core_data));9688if (counters->cores == NULL)9689goto error;96909691counters->packages = calloc(1, sizeof(struct pkg_data));9692if (counters->packages == NULL)9693goto error;96949695return;9696error:9697err(1, "calloc counters_1");9698}96999700void allocate_counters(struct counters *counters)9701{9702int i;9703int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages;9704int num_threads = topo.threads_per_core * num_cores;97059706counters->threads = calloc(num_threads, sizeof(struct thread_data));9707if (counters->threads == NULL)9708goto error;97099710for (i = 0; i < num_threads; i++)9711(counters->threads)[i].cpu_id = -1;97129713counters->cores = calloc(num_cores, sizeof(struct core_data));9714if (counters->cores == NULL)9715goto error;97169717for (i = 0; i < num_cores; i++)9718(counters->cores)[i].first_cpu = -1;97199720counters->packages = calloc(topo.num_packages, sizeof(struct pkg_data));9721if (counters->packages == NULL)9722goto error;97239724for (i = 0; i < topo.num_packages; i++)9725(counters->packages)[i].first_cpu = -1;97269727return;9728error:9729err(1, "calloc counters");9730}97319732/*9733* init_counter()9734*9735* set t->cpu_id, FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE9736*/9737void init_counter(struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base, int cpu_id)9738{9739int pkg_id = cpus[cpu_id].package_id;9740int node_id = cpus[cpu_id].logical_node_id;9741int core_id = cpus[cpu_id].core_id;9742struct thread_data *t;9743struct core_data *c;97449745/* Workaround for systems where physical_node_id==-19746* and logical_node_id==(-1 - topo.num_cpus)9747*/9748if (node_id < 0)9749node_id = 0;97509751t = &thread_base[cpu_id];9752c = &core_base[GLOBAL_CORE_ID(core_id, pkg_id)];97539754t->cpu_id = cpu_id;9755if (!cpu_is_not_allowed(cpu_id)) {97569757if (c->first_cpu < 0)9758c->first_cpu = t->cpu_id;9759if (pkg_base[pkg_id].first_cpu < 0)9760pkg_base[pkg_id].first_cpu = t->cpu_id;9761}9762}97639764int initialize_counters(int cpu_id)9765{9766init_counter(EVEN_COUNTERS, cpu_id);9767init_counter(ODD_COUNTERS, cpu_id);9768return 0;9769}97709771void allocate_output_buffer()9772{9773output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);9774outp = output_buffer;9775if (outp == NULL)9776err(-1, "calloc output buffer");9777}97789779void allocate_fd_percpu(void)9780{9781fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));9782if (fd_percpu == NULL)9783err(-1, "calloc fd_percpu");9784}97859786void allocate_irq_buffers(void)9787{9788irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));9789if (irq_column_2_cpu == NULL)9790err(-1, "calloc %d", topo.num_cpus);97919792irqs_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int));9793if (irqs_per_cpu == NULL)9794err(-1, "calloc %d IRQ", topo.max_cpu_num + 1);97959796nmi_per_cpu = calloc(topo.max_cpu_num + 1, sizeof(int));9797if (nmi_per_cpu == NULL)9798err(-1, "calloc %d NMI", topo.max_cpu_num + 1);9799}98009801int update_topo(PER_THREAD_PARAMS)9802{9803topo.allowed_cpus++;9804if ((int)t->cpu_id == c->first_cpu)9805topo.allowed_cores++;9806if ((int)t->cpu_id == p->first_cpu)9807topo.allowed_packages++;98089809return 0;9810}98119812void topology_update(void)9813{9814topo.allowed_cpus = 0;9815topo.allowed_cores = 0;9816topo.allowed_packages = 0;9817for_all_cpus(update_topo, ODD_COUNTERS);9818}98199820void setup_all_buffers(bool startup)9821{9822topology_probe(startup);9823allocate_irq_buffers();9824allocate_fd_percpu();9825allocate_counters_1(&average);9826allocate_counters(&even);9827allocate_counters(&odd);9828allocate_output_buffer();9829for_all_proc_cpus(initialize_counters);9830topology_update();9831}98329833void set_master_cpu(void)9834{9835int i;98369837for (i = 0; i < topo.max_cpu_num + 1; ++i) {9838if (cpu_is_not_allowed(i))9839continue;9840master_cpu = i;9841if (debug > 1)9842fprintf(outf, "master_cpu = %d\n", master_cpu);9843return;9844}9845err(-ENODEV, "No valid cpus found");9846}98479848bool has_added_counters(void)9849{9850/*9851* It only makes sense to call this after the command line is parsed,9852* otherwise sys structure is not populated.9853*/98549855return sys.added_core_counters | sys.added_thread_counters | sys.added_package_counters;9856}98579858void check_msr_access(void)9859{9860check_msr_driver();9861check_msr_permission();98629863if (no_msr)9864bic_disable_msr_access();9865}98669867void check_perf_access(void)9868{9869if (BIC_IS_ENABLED(BIC_IPC))9870if (!has_perf_instr_count_access())9871no_perf = 1;98729873if (BIC_IS_ENABLED(BIC_LLC_MRPS) || BIC_IS_ENABLED(BIC_LLC_HIT))9874if (!has_perf_llc_access())9875no_perf = 1;98769877if (no_perf)9878bic_disable_perf_access();9879}98809881bool perf_has_hybrid_devices(void)9882{9883/*9884* 0: unknown9885* 1: has separate perf device for p and e core9886* -1: doesn't have separate perf device for p and e core9887*/9888static int cached;98899890if (cached > 0)9891return true;98929893if (cached < 0)9894return false;98959896if (access("/sys/bus/event_source/devices/cpu_core", F_OK)) {9897cached = -1;9898return false;9899}99009901if (access("/sys/bus/event_source/devices/cpu_atom", F_OK)) {9902cached = -1;9903return false;9904}99059906cached = 1;9907return true;9908}99099910int added_perf_counters_init_(struct perf_counter_info *pinfo)9911{9912size_t num_domains = 0;9913unsigned int next_domain;9914bool *domain_visited;9915unsigned int perf_type, perf_config;9916double perf_scale;9917int fd_perf;99189919if (!pinfo)9920return 0;99219922const size_t max_num_domains = MAX(topo.max_cpu_num + 1, MAX(topo.max_core_id + 1, topo.max_package_id + 1));99239924domain_visited = calloc(max_num_domains, sizeof(*domain_visited));99259926while (pinfo) {9927switch (pinfo->scope) {9928case SCOPE_CPU:9929num_domains = topo.max_cpu_num + 1;9930break;99319932case SCOPE_CORE:9933num_domains = topo.max_core_id + 1;9934break;99359936case SCOPE_PACKAGE:9937num_domains = topo.max_package_id + 1;9938break;9939}99409941/* Allocate buffer for file descriptor for each domain. */9942pinfo->fd_perf_per_domain = calloc(num_domains, sizeof(*pinfo->fd_perf_per_domain));9943if (!pinfo->fd_perf_per_domain)9944errx(1, "%s: alloc %s", __func__, "fd_perf_per_domain");99459946for (size_t i = 0; i < num_domains; ++i)9947pinfo->fd_perf_per_domain[i] = -1;99489949pinfo->num_domains = num_domains;9950pinfo->scale = 1.0;99519952memset(domain_visited, 0, max_num_domains * sizeof(*domain_visited));99539954for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) {99559956next_domain = cpu_to_domain(pinfo, cpu);99579958assert(next_domain < num_domains);99599960if (cpu_is_not_allowed(cpu))9961continue;99629963if (domain_visited[next_domain])9964continue;99659966/*9967* Intel hybrid platforms expose different perf devices for P and E cores.9968* Instead of one, "/sys/bus/event_source/devices/cpu" device, there are9969* "/sys/bus/event_source/devices/{cpu_core,cpu_atom}".9970*9971* This makes it more complicated to the user, because most of the counters9972* are available on both and have to be handled manually, otherwise.9973*9974* Code below, allow user to use the old "cpu" name, which is translated accordingly.9975*/9976const char *perf_device = pinfo->device;99779978if (strcmp(perf_device, "cpu") == 0 && perf_has_hybrid_devices()) {9979switch (cpus[cpu].type) {9980case INTEL_PCORE_TYPE:9981perf_device = "cpu_core";9982break;99839984case INTEL_ECORE_TYPE:9985perf_device = "cpu_atom";9986break;99879988default: /* Don't change, we will probably fail and report a problem soon. */9989break;9990}9991}99929993perf_type = read_perf_type(perf_device);9994if (perf_type == (unsigned int)-1) {9995warnx("%s: perf/%s/%s: failed to read %s", __func__, perf_device, pinfo->event, "type");9996continue;9997}99989999perf_config = read_perf_config(perf_device, pinfo->event);10000if (perf_config == (unsigned int)-1) {10001warnx("%s: perf/%s/%s: failed to read %s", __func__, perf_device, pinfo->event, "config");10002continue;10003}1000410005/* Scale is not required, some counters just don't have it. */10006perf_scale = read_perf_scale(perf_device, pinfo->event);10007if (perf_scale == 0.0)10008perf_scale = 1.0;1000910010fd_perf = open_perf_counter(cpu, perf_type, perf_config, -1, 0);10011if (fd_perf == -1) {10012warnx("%s: perf/%s/%s: failed to open counter on cpu%d", __func__, perf_device, pinfo->event, cpu);10013continue;10014}1001510016domain_visited[next_domain] = 1;10017pinfo->fd_perf_per_domain[next_domain] = fd_perf;10018pinfo->scale = perf_scale;1001910020if (debug)10021fprintf(stderr, "Add perf/%s/%s cpu%d: %d\n", perf_device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]);10022}1002310024pinfo = pinfo->next;10025}1002610027free(domain_visited);1002810029return 0;10030}1003110032void added_perf_counters_init(void)10033{10034if (added_perf_counters_init_(sys.perf_tp))10035errx(1, "%s: %s", __func__, "thread");1003610037if (added_perf_counters_init_(sys.perf_cp))10038errx(1, "%s: %s", __func__, "core");1003910040if (added_perf_counters_init_(sys.perf_pp))10041errx(1, "%s: %s", __func__, "package");10042}1004310044int parse_telem_info_file(int fd_dir, const char *info_filename, const char *format, unsigned long *output)10045{10046int fd_telem_info;10047FILE *file_telem_info;10048unsigned long value;1004910050fd_telem_info = openat(fd_dir, info_filename, O_RDONLY);10051if (fd_telem_info == -1)10052return -1;1005310054file_telem_info = fdopen(fd_telem_info, "r");10055if (file_telem_info == NULL) {10056close(fd_telem_info);10057return -1;10058}1005910060if (fscanf(file_telem_info, format, &value) != 1) {10061fclose(file_telem_info);10062return -1;10063}1006410065fclose(file_telem_info);1006610067*output = value;1006810069return 0;10070}1007110072struct pmt_mmio *pmt_mmio_open(unsigned int target_guid)10073{10074struct pmt_diriter_t pmt_iter;10075const struct dirent *entry;10076struct stat st;10077int fd_telem_dir, fd_pmt;10078unsigned long guid, size, offset;10079size_t mmap_size;10080void *mmio;10081struct pmt_mmio *head = NULL, *last = NULL;10082struct pmt_mmio *new_pmt = NULL;1008310084if (stat(SYSFS_TELEM_PATH, &st) == -1)10085return NULL;1008610087pmt_diriter_init(&pmt_iter);10088entry = pmt_diriter_begin(&pmt_iter, SYSFS_TELEM_PATH);10089if (!entry) {10090pmt_diriter_remove(&pmt_iter);10091return NULL;10092}1009310094for (; entry != NULL; entry = pmt_diriter_next(&pmt_iter)) {10095if (fstatat(dirfd(pmt_iter.dir), entry->d_name, &st, 0) == -1)10096break;1009710098if (!S_ISDIR(st.st_mode))10099continue;1010010101fd_telem_dir = openat(dirfd(pmt_iter.dir), entry->d_name, O_RDONLY);10102if (fd_telem_dir == -1)10103break;1010410105if (parse_telem_info_file(fd_telem_dir, "guid", "%lx", &guid)) {10106close(fd_telem_dir);10107break;10108}1010910110if (parse_telem_info_file(fd_telem_dir, "size", "%lu", &size)) {10111close(fd_telem_dir);10112break;10113}1011410115if (guid != target_guid) {10116close(fd_telem_dir);10117continue;10118}1011910120if (parse_telem_info_file(fd_telem_dir, "offset", "%lu", &offset)) {10121close(fd_telem_dir);10122break;10123}1012410125assert(offset == 0);1012610127fd_pmt = openat(fd_telem_dir, "telem", O_RDONLY);10128if (fd_pmt == -1)10129goto loop_cleanup_and_break;1013010131mmap_size = ROUND_UP_TO_PAGE_SIZE(size);10132mmio = mmap(0, mmap_size, PROT_READ, MAP_SHARED, fd_pmt, 0);10133if (mmio != MAP_FAILED) {10134if (debug)10135fprintf(stderr, "%s: 0x%lx mmaped at: %p\n", __func__, guid, mmio);1013610137new_pmt = calloc(1, sizeof(*new_pmt));1013810139if (!new_pmt) {10140fprintf(stderr, "%s: Failed to allocate pmt_mmio\n", __func__);10141exit(1);10142}1014310144/*10145* Create linked list of mmaped regions,10146* but preserve the ordering from sysfs.10147* Ordering is important for the user to10148* use the seq=%u parameter when adding a counter.10149*/10150new_pmt->guid = guid;10151new_pmt->mmio_base = mmio;10152new_pmt->pmt_offset = offset;10153new_pmt->size = size;10154new_pmt->next = pmt_mmios;1015510156if (last)10157last->next = new_pmt;10158else10159head = new_pmt;1016010161last = new_pmt;10162}1016310164loop_cleanup_and_break:10165close(fd_pmt);10166close(fd_telem_dir);10167}1016810169pmt_diriter_remove(&pmt_iter);1017010171/*10172* If we found something, stick just10173* created linked list to the front.10174*/10175if (head)10176pmt_mmios = head;1017710178return head;10179}1018010181struct pmt_mmio *pmt_mmio_find(unsigned int guid)10182{10183struct pmt_mmio *pmmio = pmt_mmios;1018410185while (pmmio) {10186if (pmmio->guid == guid)10187return pmmio;1018810189pmmio = pmmio->next;10190}1019110192return NULL;10193}1019410195void *pmt_get_counter_pointer(struct pmt_mmio *pmmio, unsigned long counter_offset)10196{10197char *ret;1019810199/* Get base of mmaped PMT file. */10200ret = (char *)pmmio->mmio_base;1020110202/*10203* Apply PMT MMIO offset to obtain beginning of the mmaped telemetry data.10204* It's not guaranteed that the mmaped memory begins with the telemetry data10205* - we might have to apply the offset first.10206*/10207ret += pmmio->pmt_offset;1020810209/* Apply the counter offset to get the address to the mmaped counter. */10210ret += counter_offset;1021110212return ret;10213}1021410215struct pmt_mmio *pmt_add_guid(unsigned int guid, unsigned int seq)10216{10217struct pmt_mmio *ret;1021810219ret = pmt_mmio_find(guid);10220if (!ret)10221ret = pmt_mmio_open(guid);1022210223while (ret && seq) {10224ret = ret->next;10225--seq;10226}1022710228return ret;10229}1023010231enum pmt_open_mode {10232PMT_OPEN_TRY, /* Open failure is not an error. */10233PMT_OPEN_REQUIRED, /* Open failure is a fatal error. */10234};1023510236struct pmt_counter *pmt_find_counter(struct pmt_counter *pcounter, const char *name)10237{10238while (pcounter) {10239if (strcmp(pcounter->name, name) == 0)10240break;1024110242pcounter = pcounter->next;10243}1024410245return pcounter;10246}1024710248struct pmt_counter **pmt_get_scope_root(enum counter_scope scope)10249{10250switch (scope) {10251case SCOPE_CPU:10252return &sys.pmt_tp;10253case SCOPE_CORE:10254return &sys.pmt_cp;10255case SCOPE_PACKAGE:10256return &sys.pmt_pp;10257}1025810259__builtin_unreachable();10260}1026110262void pmt_counter_add_domain(struct pmt_counter *pcounter, unsigned long *pmmio, unsigned int domain_id)10263{10264/* Make sure the new domain fits. */10265if (domain_id >= pcounter->num_domains)10266pmt_counter_resize(pcounter, domain_id + 1);1026710268assert(pcounter->domains);10269assert(domain_id < pcounter->num_domains);1027010271pcounter->domains[domain_id].pcounter = pmmio;10272}1027310274int pmt_add_counter(unsigned int guid, unsigned int seq, const char *name, enum pmt_datatype type,10275unsigned int lsb, unsigned int msb, unsigned int offset, enum counter_scope scope,10276enum counter_format format, unsigned int domain_id, enum pmt_open_mode mode)10277{10278struct pmt_mmio *mmio;10279struct pmt_counter *pcounter;10280struct pmt_counter **const pmt_root = pmt_get_scope_root(scope);10281bool new_counter = false;10282int conflict = 0;1028310284if (lsb > msb) {10285fprintf(stderr, "%s: %s: `%s` must be satisfied\n", __func__, "lsb <= msb", name);10286exit(1);10287}1028810289if (msb >= 64) {10290fprintf(stderr, "%s: %s: `%s` must be satisfied\n", __func__, "msb < 64", name);10291exit(1);10292}1029310294mmio = pmt_add_guid(guid, seq);10295if (!mmio) {10296if (mode != PMT_OPEN_TRY) {10297fprintf(stderr, "%s: failed to map PMT MMIO for guid %x, seq %u\n", __func__, guid, seq);10298exit(1);10299}1030010301return 1;10302}1030310304if (offset >= mmio->size) {10305if (mode != PMT_OPEN_TRY) {10306fprintf(stderr, "%s: offset %u outside of PMT MMIO size %u\n", __func__, offset, mmio->size);10307exit(1);10308}1030910310return 1;10311}1031210313pcounter = pmt_find_counter(*pmt_root, name);10314if (!pcounter) {10315pcounter = calloc(1, sizeof(*pcounter));10316new_counter = true;10317}1031810319if (new_counter) {10320strncpy(pcounter->name, name, ARRAY_SIZE(pcounter->name) - 1);10321pcounter->type = type;10322pcounter->scope = scope;10323pcounter->lsb = lsb;10324pcounter->msb = msb;10325pcounter->format = format;10326} else {10327conflict += pcounter->type != type;10328conflict += pcounter->scope != scope;10329conflict += pcounter->lsb != lsb;10330conflict += pcounter->msb != msb;10331conflict += pcounter->format != format;10332}1033310334if (conflict) {10335fprintf(stderr, "%s: conflicting parameters for the PMT counter with the same name %s\n", __func__, name);10336exit(1);10337}1033810339pmt_counter_add_domain(pcounter, pmt_get_counter_pointer(mmio, offset), domain_id);1034010341if (new_counter) {10342pcounter->next = *pmt_root;10343*pmt_root = pcounter;10344}1034510346return 0;10347}1034810349void pmt_init(void)10350{10351int cpu_num;10352unsigned long seq, offset, mod_num;1035310354if (BIC_IS_ENABLED(BIC_Diec6)) {10355pmt_add_counter(PMT_MTL_DC6_GUID, PMT_MTL_DC6_SEQ, "Die%c6", PMT_TYPE_XTAL_TIME,10356PMT_COUNTER_MTL_DC6_LSB, PMT_COUNTER_MTL_DC6_MSB, PMT_COUNTER_MTL_DC6_OFFSET, SCOPE_PACKAGE, FORMAT_DELTA, 0, PMT_OPEN_TRY);10357}1035810359if (BIC_IS_ENABLED(BIC_CPU_c1e)) {10360seq = 0;10361offset = PMT_COUNTER_CWF_MC1E_OFFSET_BASE;10362mod_num = 0; /* Relative module number for current PMT file. */1036310364/* Open the counter for each CPU. */10365for (cpu_num = 0; cpu_num < topo.max_cpu_num;) {1036610367if (cpu_is_not_allowed(cpu_num))10368goto next_loop_iter;1036910370/*10371* Set the scope to CPU, even though CWF report the counter per module.10372* CPUs inside the same module will read from the same location, instead of reporting zeros.10373*10374* CWF with newer firmware might require a PMT_TYPE_XTAL_TIME intead of PMT_TYPE_TCORE_CLOCK.10375*/10376pmt_add_counter(PMT_CWF_MC1E_GUID, seq, "CPU%c1e", PMT_TYPE_TCORE_CLOCK,10377PMT_COUNTER_CWF_MC1E_LSB, PMT_COUNTER_CWF_MC1E_MSB, offset, SCOPE_CPU, FORMAT_DELTA, cpu_num, PMT_OPEN_TRY);1037810379/*10380* Rather complex logic for each time we go to the next loop iteration,10381* so keep it as a label.10382*/10383next_loop_iter:10384/*10385* Advance the cpu number and check if we should also advance offset to10386* the next counter inside the PMT file.10387*10388* On Clearwater Forest platform, the counter is reported per module,10389* so open the same counter for all of the CPUs inside the module.10390* That way, reported table show the correct value for all of the CPUs inside the module,10391* instead of zeros.10392*/10393++cpu_num;10394if (cpu_num % PMT_COUNTER_CWF_CPUS_PER_MODULE == 0) {10395offset += PMT_COUNTER_CWF_MC1E_OFFSET_INCREMENT;10396++mod_num;10397}1039810399/*10400* There are PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE in each PMT file.10401*10402* If that number is reached, seq must be incremented to advance to the next file in a sequence.10403* Offset inside that file and a module counter has to be reset.10404*/10405if (mod_num == PMT_COUNTER_CWF_MC1E_NUM_MODULES_PER_FILE) {10406++seq;10407offset = PMT_COUNTER_CWF_MC1E_OFFSET_BASE;10408mod_num = 0;10409}10410}10411}10412}1041310414void turbostat_init()10415{10416setup_all_buffers(true);10417set_master_cpu();10418check_msr_access();10419check_perf_access();10420process_cpuid();10421counter_info_init();10422probe_pm_features();10423msr_perf_init();10424linux_perf_init();10425rapl_perf_init();10426cstate_perf_init();10427perf_llc_init();10428perf_l2_init();10429added_perf_counters_init();10430pmt_init();1043110432for_all_cpus(get_cpu_type, ODD_COUNTERS);10433for_all_cpus(get_cpu_type, EVEN_COUNTERS);1043410435if (BIC_IS_ENABLED(BIC_IPC) && has_aperf_access && get_instr_count_fd(master_cpu) != -1)10436BIC_PRESENT(BIC_IPC);1043710438/*10439* If TSC tweak is needed, but couldn't get it,10440* disable more BICs, since it can't be reported accurately.10441*/10442if (platform->enable_tsc_tweak && !has_base_hz) {10443CLR_BIC(BIC_Busy, &bic_enabled);10444CLR_BIC(BIC_Bzy_MHz, &bic_enabled);10445}10446}1044710448void affinitize_child(void)10449{10450/* Prefer cpu_possible_set, if available */10451if (sched_setaffinity(0, cpu_possible_setsize, cpu_possible_set)) {10452warn("sched_setaffinity cpu_possible_set");1045310454/* Otherwise, allow child to run on same cpu set as turbostat */10455if (sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set))10456warn("sched_setaffinity cpu_allowed_set");10457}10458}1045910460int fork_it(char **argv)10461{10462pid_t child_pid;10463int status;1046410465snapshot_proc_sysfs_files();10466status = for_all_cpus(get_counters, EVEN_COUNTERS);10467first_counter_read = 0;10468if (status)10469exit(status);10470gettimeofday(&tv_even, (struct timezone *)NULL);1047110472child_pid = fork();10473if (!child_pid) {10474/* child */10475affinitize_child();10476execvp(argv[0], argv);10477err(errno, "exec %s", argv[0]);10478} else {1047910480/* parent */10481if (child_pid == -1)10482err(1, "fork");1048310484signal(SIGINT, SIG_IGN);10485signal(SIGQUIT, SIG_IGN);10486if (waitpid(child_pid, &status, 0) == -1)10487err(status, "waitpid");1048810489if (WIFEXITED(status))10490status = WEXITSTATUS(status);10491}10492/*10493* n.b. fork_it() does not check for errors from for_all_cpus()10494* because re-starting is problematic when forking10495*/10496snapshot_proc_sysfs_files();10497for_all_cpus(get_counters, ODD_COUNTERS);10498gettimeofday(&tv_odd, (struct timezone *)NULL);10499timersub(&tv_odd, &tv_even, &tv_delta);10500if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS))10501fprintf(outf, "%s: Counter reset detected\n", progname);10502delta_platform(&platform_counters_odd, &platform_counters_even);1050310504compute_average(EVEN_COUNTERS);10505format_all_counters(EVEN_COUNTERS);1050610507fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec / 1000000.0);1050810509flush_output_stderr();1051010511return status;10512}1051310514int get_and_dump_counters(void)10515{10516int status;1051710518snapshot_proc_sysfs_files();10519status = for_all_cpus(get_counters, ODD_COUNTERS);10520if (status)10521return status;1052210523status = for_all_cpus(dump_counters, ODD_COUNTERS);10524if (status)10525return status;1052610527flush_output_stdout();1052810529return status;10530}1053110532void print_version()10533{10534fprintf(outf, "turbostat version 2026.02.14 - Len Brown <[email protected]>\n");10535}1053610537#define COMMAND_LINE_SIZE 20481053810539void print_bootcmd(void)10540{10541char bootcmd[COMMAND_LINE_SIZE];10542FILE *fp;10543int ret;1054410545memset(bootcmd, 0, COMMAND_LINE_SIZE);10546fp = fopen("/proc/cmdline", "r");10547if (!fp)10548return;1054910550ret = fread(bootcmd, sizeof(char), COMMAND_LINE_SIZE - 1, fp);10551if (ret) {10552bootcmd[ret] = '\0';10553/* the last character is already '\n' */10554fprintf(outf, "Kernel command line: %s", bootcmd);10555}1055610557fclose(fp);10558}1055910560struct msr_counter *find_msrp_by_name(struct msr_counter *head, char *name)10561{10562struct msr_counter *mp;1056310564for (mp = head; mp; mp = mp->next) {10565if (debug)10566fprintf(stderr, "%s: %s %s\n", __func__, name, mp->name);10567if (!strcmp(name, mp->name))10568return mp;10569}10570return NULL;10571}1057210573int add_counter(unsigned int msr_num, char *path, char *name,10574unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format, int flags, int id)10575{10576struct msr_counter *msrp;1057710578if (no_msr && msr_num)10579errx(1, "Requested MSR counter 0x%x, but in --no-msr mode", msr_num);1058010581if (debug)10582fprintf(stderr, "%s(msr%d, %s, %s, width%d, scope%d, type%d, format%d, flags%x, id%d)\n",10583__func__, msr_num, path, name, width, scope, type, format, flags, id);1058410585switch (scope) {1058610587case SCOPE_CPU:10588msrp = find_msrp_by_name(sys.tp, name);10589if (msrp) {10590if (debug)10591fprintf(stderr, "%s: %s FOUND\n", __func__, name);10592break;10593}10594if (sys.added_thread_counters++ >= MAX_ADDED_THREAD_COUNTERS) {10595warnx("ignoring thread counter %s", name);10596return -1;10597}10598break;10599case SCOPE_CORE:10600msrp = find_msrp_by_name(sys.cp, name);10601if (msrp) {10602if (debug)10603fprintf(stderr, "%s: %s FOUND\n", __func__, name);10604break;10605}10606if (sys.added_core_counters++ >= MAX_ADDED_CORE_COUNTERS) {10607warnx("ignoring core counter %s", name);10608return -1;10609}10610break;10611case SCOPE_PACKAGE:10612msrp = find_msrp_by_name(sys.pp, name);10613if (msrp) {10614if (debug)10615fprintf(stderr, "%s: %s FOUND\n", __func__, name);10616break;10617}10618if (sys.added_package_counters++ >= MAX_ADDED_PACKAGE_COUNTERS) {10619warnx("ignoring package counter %s", name);10620return -1;10621}10622break;10623default:10624warnx("ignoring counter %s with unknown scope", name);10625return -1;10626}1062710628if (msrp == NULL) {10629msrp = calloc(1, sizeof(struct msr_counter));10630if (msrp == NULL)10631err(-1, "calloc msr_counter");1063210633msrp->msr_num = msr_num;10634strncpy(msrp->name, name, NAME_BYTES - 1);10635msrp->width = width;10636msrp->type = type;10637msrp->format = format;10638msrp->flags = flags;1063910640switch (scope) {10641case SCOPE_CPU:10642msrp->next = sys.tp;10643sys.tp = msrp;10644break;10645case SCOPE_CORE:10646msrp->next = sys.cp;10647sys.cp = msrp;10648break;10649case SCOPE_PACKAGE:10650msrp->next = sys.pp;10651sys.pp = msrp;10652break;10653}10654}1065510656if (path) {10657struct sysfs_path *sp;1065810659sp = calloc(1, sizeof(struct sysfs_path));10660if (sp == NULL) {10661perror("calloc");10662exit(1);10663}10664strncpy(sp->path, path, PATH_BYTES - 1);10665sp->id = id;10666sp->next = msrp->sp;10667msrp->sp = sp;10668}1066910670return 0;10671}1067210673/*10674* Initialize the fields used for identifying and opening the counter.10675*10676* Defer the initialization of any runtime buffers for actually reading10677* the counters for when we initialize all perf counters, so we can later10678* easily call re_initialize().10679*/10680struct perf_counter_info *make_perf_counter_info(const char *perf_device,10681const char *perf_event,10682const char *name,10683unsigned int width, enum counter_scope scope, enum counter_type type, enum counter_format format)10684{10685struct perf_counter_info *pinfo;1068610687pinfo = calloc(1, sizeof(*pinfo));10688if (!pinfo)10689errx(1, "%s: Failed to allocate %s/%s\n", __func__, perf_device, perf_event);1069010691strncpy(pinfo->device, perf_device, ARRAY_SIZE(pinfo->device) - 1);10692strncpy(pinfo->event, perf_event, ARRAY_SIZE(pinfo->event) - 1);1069310694strncpy(pinfo->name, name, ARRAY_SIZE(pinfo->name) - 1);10695pinfo->width = width;10696pinfo->scope = scope;10697pinfo->type = type;10698pinfo->format = format;1069910700return pinfo;10701}1070210703int add_perf_counter(const char *perf_device, const char *perf_event, const char *name_buffer, unsigned int width,10704enum counter_scope scope, enum counter_type type, enum counter_format format)10705{10706struct perf_counter_info *pinfo;1070710708switch (scope) {10709case SCOPE_CPU:10710if (sys.added_thread_perf_counters >= MAX_ADDED_THREAD_COUNTERS) {10711warnx("ignoring thread counter perf/%s/%s", perf_device, perf_event);10712return -1;10713}10714break;1071510716case SCOPE_CORE:10717if (sys.added_core_perf_counters >= MAX_ADDED_CORE_COUNTERS) {10718warnx("ignoring core counter perf/%s/%s", perf_device, perf_event);10719return -1;10720}10721break;1072210723case SCOPE_PACKAGE:10724if (sys.added_package_perf_counters >= MAX_ADDED_PACKAGE_COUNTERS) {10725warnx("ignoring package counter perf/%s/%s", perf_device, perf_event);10726return -1;10727}10728break;10729}1073010731pinfo = make_perf_counter_info(perf_device, perf_event, name_buffer, width, scope, type, format);1073210733if (!pinfo)10734return -1;1073510736switch (scope) {10737case SCOPE_CPU:10738pinfo->next = sys.perf_tp;10739sys.perf_tp = pinfo;10740++sys.added_thread_perf_counters;10741break;1074210743case SCOPE_CORE:10744pinfo->next = sys.perf_cp;10745sys.perf_cp = pinfo;10746++sys.added_core_perf_counters;10747break;1074810749case SCOPE_PACKAGE:10750pinfo->next = sys.perf_pp;10751sys.perf_pp = pinfo;10752++sys.added_package_perf_counters;10753break;10754}1075510756// FIXME: we might not have debug here yet10757if (debug)10758fprintf(stderr, "%s: %s/%s, name: %s, scope%d\n", __func__, pinfo->device, pinfo->event, pinfo->name, pinfo->scope);1075910760return 0;10761}1076210763void parse_add_command_msr(char *add_command)10764{10765int msr_num = 0;10766char *path = NULL;10767char perf_device[PERF_DEV_NAME_BYTES] = "";10768char perf_event[PERF_EVT_NAME_BYTES] = "";10769char name_buffer[PERF_NAME_BYTES] = "";10770int width = 64;10771int fail = 0;10772enum counter_scope scope = SCOPE_CPU;10773enum counter_type type = COUNTER_CYCLES;10774enum counter_format format = FORMAT_DELTA;1077510776while (add_command) {1077710778if (sscanf(add_command, "msr0x%x", &msr_num) == 1)10779goto next;1078010781if (sscanf(add_command, "msr%d", &msr_num) == 1)10782goto next;1078310784BUILD_BUG_ON(ARRAY_SIZE(perf_device) <= 31);10785BUILD_BUG_ON(ARRAY_SIZE(perf_event) <= 31);10786if (sscanf(add_command, "perf/%31[^/]/%31[^,]", &perf_device[0], &perf_event[0]) == 2)10787goto next;1078810789if (*add_command == '/') {10790path = add_command;10791goto next;10792}1079310794if (sscanf(add_command, "u%d", &width) == 1) {10795if ((width == 32) || (width == 64))10796goto next;10797width = 64;10798}10799if (!strncmp(add_command, "cpu", strlen("cpu"))) {10800scope = SCOPE_CPU;10801goto next;10802}10803if (!strncmp(add_command, "core", strlen("core"))) {10804scope = SCOPE_CORE;10805goto next;10806}10807if (!strncmp(add_command, "package", strlen("package"))) {10808scope = SCOPE_PACKAGE;10809goto next;10810}10811if (!strncmp(add_command, "cycles", strlen("cycles"))) {10812type = COUNTER_CYCLES;10813goto next;10814}10815if (!strncmp(add_command, "seconds", strlen("seconds"))) {10816type = COUNTER_SECONDS;10817goto next;10818}10819if (!strncmp(add_command, "usec", strlen("usec"))) {10820type = COUNTER_USEC;10821goto next;10822}10823if (!strncmp(add_command, "raw", strlen("raw"))) {10824format = FORMAT_RAW;10825goto next;10826}10827if (!strncmp(add_command, "average", strlen("average"))) {10828format = FORMAT_AVERAGE;10829goto next;10830}10831if (!strncmp(add_command, "delta", strlen("delta"))) {10832format = FORMAT_DELTA;10833goto next;10834}10835if (!strncmp(add_command, "percent", strlen("percent"))) {10836format = FORMAT_PERCENT;10837goto next;10838}1083910840BUILD_BUG_ON(ARRAY_SIZE(name_buffer) <= 18);10841if (sscanf(add_command, "%18s,%*s", name_buffer) == 1) {10842char *eos;1084310844eos = strchr(name_buffer, ',');10845if (eos)10846*eos = '\0';10847goto next;10848}1084910850next:10851add_command = strchr(add_command, ',');10852if (add_command) {10853*add_command = '\0';10854add_command++;10855}1085610857}10858if ((msr_num == 0) && (path == NULL) && (perf_device[0] == '\0' || perf_event[0] == '\0')) {10859fprintf(stderr, "--add: (msrDDD | msr0xXXX | /path_to_counter | perf/device/event) required\n");10860fail++;10861}1086210863/* Test for non-empty perf_device and perf_event */10864const bool is_perf_counter = perf_device[0] && perf_event[0];1086510866/* generate default column header */10867if (*name_buffer == '\0') {10868if (is_perf_counter) {10869snprintf(name_buffer, ARRAY_SIZE(name_buffer), "perf/%s", perf_event);10870} else {10871if (width == 32)10872sprintf(name_buffer, "M0x%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");10873else10874sprintf(name_buffer, "M0X%x%s", msr_num, format == FORMAT_PERCENT ? "%" : "");10875}10876}1087710878if (is_perf_counter) {10879if (add_perf_counter(perf_device, perf_event, name_buffer, width, scope, type, format))10880fail++;10881} else {10882if (add_counter(msr_num, path, name_buffer, width, scope, type, format, 0, 0))10883fail++;10884}1088510886if (fail) {10887help();10888exit(1);10889}10890}1089110892bool starts_with(const char *str, const char *prefix)10893{10894return strncmp(prefix, str, strlen(prefix)) == 0;10895}1089610897int pmt_parse_from_path(const char *target_path, unsigned int *out_guid, unsigned int *out_seq)10898{10899struct pmt_diriter_t pmt_iter;10900const struct dirent *dirname;10901struct stat stat, target_stat;10902int fd_telem_dir = -1;10903int fd_target_dir;10904unsigned int seq = 0;10905unsigned long guid, target_guid;10906int ret = -1;1090710908fd_target_dir = open(target_path, O_RDONLY | O_DIRECTORY);10909if (fd_target_dir == -1) {10910return -1;10911}1091210913if (fstat(fd_target_dir, &target_stat) == -1) {10914fprintf(stderr, "%s: Failed to stat the target: %s", __func__, strerror(errno));10915exit(1);10916}1091710918if (parse_telem_info_file(fd_target_dir, "guid", "%lx", &target_guid)) {10919fprintf(stderr, "%s: Failed to parse the target guid file: %s", __func__, strerror(errno));10920exit(1);10921}1092210923close(fd_target_dir);1092410925pmt_diriter_init(&pmt_iter);1092610927for (dirname = pmt_diriter_begin(&pmt_iter, SYSFS_TELEM_PATH); dirname != NULL; dirname = pmt_diriter_next(&pmt_iter)) {1092810929fd_telem_dir = openat(dirfd(pmt_iter.dir), dirname->d_name, O_RDONLY | O_DIRECTORY);10930if (fd_telem_dir == -1)10931continue;1093210933if (parse_telem_info_file(fd_telem_dir, "guid", "%lx", &guid)) {10934fprintf(stderr, "%s: Failed to parse the guid file: %s", __func__, strerror(errno));10935continue;10936}1093710938if (fstat(fd_telem_dir, &stat) == -1) {10939fprintf(stderr, "%s: Failed to stat %s directory: %s", __func__, dirname->d_name, strerror(errno));10940continue;10941}1094210943/*10944* If reached the same directory as target, exit the loop.10945* Seq has the correct value now.10946*/10947if (stat.st_dev == target_stat.st_dev && stat.st_ino == target_stat.st_ino) {10948ret = 0;10949break;10950}1095110952/*10953* If reached directory with the same guid,10954* but it's not the target directory yet,10955* increment seq and continue the search.10956*/10957if (guid == target_guid)10958++seq;1095910960close(fd_telem_dir);10961fd_telem_dir = -1;10962}1096310964pmt_diriter_remove(&pmt_iter);1096510966if (fd_telem_dir != -1)10967close(fd_telem_dir);1096810969if (!ret) {10970*out_guid = target_guid;10971*out_seq = seq;10972}1097310974return ret;10975}1097610977void parse_add_command_pmt(char *add_command)10978{10979char *name = NULL;10980char *type_name = NULL;10981char *format_name = NULL;10982char *direct_path = NULL;10983static const char direct_path_prefix[] = "path=";10984unsigned int offset;10985unsigned int lsb;10986unsigned int msb;10987unsigned int guid;10988unsigned int seq = 0; /* By default, pick first file in a sequence with a given GUID. */10989unsigned int domain_id;10990enum counter_scope scope = 0;10991enum pmt_datatype type = PMT_TYPE_RAW;10992enum counter_format format = FORMAT_RAW;10993bool has_offset = false;10994bool has_lsb = false;10995bool has_msb = false;10996bool has_format = true; /* Format has a default value. */10997bool has_guid = false;10998bool has_scope = false;10999bool has_type = true; /* Type has a default value. */1100011001/* Consume the "pmt," prefix. */11002add_command = strchr(add_command, ',');11003if (!add_command) {11004help();11005exit(1);11006}11007++add_command;1100811009while (add_command) {11010if (starts_with(add_command, "name=")) {11011name = add_command + strlen("name=");11012goto next;11013}1101411015if (starts_with(add_command, "type=")) {11016type_name = add_command + strlen("type=");11017goto next;11018}1101911020if (starts_with(add_command, "domain=")) {11021const size_t prefix_len = strlen("domain=");1102211023if (sscanf(add_command + prefix_len, "cpu%u", &domain_id) == 1) {11024scope = SCOPE_CPU;11025has_scope = true;11026} else if (sscanf(add_command + prefix_len, "core%u", &domain_id) == 1) {11027scope = SCOPE_CORE;11028has_scope = true;11029} else if (sscanf(add_command + prefix_len, "package%u", &domain_id) == 1) {11030scope = SCOPE_PACKAGE;11031has_scope = true;11032}1103311034if (!has_scope) {11035printf("%s: invalid value for scope. Expected cpu%%u, core%%u or package%%u.\n", __func__);11036exit(1);11037}1103811039goto next;11040}1104111042if (starts_with(add_command, "format=")) {11043format_name = add_command + strlen("format=");11044goto next;11045}1104611047if (sscanf(add_command, "offset=%u", &offset) == 1) {11048has_offset = true;11049goto next;11050}1105111052if (sscanf(add_command, "lsb=%u", &lsb) == 1) {11053has_lsb = true;11054goto next;11055}1105611057if (sscanf(add_command, "msb=%u", &msb) == 1) {11058has_msb = true;11059goto next;11060}1106111062if (sscanf(add_command, "guid=%x", &guid) == 1) {11063has_guid = true;11064goto next;11065}1106611067if (sscanf(add_command, "seq=%x", &seq) == 1)11068goto next;1106911070if (strncmp(add_command, direct_path_prefix, strlen(direct_path_prefix)) == 0) {11071direct_path = add_command + strlen(direct_path_prefix);11072goto next;11073}11074next:11075add_command = strchr(add_command, ',');11076if (add_command) {11077*add_command = '\0';11078add_command++;11079}11080}1108111082if (!name) {11083printf("%s: missing %s\n", __func__, "name");11084exit(1);11085}1108611087if (strlen(name) >= PMT_COUNTER_NAME_SIZE_BYTES) {11088printf("%s: name has to be at most %d characters long\n", __func__, PMT_COUNTER_NAME_SIZE_BYTES);11089exit(1);11090}1109111092if (format_name) {11093has_format = false;1109411095if (strcmp("raw", format_name) == 0) {11096format = FORMAT_RAW;11097has_format = true;11098}1109911100if (strcmp("average", format_name) == 0) {11101format = FORMAT_AVERAGE;11102has_format = true;11103}1110411105if (strcmp("delta", format_name) == 0) {11106format = FORMAT_DELTA;11107has_format = true;11108}1110911110if (!has_format) {11111fprintf(stderr, "%s: Invalid format %s. Expected raw, average or delta\n", __func__, format_name);11112exit(1);11113}11114}1111511116if (type_name) {11117has_type = false;1111811119if (strcmp("raw", type_name) == 0) {11120type = PMT_TYPE_RAW;11121has_type = true;11122}1112311124if (strcmp("txtal_time", type_name) == 0) {11125type = PMT_TYPE_XTAL_TIME;11126has_type = true;11127}1112811129if (strcmp("tcore_clock", type_name) == 0) {11130type = PMT_TYPE_TCORE_CLOCK;11131has_type = true;11132}1113311134if (!has_type) {11135printf("%s: invalid %s: %s\n", __func__, "type", type_name);11136exit(1);11137}11138}1113911140if (!has_offset) {11141printf("%s : missing %s\n", __func__, "offset");11142exit(1);11143}1114411145if (!has_lsb) {11146printf("%s: missing %s\n", __func__, "lsb");11147exit(1);11148}1114911150if (!has_msb) {11151printf("%s: missing %s\n", __func__, "msb");11152exit(1);11153}1115411155if (direct_path && has_guid) {11156printf("%s: path and guid+seq parameters are mutually exclusive\nnotice: passed guid=0x%x and path=%s\n", __func__, guid, direct_path);11157exit(1);11158}1115911160if (direct_path) {11161if (pmt_parse_from_path(direct_path, &guid, &seq)) {11162printf("%s: failed to parse PMT file from %s\n", __func__, direct_path);11163exit(1);11164}1116511166/* GUID was just infered from the direct path. */11167has_guid = true;11168}1116911170if (!has_guid) {11171printf("%s: missing %s\n", __func__, "guid or path");11172exit(1);11173}1117411175if (!has_scope) {11176printf("%s: missing %s\n", __func__, "scope");11177exit(1);11178}1117911180if (lsb > msb) {11181printf("%s: lsb > msb doesn't make sense\n", __func__);11182exit(1);11183}1118411185pmt_add_counter(guid, seq, name, type, lsb, msb, offset, scope, format, domain_id, PMT_OPEN_REQUIRED);11186}1118711188void parse_add_command(char *add_command)11189{11190if (strncmp(add_command, "pmt", strlen("pmt")) == 0)11191return parse_add_command_pmt(add_command);11192return parse_add_command_msr(add_command);11193}1119411195int is_deferred_add(char *name)11196{11197int i;1119811199for (i = 0; i < deferred_add_index; ++i)11200if (!strcmp(name, deferred_add_names[i])) {11201deferred_add_consumed |= (1 << i);11202return 1;11203}11204return 0;11205}1120611207int is_deferred_skip(char *name)11208{11209int i;1121011211for (i = 0; i < deferred_skip_index; ++i)11212if (!strcmp(name, deferred_skip_names[i])) {11213deferred_skip_consumed |= (1 << i);11214return 1;11215}11216return 0;11217}1121811219void verify_deferred_consumed(void)11220{11221int i;11222int fail = 0;1122311224for (i = 0; i < deferred_add_index; ++i) {11225if (!(deferred_add_consumed & (1 << i))) {11226warnx("Counter '%s' can not be added.", deferred_add_names[i]);11227fail++;11228}11229}11230for (i = 0; i < deferred_skip_index; ++i) {11231if (!(deferred_skip_consumed & (1 << i))) {11232warnx("Counter '%s' can not be skipped.", deferred_skip_names[i]);11233fail++;11234}11235}11236if (fail)11237exit(-EINVAL);11238}1123911240void probe_cpuidle_residency(void)11241{11242char path[64];11243char name_buf[16];11244FILE *input;11245int state;11246int min_state = 1024, max_state = 0;11247char *sp;1124811249for (state = 10; state >= 0; --state) {1125011251sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", master_cpu, state);11252input = fopen(path, "r");11253if (input == NULL)11254continue;11255if (!fgets(name_buf, sizeof(name_buf), input))11256err(1, "%s: failed to read file", path);1125711258/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */11259sp = strchr(name_buf, '-');11260if (!sp)11261sp = strchrnul(name_buf, '\n');11262*sp = '%';11263*(sp + 1) = '\0';1126411265remove_underbar(name_buf);1126611267fclose(input);1126811269sprintf(path, "cpuidle/state%d/time", state);1127011271if (!DO_BIC(BIC_pct_idle) && !is_deferred_add(name_buf))11272continue;1127311274if (is_deferred_skip(name_buf))11275continue;1127611277add_counter(0, path, name_buf, 32, SCOPE_CPU, COUNTER_USEC, FORMAT_PERCENT, SYSFS_PERCPU, 0);1127811279if (state > max_state)11280max_state = state;11281if (state < min_state)11282min_state = state;11283}11284}1128511286void probe_cpuidle_counts(void)11287{11288char path[64];11289char name_buf[16];11290FILE *input;11291int state;11292int min_state = 1024, max_state = 0;11293char *sp;1129411295if (!DO_BIC(BIC_cpuidle))11296return;1129711298for (state = 10; state >= 0; --state) {1129911300sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", master_cpu, state);11301input = fopen(path, "r");11302if (input == NULL)11303continue;11304if (!fgets(name_buf, sizeof(name_buf), input))11305err(1, "%s: failed to read file", path);11306fclose(input);1130711308remove_underbar(name_buf);1130911310if (!DO_BIC(BIC_cpuidle) && !is_deferred_add(name_buf))11311continue;1131211313if (is_deferred_skip(name_buf))11314continue;1131511316/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */11317sp = strchr(name_buf, '-');11318if (!sp)11319sp = strchrnul(name_buf, '\n');1132011321/*11322* The 'below' sysfs file always contains 0 for the deepest state (largest index),11323* do not add it.11324*/11325if (state != max_state) {11326/*11327* Add 'C1+' for C1, and so on. The 'below' sysfs file always contains 0 for11328* the last state, so do not add it.11329*/1133011331*sp = '+';11332*(sp + 1) = '\0';11333sprintf(path, "cpuidle/state%d/below", state);11334add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);11335}1133611337*sp = '\0';11338sprintf(path, "cpuidle/state%d/usage", state);11339add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);1134011341/*11342* The 'above' sysfs file always contains 0 for the shallowest state (smallest11343* index), do not add it.11344*/11345if (state != min_state) {11346*sp = '-';11347*(sp + 1) = '\0';11348sprintf(path, "cpuidle/state%d/above", state);11349add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);11350}11351}11352}1135311354/*11355* parse cpuset with following syntax11356* 1,2,4..6,8-10 and set bits in cpu_subset11357*/11358void parse_cpu_command(char *optarg)11359{11360if (!strcmp(optarg, "core")) {11361if (cpu_subset)11362goto error;11363show_core_only++;11364return;11365}11366if (!strcmp(optarg, "package")) {11367if (cpu_subset)11368goto error;11369show_pkg_only++;11370return;11371}11372if (show_core_only || show_pkg_only)11373goto error;1137411375cpu_subset = CPU_ALLOC(CPU_SUBSET_MAXCPUS);11376if (cpu_subset == NULL)11377err(3, "CPU_ALLOC");11378cpu_subset_size = CPU_ALLOC_SIZE(CPU_SUBSET_MAXCPUS);1137911380CPU_ZERO_S(cpu_subset_size, cpu_subset);1138111382if (parse_cpu_str(optarg, cpu_subset, cpu_subset_size))11383goto error;1138411385return;1138611387error:11388fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);11389help();11390exit(-1);11391}1139211393void cmdline(int argc, char **argv)11394{11395int opt;11396int option_index = 0;11397static struct option long_options[] = {11398{ "add", required_argument, 0, 'a' },11399{ "cpu", required_argument, 0, 'c' },11400{ "Dump", no_argument, 0, 'D' },11401{ "debug", no_argument, 0, 'd' }, /* internal, not documented */11402{ "enable", required_argument, 0, 'e' },11403{ "force", no_argument, 0, 'f' },11404{ "interval", required_argument, 0, 'i' },11405{ "IPC", no_argument, 0, 'I' },11406{ "num_iterations", required_argument, 0, 'n' },11407{ "header_iterations", required_argument, 0, 'N' },11408{ "help", no_argument, 0, 'h' },11409{ "hide", required_argument, 0, 'H' }, // meh, -h taken by --help11410{ "Joules", no_argument, 0, 'J' },11411{ "list", no_argument, 0, 'l' },11412{ "out", required_argument, 0, 'o' },11413{ "quiet", no_argument, 0, 'q' },11414{ "no-msr", no_argument, 0, 'M' },11415{ "no-perf", no_argument, 0, 'P' },11416{ "show", required_argument, 0, 's' },11417{ "Summary", no_argument, 0, 'S' },11418{ "TCC", required_argument, 0, 'T' },11419{ "version", no_argument, 0, 'v' },11420{ 0, 0, 0, 0 }11421};1142211423progname = argv[0];1142411425/*11426* Parse some options early, because they may make other options invalid,11427* like adding the MSR counter with --add and at the same time using --no-msr.11428*/11429while ((opt = getopt_long_only(argc, argv, "+:MP", long_options, &option_index)) != -1) {11430switch (opt) {11431case 'M':11432no_msr = 1;11433break;11434case 'P':11435no_perf = 1;11436break;11437default:11438break;11439}11440}11441optind = 0;1144211443while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:N:o:qMST:v", long_options, &option_index)) != -1) {11444switch (opt) {11445case 'a':11446parse_add_command(optarg);11447break;11448case 'c':11449parse_cpu_command(optarg);11450break;11451case 'D':11452dump_only++;11453/*11454* Force the no_perf early to prevent using it as a source.11455* User asks for raw values, but perf returns them relative11456* to the opening of the file descriptor.11457*/11458no_perf = 1;11459break;11460case 'e':11461/* --enable specified counter, without clearning existing list */11462bic_lookup(&bic_enabled, optarg, SHOW_LIST);11463break;11464case 'f':11465force_load++;11466break;11467case 'd':11468debug++;11469bic_set_all(&bic_enabled);11470break;11471case 'H':11472/*11473* --hide: do not show those specified11474* multiple invocations simply clear more bits in enabled mask11475*/11476{11477cpu_set_t bic_group_hide;1147811479BIC_INIT(&bic_group_hide);1148011481bic_lookup(&bic_group_hide, optarg, HIDE_LIST);11482bic_clear_bits(&bic_enabled, &bic_group_hide);11483}11484break;11485case 'h':11486help();11487exit(1);11488case 'i':11489{11490double interval = strtod(optarg, NULL);1149111492if (interval < 0.001) {11493fprintf(outf, "interval %f seconds is too small\n", interval);11494exit(2);11495}1149611497interval_tv.tv_sec = interval_ts.tv_sec = interval;11498interval_tv.tv_usec = (interval - interval_tv.tv_sec) * 1000000;11499interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000;11500}11501break;11502case 'J':11503rapl_joules++;11504break;11505case 'l':11506bic_set_all(&bic_enabled);11507list_header_only++;11508quiet++;11509break;11510case 'o':11511outf = fopen_or_die(optarg, "w");11512break;11513case 'q':11514quiet = 1;11515break;11516case 'M':11517case 'P':11518/* Parsed earlier */11519break;11520case 'n':11521num_iterations = strtoul(optarg, NULL, 0);11522errno = 0;1152311524if (errno || num_iterations == 0)11525errx(-1, "invalid iteration count: %s", optarg);11526break;11527case 'N':11528header_iterations = strtoul(optarg, NULL, 0);11529errno = 0;1153011531if (errno || header_iterations == 0)11532errx(-1, "invalid header iteration count: %s", optarg);11533break;11534case 's':11535/*11536* --show: show only those specified11537* The 1st invocation will clear and replace the enabled mask11538* subsequent invocations can add to it.11539*/11540if (shown == 0)11541BIC_INIT(&bic_enabled);11542bic_lookup(&bic_enabled, optarg, SHOW_LIST);11543shown = 1;11544break;11545case 'S':11546summary_only++;11547break;11548case 'T':11549tj_max_override = atoi(optarg);11550break;11551case 'v':11552print_version();11553exit(0);11554break;11555default:11556help();11557exit(1);11558}11559}11560}1156111562void set_rlimit(void)11563{11564struct rlimit limit;1156511566if (getrlimit(RLIMIT_NOFILE, &limit) < 0)11567err(1, "Failed to get rlimit");1156811569if (limit.rlim_max < MAX_NOFILE)11570limit.rlim_max = MAX_NOFILE;11571if (limit.rlim_cur < MAX_NOFILE)11572limit.rlim_cur = MAX_NOFILE;1157311574if (setrlimit(RLIMIT_NOFILE, &limit) < 0)11575err(1, "Failed to set rlimit");11576}1157711578int main(int argc, char **argv)11579{11580int fd, ret;1158111582bic_groups_init();1158311584fd = open("/sys/fs/cgroup/cgroup.procs", O_WRONLY);11585if (fd < 0)11586goto skip_cgroup_setting;1158711588ret = write(fd, "0\n", 2);11589if (ret == -1)11590perror("Can't update cgroup\n");1159111592close(fd);1159311594skip_cgroup_setting:11595outf = stderr;11596cmdline(argc, argv);1159711598if (!quiet) {11599print_version();11600print_bootcmd();11601}1160211603probe_cpuidle_residency();11604probe_cpuidle_counts();1160511606verify_deferred_consumed();1160711608if (!getuid())11609set_rlimit();1161011611turbostat_init();1161211613if (!no_msr)11614msr_sum_record();1161511616/* dump counters and exit */11617if (dump_only)11618return get_and_dump_counters();1161911620/* list header and exit */11621if (list_header_only) {11622print_header(",");11623flush_output_stdout();11624return 0;11625}1162611627/*11628* if any params left, it must be a command to fork11629*/11630if (argc - optind)11631return fork_it(argv + optind);11632else11633turbostat_loop();1163411635return 0;11636}116371163811639