blob: ed0ab838bcc5dc7ff7dbc93c7b182831bbdcb716 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Jiri Olsace1e22b2016-02-15 09:34:35 +01002#include <stddef.h>
3#include <stdlib.h>
4#include <string.h>
5#include <errno.h>
Jiri Olsa54fbad52016-02-24 09:46:42 +01006#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <api/fs/fs.h>
Arnaldo Carvalho de Melo877a7a12017-04-17 11:39:06 -030010#include <linux/kernel.h>
Arnaldo Carvalho de Melod3300a32019-08-30 15:09:54 -030011#include "map_symbol.h"
Jiri Olsaacbe6132016-02-15 09:34:34 +010012#include "mem-events.h"
Jiri Olsace1e22b2016-02-15 09:34:35 +010013#include "debug.h"
Jiri Olsa0c877d72016-02-24 09:46:46 +010014#include "symbol.h"
Jin Yaoe7ce8d12021-05-27 08:16:06 +080015#include "pmu.h"
16#include "pmu-hybrid.h"
Jiri Olsaacbe6132016-02-15 09:34:34 +010017
Jiri Olsab0d745b2016-06-14 20:19:11 +020018unsigned int perf_mem_events__loads_ldlat = 30;
19
Jiri Olsa54fbad52016-02-24 09:46:42 +010020#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
Jiri Olsaacbe6132016-02-15 09:34:34 +010021
Leo Yaneaf6aae2020-11-06 17:48:46 +080022static struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
Leo Yanf9f16df2020-11-06 17:48:45 +080023 E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "cpu/events/mem-loads"),
24 E("ldlat-stores", "cpu/mem-stores/P", "cpu/events/mem-stores"),
Leo Yan4ba24522020-11-06 17:48:47 +080025 E(NULL, NULL, NULL),
Jiri Olsaacbe6132016-02-15 09:34:34 +010026};
Jiri Olsa54fbad52016-02-24 09:46:42 +010027#undef E
Jiri Olsaacbe6132016-02-15 09:34:34 +010028
Jiri Olsab0d745b2016-06-14 20:19:11 +020029static char mem_loads_name[100];
30static bool mem_loads_name__init;
31
Leo Yaneaf6aae2020-11-06 17:48:46 +080032struct perf_mem_event * __weak perf_mem_events__ptr(int i)
33{
34 if (i >= PERF_MEM_EVENTS__MAX)
35 return NULL;
36
37 return &perf_mem_events[i];
38}
39
Jin Yaod2f327a2021-05-27 08:16:04 +080040char * __weak perf_mem_events__name(int i, char *pmu_name __maybe_unused)
Jiri Olsa2ba7ac52016-02-24 09:46:43 +010041{
Leo Yaneaf6aae2020-11-06 17:48:46 +080042 struct perf_mem_event *e = perf_mem_events__ptr(i);
43
44 if (!e)
45 return NULL;
46
Jiri Olsab0d745b2016-06-14 20:19:11 +020047 if (i == PERF_MEM_EVENTS__LOAD) {
48 if (!mem_loads_name__init) {
49 mem_loads_name__init = true;
50 scnprintf(mem_loads_name, sizeof(mem_loads_name),
Leo Yaneaf6aae2020-11-06 17:48:46 +080051 e->name, perf_mem_events__loads_ldlat);
Jiri Olsab0d745b2016-06-14 20:19:11 +020052 }
53 return mem_loads_name;
54 }
55
Leo Yaneaf6aae2020-11-06 17:48:46 +080056 return (char *)e->name;
Jiri Olsa2ba7ac52016-02-24 09:46:43 +010057}
58
Kan Liang2a57d402021-02-02 12:09:06 -080059__weak bool is_mem_loads_aux_event(struct evsel *leader __maybe_unused)
60{
61 return false;
62}
63
Jiri Olsace1e22b2016-02-15 09:34:35 +010064int perf_mem_events__parse(const char *str)
65{
66 char *tok, *saveptr = NULL;
67 bool found = false;
68 char *buf;
69 int j;
70
71 /* We need buffer that we know we can write to. */
72 buf = malloc(strlen(str) + 1);
73 if (!buf)
74 return -ENOMEM;
75
76 strcpy(buf, str);
77
78 tok = strtok_r((char *)buf, ",", &saveptr);
79
80 while (tok) {
81 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
Leo Yaneaf6aae2020-11-06 17:48:46 +080082 struct perf_mem_event *e = perf_mem_events__ptr(j);
Jiri Olsace1e22b2016-02-15 09:34:35 +010083
Leo Yan4ba24522020-11-06 17:48:47 +080084 if (!e->tag)
85 continue;
86
Jiri Olsace1e22b2016-02-15 09:34:35 +010087 if (strstr(e->tag, tok))
88 e->record = found = true;
89 }
90
91 tok = strtok_r(NULL, ",", &saveptr);
92 }
93
94 free(buf);
95
96 if (found)
97 return 0;
98
99 pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
100 return -1;
101}
Jiri Olsa54fbad52016-02-24 09:46:42 +0100102
Jin Yaoe7ce8d12021-05-27 08:16:06 +0800103static bool perf_mem_event__supported(const char *mnt, char *sysfs_name)
104{
105 char path[PATH_MAX];
106 struct stat st;
107
108 scnprintf(path, PATH_MAX, "%s/devices/%s", mnt, sysfs_name);
109 return !stat(path, &st);
110}
111
Jiri Olsa54fbad52016-02-24 09:46:42 +0100112int perf_mem_events__init(void)
113{
114 const char *mnt = sysfs__mount();
115 bool found = false;
116 int j;
117
118 if (!mnt)
119 return -ENOENT;
120
121 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
Leo Yaneaf6aae2020-11-06 17:48:46 +0800122 struct perf_mem_event *e = perf_mem_events__ptr(j);
Jin Yaoe7ce8d12021-05-27 08:16:06 +0800123 struct perf_pmu *pmu;
124 char sysfs_name[100];
Jiri Olsa54fbad52016-02-24 09:46:42 +0100125
Leo Yan4ba24522020-11-06 17:48:47 +0800126 /*
127 * If the event entry isn't valid, skip initialization
128 * and "e->supported" will keep false.
129 */
130 if (!e->tag)
131 continue;
132
Jin Yaoe7ce8d12021-05-27 08:16:06 +0800133 if (!perf_pmu__has_hybrid()) {
134 scnprintf(sysfs_name, sizeof(sysfs_name),
135 e->sysfs_name, "cpu");
136 e->supported = perf_mem_event__supported(mnt, sysfs_name);
137 } else {
138 perf_pmu__for_each_hybrid_pmu(pmu) {
139 scnprintf(sysfs_name, sizeof(sysfs_name),
140 e->sysfs_name, pmu->name);
141 e->supported |= perf_mem_event__supported(mnt, sysfs_name);
142 }
143 }
Jiri Olsa54fbad52016-02-24 09:46:42 +0100144
Jin Yaoe7ce8d12021-05-27 08:16:06 +0800145 if (e->supported)
146 found = true;
Jiri Olsa54fbad52016-02-24 09:46:42 +0100147 }
148
149 return found ? 0 : -ENOENT;
150}
Jiri Olsa0c877d72016-02-24 09:46:46 +0100151
Ian Rogersb027cc62020-05-07 15:06:04 -0700152void perf_mem_events__list(void)
153{
154 int j;
155
156 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
Leo Yaneaf6aae2020-11-06 17:48:46 +0800157 struct perf_mem_event *e = perf_mem_events__ptr(j);
Ian Rogersb027cc62020-05-07 15:06:04 -0700158
159 fprintf(stderr, "%-13s%-*s%s\n",
Leo Yan4ba24522020-11-06 17:48:47 +0800160 e->tag ?: "",
Ian Rogersb027cc62020-05-07 15:06:04 -0700161 verbose > 0 ? 25 : 0,
Jin Yaod2f327a2021-05-27 08:16:04 +0800162 verbose > 0 ? perf_mem_events__name(j, NULL) : "",
Ian Rogersb027cc62020-05-07 15:06:04 -0700163 e->supported ? ": available" : "");
164 }
165}
166
Jin Yao4a9086a2021-05-27 08:16:07 +0800167static void perf_mem_events__print_unsupport_hybrid(struct perf_mem_event *e,
168 int idx)
169{
170 const char *mnt = sysfs__mount();
171 char sysfs_name[100];
172 struct perf_pmu *pmu;
173
174 perf_pmu__for_each_hybrid_pmu(pmu) {
175 scnprintf(sysfs_name, sizeof(sysfs_name), e->sysfs_name,
176 pmu->name);
177 if (!perf_mem_event__supported(mnt, sysfs_name)) {
178 pr_err("failed: event '%s' not supported\n",
179 perf_mem_events__name(idx, pmu->name));
180 }
181 }
182}
183
184int perf_mem_events__record_args(const char **rec_argv, int *argv_nr,
185 char **rec_tmp, int *tmp_nr)
186{
187 int i = *argv_nr, k = 0;
188 struct perf_mem_event *e;
189 struct perf_pmu *pmu;
190 char *s;
191
192 for (int j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
193 e = perf_mem_events__ptr(j);
194 if (!e->record)
195 continue;
196
197 if (!perf_pmu__has_hybrid()) {
198 if (!e->supported) {
199 pr_err("failed: event '%s' not supported\n",
200 perf_mem_events__name(j, NULL));
201 return -1;
202 }
203
204 rec_argv[i++] = "-e";
205 rec_argv[i++] = perf_mem_events__name(j, NULL);
206 } else {
207 if (!e->supported) {
208 perf_mem_events__print_unsupport_hybrid(e, j);
209 return -1;
210 }
211
212 perf_pmu__for_each_hybrid_pmu(pmu) {
213 rec_argv[i++] = "-e";
214 s = perf_mem_events__name(j, pmu->name);
215 if (s) {
216 s = strdup(s);
217 if (!s)
218 return -1;
219
220 rec_argv[i++] = s;
221 rec_tmp[k++] = s;
222 }
223 }
224 }
225 }
226
227 *argv_nr = i;
228 *tmp_nr = k;
229 return 0;
230}
231
Jiri Olsa0c877d72016-02-24 09:46:46 +0100232static const char * const tlb_access[] = {
233 "N/A",
234 "HIT",
235 "MISS",
236 "L1",
237 "L2",
238 "Walker",
239 "Fault",
240};
241
Jiri Olsab1a5fbea2016-02-24 09:46:50 +0100242int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
Jiri Olsa0c877d72016-02-24 09:46:46 +0100243{
244 size_t l = 0, i;
245 u64 m = PERF_MEM_TLB_NA;
246 u64 hit, miss;
247
248 sz -= 1; /* -1 for null termination */
249 out[0] = '\0';
250
251 if (mem_info)
252 m = mem_info->data_src.mem_dtlb;
253
254 hit = m & PERF_MEM_TLB_HIT;
255 miss = m & PERF_MEM_TLB_MISS;
256
257 /* already taken care of */
258 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
259
260 for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
261 if (!(m & 0x1))
262 continue;
263 if (l) {
264 strcat(out, " or ");
265 l += 4;
266 }
Jiri Olsab1a5fbea2016-02-24 09:46:50 +0100267 l += scnprintf(out + l, sz - l, tlb_access[i]);
Jiri Olsa0c877d72016-02-24 09:46:46 +0100268 }
269 if (*out == '\0')
Jiri Olsab1a5fbea2016-02-24 09:46:50 +0100270 l += scnprintf(out, sz - l, "N/A");
Jiri Olsa0c877d72016-02-24 09:46:46 +0100271 if (hit)
Jiri Olsab1a5fbea2016-02-24 09:46:50 +0100272 l += scnprintf(out + l, sz - l, " hit");
Jiri Olsa0c877d72016-02-24 09:46:46 +0100273 if (miss)
Jiri Olsab1a5fbea2016-02-24 09:46:50 +0100274 l += scnprintf(out + l, sz - l, " miss");
275
276 return l;
Jiri Olsa0c877d72016-02-24 09:46:46 +0100277}
Jiri Olsa071e9a12016-02-24 09:46:47 +0100278
279static const char * const mem_lvl[] = {
280 "N/A",
281 "HIT",
282 "MISS",
283 "L1",
284 "LFB",
285 "L2",
286 "L3",
287 "Local RAM",
288 "Remote RAM (1 hop)",
289 "Remote RAM (2 hops)",
290 "Remote Cache (1 hop)",
291 "Remote Cache (2 hops)",
292 "I/O",
293 "Uncached",
294};
295
Andi Kleen52839e62017-08-16 15:21:55 -0700296static const char * const mem_lvlnum[] = {
297 [PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache",
298 [PERF_MEM_LVLNUM_LFB] = "LFB",
299 [PERF_MEM_LVLNUM_RAM] = "RAM",
300 [PERF_MEM_LVLNUM_PMEM] = "PMEM",
301 [PERF_MEM_LVLNUM_NA] = "N/A",
302};
303
Kajol Jaincae1d752021-10-06 19:36:53 +0530304static const char * const mem_hops[] = {
305 "N/A",
306 /*
307 * While printing, 'Remote' will be added to represent
308 * 'Remote core, same node' accesses as remote field need
309 * to be set with mem_hops field.
310 */
311 "core, same node",
Kajol Jain7fbddf42021-12-06 14:47:47 +0530312 "node, same socket",
313 "socket, same board",
314 "board",
Kajol Jaincae1d752021-10-06 19:36:53 +0530315};
316
Jiri Olsa96907562016-02-24 09:46:51 +0100317int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
Jiri Olsa071e9a12016-02-24 09:46:47 +0100318{
319 size_t i, l = 0;
320 u64 m = PERF_MEM_LVL_NA;
321 u64 hit, miss;
Kajol Jain7fbddf42021-12-06 14:47:47 +0530322 int printed = 0;
Jiri Olsa071e9a12016-02-24 09:46:47 +0100323
324 if (mem_info)
325 m = mem_info->data_src.mem_lvl;
326
327 sz -= 1; /* -1 for null termination */
328 out[0] = '\0';
329
330 hit = m & PERF_MEM_LVL_HIT;
331 miss = m & PERF_MEM_LVL_MISS;
332
333 /* already taken care of */
334 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
335
Andi Kleen52839e62017-08-16 15:21:55 -0700336 if (mem_info && mem_info->data_src.mem_remote) {
337 strcat(out, "Remote ");
338 l += 7;
339 }
340
Kajol Jain7fbddf42021-12-06 14:47:47 +0530341 /*
342 * Incase mem_hops field is set, we can skip printing data source via
343 * PERF_MEM_LVL namespace.
344 */
345 if (mem_info && mem_info->data_src.mem_hops) {
Kajol Jaincae1d752021-10-06 19:36:53 +0530346 l += scnprintf(out + l, sz - l, "%s ", mem_hops[mem_info->data_src.mem_hops]);
Kajol Jain7fbddf42021-12-06 14:47:47 +0530347 } else {
348 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
349 if (!(m & 0x1))
350 continue;
351 if (printed++) {
352 strcat(out, " or ");
353 l += 4;
354 }
355 l += scnprintf(out + l, sz - l, mem_lvl[i]);
Jiri Olsa071e9a12016-02-24 09:46:47 +0100356 }
Jiri Olsa071e9a12016-02-24 09:46:47 +0100357 }
Andi Kleen52839e62017-08-16 15:21:55 -0700358
359 if (mem_info && mem_info->data_src.mem_lvl_num) {
360 int lvl = mem_info->data_src.mem_lvl_num;
361 if (printed++) {
362 strcat(out, " or ");
363 l += 4;
364 }
365 if (mem_lvlnum[lvl])
366 l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]);
367 else
368 l += scnprintf(out + l, sz - l, "L%d", lvl);
369 }
370
371 if (l == 0)
372 l += scnprintf(out + l, sz - l, "N/A");
Jiri Olsa071e9a12016-02-24 09:46:47 +0100373 if (hit)
Jiri Olsa96907562016-02-24 09:46:51 +0100374 l += scnprintf(out + l, sz - l, " hit");
Jiri Olsa071e9a12016-02-24 09:46:47 +0100375 if (miss)
Jiri Olsa96907562016-02-24 09:46:51 +0100376 l += scnprintf(out + l, sz - l, " miss");
377
378 return l;
Jiri Olsa071e9a12016-02-24 09:46:47 +0100379}
Jiri Olsa2c07af12016-02-24 09:46:48 +0100380
381static const char * const snoop_access[] = {
382 "N/A",
383 "None",
Jiri Olsa2c07af12016-02-24 09:46:48 +0100384 "Hit",
Andi Kleen166ebdd2017-04-19 10:49:40 -0700385 "Miss",
Jiri Olsa2c07af12016-02-24 09:46:48 +0100386 "HitM",
387};
388
Jiri Olsa149d7502016-02-24 09:46:52 +0100389int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
Jiri Olsa2c07af12016-02-24 09:46:48 +0100390{
391 size_t i, l = 0;
392 u64 m = PERF_MEM_SNOOP_NA;
393
394 sz -= 1; /* -1 for null termination */
395 out[0] = '\0';
396
397 if (mem_info)
398 m = mem_info->data_src.mem_snoop;
399
400 for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
401 if (!(m & 0x1))
402 continue;
403 if (l) {
404 strcat(out, " or ");
405 l += 4;
406 }
Jiri Olsa149d7502016-02-24 09:46:52 +0100407 l += scnprintf(out + l, sz - l, snoop_access[i]);
Jiri Olsa2c07af12016-02-24 09:46:48 +0100408 }
Andi Kleen52839e62017-08-16 15:21:55 -0700409 if (mem_info &&
410 (mem_info->data_src.mem_snoopx & PERF_MEM_SNOOPX_FWD)) {
411 if (l) {
412 strcat(out, " or ");
413 l += 4;
414 }
415 l += scnprintf(out + l, sz - l, "Fwd");
416 }
Jiri Olsa2c07af12016-02-24 09:46:48 +0100417
418 if (*out == '\0')
Jiri Olsa149d7502016-02-24 09:46:52 +0100419 l += scnprintf(out, sz - l, "N/A");
420
421 return l;
Jiri Olsa2c07af12016-02-24 09:46:48 +0100422}
Jiri Olsa69a77272016-02-24 09:46:49 +0100423
Jiri Olsa8b0819c2016-02-24 09:46:53 +0100424int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
Jiri Olsa69a77272016-02-24 09:46:49 +0100425{
426 u64 mask = PERF_MEM_LOCK_NA;
Jiri Olsa8b0819c2016-02-24 09:46:53 +0100427 int l;
Jiri Olsa69a77272016-02-24 09:46:49 +0100428
429 if (mem_info)
430 mask = mem_info->data_src.mem_lock;
431
432 if (mask & PERF_MEM_LOCK_NA)
Jiri Olsa8b0819c2016-02-24 09:46:53 +0100433 l = scnprintf(out, sz, "N/A");
Jiri Olsa69a77272016-02-24 09:46:49 +0100434 else if (mask & PERF_MEM_LOCK_LOCKED)
Jiri Olsa8b0819c2016-02-24 09:46:53 +0100435 l = scnprintf(out, sz, "Yes");
Jiri Olsa69a77272016-02-24 09:46:49 +0100436 else
Jiri Olsa8b0819c2016-02-24 09:46:53 +0100437 l = scnprintf(out, sz, "No");
438
439 return l;
Jiri Olsa69a77272016-02-24 09:46:49 +0100440}
Jiri Olsac19ac912016-02-24 09:46:54 +0100441
Kan Lianga054c292021-02-02 12:09:07 -0800442int perf_mem__blk_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
443{
444 size_t l = 0;
445 u64 mask = PERF_MEM_BLK_NA;
446
447 sz -= 1; /* -1 for null termination */
448 out[0] = '\0';
449
450 if (mem_info)
451 mask = mem_info->data_src.mem_blk;
452
453 if (!mask || (mask & PERF_MEM_BLK_NA)) {
454 l += scnprintf(out + l, sz - l, " N/A");
455 return l;
456 }
457 if (mask & PERF_MEM_BLK_DATA)
458 l += scnprintf(out + l, sz - l, " Data");
459 if (mask & PERF_MEM_BLK_ADDR)
460 l += scnprintf(out + l, sz - l, " Addr");
461
462 return l;
463}
464
Jiri Olsac19ac912016-02-24 09:46:54 +0100465int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
466{
467 int i = 0;
468
469 i += perf_mem__lvl_scnprintf(out, sz, mem_info);
470 i += scnprintf(out + i, sz - i, "|SNP ");
471 i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
472 i += scnprintf(out + i, sz - i, "|TLB ");
473 i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
474 i += scnprintf(out + i, sz - i, "|LCK ");
475 i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
Kan Lianga054c292021-02-02 12:09:07 -0800476 i += scnprintf(out + i, sz - i, "|BLK ");
477 i += perf_mem__blk_scnprintf(out + i, sz - i, mem_info);
Jiri Olsac19ac912016-02-24 09:46:54 +0100478
479 return i;
480}
Jiri Olsaaadddd62016-09-22 17:36:30 +0200481
482int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
483{
484 union perf_mem_data_src *data_src = &mi->data_src;
485 u64 daddr = mi->daddr.addr;
486 u64 op = data_src->mem_op;
487 u64 lvl = data_src->mem_lvl;
488 u64 snoop = data_src->mem_snoop;
489 u64 lock = data_src->mem_lock;
Kan Liangd9d5d7672021-02-02 12:09:08 -0800490 u64 blk = data_src->mem_blk;
Jiri Olsa12c15302017-08-24 10:57:32 +0200491 /*
492 * Skylake might report unknown remote level via this
493 * bit, consider it when evaluating remote HITMs.
Kajol Jaincae1d752021-10-06 19:36:53 +0530494 *
495 * Incase of power, remote field can also be used to denote cache
496 * accesses from the another core of same node. Hence, setting
497 * mrem only when HOPS is zero along with set remote field.
Jiri Olsa12c15302017-08-24 10:57:32 +0200498 */
Kajol Jaincae1d752021-10-06 19:36:53 +0530499 bool mrem = (data_src->mem_remote && !data_src->mem_hops);
Jiri Olsaaadddd62016-09-22 17:36:30 +0200500 int err = 0;
501
Jiri Olsadba8ab92016-11-21 22:33:29 +0100502#define HITM_INC(__f) \
503do { \
504 stats->__f++; \
505 stats->tot_hitm++; \
506} while (0)
507
Jiri Olsaaadddd62016-09-22 17:36:30 +0200508#define P(a, b) PERF_MEM_##a##_##b
509
510 stats->nr_entries++;
511
512 if (lock & P(LOCK, LOCKED)) stats->locks++;
513
Kan Liangd9d5d7672021-02-02 12:09:08 -0800514 if (blk & P(BLK, DATA)) stats->blk_data++;
515 if (blk & P(BLK, ADDR)) stats->blk_addr++;
516
Jiri Olsaaadddd62016-09-22 17:36:30 +0200517 if (op & P(OP, LOAD)) {
518 /* load */
519 stats->load++;
520
521 if (!daddr) {
522 stats->ld_noadrs++;
523 return -1;
524 }
525
526 if (lvl & P(LVL, HIT)) {
527 if (lvl & P(LVL, UNC)) stats->ld_uncache++;
528 if (lvl & P(LVL, IO)) stats->ld_io++;
529 if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
530 if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
531 if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
532 if (lvl & P(LVL, L3 )) {
533 if (snoop & P(SNOOP, HITM))
Jiri Olsadba8ab92016-11-21 22:33:29 +0100534 HITM_INC(lcl_hitm);
Jiri Olsaaadddd62016-09-22 17:36:30 +0200535 else
536 stats->ld_llchit++;
537 }
538
539 if (lvl & P(LVL, LOC_RAM)) {
540 stats->lcl_dram++;
541 if (snoop & P(SNOOP, HIT))
542 stats->ld_shared++;
543 else
544 stats->ld_excl++;
545 }
546
547 if ((lvl & P(LVL, REM_RAM1)) ||
Jiri Olsa12c15302017-08-24 10:57:32 +0200548 (lvl & P(LVL, REM_RAM2)) ||
549 mrem) {
Jiri Olsaaadddd62016-09-22 17:36:30 +0200550 stats->rmt_dram++;
551 if (snoop & P(SNOOP, HIT))
552 stats->ld_shared++;
553 else
554 stats->ld_excl++;
555 }
556 }
557
558 if ((lvl & P(LVL, REM_CCE1)) ||
Jiri Olsa12c15302017-08-24 10:57:32 +0200559 (lvl & P(LVL, REM_CCE2)) ||
560 mrem) {
Jiri Olsaaadddd62016-09-22 17:36:30 +0200561 if (snoop & P(SNOOP, HIT))
562 stats->rmt_hit++;
563 else if (snoop & P(SNOOP, HITM))
Jiri Olsadba8ab92016-11-21 22:33:29 +0100564 HITM_INC(rmt_hitm);
Jiri Olsaaadddd62016-09-22 17:36:30 +0200565 }
566
567 if ((lvl & P(LVL, MISS)))
568 stats->ld_miss++;
569
570 } else if (op & P(OP, STORE)) {
571 /* store */
572 stats->store++;
573
574 if (!daddr) {
575 stats->st_noadrs++;
576 return -1;
577 }
578
579 if (lvl & P(LVL, HIT)) {
580 if (lvl & P(LVL, UNC)) stats->st_uncache++;
581 if (lvl & P(LVL, L1 )) stats->st_l1hit++;
582 }
583 if (lvl & P(LVL, MISS))
584 if (lvl & P(LVL, L1)) stats->st_l1miss++;
585 } else {
586 /* unparsable data_src? */
587 stats->noparse++;
588 return -1;
589 }
590
Arnaldo Carvalho de Melod46a4cd2019-11-04 15:57:38 -0300591 if (!mi->daddr.ms.map || !mi->iaddr.ms.map) {
Jiri Olsaaadddd62016-09-22 17:36:30 +0200592 stats->nomap++;
593 return -1;
594 }
595
596#undef P
Jiri Olsadba8ab92016-11-21 22:33:29 +0100597#undef HITM_INC
Jiri Olsaaadddd62016-09-22 17:36:30 +0200598 return err;
599}
Jiri Olsa0a9a24c2016-09-22 17:36:31 +0200600
601void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
602{
603 stats->nr_entries += add->nr_entries;
604
605 stats->locks += add->locks;
606 stats->store += add->store;
607 stats->st_uncache += add->st_uncache;
608 stats->st_noadrs += add->st_noadrs;
609 stats->st_l1hit += add->st_l1hit;
610 stats->st_l1miss += add->st_l1miss;
611 stats->load += add->load;
612 stats->ld_excl += add->ld_excl;
613 stats->ld_shared += add->ld_shared;
614 stats->ld_uncache += add->ld_uncache;
615 stats->ld_io += add->ld_io;
616 stats->ld_miss += add->ld_miss;
617 stats->ld_noadrs += add->ld_noadrs;
618 stats->ld_fbhit += add->ld_fbhit;
619 stats->ld_l1hit += add->ld_l1hit;
620 stats->ld_l2hit += add->ld_l2hit;
621 stats->ld_llchit += add->ld_llchit;
622 stats->lcl_hitm += add->lcl_hitm;
623 stats->rmt_hitm += add->rmt_hitm;
Jiri Olsadba8ab92016-11-21 22:33:29 +0100624 stats->tot_hitm += add->tot_hitm;
Jiri Olsa0a9a24c2016-09-22 17:36:31 +0200625 stats->rmt_hit += add->rmt_hit;
626 stats->lcl_dram += add->lcl_dram;
627 stats->rmt_dram += add->rmt_dram;
Kan Liangd9d5d7672021-02-02 12:09:08 -0800628 stats->blk_data += add->blk_data;
629 stats->blk_addr += add->blk_addr;
Jiri Olsa0a9a24c2016-09-22 17:36:31 +0200630 stats->nomap += add->nomap;
631 stats->noparse += add->noparse;
632}