1 2 /* SPDX-License-Identifier: GPL-2.0 */ 3 /* THIS FILE WAS AUTOGENERATED BY jevents.py arch=none model=none ! */ 4 5 #include <pmu-events/pmu-events.h> 6 #include "util/header.h" 7 #include "util/pmu.h" 8 #include <string.h> 9 #include <stddef.h> 10 11 struct compact_pmu_event { 12 int offset; 13 }; 14 15 struct pmu_table_entry { 16 const struct compact_pmu_event *entries; 17 uint32_t num_entries; 18 struct compact_pmu_event pmu_name; 19 }; 20 21 static const char *const big_c_string = 22 /* offset=0 */ "tool\000" 23 /* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" 24 /* offset=81 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" 25 /* offset=151 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" 26 /* offset=219 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" 27 /* offset=295 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" 28 /* offset=440 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" 29 /* offset=543 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" 30 /* offset=660 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" 31 /* offset=736 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" 32 /* offset=822 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" 33 /* offset=932 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" 34 /* offset=1039 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" 35 /* offset=1138 */ "default_core\000" 36 /* offset=1151 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" 37 /* offset=1213 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" 38 /* offset=1275 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" 39 /* offset=1373 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" 40 /* offset=1475 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" 41 /* offset=1608 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" 42 /* offset=1726 */ "hisi_sccl,ddrc\000" 43 /* offset=1741 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000DDRC write commands\000" 44 /* offset=1830 */ "uncore_cbox\000" 45 /* offset=1842 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000" 46 /* offset=2076 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000UNC_CBO_HYPHEN\000" 47 /* offset=2144 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000UNC_CBO_TWO_HYPH\000" 48 /* offset=2218 */ "hisi_sccl,l3c\000" 49 /* offset=2232 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000Total read hits\000" 50 /* offset=2315 */ "uncore_imc_free_running\000" 51 /* offset=2339 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000Total cache misses\000" 52 /* offset=2437 */ "uncore_imc\000" 53 /* offset=2448 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000Total cache hits\000" 54 /* offset=2529 */ "uncore_sys_ddr_pmu\000" 55 /* offset=2548 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" 56 /* offset=2624 */ "uncore_sys_ccn_pmu\000" 57 /* offset=2643 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" 58 /* offset=2720 */ "uncore_sys_cmn_pmu\000" 59 /* offset=2739 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" 60 /* offset=2882 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" 61 /* offset=2904 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" 62 /* offset=2967 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" 63 /* offset=3133 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 64 /* offset=3197 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 65 /* offset=3264 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" 66 /* offset=3335 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" 67 /* offset=3429 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" 68 /* offset=3563 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" 69 /* offset=3627 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" 70 /* offset=3695 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" 71 /* offset=3765 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" 72 /* offset=3787 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" 73 /* offset=3809 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" 74 /* offset=3829 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" 75 ; 76 77 static const struct compact_pmu_event pmu_events__common_tool[] = { 78 { 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ 79 { 219 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ 80 { 295 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ 81 { 440 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */ 82 { 543 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */ 83 { 660 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */ 84 { 736 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */ 85 { 822 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */ 86 { 932 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ 87 { 151 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ 88 { 1039 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ 89 { 81 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ 90 91 }; 92 93 const struct pmu_table_entry pmu_events__common[] = { 94 { 95 .entries = pmu_events__common_tool, 96 .num_entries = ARRAY_SIZE(pmu_events__common_tool), 97 .pmu_name = { 0 /* tool\000 */ }, 98 }, 99 }; 100 101 static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { 102 { 1151 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ 103 { 1213 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ 104 { 1475 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ 105 { 1608 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ 106 { 1275 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ 107 { 1373 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ 108 }; 109 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { 110 { 1741 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000DDRC write commands\000 */ 111 }; 112 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { 113 { 2232 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000Total read hits\000 */ 114 }; 115 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { 116 { 2076 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000UNC_CBO_HYPHEN\000 */ 117 { 2144 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000UNC_CBO_TWO_HYPH\000 */ 118 { 1842 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */ 119 }; 120 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = { 121 { 2448 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000Total cache hits\000 */ 122 }; 123 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { 124 { 2339 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000Total cache misses\000 */ 125 126 }; 127 128 const struct pmu_table_entry pmu_events__test_soc_cpu[] = { 129 { 130 .entries = pmu_events__test_soc_cpu_default_core, 131 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core), 132 .pmu_name = { 1138 /* default_core\000 */ }, 133 }, 134 { 135 .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, 136 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), 137 .pmu_name = { 1726 /* hisi_sccl,ddrc\000 */ }, 138 }, 139 { 140 .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, 141 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), 142 .pmu_name = { 2218 /* hisi_sccl,l3c\000 */ }, 143 }, 144 { 145 .entries = pmu_events__test_soc_cpu_uncore_cbox, 146 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), 147 .pmu_name = { 1830 /* uncore_cbox\000 */ }, 148 }, 149 { 150 .entries = pmu_events__test_soc_cpu_uncore_imc, 151 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), 152 .pmu_name = { 2437 /* uncore_imc\000 */ }, 153 }, 154 { 155 .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, 156 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), 157 .pmu_name = { 2315 /* uncore_imc_free_running\000 */ }, 158 }, 159 }; 160 161 static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { 162 { 2882 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ 163 { 3563 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ 164 { 3335 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ 165 { 3429 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ 166 { 3627 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 167 { 3695 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 168 { 2967 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ 169 { 2904 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ 170 { 3829 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ 171 { 3765 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ 172 { 3787 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ 173 { 3809 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ 174 { 3264 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ 175 { 3133 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 176 { 3197 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 177 178 }; 179 180 const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { 181 { 182 .entries = pmu_metrics__test_soc_cpu_default_core, 183 .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core), 184 .pmu_name = { 1138 /* default_core\000 */ }, 185 }, 186 }; 187 188 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { 189 { 2643 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ 190 }; 191 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { 192 { 2739 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ 193 }; 194 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { 195 { 2548 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ 196 197 }; 198 199 const struct pmu_table_entry pmu_events__test_soc_sys[] = { 200 { 201 .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, 202 .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), 203 .pmu_name = { 2624 /* uncore_sys_ccn_pmu\000 */ }, 204 }, 205 { 206 .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, 207 .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), 208 .pmu_name = { 2720 /* uncore_sys_cmn_pmu\000 */ }, 209 }, 210 { 211 .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, 212 .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), 213 .pmu_name = { 2529 /* uncore_sys_ddr_pmu\000 */ }, 214 }, 215 }; 216 217 218 /* Struct used to make the PMU event table implementation opaque to callers. */ 219 struct pmu_events_table { 220 const struct pmu_table_entry *pmus; 221 uint32_t num_pmus; 222 }; 223 224 /* Struct used to make the PMU metric table implementation opaque to callers. */ 225 struct pmu_metrics_table { 226 const struct pmu_table_entry *pmus; 227 uint32_t num_pmus; 228 }; 229 230 /* 231 * Map a CPU to its table of PMU events. The CPU is identified by the 232 * cpuid field, which is an arch-specific identifier for the CPU. 233 * The identifier specified in tools/perf/pmu-events/arch/xxx/mapfile 234 * must match the get_cpuid_str() in tools/perf/arch/xxx/util/header.c) 235 * 236 * The cpuid can contain any character other than the comma. 237 */ 238 struct pmu_events_map { 239 const char *arch; 240 const char *cpuid; 241 struct pmu_events_table event_table; 242 struct pmu_metrics_table metric_table; 243 }; 244 245 /* 246 * Global table mapping each known CPU for the architecture to its 247 * table of PMU events. 248 */ 249 const struct pmu_events_map pmu_events_map[] = { 250 { 251 .arch = "common", 252 .cpuid = "common", 253 .event_table = { 254 .pmus = pmu_events__common, 255 .num_pmus = ARRAY_SIZE(pmu_events__common), 256 }, 257 .metric_table = {}, 258 }, 259 { 260 .arch = "testarch", 261 .cpuid = "testcpu", 262 .event_table = { 263 .pmus = pmu_events__test_soc_cpu, 264 .num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu), 265 }, 266 .metric_table = { 267 .pmus = pmu_metrics__test_soc_cpu, 268 .num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu), 269 } 270 }, 271 { 272 .arch = 0, 273 .cpuid = 0, 274 .event_table = { 0, 0 }, 275 .metric_table = { 0, 0 }, 276 } 277 }; 278 279 struct pmu_sys_events { 280 const char *name; 281 struct pmu_events_table event_table; 282 struct pmu_metrics_table metric_table; 283 }; 284 285 static const struct pmu_sys_events pmu_sys_event_tables[] = { 286 { 287 .event_table = { 288 .pmus = pmu_events__test_soc_sys, 289 .num_pmus = ARRAY_SIZE(pmu_events__test_soc_sys) 290 }, 291 .name = "pmu_events__test_soc_sys", 292 }, 293 { 294 .event_table = { 0, 0 }, 295 .metric_table = { 0, 0 }, 296 }, 297 }; 298 299 static void decompress_event(int offset, struct pmu_event *pe) 300 { 301 const char *p = &big_c_string[offset]; 302 303 pe->name = (*p == '\0' ? NULL : p); 304 while (*p++); 305 pe->topic = (*p == '\0' ? NULL : p); 306 while (*p++); 307 pe->desc = (*p == '\0' ? NULL : p); 308 while (*p++); 309 pe->event = (*p == '\0' ? NULL : p); 310 while (*p++); 311 pe->compat = (*p == '\0' ? NULL : p); 312 while (*p++); 313 pe->deprecated = *p - '0'; 314 p++; 315 pe->perpkg = *p - '0'; 316 p++; 317 pe->unit = (*p == '\0' ? NULL : p); 318 while (*p++); 319 pe->retirement_latency_mean = (*p == '\0' ? NULL : p); 320 while (*p++); 321 pe->retirement_latency_min = (*p == '\0' ? NULL : p); 322 while (*p++); 323 pe->retirement_latency_max = (*p == '\0' ? NULL : p); 324 while (*p++); 325 pe->long_desc = (*p == '\0' ? NULL : p); 326 } 327 328 static void decompress_metric(int offset, struct pmu_metric *pm) 329 { 330 const char *p = &big_c_string[offset]; 331 332 pm->metric_name = (*p == '\0' ? NULL : p); 333 while (*p++); 334 pm->metric_group = (*p == '\0' ? NULL : p); 335 while (*p++); 336 pm->metric_expr = (*p == '\0' ? NULL : p); 337 while (*p++); 338 pm->metric_threshold = (*p == '\0' ? NULL : p); 339 while (*p++); 340 pm->desc = (*p == '\0' ? NULL : p); 341 while (*p++); 342 pm->long_desc = (*p == '\0' ? NULL : p); 343 while (*p++); 344 pm->unit = (*p == '\0' ? NULL : p); 345 while (*p++); 346 pm->compat = (*p == '\0' ? NULL : p); 347 while (*p++); 348 pm->metricgroup_no_group = (*p == '\0' ? NULL : p); 349 while (*p++); 350 pm->default_metricgroup_name = (*p == '\0' ? NULL : p); 351 while (*p++); 352 pm->aggr_mode = *p - '0'; 353 p++; 354 pm->event_grouping = *p - '0'; 355 } 356 357 static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table, 358 const struct pmu_table_entry *pmu, 359 pmu_event_iter_fn fn, 360 void *data) 361 { 362 int ret; 363 struct pmu_event pe = { 364 .pmu = &big_c_string[pmu->pmu_name.offset], 365 }; 366 367 for (uint32_t i = 0; i < pmu->num_entries; i++) { 368 decompress_event(pmu->entries[i].offset, &pe); 369 if (!pe.name) 370 continue; 371 ret = fn(&pe, table, data); 372 if (ret) 373 return ret; 374 } 375 return 0; 376 } 377 378 static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table, 379 const struct pmu_table_entry *pmu, 380 const char *name, 381 pmu_event_iter_fn fn, 382 void *data) 383 { 384 struct pmu_event pe = { 385 .pmu = &big_c_string[pmu->pmu_name.offset], 386 }; 387 int low = 0, high = pmu->num_entries - 1; 388 389 while (low <= high) { 390 int cmp, mid = (low + high) / 2; 391 392 decompress_event(pmu->entries[mid].offset, &pe); 393 394 if (!pe.name && !name) 395 goto do_call; 396 397 if (!pe.name && name) { 398 low = mid + 1; 399 continue; 400 } 401 if (pe.name && !name) { 402 high = mid - 1; 403 continue; 404 } 405 406 cmp = strcasecmp(pe.name, name); 407 if (cmp < 0) { 408 low = mid + 1; 409 continue; 410 } 411 if (cmp > 0) { 412 high = mid - 1; 413 continue; 414 } 415 do_call: 416 return fn ? fn(&pe, table, data) : 0; 417 } 418 return PMU_EVENTS__NOT_FOUND; 419 } 420 421 int pmu_events_table__for_each_event(const struct pmu_events_table *table, 422 struct perf_pmu *pmu, 423 pmu_event_iter_fn fn, 424 void *data) 425 { 426 for (size_t i = 0; i < table->num_pmus; i++) { 427 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 428 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 429 int ret; 430 431 if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) 432 continue; 433 434 ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); 435 if (ret) 436 return ret; 437 } 438 return 0; 439 } 440 441 int pmu_events_table__find_event(const struct pmu_events_table *table, 442 struct perf_pmu *pmu, 443 const char *name, 444 pmu_event_iter_fn fn, 445 void *data) 446 { 447 for (size_t i = 0; i < table->num_pmus; i++) { 448 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 449 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 450 int ret; 451 452 if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) 453 continue; 454 455 ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); 456 if (ret != PMU_EVENTS__NOT_FOUND) 457 return ret; 458 } 459 return PMU_EVENTS__NOT_FOUND; 460 } 461 462 size_t pmu_events_table__num_events(const struct pmu_events_table *table, 463 struct perf_pmu *pmu) 464 { 465 size_t count = 0; 466 467 for (size_t i = 0; i < table->num_pmus; i++) { 468 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 469 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 470 471 if (perf_pmu__name_wildcard_match(pmu, pmu_name)) 472 count += table_pmu->num_entries; 473 } 474 return count; 475 } 476 477 static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table, 478 const struct pmu_table_entry *pmu, 479 pmu_metric_iter_fn fn, 480 void *data) 481 { 482 int ret; 483 struct pmu_metric pm = { 484 .pmu = &big_c_string[pmu->pmu_name.offset], 485 }; 486 487 for (uint32_t i = 0; i < pmu->num_entries; i++) { 488 decompress_metric(pmu->entries[i].offset, &pm); 489 if (!pm.metric_expr) 490 continue; 491 ret = fn(&pm, table, data); 492 if (ret) 493 return ret; 494 } 495 return 0; 496 } 497 498 static int pmu_metrics_table__find_metric_pmu(const struct pmu_metrics_table *table, 499 const struct pmu_table_entry *pmu, 500 const char *metric, 501 pmu_metric_iter_fn fn, 502 void *data) 503 { 504 struct pmu_metric pm = { 505 .pmu = &big_c_string[pmu->pmu_name.offset], 506 }; 507 int low = 0, high = pmu->num_entries - 1; 508 509 while (low <= high) { 510 int cmp, mid = (low + high) / 2; 511 512 decompress_metric(pmu->entries[mid].offset, &pm); 513 514 if (!pm.metric_name && !metric) 515 goto do_call; 516 517 if (!pm.metric_name && metric) { 518 low = mid + 1; 519 continue; 520 } 521 if (pm.metric_name && !metric) { 522 high = mid - 1; 523 continue; 524 } 525 526 cmp = strcmp(pm.metric_name, metric); 527 if (cmp < 0) { 528 low = mid + 1; 529 continue; 530 } 531 if (cmp > 0) { 532 high = mid - 1; 533 continue; 534 } 535 do_call: 536 return fn ? fn(&pm, table, data) : 0; 537 } 538 return PMU_METRICS__NOT_FOUND; 539 } 540 541 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, 542 pmu_metric_iter_fn fn, 543 void *data) 544 { 545 for (size_t i = 0; i < table->num_pmus; i++) { 546 int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], 547 fn, data); 548 549 if (ret) 550 return ret; 551 } 552 return 0; 553 } 554 555 int pmu_metrics_table__find_metric(const struct pmu_metrics_table *table, 556 struct perf_pmu *pmu, 557 const char *metric, 558 pmu_metric_iter_fn fn, 559 void *data) 560 { 561 for (size_t i = 0; i < table->num_pmus; i++) { 562 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 563 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 564 int ret; 565 566 if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) 567 continue; 568 569 ret = pmu_metrics_table__find_metric_pmu(table, table_pmu, metric, fn, data); 570 if (ret != PMU_METRICS__NOT_FOUND) 571 return ret; 572 } 573 return PMU_METRICS__NOT_FOUND; 574 } 575 576 static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) 577 { 578 static struct { 579 const struct pmu_events_map *map; 580 struct perf_cpu cpu; 581 } last_result; 582 static struct { 583 const struct pmu_events_map *map; 584 char *cpuid; 585 } last_map_search; 586 static bool has_last_result, has_last_map_search; 587 const struct pmu_events_map *map = NULL; 588 char *cpuid = NULL; 589 size_t i; 590 591 if (has_last_result && last_result.cpu.cpu == cpu.cpu) 592 return last_result.map; 593 594 cpuid = get_cpuid_allow_env_override(cpu); 595 596 /* 597 * On some platforms which uses cpus map, cpuid can be NULL for 598 * PMUs other than CORE PMUs. 599 */ 600 if (!cpuid) 601 goto out_update_last_result; 602 603 if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { 604 map = last_map_search.map; 605 free(cpuid); 606 } else { 607 i = 0; 608 for (;;) { 609 map = &pmu_events_map[i++]; 610 611 if (!map->arch) { 612 map = NULL; 613 break; 614 } 615 616 if (!strcmp_cpuid_str(map->cpuid, cpuid)) 617 break; 618 } 619 free(last_map_search.cpuid); 620 last_map_search.cpuid = cpuid; 621 last_map_search.map = map; 622 has_last_map_search = true; 623 } 624 out_update_last_result: 625 last_result.cpu = cpu; 626 last_result.map = map; 627 has_last_result = true; 628 return map; 629 } 630 631 static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) 632 { 633 struct perf_cpu cpu = {-1}; 634 635 if (pmu) 636 cpu = perf_cpu_map__min(pmu->cpus); 637 return map_for_cpu(cpu); 638 } 639 640 const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) 641 { 642 const struct pmu_events_map *map = map_for_pmu(pmu); 643 644 if (!map) 645 return NULL; 646 647 if (!pmu) 648 return &map->event_table; 649 650 for (size_t i = 0; i < map->event_table.num_pmus; i++) { 651 const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; 652 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 653 654 if (perf_pmu__name_wildcard_match(pmu, pmu_name)) 655 return &map->event_table; 656 } 657 return NULL; 658 } 659 660 const struct pmu_metrics_table *pmu_metrics_table__find(void) 661 { 662 struct perf_cpu cpu = {-1}; 663 const struct pmu_events_map *map = map_for_cpu(cpu); 664 665 return map ? &map->metric_table : NULL; 666 } 667 668 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) 669 { 670 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 671 tables->arch; 672 tables++) { 673 if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) 674 return &tables->event_table; 675 } 676 return NULL; 677 } 678 679 const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid) 680 { 681 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 682 tables->arch; 683 tables++) { 684 if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) 685 return &tables->metric_table; 686 } 687 return NULL; 688 } 689 690 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) 691 { 692 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 693 tables->arch; 694 tables++) { 695 int ret = pmu_events_table__for_each_event(&tables->event_table, 696 /*pmu=*/ NULL, fn, data); 697 698 if (ret) 699 return ret; 700 } 701 return 0; 702 } 703 704 int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data) 705 { 706 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 707 tables->arch; 708 tables++) { 709 int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); 710 711 if (ret) 712 return ret; 713 } 714 return 0; 715 } 716 717 const struct pmu_events_table *find_sys_events_table(const char *name) 718 { 719 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 720 tables->name; 721 tables++) { 722 if (!strcmp(tables->name, name)) 723 return &tables->event_table; 724 } 725 return NULL; 726 } 727 728 int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) 729 { 730 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 731 tables->name; 732 tables++) { 733 int ret = pmu_events_table__for_each_event(&tables->event_table, 734 /*pmu=*/ NULL, fn, data); 735 736 if (ret) 737 return ret; 738 } 739 return 0; 740 } 741 742 int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data) 743 { 744 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 745 tables->name; 746 tables++) { 747 int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); 748 749 if (ret) 750 return ret; 751 } 752 return 0; 753 } 754 755 static const int metricgroups[][2] = { 756 757 }; 758 759 const char *describe_metricgroup(const char *group) 760 { 761 int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1; 762 763 while (low <= high) { 764 int mid = (low + high) / 2; 765 const char *mgroup = &big_c_string[metricgroups[mid][0]]; 766 int cmp = strcmp(mgroup, group); 767 768 if (cmp == 0) { 769 return &big_c_string[metricgroups[mid][1]]; 770 } else if (cmp < 0) { 771 low = mid + 1; 772 } else { 773 high = mid - 1; 774 } 775 } 776 return NULL; 777 } 778