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" 24 /* offset=78 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000" 25 /* offset=145 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000" 26 /* offset=210 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000" 27 /* offset=283 */ "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" 28 /* offset=425 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000" 29 /* offset=525 */ "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" 30 /* offset=639 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000" 31 /* offset=712 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000" 32 /* offset=795 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000" 33 /* offset=902 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000" 34 /* offset=1006 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000" 35 /* offset=1102 */ "default_core\000" 36 /* offset=1115 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000" 37 /* offset=1174 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000" 38 /* offset=1233 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000" 39 /* offset=1328 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000" 40 /* offset=1427 */ "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" 41 /* offset=1557 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000" 42 /* offset=1672 */ "hisi_sccl,ddrc\000" 43 /* offset=1687 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000" 44 /* offset=1773 */ "uncore_cbox\000" 45 /* offset=1785 */ "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\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000" 46 /* offset=2016 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000" 47 /* offset=2081 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000" 48 /* offset=2152 */ "hisi_sccl,l3c\000" 49 /* offset=2166 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000" 50 /* offset=2246 */ "uncore_imc_free_running\000" 51 /* offset=2270 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000" 52 /* offset=2365 */ "uncore_imc\000" 53 /* offset=2376 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000" 54 /* offset=2454 */ "uncore_sys_ddr_pmu\000" 55 /* offset=2473 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000" 56 /* offset=2546 */ "uncore_sys_ccn_pmu\000" 57 /* offset=2565 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000" 58 /* offset=2639 */ "uncore_sys_cmn_pmu\000" 59 /* offset=2658 */ "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" 60 /* offset=2798 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" 61 /* offset=2820 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" 62 /* offset=2883 */ "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=3049 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 64 /* offset=3113 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 65 /* offset=3180 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" 66 /* offset=3251 */ "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=3345 */ "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=3479 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" 69 /* offset=3543 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" 70 /* offset=3611 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" 71 /* offset=3681 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" 72 /* offset=3703 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" 73 /* offset=3725 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" 74 /* offset=3745 */ "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 */ 79 { 210 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000 */ 80 { 283 }, /* 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 */ 81 { 425 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000 */ 82 { 525 }, /* 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 */ 83 { 639 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000 */ 84 { 712 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000 */ 85 { 795 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000 */ 86 { 902 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000 */ 87 { 145 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000 */ 88 { 1006 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000 */ 89 { 78 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\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 { 1115 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */ 103 { 1174 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */ 104 { 1427 }, /* 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 */ 105 { 1557 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */ 106 { 1233 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */ 107 { 1328 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */ 108 }; 109 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { 110 { 1687 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */ 111 }; 112 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { 113 { 2166 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */ 114 }; 115 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { 116 { 2016 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */ 117 { 2081 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */ 118 { 1785 }, /* 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\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 { 2376 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */ 122 }; 123 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { 124 { 2270 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\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 = { 1102 /* 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 = { 1672 /* 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 = { 2152 /* 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 = { 1773 /* 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 = { 2365 /* 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 = { 2246 /* uncore_imc_free_running\000 */ }, 158 }, 159 }; 160 161 static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { 162 { 2798 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ 163 { 3479 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ 164 { 3251 }, /* 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 { 3345 }, /* 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 { 3543 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 167 { 3611 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 168 { 2883 }, /* 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 { 2820 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ 170 { 3745 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ 171 { 3681 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ 172 { 3703 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ 173 { 3725 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ 174 { 3180 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ 175 { 3049 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 176 { 3113 }, /* 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 = { 1102 /* default_core\000 */ }, 185 }, 186 }; 187 188 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { 189 { 2565 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */ 190 }; 191 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { 192 { 2658 }, /* 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 */ 193 }; 194 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { 195 { 2473 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\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 = { 2546 /* 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 = { 2639 /* 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 = { 2454 /* 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->long_desc = (*p == '\0' ? NULL : p); 320 } 321 322 static void decompress_metric(int offset, struct pmu_metric *pm) 323 { 324 const char *p = &big_c_string[offset]; 325 326 pm->metric_name = (*p == '\0' ? NULL : p); 327 while (*p++); 328 pm->metric_group = (*p == '\0' ? NULL : p); 329 while (*p++); 330 pm->metric_expr = (*p == '\0' ? NULL : p); 331 while (*p++); 332 pm->metric_threshold = (*p == '\0' ? NULL : p); 333 while (*p++); 334 pm->desc = (*p == '\0' ? NULL : p); 335 while (*p++); 336 pm->long_desc = (*p == '\0' ? NULL : p); 337 while (*p++); 338 pm->unit = (*p == '\0' ? NULL : p); 339 while (*p++); 340 pm->compat = (*p == '\0' ? NULL : p); 341 while (*p++); 342 pm->metricgroup_no_group = (*p == '\0' ? NULL : p); 343 while (*p++); 344 pm->default_metricgroup_name = (*p == '\0' ? NULL : p); 345 while (*p++); 346 pm->aggr_mode = *p - '0'; 347 p++; 348 pm->event_grouping = *p - '0'; 349 } 350 351 static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table, 352 const struct pmu_table_entry *pmu, 353 pmu_event_iter_fn fn, 354 void *data) 355 { 356 int ret; 357 struct pmu_event pe = { 358 .pmu = &big_c_string[pmu->pmu_name.offset], 359 }; 360 361 for (uint32_t i = 0; i < pmu->num_entries; i++) { 362 decompress_event(pmu->entries[i].offset, &pe); 363 if (!pe.name) 364 continue; 365 ret = fn(&pe, table, data); 366 if (ret) 367 return ret; 368 } 369 return 0; 370 } 371 372 static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table, 373 const struct pmu_table_entry *pmu, 374 const char *name, 375 pmu_event_iter_fn fn, 376 void *data) 377 { 378 struct pmu_event pe = { 379 .pmu = &big_c_string[pmu->pmu_name.offset], 380 }; 381 int low = 0, high = pmu->num_entries - 1; 382 383 while (low <= high) { 384 int cmp, mid = (low + high) / 2; 385 386 decompress_event(pmu->entries[mid].offset, &pe); 387 388 if (!pe.name && !name) 389 goto do_call; 390 391 if (!pe.name && name) { 392 low = mid + 1; 393 continue; 394 } 395 if (pe.name && !name) { 396 high = mid - 1; 397 continue; 398 } 399 400 cmp = strcasecmp(pe.name, name); 401 if (cmp < 0) { 402 low = mid + 1; 403 continue; 404 } 405 if (cmp > 0) { 406 high = mid - 1; 407 continue; 408 } 409 do_call: 410 return fn ? fn(&pe, table, data) : 0; 411 } 412 return PMU_EVENTS__NOT_FOUND; 413 } 414 415 int pmu_events_table__for_each_event(const struct pmu_events_table *table, 416 struct perf_pmu *pmu, 417 pmu_event_iter_fn fn, 418 void *data) 419 { 420 for (size_t i = 0; i < table->num_pmus; i++) { 421 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 422 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 423 int ret; 424 425 if (pmu && !pmu__name_match(pmu, pmu_name)) 426 continue; 427 428 ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); 429 if (ret) 430 return ret; 431 } 432 return 0; 433 } 434 435 int pmu_events_table__find_event(const struct pmu_events_table *table, 436 struct perf_pmu *pmu, 437 const char *name, 438 pmu_event_iter_fn fn, 439 void *data) 440 { 441 for (size_t i = 0; i < table->num_pmus; i++) { 442 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 443 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 444 int ret; 445 446 if (!pmu__name_match(pmu, pmu_name)) 447 continue; 448 449 ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); 450 if (ret != PMU_EVENTS__NOT_FOUND) 451 return ret; 452 } 453 return PMU_EVENTS__NOT_FOUND; 454 } 455 456 size_t pmu_events_table__num_events(const struct pmu_events_table *table, 457 struct perf_pmu *pmu) 458 { 459 size_t count = 0; 460 461 for (size_t i = 0; i < table->num_pmus; i++) { 462 const struct pmu_table_entry *table_pmu = &table->pmus[i]; 463 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 464 465 if (pmu__name_match(pmu, pmu_name)) 466 count += table_pmu->num_entries; 467 } 468 return count; 469 } 470 471 static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table, 472 const struct pmu_table_entry *pmu, 473 pmu_metric_iter_fn fn, 474 void *data) 475 { 476 int ret; 477 struct pmu_metric pm = { 478 .pmu = &big_c_string[pmu->pmu_name.offset], 479 }; 480 481 for (uint32_t i = 0; i < pmu->num_entries; i++) { 482 decompress_metric(pmu->entries[i].offset, &pm); 483 if (!pm.metric_expr) 484 continue; 485 ret = fn(&pm, table, data); 486 if (ret) 487 return ret; 488 } 489 return 0; 490 } 491 492 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, 493 pmu_metric_iter_fn fn, 494 void *data) 495 { 496 for (size_t i = 0; i < table->num_pmus; i++) { 497 int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], 498 fn, data); 499 500 if (ret) 501 return ret; 502 } 503 return 0; 504 } 505 506 static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) 507 { 508 static struct { 509 const struct pmu_events_map *map; 510 struct perf_cpu cpu; 511 } last_result; 512 static struct { 513 const struct pmu_events_map *map; 514 char *cpuid; 515 } last_map_search; 516 static bool has_last_result, has_last_map_search; 517 const struct pmu_events_map *map = NULL; 518 char *cpuid = NULL; 519 size_t i; 520 521 if (has_last_result && last_result.cpu.cpu == cpu.cpu) 522 return last_result.map; 523 524 cpuid = get_cpuid_allow_env_override(cpu); 525 526 /* 527 * On some platforms which uses cpus map, cpuid can be NULL for 528 * PMUs other than CORE PMUs. 529 */ 530 if (!cpuid) 531 goto out_update_last_result; 532 533 if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { 534 map = last_map_search.map; 535 free(cpuid); 536 } else { 537 i = 0; 538 for (;;) { 539 map = &pmu_events_map[i++]; 540 541 if (!map->arch) { 542 map = NULL; 543 break; 544 } 545 546 if (!strcmp_cpuid_str(map->cpuid, cpuid)) 547 break; 548 } 549 free(last_map_search.cpuid); 550 last_map_search.cpuid = cpuid; 551 last_map_search.map = map; 552 has_last_map_search = true; 553 } 554 out_update_last_result: 555 last_result.cpu = cpu; 556 last_result.map = map; 557 has_last_result = true; 558 return map; 559 } 560 561 static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) 562 { 563 struct perf_cpu cpu = {-1}; 564 565 if (pmu) 566 cpu = perf_cpu_map__min(pmu->cpus); 567 return map_for_cpu(cpu); 568 } 569 570 const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) 571 { 572 const struct pmu_events_map *map = map_for_pmu(pmu); 573 574 if (!map) 575 return NULL; 576 577 if (!pmu) 578 return &map->event_table; 579 580 for (size_t i = 0; i < map->event_table.num_pmus; i++) { 581 const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; 582 const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 583 584 if (pmu__name_match(pmu, pmu_name)) 585 return &map->event_table; 586 } 587 return NULL; 588 } 589 590 const struct pmu_metrics_table *pmu_metrics_table__find(void) 591 { 592 struct perf_cpu cpu = {-1}; 593 const struct pmu_events_map *map = map_for_cpu(cpu); 594 595 return map ? &map->metric_table : NULL; 596 } 597 598 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) 599 { 600 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 601 tables->arch; 602 tables++) { 603 if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) 604 return &tables->event_table; 605 } 606 return NULL; 607 } 608 609 const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid) 610 { 611 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 612 tables->arch; 613 tables++) { 614 if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) 615 return &tables->metric_table; 616 } 617 return NULL; 618 } 619 620 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) 621 { 622 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 623 tables->arch; 624 tables++) { 625 int ret = pmu_events_table__for_each_event(&tables->event_table, 626 /*pmu=*/ NULL, fn, data); 627 628 if (ret) 629 return ret; 630 } 631 return 0; 632 } 633 634 int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data) 635 { 636 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 637 tables->arch; 638 tables++) { 639 int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); 640 641 if (ret) 642 return ret; 643 } 644 return 0; 645 } 646 647 const struct pmu_events_table *find_sys_events_table(const char *name) 648 { 649 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 650 tables->name; 651 tables++) { 652 if (!strcmp(tables->name, name)) 653 return &tables->event_table; 654 } 655 return NULL; 656 } 657 658 int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) 659 { 660 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 661 tables->name; 662 tables++) { 663 int ret = pmu_events_table__for_each_event(&tables->event_table, 664 /*pmu=*/ NULL, fn, data); 665 666 if (ret) 667 return ret; 668 } 669 return 0; 670 } 671 672 int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data) 673 { 674 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 675 tables->name; 676 tables++) { 677 int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); 678 679 if (ret) 680 return ret; 681 } 682 return 0; 683 } 684 685 static const int metricgroups[][2] = { 686 687 }; 688 689 const char *describe_metricgroup(const char *group) 690 { 691 int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1; 692 693 while (low <= high) { 694 int mid = (low + high) / 2; 695 const char *mgroup = &big_c_string[metricgroups[mid][0]]; 696 int cmp = strcmp(mgroup, group); 697 698 if (cmp == 0) { 699 return &big_c_string[metricgroups[mid][1]]; 700 } else if (cmp < 0) { 701 low = mid + 1; 702 } else { 703 high = mid - 1; 704 } 705 } 706 return NULL; 707 } 708