1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * An empty pmu-events.c file used when there is no architecture json files in
4 * arch or when the jevents.py script cannot be run.
5 *
6 * The test cpu/soc is provided for testing.
7 */
8 #include "pmu-events/pmu-events.h"
9 #include "util/header.h"
10 #include "util/pmu.h"
11 #include <string.h>
12 #include <stddef.h>
13
14 static const struct pmu_event pme_test_soc_cpu[] = {
15 {
16 .name = "l3_cache_rd",
17 .event = "event=0x40",
18 .desc = "L3 cache access, read",
19 .topic = "cache",
20 .long_desc = "Attributable Level 3 cache access, read",
21 },
22 {
23 .name = "segment_reg_loads.any",
24 .event = "event=0x6,period=200000,umask=0x80",
25 .desc = "Number of segment register loads",
26 .topic = "other",
27 },
28 {
29 .name = "dispatch_blocked.any",
30 .event = "event=0x9,period=200000,umask=0x20",
31 .desc = "Memory cluster signals to block micro-op dispatch for any reason",
32 .topic = "other",
33 },
34 {
35 .name = "eist_trans",
36 .event = "event=0x3a,period=200000,umask=0x0",
37 .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
38 .topic = "other",
39 },
40 {
41 .name = "uncore_hisi_ddrc.flux_wcmd",
42 .event = "event=0x2",
43 .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
44 .topic = "uncore",
45 .long_desc = "DDRC write commands",
46 .pmu = "hisi_sccl,ddrc",
47 },
48 {
49 .name = "unc_cbo_xsnp_response.miss_eviction",
50 .event = "event=0x22,umask=0x81",
51 .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
52 .topic = "uncore",
53 .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
54 .pmu = "uncore_cbox",
55 },
56 {
57 .name = "event-hyphen",
58 .event = "event=0xe0,umask=0x00",
59 .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
60 .topic = "uncore",
61 .long_desc = "UNC_CBO_HYPHEN",
62 .pmu = "uncore_cbox",
63 },
64 {
65 .name = "event-two-hyph",
66 .event = "event=0xc0,umask=0x00",
67 .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
68 .topic = "uncore",
69 .long_desc = "UNC_CBO_TWO_HYPH",
70 .pmu = "uncore_cbox",
71 },
72 {
73 .name = "uncore_hisi_l3c.rd_hit_cpipe",
74 .event = "event=0x7",
75 .desc = "Total read hits. Unit: hisi_sccl,l3c ",
76 .topic = "uncore",
77 .long_desc = "Total read hits",
78 .pmu = "hisi_sccl,l3c",
79 },
80 {
81 .name = "uncore_imc_free_running.cache_miss",
82 .event = "event=0x12",
83 .desc = "Total cache misses. Unit: uncore_imc_free_running ",
84 .topic = "uncore",
85 .long_desc = "Total cache misses",
86 .pmu = "uncore_imc_free_running",
87 },
88 {
89 .name = "uncore_imc.cache_hits",
90 .event = "event=0x34",
91 .desc = "Total cache hits. Unit: uncore_imc ",
92 .topic = "uncore",
93 .long_desc = "Total cache hits",
94 .pmu = "uncore_imc",
95 },
96 {
97 .name = "bp_l1_btb_correct",
98 .event = "event=0x8a",
99 .desc = "L1 BTB Correction",
100 .topic = "branch",
101 },
102 {
103 .name = "bp_l2_btb_correct",
104 .event = "event=0x8b",
105 .desc = "L2 BTB Correction",
106 .topic = "branch",
107 },
108 {
109 .metric_expr = "1 / IPC",
110 .metric_name = "CPI",
111 },
112 {
113 .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
114 .metric_name = "IPC",
115 .metric_group = "group1",
116 },
117 {
118 .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
119 "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
120 .metric_name = "Frontend_Bound_SMT",
121 },
122 {
123 .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
124 .metric_name = "dcache_miss_cpi",
125 },
126 {
127 .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
128 .metric_name = "icache_miss_cycles",
129 },
130 {
131 .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
132 .metric_name = "cache_miss_cycles",
133 .metric_group = "group1",
134 },
135 {
136 .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
137 .metric_name = "DCache_L2_All_Hits",
138 },
139 {
140 .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
141 "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
142 .metric_name = "DCache_L2_All_Miss",
143 },
144 {
145 .metric_expr = "DCache_L2_All_Hits + DCache_L2_All_Miss",
146 .metric_name = "DCache_L2_All",
147 },
148 {
149 .metric_expr = "d_ratio(DCache_L2_All_Hits, DCache_L2_All)",
150 .metric_name = "DCache_L2_Hits",
151 },
152 {
153 .metric_expr = "d_ratio(DCache_L2_All_Miss, DCache_L2_All)",
154 .metric_name = "DCache_L2_Misses",
155 },
156 {
157 .metric_expr = "ipc + M2",
158 .metric_name = "M1",
159 },
160 {
161 .metric_expr = "ipc + M1",
162 .metric_name = "M2",
163 },
164 {
165 .metric_expr = "1/M3",
166 .metric_name = "M3",
167 },
168 {
169 .metric_expr = "64 * l1d.replacement / 1000000000 / duration_time",
170 .metric_name = "L1D_Cache_Fill_BW",
171 },
172 {
173 .name = 0,
174 .event = 0,
175 .desc = 0,
176 },
177 };
178
179 /* Struct used to make the PMU event table implementation opaque to callers. */
180 struct pmu_events_table {
181 const struct pmu_event *entries;
182 };
183
184 /*
185 * Map a CPU to its table of PMU events. The CPU is identified by the
186 * cpuid field, which is an arch-specific identifier for the CPU.
187 * The identifier specified in tools/perf/pmu-events/arch/xxx/mapfile
188 * must match the get_cpuid_str() in tools/perf/arch/xxx/util/header.c)
189 *
190 * The cpuid can contain any character other than the comma.
191 */
192 struct pmu_events_map {
193 const char *arch;
194 const char *cpuid;
195 const struct pmu_events_table table;
196 };
197
198 /*
199 * Global table mapping each known CPU for the architecture to its
200 * table of PMU events.
201 */
202 static const struct pmu_events_map pmu_events_map[] = {
203 {
204 .arch = "testarch",
205 .cpuid = "testcpu",
206 .table = { pme_test_soc_cpu },
207 },
208 {
209 .arch = 0,
210 .cpuid = 0,
211 .table = { 0 },
212 },
213 };
214
215 static const struct pmu_event pme_test_soc_sys[] = {
216 {
217 .name = "sys_ddr_pmu.write_cycles",
218 .event = "event=0x2b",
219 .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
220 .compat = "v8",
221 .topic = "uncore",
222 .pmu = "uncore_sys_ddr_pmu",
223 },
224 {
225 .name = "sys_ccn_pmu.read_cycles",
226 .event = "config=0x2c",
227 .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
228 .compat = "0x01",
229 .topic = "uncore",
230 .pmu = "uncore_sys_ccn_pmu",
231 },
232 {
233 .name = 0,
234 .event = 0,
235 .desc = 0,
236 },
237 };
238
239 struct pmu_sys_events {
240 const char *name;
241 const struct pmu_events_table table;
242 };
243
244 static const struct pmu_sys_events pmu_sys_event_tables[] = {
245 {
246 .table = { pme_test_soc_sys },
247 .name = "pme_test_soc_sys",
248 },
249 {
250 .table = { 0 }
251 },
252 };
253
pmu_events_table_for_each_event(const struct pmu_events_table * table,pmu_event_iter_fn fn,void * data)254 int pmu_events_table_for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
255 void *data)
256 {
257 for (const struct pmu_event *pe = &table->entries[0];
258 pe->name || pe->metric_group || pe->metric_name;
259 pe++) {
260 int ret = fn(pe, table, data);
261
262 if (ret)
263 return ret;
264 }
265 return 0;
266 }
267
perf_pmu__find_table(struct perf_pmu * pmu)268 const struct pmu_events_table *perf_pmu__find_table(struct perf_pmu *pmu)
269 {
270 const struct pmu_events_table *table = NULL;
271 char *cpuid = perf_pmu__getcpuid(pmu);
272 int i;
273
274 /* on some platforms which uses cpus map, cpuid can be NULL for
275 * PMUs other than CORE PMUs.
276 */
277 if (!cpuid)
278 return NULL;
279
280 i = 0;
281 for (;;) {
282 const struct pmu_events_map *map = &pmu_events_map[i++];
283
284 if (!map->cpuid)
285 break;
286
287 if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
288 table = &map->table;
289 break;
290 }
291 }
292 free(cpuid);
293 return table;
294 }
295
find_core_events_table(const char * arch,const char * cpuid)296 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
297 {
298 for (const struct pmu_events_map *tables = &pmu_events_map[0];
299 tables->arch;
300 tables++) {
301 if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
302 return &tables->table;
303 }
304 return NULL;
305 }
306
pmu_for_each_core_event(pmu_event_iter_fn fn,void * data)307 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
308 {
309 for (const struct pmu_events_map *tables = &pmu_events_map[0];
310 tables->arch;
311 tables++) {
312 int ret = pmu_events_table_for_each_event(&tables->table, fn, data);
313
314 if (ret)
315 return ret;
316 }
317 return 0;
318 }
319
find_sys_events_table(const char * name)320 const struct pmu_events_table *find_sys_events_table(const char *name)
321 {
322 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
323 tables->name;
324 tables++) {
325 if (!strcmp(tables->name, name))
326 return &tables->table;
327 }
328 return NULL;
329 }
330
pmu_for_each_sys_event(pmu_event_iter_fn fn,void * data)331 int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
332 {
333 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
334 tables->name;
335 tables++) {
336 int ret = pmu_events_table_for_each_event(&tables->table, fn, data);
337
338 if (ret)
339 return ret;
340 }
341 return 0;
342 }
343