Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'turbostat-2024.11.30' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux

Pull turbostat updates from Len Brown:

- assorted minor bug fixes

- assorted platform specific tweaks

- initial RAPL PSYS (SysWatt) support

* tag 'turbostat-2024.11.30' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux:
tools/power turbostat: 2024.11.30
tools/power turbostat: Add RAPL psys as a built-in counter
tools/power turbostat: Fix child's argument forwarding
tools/power turbostat: Force --no-perf in --dump mode
tools/power turbostat: Add support for /sys/class/drm/card1
tools/power turbostat: Cache graphics sysfs file descriptors during probe
tools/power turbostat: Consolidate graphics sysfs access
tools/power turbostat: Remove unnecessary fflush() call
tools/power turbostat: Enhance platform divergence description
tools/power turbostat: Add initial support for GraniteRapids-D
tools/power turbostat: Remove PC3 support on Lunarlake
tools/power turbostat: Rename arl_features to lnl_features
tools/power turbostat: Add back PC8 support on Arrowlake
tools/power turbostat: Remove PC7/PC9 support on MTL
tools/power turbostat: Honor --show CPU, even when even when num_cpus=1
tools/power turbostat: Fix trailing '\n' parsing
tools/power turbostat: Allow using cpu device in perf counters on hybrid platforms
tools/power turbostat: Fix column printing for PMT xtal_time counters
tools/power turbostat: fix GCC9 build regression

