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 
180 /*
181  * Map a CPU to its table of PMU events. The CPU is identified by the
182  * cpuid field, which is an arch-specific identifier for the CPU.
183  * The identifier specified in tools/perf/pmu-events/arch/xxx/mapfile
184  * must match the get_cpuid_str() in tools/perf/arch/xxx/util/header.c)
185  *
186  * The  cpuid can contain any character other than the comma.
187  */
188 struct pmu_events_map {
189 	const char *arch;
190 	const char *cpuid;
191 	const struct pmu_event *table;
192 };
193 
194 /*
195  * Global table mapping each known CPU for the architecture to its
196  * table of PMU events.
197  */
198 static const struct pmu_events_map pmu_events_map[] = {
199 	{
200 		.arch = "testarch",
201 		.cpuid = "testcpu",
202 		.table = pme_test_soc_cpu,
203 	},
204 	{
205 		.arch = 0,
206 		.cpuid = 0,
207 		.table = 0,
208 	},
209 };
210 
211 static const struct pmu_event pme_test_soc_sys[] = {
212 	{
213 		.name = "sys_ddr_pmu.write_cycles",
214 		.event = "event=0x2b",
215 		.desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
216 		.compat = "v8",
217 		.topic = "uncore",
218 		.pmu = "uncore_sys_ddr_pmu",
219 	},
220 	{
221 		.name = "sys_ccn_pmu.read_cycles",
222 		.event = "config=0x2c",
223 		.desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
224 		.compat = "0x01",
225 		.topic = "uncore",
226 		.pmu = "uncore_sys_ccn_pmu",
227 	},
228 	{
229 		.name = 0,
230 		.event = 0,
231 		.desc = 0,
232 	},
233 };
234 
235 struct pmu_sys_events {
236 	const char *name;
237 	const struct pmu_event *table;
238 };
239 
240 static const struct pmu_sys_events pmu_sys_event_tables[] = {
241 	{
242 		.table = pme_test_soc_sys,
243 		.name = "pme_test_soc_sys",
244 	},
245 	{
246 		.table = 0
247 	},
248 };
249 
250 const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu)
251 {
252 	const struct pmu_event *table = NULL;
253 	char *cpuid = perf_pmu__getcpuid(pmu);
254 	int i;
255 
256 	/* on some platforms which uses cpus map, cpuid can be NULL for
257 	 * PMUs other than CORE PMUs.
258 	 */
259 	if (!cpuid)
260 		return NULL;
261 
262 	i = 0;
263 	for (;;) {
264 		const struct pmu_events_map *map = &pmu_events_map[i++];
265 
266 		if (!map->table)
267 			break;
268 
269 		if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
270 			table = map->table;
271 			break;
272 		}
273 	}
274 	free(cpuid);
275 	return table;
276 }
277 
278 const struct pmu_event *find_core_events_table(const char *arch, const char *cpuid)
279 {
280 	for (const struct pmu_events_map *tables = &pmu_events_map[0];
281 	     tables->table;
282 	     tables++) {
283 		if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
284 			return tables->table;
285 	}
286 	return NULL;
287 }
288 
289 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
290 {
291 	for (const struct pmu_events_map *tables = &pmu_events_map[0];
292 	     tables->table;
293 	     tables++) {
294 		for (const struct pmu_event *pe = &tables->table[0];
295 		     pe->name || pe->metric_group || pe->metric_name;
296 		     pe++) {
297 			int ret = fn(pe, &tables->table[0], data);
298 
299 			if (ret)
300 				return ret;
301 		}
302 	}
303 	return 0;
304 }
305 
306 const struct pmu_event *find_sys_events_table(const char *name)
307 {
308 	for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
309 	     tables->name;
310 	     tables++) {
311 		if (!strcmp(tables->name, name))
312 			return tables->table;
313 	}
314 	return NULL;
315 }
316 
317 int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
318 {
319 	for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
320 	     tables->name;
321 	     tables++) {
322 		for (const struct pmu_event *pe = &tables->table[0];
323 		     pe->name || pe->metric_group || pe->metric_name;
324 		     pe++) {
325 			int ret = fn(pe, &tables->table[0], data);
326 
327 			if (ret)
328 				return ret;
329 		}
330 	}
331 	return 0;
332 }
333