+330 -132
+27
tools/power/x86/turbostat/turbostat.8
··· 33 33 msr0xXXX is a hex offset, eg. msr0x10 34 34 /sys/path... is an absolute path to a sysfs attribute 35 35 <device> is a perf device from /sys/bus/event_source/devices/<device> eg. cstate_core 36 + On Intel hybrid platforms, instead of one "cpu" perf device there are two, "cpu_core" and "cpu_atom" devices for P and E cores respectively. 37 + Turbostat, in this case, allow user to use "cpu" device and will automatically detect the type of a CPU and translate it to "cpu_core" and "cpu_atom" accordingly. 38 + For a complete example see "ADD PERF COUNTER EXAMPLE #2 (using virtual "cpu" device)". 36 39 <event> is a perf event for given device from /sys/bus/event_source/devices/<device>/events/<event> eg. c1-residency 37 40 perf/cstate_core/c1-residency would then use /sys/bus/event_source/devices/cstate_core/events/c1-residency 38 41 ··· 189 186 \fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors. 190 187 .PP 191 188 \fBRAMWatt\fP Watts consumed by the DRAM DIMMS -- available only on server processors. 189 + .PP 190 + \fBSysWatt\fP Watts consumed by the whole platform (RAPL PSYS). Disabled by default. Enable with --enable SysWatt. 192 191 .PP 193 192 \fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package. Note that the system summary is the sum of the package throttling time, and thus may be higher than 100% on a multi-package system. Note that the meaning of this field is model specific. For example, some hardware increments this counter when RAPL responds to thermal limits, but does not increment this counter when RAPL responds to power limits. Comparing PkgWatt and PkgTmp to system limits is necessary. 194 193 .PP ··· 389 384 1 45.94 45.94 390 385 2 23.83 23.83 391 386 3 23.84 23.84 387 + 388 + .fi 389 + 390 + .SH ADD PERF COUNTER EXAMPLE #2 (using virtual cpu device) 391 + Here we run on hybrid, Raptor Lake platform. 392 + We limit turbostat to show output for just cpu0 (pcore) and cpu12 (ecore). 393 + We add a counter showing number of L3 cache misses, using virtual "cpu" device, 394 + labeling it with the column header, "VCMISS". 395 + We add a counter showing number of L3 cache misses, using virtual "cpu_core" device, 396 + labeling it with the column header, "PCMISS". This will fail on ecore cpu12. 397 + We add a counter showing number of L3 cache misses, using virtual "cpu_atom" device, 398 + labeling it with the column header, "ECMISS". This will fail on pcore cpu0. 399 + We display it only once, after the conclusion of 0.1 second sleep. 400 + .nf 401 + sudo ./turbostat --quiet --cpu 0,12 --show CPU --add perf/cpu/cache-misses,cpu,delta,raw,VCMISS --add perf/cpu_core/cache-misses,cpu,delta,raw,PCMISS --add perf/cpu_atom/cache-misses,cpu,delta,raw,ECMISS sleep .1 402 + turbostat: added_perf_counters_init_: perf/cpu_atom/cache-misses: failed to open counter on cpu0 403 + turbostat: added_perf_counters_init_: perf/cpu_core/cache-misses: failed to open counter on cpu12 404 + 0.104630 sec 405 + CPU ECMISS PCMISS VCMISS 406 + - 0x0000000000000000 0x0000000000000000 0x0000000000000000 407 + 0 0x0000000000000000 0x0000000000007951 0x0000000000007796 408 + 12 0x000000000001137a 0x0000000000000000 0x0000000000011392 392 409 393 410 .fi 394 411
+303 -132
tools/power/x86/turbostat/turbostat.c
··· 31 31 ) 32 32 // end copied section 33 33 34 + #define CPUID_LEAF_MODEL_ID 0x1A 35 + #define CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT 24 36 + 34 37 #define X86_VENDOR_INTEL 0 35 38 36 39 #include INTEL_FAMILY_HEADER ··· 91 88 #define COUNTER_KIND_PERF_PREFIX_LEN strlen(COUNTER_KIND_PERF_PREFIX) 92 89 #define PERF_DEV_NAME_BYTES 32 93 90 #define PERF_EVT_NAME_BYTES 32 91 + 92 + #define INTEL_ECORE_TYPE 0x20 93 + #define INTEL_PCORE_TYPE 0x40 94 94 95 95 enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; 96 96 enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M }; ··· 200 194 { 0x0, "SAMMHz", NULL, 0, 0, 0, NULL, 0 }, 201 195 { 0x0, "SAMAMHz", NULL, 0, 0, 0, NULL, 0 }, 202 196 { 0x0, "Die%c6", NULL, 0, 0, 0, NULL, 0 }, 197 + { 0x0, "SysWatt", NULL, 0, 0, 0, NULL, 0 }, 198 + { 0x0, "Sys_J", NULL, 0, 0, 0, NULL, 0 }, 203 199 }; 204 200 205 201 #define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter)) ··· 264 256 #define BIC_SAMMHz (1ULL << 56) 265 257 #define BIC_SAMACTMHz (1ULL << 57) 266 258 #define BIC_Diec6 (1ULL << 58) 259 + #define BIC_SysWatt (1ULL << 59) 260 + #define BIC_Sys_J (1ULL << 60) 267 261 268 262 #define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die ) 269 263 #define BIC_THERMAL_PWR ( BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__) ··· 273 263 #define BIC_IDLE (BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6) 274 264 #define BIC_OTHER ( BIC_IRQ | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC) 275 265 276 - #define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC) 266 + #define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC | BIC_SysWatt | BIC_Sys_J) 277 267 278 268 unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT); 279 269 unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC; ··· 380 370 }; 381 371 382 372 struct gfx_sysfs_info { 383 - const char *path; 384 373 FILE *fp; 385 374 unsigned int val; 386 375 unsigned long long val_ull; ··· 511 502 RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */ 512 503 RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */ 513 504 RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */ 505 + RAPL_PLATFORM_ENERGY_LIMIT = BIT(17), /* 0x64c MSR_PLATFORM_ENERGY_LIMIT */ 506 + RAPL_PLATFORM_ENERGY_STATUS = BIT(18), /* 0x64d MSR_PLATFORM_ENERGY_STATUS */ 514 507 }; 515 508 516 509 #define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT) 517 510 #define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT) 518 511 #define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT) 519 512 #define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS) 513 + #define RAPL_PSYS (RAPL_PLATFORM_ENERGY_STATUS | RAPL_PLATFORM_ENERGY_LIMIT) 520 514 521 515 #define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO) 522 516 #define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO) ··· 720 708 .has_ext_cst_msrs = 1, 721 709 .trl_msrs = TRL_BASE, 722 710 .tcc_offset_bits = 6, 723 - .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, 711 + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS, 724 712 .enable_tsc_tweak = 1, 725 713 }; 726 714 ··· 737 725 .has_ext_cst_msrs = 1, 738 726 .trl_msrs = TRL_BASE, 739 727 .tcc_offset_bits = 6, 740 - .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, 728 + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS, 741 729 .enable_tsc_tweak = 1, 742 730 }; 743 731 732 + /* Copied from cnl_features, with PC7/PC9 removed */ 744 733 static const struct platform_features adl_features = { 745 - .has_msr_misc_feature_control = 1, 746 - .has_msr_misc_pwr_mgmt = 1, 747 - .has_nhm_msrs = 1, 748 - .has_config_tdp = 1, 749 - .bclk_freq = BCLK_100MHZ, 750 - .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10, 751 - .cst_limit = CST_LIMIT_HSW, 752 - .has_irtl_msrs = 1, 753 - .has_msr_core_c1_res = 1, 754 - .has_ext_cst_msrs = 1, 755 - .trl_msrs = TRL_BASE, 756 - .tcc_offset_bits = 6, 757 - .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, 758 - .enable_tsc_tweak = 1, 734 + .has_msr_misc_feature_control = cnl_features.has_msr_misc_feature_control, 735 + .has_msr_misc_pwr_mgmt = cnl_features.has_msr_misc_pwr_mgmt, 736 + .has_nhm_msrs = cnl_features.has_nhm_msrs, 737 + .has_config_tdp = cnl_features.has_config_tdp, 738 + .bclk_freq = cnl_features.bclk_freq, 739 + .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10, 740 + .cst_limit = cnl_features.cst_limit, 741 + .has_irtl_msrs = cnl_features.has_irtl_msrs, 742 + .has_msr_core_c1_res = cnl_features.has_msr_core_c1_res, 743 + .has_ext_cst_msrs = cnl_features.has_ext_cst_msrs, 744 + .trl_msrs = cnl_features.trl_msrs, 745 + .tcc_offset_bits = cnl_features.tcc_offset_bits, 746 + .rapl_msrs = cnl_features.rapl_msrs, 747 + .enable_tsc_tweak = cnl_features.enable_tsc_tweak, 759 748 }; 760 749 761 - static const struct platform_features arl_features = { 762 - .has_msr_misc_feature_control = 1, 763 - .has_msr_misc_pwr_mgmt = 1, 764 - .has_nhm_msrs = 1, 765 - .has_config_tdp = 1, 766 - .bclk_freq = BCLK_100MHZ, 767 - .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC10, 768 - .cst_limit = CST_LIMIT_HSW, 769 - .has_irtl_msrs = 1, 770 - .has_msr_core_c1_res = 1, 771 - .has_ext_cst_msrs = 1, 772 - .trl_msrs = TRL_BASE, 773 - .tcc_offset_bits = 6, 774 - .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, 775 - .enable_tsc_tweak = 1, 750 + /* Copied from adl_features, with PC3/PC8 removed */ 751 + static const struct platform_features lnl_features = { 752 + .has_msr_misc_feature_control = adl_features.has_msr_misc_feature_control, 753 + .has_msr_misc_pwr_mgmt = adl_features.has_msr_misc_pwr_mgmt, 754 + .has_nhm_msrs = adl_features.has_nhm_msrs, 755 + .has_config_tdp = adl_features.has_config_tdp, 756 + .bclk_freq = adl_features.bclk_freq, 757 + .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC6 | PC10, 758 + .cst_limit = adl_features.cst_limit, 759 + .has_irtl_msrs = adl_features.has_irtl_msrs, 760 + .has_msr_core_c1_res = adl_features.has_msr_core_c1_res, 761 + .has_ext_cst_msrs = adl_features.has_ext_cst_msrs, 762 + .trl_msrs = adl_features.trl_msrs, 763 + .tcc_offset_bits = adl_features.tcc_offset_bits, 764 + .rapl_msrs = adl_features.rapl_msrs, 765 + .enable_tsc_tweak = adl_features.enable_tsc_tweak, 776 766 }; 777 767 778 768 static const struct platform_features skx_features = { ··· 804 790 .has_irtl_msrs = 1, 805 791 .has_cst_prewake_bit = 1, 806 792 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 807 - .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 793 + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 808 794 .has_fixed_rapl_unit = 1, 809 795 }; 810 796 ··· 820 806 .has_irtl_msrs = 1, 821 807 .has_cst_prewake_bit = 1, 822 808 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 823 - .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 809 + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 824 810 }; 825 811 826 812 static const struct platform_features srf_features = { ··· 836 822 .has_irtl_msrs = 1, 837 823 .has_cst_prewake_bit = 1, 838 824 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 839 - .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 825 + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 840 826 }; 841 827 842 828 static const struct platform_features grr_features = { ··· 852 838 .has_irtl_msrs = 1, 853 839 .has_cst_prewake_bit = 1, 854 840 .trl_msrs = TRL_BASE | TRL_CORECOUNT, 855 - .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, 841 + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS, 856 842 }; 857 843 858 844 static const struct platform_features slv_features = { ··· 1011 997 { INTEL_SAPPHIRERAPIDS_X, &spr_features }, 1012 998 { INTEL_EMERALDRAPIDS_X, &spr_features }, 1013 999 { INTEL_GRANITERAPIDS_X, &spr_features }, 1000 + { INTEL_GRANITERAPIDS_D, &spr_features }, 1014 1001 { INTEL_LAKEFIELD, &cnl_features }, 1015 1002 { INTEL_ALDERLAKE, &adl_features }, 1016 1003 { INTEL_ALDERLAKE_L, &adl_features }, 1017 1004 { INTEL_RAPTORLAKE, &adl_features }, 1018 1005 { INTEL_RAPTORLAKE_P, &adl_features }, 1019 1006 { INTEL_RAPTORLAKE_S, &adl_features }, 1020 - { INTEL_METEORLAKE, &cnl_features }, 1021 - { INTEL_METEORLAKE_L, &cnl_features }, 1022 - { INTEL_ARROWLAKE_H, &arl_features }, 1023 - { INTEL_ARROWLAKE_U, &arl_features }, 1024 - { INTEL_ARROWLAKE, &arl_features }, 1025 - { INTEL_LUNARLAKE_M, &arl_features }, 1007 + { INTEL_METEORLAKE, &adl_features }, 1008 + { INTEL_METEORLAKE_L, &adl_features }, 1009 + { INTEL_ARROWLAKE_H, &adl_features }, 1010 + { INTEL_ARROWLAKE_U, &adl_features }, 1011 + { INTEL_ARROWLAKE, &adl_features }, 1012 + { INTEL_LUNARLAKE_M, &lnl_features }, 1026 1013 { INTEL_ATOM_SILVERMONT, &slv_features }, 1027 1014 { INTEL_ATOM_SILVERMONT_D, &slvd_features }, 1028 1015 { INTEL_ATOM_AIRMONT, &amt_features }, ··· 1115 1100 RAPL_RCI_INDEX_PKG_PERF_STATUS = 4, 1116 1101 RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5, 1117 1102 RAPL_RCI_INDEX_CORE_ENERGY = 6, 1103 + RAPL_RCI_INDEX_ENERGY_PLATFORM = 7, 1118 1104 NUM_RAPL_COUNTERS, 1119 1105 }; 1120 1106 ··· 1142 1126 struct rapl_counter_info_t *rapl_counter_info_perdomain; 1143 1127 unsigned int rapl_counter_info_perdomain_size; 1144 1128 1129 + #define RAPL_COUNTER_FLAG_PLATFORM_COUNTER (1u << 0) 1145 1130 #define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1) 1146 1131 1147 1132 struct rapl_counter_arch_info { ··· 1263 1246 .bic = BIC_CorWatt | BIC_Cor_J, 1264 1247 .compat_scale = 1.0, 1265 1248 .flags = 0, 1249 + }, 1250 + { 1251 + .feature_mask = RAPL_PSYS, 1252 + .perf_subsys = "power", 1253 + .perf_name = "energy-psys", 1254 + .msr = MSR_PLATFORM_ENERGY_STATUS, 1255 + .msr_mask = 0x00000000FFFFFFFF, 1256 + .msr_shift = 0, 1257 + .platform_rapl_msr_scale = &rapl_energy_units, 1258 + .rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM, 1259 + .bic = BIC_SysWatt | BIC_Sys_J, 1260 + .compat_scale = 1.0, 1261 + .flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM, 1266 1262 }, 1267 1263 }; 1268 1264 ··· 1704 1674 IDX_PP1_ENERGY, 1705 1675 IDX_PKG_PERF, 1706 1676 IDX_DRAM_PERF, 1677 + IDX_PSYS_ENERGY, 1707 1678 IDX_COUNT, 1708 1679 }; 1709 1680 ··· 1749 1718 case IDX_DRAM_PERF: 1750 1719 offset = MSR_DRAM_PERF_STATUS; 1751 1720 break; 1721 + case IDX_PSYS_ENERGY: 1722 + offset = MSR_PLATFORM_ENERGY_STATUS; 1723 + break; 1752 1724 default: 1753 1725 offset = -1; 1754 1726 } ··· 1782 1748 case MSR_DRAM_PERF_STATUS: 1783 1749 idx = IDX_DRAM_PERF; 1784 1750 break; 1751 + case MSR_PLATFORM_ENERGY_STATUS: 1752 + idx = IDX_PSYS_ENERGY; 1753 + break; 1785 1754 default: 1786 1755 idx = -1; 1787 1756 } ··· 1806 1769 return platform->rapl_msrs & RAPL_PKG_PERF_STATUS; 1807 1770 case IDX_DRAM_PERF: 1808 1771 return platform->rapl_msrs & RAPL_DRAM_PERF_STATUS; 1772 + case IDX_PSYS_ENERGY: 1773 + return platform->rapl_msrs & RAPL_PSYS; 1809 1774 default: 1810 1775 return 0; 1811 1776 } ··· 1879 1840 struct pkg_data packages; 1880 1841 } average; 1881 1842 1843 + struct platform_counters { 1844 + struct rapl_counter energy_psys; /* MSR_PLATFORM_ENERGY_STATUS */ 1845 + } platform_counters_odd, platform_counters_even; 1846 + 1882 1847 struct cpu_topology { 1883 1848 int physical_package_id; 1884 1849 int die_id; ··· 1891 1848 int logical_node_id; /* 0-based count within the package */ 1892 1849 int physical_core_id; 1893 1850 int thread_id; 1851 + int type; 1894 1852 cpu_set_t *put_ids; /* Processing Unit/Thread IDs */ 1895 1853 } *cpus; 1896 1854 ··· 2335 2291 break; 2336 2292 2337 2293 case PMT_TYPE_XTAL_TIME: 2338 - outp += sprintf(outp, "%s%s", delim, ppmt->name); 2294 + outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), ppmt->name); 2339 2295 break; 2340 2296 } 2341 2297 ··· 2409 2365 break; 2410 2366 2411 2367 case PMT_TYPE_XTAL_TIME: 2412 - outp += sprintf(outp, "%s%s", delim, ppmt->name); 2368 + outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), ppmt->name); 2413 2369 break; 2414 2370 } 2415 2371 ··· 2540 2496 break; 2541 2497 2542 2498 case PMT_TYPE_XTAL_TIME: 2543 - outp += sprintf(outp, "%s%s", delim, ppmt->name); 2499 + outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), ppmt->name); 2544 2500 break; 2545 2501 } 2546 2502 2547 2503 ppmt = ppmt->next; 2548 2504 } 2505 + 2506 + if (DO_BIC(BIC_SysWatt)) 2507 + outp += sprintf(outp, "%sSysWatt", (printed++ ? delim : "")); 2508 + if (DO_BIC(BIC_Sys_J)) 2509 + outp += sprintf(outp, "%sSys_J", (printed++ ? delim : "")); 2549 2510 2550 2511 outp += sprintf(outp, "\n"); 2551 2512 } ··· 2559 2510 { 2560 2511 int i; 2561 2512 struct msr_counter *mp; 2513 + struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even; 2562 2514 2563 2515 outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p); 2564 2516 ··· 2631 2581 outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores.raw_value); 2632 2582 outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx.raw_value); 2633 2583 outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram.raw_value); 2584 + outp += sprintf(outp, "Joules PSYS: %0llX\n", pplat_cnt->energy_psys.raw_value); 2634 2585 outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status.raw_value); 2635 2586 outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status.raw_value); 2636 2587 outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); ··· 2670 2619 */ 2671 2620 int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) 2672 2621 { 2622 + static int count; 2623 + 2624 + struct platform_counters *pplat_cnt = NULL; 2673 2625 double interval_float, tsc; 2674 2626 char *fmt8; 2675 2627 int i; ··· 2681 2627 struct pmt_counter *ppmt; 2682 2628 char *delim = "\t"; 2683 2629 int printed = 0; 2630 + 2631 + if (t == &average.threads) { 2632 + pplat_cnt = count & 1 ? &platform_counters_odd : &platform_counters_even; 2633 + ++count; 2634 + } 2684 2635 2685 2636 /* if showing only 1st thread in core and this isn't one, bail out */ 2686 2637 if (show_core_only && !is_cpu_first_thread_in_core(t, c, p)) ··· 2847 2788 } 2848 2789 2849 2790 for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) { 2791 + const unsigned long value_raw = t->pmt_counter[i]; 2792 + const double value_converted = 100.0 * value_raw / crystal_hz / interval_float; 2850 2793 switch (ppmt->type) { 2851 2794 case PMT_TYPE_RAW: 2852 2795 if (pmt_counter_get_width(ppmt) <= 32) ··· 2860 2799 break; 2861 2800 2862 2801 case PMT_TYPE_XTAL_TIME: 2863 - const unsigned long value_raw = t->pmt_counter[i]; 2864 - const double value_converted = 100.0 * value_raw / crystal_hz / interval_float; 2865 - 2866 2802 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 2867 2803 break; 2868 2804 } ··· 2927 2869 } 2928 2870 2929 2871 for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) { 2872 + const unsigned long value_raw = c->pmt_counter[i]; 2873 + const double value_converted = 100.0 * value_raw / crystal_hz / interval_float; 2930 2874 switch (ppmt->type) { 2931 2875 case PMT_TYPE_RAW: 2932 2876 if (pmt_counter_get_width(ppmt) <= 32) ··· 2940 2880 break; 2941 2881 2942 2882 case PMT_TYPE_XTAL_TIME: 2943 - const unsigned long value_raw = c->pmt_counter[i]; 2944 - const double value_converted = 100.0 * value_raw / crystal_hz / interval_float; 2945 - 2946 2883 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 2947 2884 break; 2948 2885 } ··· 3125 3068 } 3126 3069 3127 3070 for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) { 3071 + const unsigned long value_raw = p->pmt_counter[i]; 3072 + const double value_converted = 100.0 * value_raw / crystal_hz / interval_float; 3128 3073 switch (ppmt->type) { 3129 3074 case PMT_TYPE_RAW: 3130 3075 if (pmt_counter_get_width(ppmt) <= 32) ··· 3138 3079 break; 3139 3080 3140 3081 case PMT_TYPE_XTAL_TIME: 3141 - const unsigned long value_raw = p->pmt_counter[i]; 3142 - const double value_converted = 100.0 * value_raw / crystal_hz / interval_float; 3143 - 3144 3082 outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted); 3145 3083 break; 3146 3084 } 3147 3085 } 3086 + 3087 + if (DO_BIC(BIC_SysWatt) && (t == &average.threads)) 3088 + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 3089 + rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_WATTS, interval_float)); 3090 + if (DO_BIC(BIC_Sys_J) && (t == &average.threads)) 3091 + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 3092 + rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_JOULES, interval_float)); 3148 3093 3149 3094 done: 3150 3095 if (*(outp - 1) != '\n') ··· 3455 3392 retval = delta_package(p, p2); 3456 3393 3457 3394 return retval; 3395 + } 3396 + 3397 + void delta_platform(struct platform_counters *new, struct platform_counters *old) 3398 + { 3399 + old->energy_psys.raw_value = new->energy_psys.raw_value - old->energy_psys.raw_value; 3458 3400 } 3459 3401 3460 3402 void rapl_counter_clear(struct rapl_counter *c) ··· 4191 4123 4192 4124 void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx) 4193 4125 { 4126 + if (rci->source[idx] == COUNTER_SOURCE_NONE) 4127 + return; 4128 + 4194 4129 rc->raw_value = rci->data[idx]; 4195 4130 rc->unit = rci->unit[idx]; 4196 4131 rc->scale = rci->scale[idx]; ··· 4201 4130 4202 4131 int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p) 4203 4132 { 4133 + struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even; 4204 4134 unsigned long long perf_data[NUM_RAPL_COUNTERS + 1]; 4205 4135 struct rapl_counter_info_t *rci; 4206 4136 ··· 4229 4157 for (unsigned int i = 0, pi = 1; i < NUM_RAPL_COUNTERS; ++i) { 4230 4158 switch (rci->source[i]) { 4231 4159 case COUNTER_SOURCE_NONE: 4160 + rci->data[i] = 0; 4232 4161 break; 4233 4162 4234 4163 case COUNTER_SOURCE_PERF: ··· 4268 4195 } 4269 4196 } 4270 4197 4271 - BUILD_BUG_ON(NUM_RAPL_COUNTERS != 7); 4198 + BUILD_BUG_ON(NUM_RAPL_COUNTERS != 8); 4272 4199 write_rapl_counter(&p->energy_pkg, rci, RAPL_RCI_INDEX_ENERGY_PKG); 4273 4200 write_rapl_counter(&p->energy_cores, rci, RAPL_RCI_INDEX_ENERGY_CORES); 4274 4201 write_rapl_counter(&p->energy_dram, rci, RAPL_RCI_INDEX_DRAM); ··· 4276 4203 write_rapl_counter(&p->rapl_pkg_perf_status, rci, RAPL_RCI_INDEX_PKG_PERF_STATUS); 4277 4204 write_rapl_counter(&p->rapl_dram_perf_status, rci, RAPL_RCI_INDEX_DRAM_PERF_STATUS); 4278 4205 write_rapl_counter(&c->core_energy, rci, RAPL_RCI_INDEX_CORE_ENERGY); 4206 + write_rapl_counter(&pplat_cnt->energy_psys, rci, RAPL_RCI_INDEX_ENERGY_PLATFORM); 4279 4207 4280 4208 return 0; 4281 4209 } ··· 5459 5385 if (*next == '-') /* no negative cpu numbers */ 5460 5386 return 1; 5461 5387 5388 + if (*next == '\0' || *next == '\n') 5389 + break; 5390 + 5462 5391 start = strtoul(next, &next, 10); 5463 5392 5464 5393 if (start >= CPU_SUBSET_MAXCPUS) ··· 5733 5656 return 0; 5734 5657 } 5735 5658 5659 + int set_my_cpu_type(void) 5660 + { 5661 + unsigned int eax, ebx, ecx, edx; 5662 + unsigned int max_level; 5663 + 5664 + __cpuid(0, max_level, ebx, ecx, edx); 5665 + 5666 + if (max_level < CPUID_LEAF_MODEL_ID) 5667 + return 0; 5668 + 5669 + __cpuid(CPUID_LEAF_MODEL_ID, eax, ebx, ecx, edx); 5670 + 5671 + return (eax >> CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT); 5672 + } 5673 + 5674 + int set_cpu_hybrid_type(int cpu) 5675 + { 5676 + if (cpu_migrate(cpu)) 5677 + return -1; 5678 + 5679 + int type = set_my_cpu_type(); 5680 + 5681 + cpus[cpu].type = type; 5682 + return 0; 5683 + } 5684 + 5736 5685 /* 5737 5686 * snapshot_proc_interrupts() 5738 5687 * ··· 5831 5728 */ 5832 5729 int snapshot_graphics(int idx) 5833 5730 { 5834 - FILE *fp; 5835 5731 int retval; 5732 + 5733 + rewind(gfx_info[idx].fp); 5836 5734 5837 5735 switch (idx) { 5838 5736 case GFX_rc6: 5839 5737 case SAM_mc6: 5840 - fp = fopen_or_die(gfx_info[idx].path, "r"); 5841 - retval = fscanf(fp, "%lld", &gfx_info[idx].val_ull); 5738 + retval = fscanf(gfx_info[idx].fp, "%lld", &gfx_info[idx].val_ull); 5842 5739 if (retval != 1) 5843 5740 err(1, "rc6"); 5844 - fclose(fp); 5845 5741 return 0; 5846 5742 case GFX_MHz: 5847 5743 case GFX_ACTMHz: 5848 5744 case SAM_MHz: 5849 5745 case SAM_ACTMHz: 5850 - if (gfx_info[idx].fp == NULL) { 5851 - gfx_info[idx].fp = fopen_or_die(gfx_info[idx].path, "r"); 5852 - } else { 5853 - rewind(gfx_info[idx].fp); 5854 - fflush(gfx_info[idx].fp); 5855 - } 5856 5746 retval = fscanf(gfx_info[idx].fp, "%d", &gfx_info[idx].val); 5857 5747 if (retval != 1) 5858 5748 err(1, "MHz"); ··· 6212 6116 re_initialize(); 6213 6117 goto restart; 6214 6118 } 6119 + delta_platform(&platform_counters_odd, &platform_counters_even); 6215 6120 compute_average(EVEN_COUNTERS); 6216 6121 format_all_counters(EVEN_COUNTERS); 6217 6122 flush_output_stdout(); ··· 6236 6139 re_initialize(); 6237 6140 goto restart; 6238 6141 } 6142 + delta_platform(&platform_counters_even, &platform_counters_odd); 6239 6143 compute_average(ODD_COUNTERS); 6240 6144 format_all_counters(ODD_COUNTERS); 6241 6145 flush_output_stdout(); ··· 6540 6442 probe_intel_uncore_frequency_legacy(); 6541 6443 } 6542 6444 6445 + static void set_graphics_fp(char *path, int idx) 6446 + { 6447 + if (!access(path, R_OK)) 6448 + gfx_info[idx].fp = fopen_or_die(path, "r"); 6449 + } 6450 + 6451 + /* Enlarge this if there are /sys/class/drm/card2 ... */ 6452 + #define GFX_MAX_CARDS 2 6453 + 6543 6454 static void probe_graphics(void) 6544 6455 { 6456 + char path[PATH_MAX]; 6457 + int i; 6458 + 6545 6459 /* Xe graphics sysfs knobs */ 6546 6460 if (!access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) { 6547 6461 FILE *fp; 6548 6462 char buf[8]; 6549 6463 bool gt0_is_gt; 6550 - int idx; 6551 6464 6552 6465 fp = fopen("/sys/class/drm/card0/device/tile0/gt0/gtidle/name", "r"); 6553 6466 if (!fp) ··· 6577 6468 else 6578 6469 goto next; 6579 6470 6580 - idx = gt0_is_gt ? GFX_rc6 : SAM_mc6; 6581 - gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms"; 6471 + set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", gt0_is_gt ? GFX_rc6 : SAM_mc6); 6582 6472 6583 - idx = gt0_is_gt ? GFX_MHz : SAM_MHz; 6584 - if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", R_OK)) 6585 - gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq"; 6473 + set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", gt0_is_gt ? GFX_MHz : SAM_MHz); 6586 6474 6587 - idx = gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz; 6588 - if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", R_OK)) 6589 - gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq"; 6475 + set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz); 6590 6476 6591 - idx = gt0_is_gt ? SAM_mc6 : GFX_rc6; 6592 - if (!access("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", R_OK)) 6593 - gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms"; 6477 + set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", gt0_is_gt ? SAM_mc6 : GFX_rc6); 6594 6478 6595 - idx = gt0_is_gt ? SAM_MHz : GFX_MHz; 6596 - if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", R_OK)) 6597 - gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq"; 6479 + set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", gt0_is_gt ? SAM_MHz : GFX_MHz); 6598 6480 6599 - idx = gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz; 6600 - if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", R_OK)) 6601 - gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq"; 6481 + set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz); 6602 6482 6603 6483 goto end; 6604 6484 } 6605 6485 6606 6486 next: 6607 6487 /* New i915 graphics sysfs knobs */ 6608 - if (!access("/sys/class/drm/card0/gt/gt0/rc6_residency_ms", R_OK)) { 6609 - gfx_info[GFX_rc6].path = "/sys/class/drm/card0/gt/gt0/rc6_residency_ms"; 6610 - 6611 - if (!access("/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz", R_OK)) 6612 - gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz"; 6613 - 6614 - if (!access("/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz", R_OK)) 6615 - gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz"; 6616 - 6617 - if (!access("/sys/class/drm/card0/gt/gt1/rc6_residency_ms", R_OK)) 6618 - gfx_info[SAM_mc6].path = "/sys/class/drm/card0/gt/gt1/rc6_residency_ms"; 6619 - 6620 - if (!access("/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz", R_OK)) 6621 - gfx_info[SAM_MHz].path = "/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz"; 6622 - 6623 - if (!access("/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz", R_OK)) 6624 - gfx_info[SAM_ACTMHz].path = "/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz"; 6625 - 6626 - goto end; 6488 + for (i = 0; i < GFX_MAX_CARDS; i++) { 6489 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i); 6490 + if (!access(path, R_OK)) 6491 + break; 6627 6492 } 6628 6493 6494 + if (i == GFX_MAX_CARDS) 6495 + goto legacy_i915; 6496 + 6497 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i); 6498 + set_graphics_fp(path, GFX_rc6); 6499 + 6500 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_cur_freq_mhz", i); 6501 + set_graphics_fp(path, GFX_MHz); 6502 + 6503 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_act_freq_mhz", i); 6504 + set_graphics_fp(path, GFX_ACTMHz); 6505 + 6506 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rc6_residency_ms", i); 6507 + set_graphics_fp(path, SAM_mc6); 6508 + 6509 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_cur_freq_mhz", i); 6510 + set_graphics_fp(path, SAM_MHz); 6511 + 6512 + snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_act_freq_mhz", i); 6513 + set_graphics_fp(path, SAM_ACTMHz); 6514 + 6515 + goto end; 6516 + 6517 + legacy_i915: 6629 6518 /* Fall back to traditional i915 graphics sysfs knobs */ 6630 - if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) 6631 - gfx_info[GFX_rc6].path = "/sys/class/drm/card0/power/rc6_residency_ms"; 6519 + set_graphics_fp("/sys/class/drm/card0/power/rc6_residency_ms", GFX_rc6); 6632 6520 6633 - if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK)) 6634 - gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt_cur_freq_mhz"; 6635 - else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) 6636 - gfx_info[GFX_MHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz"; 6521 + set_graphics_fp("/sys/class/drm/card0/gt_cur_freq_mhz", GFX_MHz); 6522 + if (!gfx_info[GFX_MHz].fp) 6523 + set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", GFX_MHz); 6637 6524 6638 - if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK)) 6639 - gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt_act_freq_mhz"; 6640 - else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) 6641 - gfx_info[GFX_ACTMHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz"; 6525 + set_graphics_fp("/sys/class/drm/card0/gt_act_freq_mhz", GFX_ACTMHz); 6526 + if (!gfx_info[GFX_ACTMHz].fp) 6527 + set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", GFX_ACTMHz); 6642 6528 6643 6529 end: 6644 - if (gfx_info[GFX_rc6].path) 6530 + if (gfx_info[GFX_rc6].fp) 6645 6531 BIC_PRESENT(BIC_GFX_rc6); 6646 - if (gfx_info[GFX_MHz].path) 6532 + if (gfx_info[GFX_MHz].fp) 6647 6533 BIC_PRESENT(BIC_GFXMHz); 6648 - if (gfx_info[GFX_ACTMHz].path) 6534 + if (gfx_info[GFX_ACTMHz].fp) 6649 6535 BIC_PRESENT(BIC_GFXACTMHz); 6650 - if (gfx_info[SAM_mc6].path) 6536 + if (gfx_info[SAM_mc6].fp) 6651 6537 BIC_PRESENT(BIC_SAM_mc6); 6652 - if (gfx_info[SAM_MHz].path) 6538 + if (gfx_info[SAM_MHz].fp) 6653 6539 BIC_PRESENT(BIC_SAMMHz); 6654 - if (gfx_info[SAM_ACTMHz].path) 6540 + if (gfx_info[SAM_ACTMHz].fp) 6655 6541 BIC_PRESENT(BIC_SAMACTMHz); 6656 6542 } 6657 6543 ··· 7015 6911 unsigned long long msr; 7016 6912 unsigned int time_unit; 7017 6913 double tdp; 7018 - const unsigned long long bic_watt_bits = BIC_PkgWatt | BIC_CorWatt | BIC_RAMWatt | BIC_GFXWatt; 7019 - const unsigned long long bic_joules_bits = BIC_Pkg_J | BIC_Cor_J | BIC_RAM_J | BIC_GFX_J; 6914 + const unsigned long long bic_watt_bits = BIC_SysWatt | BIC_PkgWatt | BIC_CorWatt | BIC_RAMWatt | BIC_GFXWatt; 6915 + const unsigned long long bic_joules_bits = BIC_Sys_J | BIC_Pkg_J | BIC_Cor_J | BIC_RAM_J | BIC_GFX_J; 7020 6916 7021 6917 if (rapl_joules) 7022 6918 bic_enabled &= ~bic_watt_bits; ··· 7676 7572 7677 7573 domain_visited[next_domain] = 1; 7678 7574 7575 + if ((cai->flags & RAPL_COUNTER_FLAG_PLATFORM_COUNTER) && (cpu != base_cpu)) 7576 + continue; 7577 + 7679 7578 struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain]; 7680 7579 7681 7580 /* Check if the counter is enabled and accessible */ ··· 8303 8196 set_max_cpu_num(); 8304 8197 topo.num_cpus = 0; 8305 8198 for_all_proc_cpus(count_cpus); 8306 - if (!summary_only && topo.num_cpus > 1) 8199 + if (!summary_only) 8307 8200 BIC_PRESENT(BIC_CPU); 8308 8201 8309 8202 if (debug > 1) ··· 8391 8284 8392 8285 for_all_proc_cpus(init_thread_id); 8393 8286 8287 + for_all_proc_cpus(set_cpu_hybrid_type); 8288 + 8394 8289 /* 8395 8290 * For online cpus 8396 8291 * find max_core_id, max_package_id ··· 8441 8332 topo.cores_per_node = max_core_id + 1; 8442 8333 if (debug > 1) 8443 8334 fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node); 8444 - if (!summary_only && topo.cores_per_node > 1) 8335 + if (!summary_only) 8445 8336 BIC_PRESENT(BIC_Core); 8446 8337 8447 8338 topo.num_die = topo.max_die_id + 1; ··· 8657 8548 bic_enabled &= ~BIC_IPC; 8658 8549 } 8659 8550 8551 + bool perf_has_hybrid_devices(void) 8552 + { 8553 + /* 8554 + * 0: unknown 8555 + * 1: has separate perf device for p and e core 8556 + * -1: doesn't have separate perf device for p and e core 8557 + */ 8558 + static int cached; 8559 + 8560 + if (cached > 0) 8561 + return true; 8562 + 8563 + if (cached < 0) 8564 + return false; 8565 + 8566 + if (access("/sys/bus/event_source/devices/cpu_core", F_OK)) { 8567 + cached = -1; 8568 + return false; 8569 + } 8570 + 8571 + if (access("/sys/bus/event_source/devices/cpu_atom", F_OK)) { 8572 + cached = -1; 8573 + return false; 8574 + } 8575 + 8576 + cached = 1; 8577 + return true; 8578 + } 8579 + 8660 8580 int added_perf_counters_init_(struct perf_counter_info *pinfo) 8661 8581 { 8662 8582 size_t num_domains = 0; ··· 8742 8604 if (domain_visited[next_domain]) 8743 8605 continue; 8744 8606 8745 - perf_type = read_perf_type(pinfo->device); 8607 + /* 8608 + * Intel hybrid platforms expose different perf devices for P and E cores. 8609 + * Instead of one, "/sys/bus/event_source/devices/cpu" device, there are 8610 + * "/sys/bus/event_source/devices/{cpu_core,cpu_atom}". 8611 + * 8612 + * This makes it more complicated to the user, because most of the counters 8613 + * are available on both and have to be handled manually, otherwise. 8614 + * 8615 + * Code below, allow user to use the old "cpu" name, which is translated accordingly. 8616 + */ 8617 + const char *perf_device = pinfo->device; 8618 + 8619 + if (strcmp(perf_device, "cpu") == 0 && perf_has_hybrid_devices()) { 8620 + switch (cpus[cpu].type) { 8621 + case INTEL_PCORE_TYPE: 8622 + perf_device = "cpu_core"; 8623 + break; 8624 + 8625 + case INTEL_ECORE_TYPE: 8626 + perf_device = "cpu_atom"; 8627 + break; 8628 + 8629 + default: /* Don't change, we will probably fail and report a problem soon. */ 8630 + break; 8631 + } 8632 + } 8633 + 8634 + perf_type = read_perf_type(perf_device); 8746 8635 if (perf_type == (unsigned int)-1) { 8747 8636 warnx("%s: perf/%s/%s: failed to read %s", 8748 - __func__, pinfo->device, pinfo->event, "type"); 8637 + __func__, perf_device, pinfo->event, "type"); 8749 8638 continue; 8750 8639 } 8751 8640 8752 - perf_config = read_perf_config(pinfo->device, pinfo->event); 8641 + perf_config = read_perf_config(perf_device, pinfo->event); 8753 8642 if (perf_config == (unsigned int)-1) { 8754 8643 warnx("%s: perf/%s/%s: failed to read %s", 8755 - __func__, pinfo->device, pinfo->event, "config"); 8644 + __func__, perf_device, pinfo->event, "config"); 8756 8645 continue; 8757 8646 } 8758 8647 8759 8648 /* Scale is not required, some counters just don't have it. */ 8760 - perf_scale = read_perf_scale(pinfo->device, pinfo->event); 8649 + perf_scale = read_perf_scale(perf_device, pinfo->event); 8761 8650 if (perf_scale == 0.0) 8762 8651 perf_scale = 1.0; 8763 8652 8764 8653 fd_perf = open_perf_counter(cpu, perf_type, perf_config, -1, 0); 8765 8654 if (fd_perf == -1) { 8766 8655 warnx("%s: perf/%s/%s: failed to open counter on cpu%d", 8767 - __func__, pinfo->device, pinfo->event, cpu); 8656 + __func__, perf_device, pinfo->event, cpu); 8768 8657 continue; 8769 8658 } 8770 8659 ··· 8801 8636 8802 8637 if (debug) 8803 8638 fprintf(stderr, "Add perf/%s/%s cpu%d: %d\n", 8804 - pinfo->device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]); 8639 + perf_device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]); 8805 8640 } 8806 8641 8807 8642 pinfo = pinfo->next; ··· 9236 9071 9237 9072 void print_version() 9238 9073 { 9239 - fprintf(outf, "turbostat version 2024.07.26 - Len Brown <lenb@kernel.org>\n"); 9074 + fprintf(outf, "turbostat version 2024.11.30 - Len Brown <lenb@kernel.org>\n"); 9240 9075 } 9241 9076 9242 9077 #define COMMAND_LINE_SIZE 2048 ··· 9946 9781 * Parse some options early, because they may make other options invalid, 9947 9782 * like adding the MSR counter with --add and at the same time using --no-msr. 9948 9783 */ 9949 - while ((opt = getopt_long_only(argc, argv, "MPn:", long_options, &option_index)) != -1) { 9784 + while ((opt = getopt_long_only(argc, argv, "+MPn:", long_options, &option_index)) != -1) { 9950 9785 switch (opt) { 9951 9786 case 'M': 9952 9787 no_msr = 1; ··· 9970 9805 break; 9971 9806 case 'D': 9972 9807 dump_only++; 9808 + /* 9809 + * Force the no_perf early to prevent using it as a source. 9810 + * User asks for raw values, but perf returns them relative 9811 + * to the opening of the file descriptor. 9812 + */ 9813 + no_perf = 1; 9973 9814 break; 9974 9815 case 'e': 9975 9816 /* --enable specified counter */