xref: /openbmc/linux/tools/perf/util/mem-events.c (revision b2441318)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2ce1e22b0SJiri Olsa #include <stddef.h>
3ce1e22b0SJiri Olsa #include <stdlib.h>
4ce1e22b0SJiri Olsa #include <string.h>
5ce1e22b0SJiri Olsa #include <errno.h>
654fbad54SJiri Olsa #include <sys/types.h>
754fbad54SJiri Olsa #include <sys/stat.h>
854fbad54SJiri Olsa #include <unistd.h>
954fbad54SJiri Olsa #include <api/fs/fs.h>
10877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h>
11acbe613eSJiri Olsa #include "mem-events.h"
12ce1e22b0SJiri Olsa #include "debug.h"
130c877d75SJiri Olsa #include "symbol.h"
14aadddd68SJiri Olsa #include "sort.h"
15acbe613eSJiri Olsa 
16b0d745b3SJiri Olsa unsigned int perf_mem_events__loads_ldlat = 30;
17b0d745b3SJiri Olsa 
1854fbad54SJiri Olsa #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
19acbe613eSJiri Olsa 
20acbe613eSJiri Olsa struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
21b0d745b3SJiri Olsa 	E("ldlat-loads",	"cpu/mem-loads,ldlat=%u/P",	"mem-loads"),
2254fbad54SJiri Olsa 	E("ldlat-stores",	"cpu/mem-stores/P",		"mem-stores"),
23acbe613eSJiri Olsa };
2454fbad54SJiri Olsa #undef E
25acbe613eSJiri Olsa 
26acbe613eSJiri Olsa #undef E
27ce1e22b0SJiri Olsa 
28b0d745b3SJiri Olsa static char mem_loads_name[100];
29b0d745b3SJiri Olsa static bool mem_loads_name__init;
30b0d745b3SJiri Olsa 
312ba7ac58SJiri Olsa char *perf_mem_events__name(int i)
322ba7ac58SJiri Olsa {
33b0d745b3SJiri Olsa 	if (i == PERF_MEM_EVENTS__LOAD) {
34b0d745b3SJiri Olsa 		if (!mem_loads_name__init) {
35b0d745b3SJiri Olsa 			mem_loads_name__init = true;
36b0d745b3SJiri Olsa 			scnprintf(mem_loads_name, sizeof(mem_loads_name),
37b0d745b3SJiri Olsa 				  perf_mem_events[i].name,
38b0d745b3SJiri Olsa 				  perf_mem_events__loads_ldlat);
39b0d745b3SJiri Olsa 		}
40b0d745b3SJiri Olsa 		return mem_loads_name;
41b0d745b3SJiri Olsa 	}
42b0d745b3SJiri Olsa 
432ba7ac58SJiri Olsa 	return (char *)perf_mem_events[i].name;
442ba7ac58SJiri Olsa }
452ba7ac58SJiri Olsa 
46ce1e22b0SJiri Olsa int perf_mem_events__parse(const char *str)
47ce1e22b0SJiri Olsa {
48ce1e22b0SJiri Olsa 	char *tok, *saveptr = NULL;
49ce1e22b0SJiri Olsa 	bool found = false;
50ce1e22b0SJiri Olsa 	char *buf;
51ce1e22b0SJiri Olsa 	int j;
52ce1e22b0SJiri Olsa 
53ce1e22b0SJiri Olsa 	/* We need buffer that we know we can write to. */
54ce1e22b0SJiri Olsa 	buf = malloc(strlen(str) + 1);
55ce1e22b0SJiri Olsa 	if (!buf)
56ce1e22b0SJiri Olsa 		return -ENOMEM;
57ce1e22b0SJiri Olsa 
58ce1e22b0SJiri Olsa 	strcpy(buf, str);
59ce1e22b0SJiri Olsa 
60ce1e22b0SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
61ce1e22b0SJiri Olsa 
62ce1e22b0SJiri Olsa 	while (tok) {
63ce1e22b0SJiri Olsa 		for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
64ce1e22b0SJiri Olsa 			struct perf_mem_event *e = &perf_mem_events[j];
65ce1e22b0SJiri Olsa 
66ce1e22b0SJiri Olsa 			if (strstr(e->tag, tok))
67ce1e22b0SJiri Olsa 				e->record = found = true;
68ce1e22b0SJiri Olsa 		}
69ce1e22b0SJiri Olsa 
70ce1e22b0SJiri Olsa 		tok = strtok_r(NULL, ",", &saveptr);
71ce1e22b0SJiri Olsa 	}
72ce1e22b0SJiri Olsa 
73ce1e22b0SJiri Olsa 	free(buf);
74ce1e22b0SJiri Olsa 
75ce1e22b0SJiri Olsa 	if (found)
76ce1e22b0SJiri Olsa 		return 0;
77ce1e22b0SJiri Olsa 
78ce1e22b0SJiri Olsa 	pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
79ce1e22b0SJiri Olsa 	return -1;
80ce1e22b0SJiri Olsa }
8154fbad54SJiri Olsa 
8254fbad54SJiri Olsa int perf_mem_events__init(void)
8354fbad54SJiri Olsa {
8454fbad54SJiri Olsa 	const char *mnt = sysfs__mount();
8554fbad54SJiri Olsa 	bool found = false;
8654fbad54SJiri Olsa 	int j;
8754fbad54SJiri Olsa 
8854fbad54SJiri Olsa 	if (!mnt)
8954fbad54SJiri Olsa 		return -ENOENT;
9054fbad54SJiri Olsa 
9154fbad54SJiri Olsa 	for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
9254fbad54SJiri Olsa 		char path[PATH_MAX];
9354fbad54SJiri Olsa 		struct perf_mem_event *e = &perf_mem_events[j];
9454fbad54SJiri Olsa 		struct stat st;
9554fbad54SJiri Olsa 
9654fbad54SJiri Olsa 		scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
9754fbad54SJiri Olsa 			  mnt, e->sysfs_name);
9854fbad54SJiri Olsa 
9954fbad54SJiri Olsa 		if (!stat(path, &st))
10054fbad54SJiri Olsa 			e->supported = found = true;
10154fbad54SJiri Olsa 	}
10254fbad54SJiri Olsa 
10354fbad54SJiri Olsa 	return found ? 0 : -ENOENT;
10454fbad54SJiri Olsa }
1050c877d75SJiri Olsa 
1060c877d75SJiri Olsa static const char * const tlb_access[] = {
1070c877d75SJiri Olsa 	"N/A",
1080c877d75SJiri Olsa 	"HIT",
1090c877d75SJiri Olsa 	"MISS",
1100c877d75SJiri Olsa 	"L1",
1110c877d75SJiri Olsa 	"L2",
1120c877d75SJiri Olsa 	"Walker",
1130c877d75SJiri Olsa 	"Fault",
1140c877d75SJiri Olsa };
1150c877d75SJiri Olsa 
116b1a5fbeaSJiri Olsa int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
1170c877d75SJiri Olsa {
1180c877d75SJiri Olsa 	size_t l = 0, i;
1190c877d75SJiri Olsa 	u64 m = PERF_MEM_TLB_NA;
1200c877d75SJiri Olsa 	u64 hit, miss;
1210c877d75SJiri Olsa 
1220c877d75SJiri Olsa 	sz -= 1; /* -1 for null termination */
1230c877d75SJiri Olsa 	out[0] = '\0';
1240c877d75SJiri Olsa 
1250c877d75SJiri Olsa 	if (mem_info)
1260c877d75SJiri Olsa 		m = mem_info->data_src.mem_dtlb;
1270c877d75SJiri Olsa 
1280c877d75SJiri Olsa 	hit = m & PERF_MEM_TLB_HIT;
1290c877d75SJiri Olsa 	miss = m & PERF_MEM_TLB_MISS;
1300c877d75SJiri Olsa 
1310c877d75SJiri Olsa 	/* already taken care of */
1320c877d75SJiri Olsa 	m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
1330c877d75SJiri Olsa 
1340c877d75SJiri Olsa 	for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
1350c877d75SJiri Olsa 		if (!(m & 0x1))
1360c877d75SJiri Olsa 			continue;
1370c877d75SJiri Olsa 		if (l) {
1380c877d75SJiri Olsa 			strcat(out, " or ");
1390c877d75SJiri Olsa 			l += 4;
1400c877d75SJiri Olsa 		}
141b1a5fbeaSJiri Olsa 		l += scnprintf(out + l, sz - l, tlb_access[i]);
1420c877d75SJiri Olsa 	}
1430c877d75SJiri Olsa 	if (*out == '\0')
144b1a5fbeaSJiri Olsa 		l += scnprintf(out, sz - l, "N/A");
1450c877d75SJiri Olsa 	if (hit)
146b1a5fbeaSJiri Olsa 		l += scnprintf(out + l, sz - l, " hit");
1470c877d75SJiri Olsa 	if (miss)
148b1a5fbeaSJiri Olsa 		l += scnprintf(out + l, sz - l, " miss");
149b1a5fbeaSJiri Olsa 
150b1a5fbeaSJiri Olsa 	return l;
1510c877d75SJiri Olsa }
152071e9a1eSJiri Olsa 
153071e9a1eSJiri Olsa static const char * const mem_lvl[] = {
154071e9a1eSJiri Olsa 	"N/A",
155071e9a1eSJiri Olsa 	"HIT",
156071e9a1eSJiri Olsa 	"MISS",
157071e9a1eSJiri Olsa 	"L1",
158071e9a1eSJiri Olsa 	"LFB",
159071e9a1eSJiri Olsa 	"L2",
160071e9a1eSJiri Olsa 	"L3",
161071e9a1eSJiri Olsa 	"Local RAM",
162071e9a1eSJiri Olsa 	"Remote RAM (1 hop)",
163071e9a1eSJiri Olsa 	"Remote RAM (2 hops)",
164071e9a1eSJiri Olsa 	"Remote Cache (1 hop)",
165071e9a1eSJiri Olsa 	"Remote Cache (2 hops)",
166071e9a1eSJiri Olsa 	"I/O",
167071e9a1eSJiri Olsa 	"Uncached",
168071e9a1eSJiri Olsa };
169071e9a1eSJiri Olsa 
17052839e65SAndi Kleen static const char * const mem_lvlnum[] = {
17152839e65SAndi Kleen 	[PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache",
17252839e65SAndi Kleen 	[PERF_MEM_LVLNUM_LFB] = "LFB",
17352839e65SAndi Kleen 	[PERF_MEM_LVLNUM_RAM] = "RAM",
17452839e65SAndi Kleen 	[PERF_MEM_LVLNUM_PMEM] = "PMEM",
17552839e65SAndi Kleen 	[PERF_MEM_LVLNUM_NA] = "N/A",
17652839e65SAndi Kleen };
17752839e65SAndi Kleen 
17896907563SJiri Olsa int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
179071e9a1eSJiri Olsa {
180071e9a1eSJiri Olsa 	size_t i, l = 0;
181071e9a1eSJiri Olsa 	u64 m =  PERF_MEM_LVL_NA;
182071e9a1eSJiri Olsa 	u64 hit, miss;
18352839e65SAndi Kleen 	int printed;
184071e9a1eSJiri Olsa 
185071e9a1eSJiri Olsa 	if (mem_info)
186071e9a1eSJiri Olsa 		m  = mem_info->data_src.mem_lvl;
187071e9a1eSJiri Olsa 
188071e9a1eSJiri Olsa 	sz -= 1; /* -1 for null termination */
189071e9a1eSJiri Olsa 	out[0] = '\0';
190071e9a1eSJiri Olsa 
191071e9a1eSJiri Olsa 	hit = m & PERF_MEM_LVL_HIT;
192071e9a1eSJiri Olsa 	miss = m & PERF_MEM_LVL_MISS;
193071e9a1eSJiri Olsa 
194071e9a1eSJiri Olsa 	/* already taken care of */
195071e9a1eSJiri Olsa 	m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
196071e9a1eSJiri Olsa 
19752839e65SAndi Kleen 
19852839e65SAndi Kleen 	if (mem_info && mem_info->data_src.mem_remote) {
19952839e65SAndi Kleen 		strcat(out, "Remote ");
20052839e65SAndi Kleen 		l += 7;
20152839e65SAndi Kleen 	}
20252839e65SAndi Kleen 
20352839e65SAndi Kleen 	printed = 0;
204071e9a1eSJiri Olsa 	for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
205071e9a1eSJiri Olsa 		if (!(m & 0x1))
206071e9a1eSJiri Olsa 			continue;
20752839e65SAndi Kleen 		if (printed++) {
208071e9a1eSJiri Olsa 			strcat(out, " or ");
209071e9a1eSJiri Olsa 			l += 4;
210071e9a1eSJiri Olsa 		}
21196907563SJiri Olsa 		l += scnprintf(out + l, sz - l, mem_lvl[i]);
212071e9a1eSJiri Olsa 	}
21352839e65SAndi Kleen 
21452839e65SAndi Kleen 	if (mem_info && mem_info->data_src.mem_lvl_num) {
21552839e65SAndi Kleen 		int lvl = mem_info->data_src.mem_lvl_num;
21652839e65SAndi Kleen 		if (printed++) {
21752839e65SAndi Kleen 			strcat(out, " or ");
21852839e65SAndi Kleen 			l += 4;
21952839e65SAndi Kleen 		}
22052839e65SAndi Kleen 		if (mem_lvlnum[lvl])
22152839e65SAndi Kleen 			l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]);
22252839e65SAndi Kleen 		else
22352839e65SAndi Kleen 			l += scnprintf(out + l, sz - l, "L%d", lvl);
22452839e65SAndi Kleen 	}
22552839e65SAndi Kleen 
22652839e65SAndi Kleen 	if (l == 0)
22752839e65SAndi Kleen 		l += scnprintf(out + l, sz - l, "N/A");
228071e9a1eSJiri Olsa 	if (hit)
22996907563SJiri Olsa 		l += scnprintf(out + l, sz - l, " hit");
230071e9a1eSJiri Olsa 	if (miss)
23196907563SJiri Olsa 		l += scnprintf(out + l, sz - l, " miss");
23296907563SJiri Olsa 
23396907563SJiri Olsa 	return l;
234071e9a1eSJiri Olsa }
2352c07af13SJiri Olsa 
2362c07af13SJiri Olsa static const char * const snoop_access[] = {
2372c07af13SJiri Olsa 	"N/A",
2382c07af13SJiri Olsa 	"None",
2392c07af13SJiri Olsa 	"Hit",
240166ebdd2SAndi Kleen 	"Miss",
2412c07af13SJiri Olsa 	"HitM",
2422c07af13SJiri Olsa };
2432c07af13SJiri Olsa 
244149d7507SJiri Olsa int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
2452c07af13SJiri Olsa {
2462c07af13SJiri Olsa 	size_t i, l = 0;
2472c07af13SJiri Olsa 	u64 m = PERF_MEM_SNOOP_NA;
2482c07af13SJiri Olsa 
2492c07af13SJiri Olsa 	sz -= 1; /* -1 for null termination */
2502c07af13SJiri Olsa 	out[0] = '\0';
2512c07af13SJiri Olsa 
2522c07af13SJiri Olsa 	if (mem_info)
2532c07af13SJiri Olsa 		m = mem_info->data_src.mem_snoop;
2542c07af13SJiri Olsa 
2552c07af13SJiri Olsa 	for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
2562c07af13SJiri Olsa 		if (!(m & 0x1))
2572c07af13SJiri Olsa 			continue;
2582c07af13SJiri Olsa 		if (l) {
2592c07af13SJiri Olsa 			strcat(out, " or ");
2602c07af13SJiri Olsa 			l += 4;
2612c07af13SJiri Olsa 		}
262149d7507SJiri Olsa 		l += scnprintf(out + l, sz - l, snoop_access[i]);
2632c07af13SJiri Olsa 	}
26452839e65SAndi Kleen 	if (mem_info &&
26552839e65SAndi Kleen 	     (mem_info->data_src.mem_snoopx & PERF_MEM_SNOOPX_FWD)) {
26652839e65SAndi Kleen 		if (l) {
26752839e65SAndi Kleen 			strcat(out, " or ");
26852839e65SAndi Kleen 			l += 4;
26952839e65SAndi Kleen 		}
27052839e65SAndi Kleen 		l += scnprintf(out + l, sz - l, "Fwd");
27152839e65SAndi Kleen 	}
2722c07af13SJiri Olsa 
2732c07af13SJiri Olsa 	if (*out == '\0')
274149d7507SJiri Olsa 		l += scnprintf(out, sz - l, "N/A");
275149d7507SJiri Olsa 
276149d7507SJiri Olsa 	return l;
2772c07af13SJiri Olsa }
27869a77275SJiri Olsa 
2798b0819c8SJiri Olsa int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
28069a77275SJiri Olsa {
28169a77275SJiri Olsa 	u64 mask = PERF_MEM_LOCK_NA;
2828b0819c8SJiri Olsa 	int l;
28369a77275SJiri Olsa 
28469a77275SJiri Olsa 	if (mem_info)
28569a77275SJiri Olsa 		mask = mem_info->data_src.mem_lock;
28669a77275SJiri Olsa 
28769a77275SJiri Olsa 	if (mask & PERF_MEM_LOCK_NA)
2888b0819c8SJiri Olsa 		l = scnprintf(out, sz, "N/A");
28969a77275SJiri Olsa 	else if (mask & PERF_MEM_LOCK_LOCKED)
2908b0819c8SJiri Olsa 		l = scnprintf(out, sz, "Yes");
29169a77275SJiri Olsa 	else
2928b0819c8SJiri Olsa 		l = scnprintf(out, sz, "No");
2938b0819c8SJiri Olsa 
2948b0819c8SJiri Olsa 	return l;
29569a77275SJiri Olsa }
296c19ac912SJiri Olsa 
297c19ac912SJiri Olsa int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
298c19ac912SJiri Olsa {
299c19ac912SJiri Olsa 	int i = 0;
300c19ac912SJiri Olsa 
301c19ac912SJiri Olsa 	i += perf_mem__lvl_scnprintf(out, sz, mem_info);
302c19ac912SJiri Olsa 	i += scnprintf(out + i, sz - i, "|SNP ");
303c19ac912SJiri Olsa 	i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
304c19ac912SJiri Olsa 	i += scnprintf(out + i, sz - i, "|TLB ");
305c19ac912SJiri Olsa 	i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
306c19ac912SJiri Olsa 	i += scnprintf(out + i, sz - i, "|LCK ");
307c19ac912SJiri Olsa 	i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
308c19ac912SJiri Olsa 
309c19ac912SJiri Olsa 	return i;
310c19ac912SJiri Olsa }
311aadddd68SJiri Olsa 
312aadddd68SJiri Olsa int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
313aadddd68SJiri Olsa {
314aadddd68SJiri Olsa 	union perf_mem_data_src *data_src = &mi->data_src;
315aadddd68SJiri Olsa 	u64 daddr  = mi->daddr.addr;
316aadddd68SJiri Olsa 	u64 op     = data_src->mem_op;
317aadddd68SJiri Olsa 	u64 lvl    = data_src->mem_lvl;
318aadddd68SJiri Olsa 	u64 snoop  = data_src->mem_snoop;
319aadddd68SJiri Olsa 	u64 lock   = data_src->mem_lock;
32012c15302SJiri Olsa 	/*
32112c15302SJiri Olsa 	 * Skylake might report unknown remote level via this
32212c15302SJiri Olsa 	 * bit, consider it when evaluating remote HITMs.
32312c15302SJiri Olsa 	 */
32412c15302SJiri Olsa 	bool mrem  = data_src->mem_remote;
325aadddd68SJiri Olsa 	int err = 0;
326aadddd68SJiri Olsa 
327dba8ab93SJiri Olsa #define HITM_INC(__f)		\
328dba8ab93SJiri Olsa do {				\
329dba8ab93SJiri Olsa 	stats->__f++;		\
330dba8ab93SJiri Olsa 	stats->tot_hitm++;	\
331dba8ab93SJiri Olsa } while (0)
332dba8ab93SJiri Olsa 
333aadddd68SJiri Olsa #define P(a, b) PERF_MEM_##a##_##b
334aadddd68SJiri Olsa 
335aadddd68SJiri Olsa 	stats->nr_entries++;
336aadddd68SJiri Olsa 
337aadddd68SJiri Olsa 	if (lock & P(LOCK, LOCKED)) stats->locks++;
338aadddd68SJiri Olsa 
339aadddd68SJiri Olsa 	if (op & P(OP, LOAD)) {
340aadddd68SJiri Olsa 		/* load */
341aadddd68SJiri Olsa 		stats->load++;
342aadddd68SJiri Olsa 
343aadddd68SJiri Olsa 		if (!daddr) {
344aadddd68SJiri Olsa 			stats->ld_noadrs++;
345aadddd68SJiri Olsa 			return -1;
346aadddd68SJiri Olsa 		}
347aadddd68SJiri Olsa 
348aadddd68SJiri Olsa 		if (lvl & P(LVL, HIT)) {
349aadddd68SJiri Olsa 			if (lvl & P(LVL, UNC)) stats->ld_uncache++;
350aadddd68SJiri Olsa 			if (lvl & P(LVL, IO))  stats->ld_io++;
351aadddd68SJiri Olsa 			if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
352aadddd68SJiri Olsa 			if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
353aadddd68SJiri Olsa 			if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
354aadddd68SJiri Olsa 			if (lvl & P(LVL, L3 )) {
355aadddd68SJiri Olsa 				if (snoop & P(SNOOP, HITM))
356dba8ab93SJiri Olsa 					HITM_INC(lcl_hitm);
357aadddd68SJiri Olsa 				else
358aadddd68SJiri Olsa 					stats->ld_llchit++;
359aadddd68SJiri Olsa 			}
360aadddd68SJiri Olsa 
361aadddd68SJiri Olsa 			if (lvl & P(LVL, LOC_RAM)) {
362aadddd68SJiri Olsa 				stats->lcl_dram++;
363aadddd68SJiri Olsa 				if (snoop & P(SNOOP, HIT))
364aadddd68SJiri Olsa 					stats->ld_shared++;
365aadddd68SJiri Olsa 				else
366aadddd68SJiri Olsa 					stats->ld_excl++;
367aadddd68SJiri Olsa 			}
368aadddd68SJiri Olsa 
369aadddd68SJiri Olsa 			if ((lvl & P(LVL, REM_RAM1)) ||
37012c15302SJiri Olsa 			    (lvl & P(LVL, REM_RAM2)) ||
37112c15302SJiri Olsa 			     mrem) {
372aadddd68SJiri Olsa 				stats->rmt_dram++;
373aadddd68SJiri Olsa 				if (snoop & P(SNOOP, HIT))
374aadddd68SJiri Olsa 					stats->ld_shared++;
375aadddd68SJiri Olsa 				else
376aadddd68SJiri Olsa 					stats->ld_excl++;
377aadddd68SJiri Olsa 			}
378aadddd68SJiri Olsa 		}
379aadddd68SJiri Olsa 
380aadddd68SJiri Olsa 		if ((lvl & P(LVL, REM_CCE1)) ||
38112c15302SJiri Olsa 		    (lvl & P(LVL, REM_CCE2)) ||
38212c15302SJiri Olsa 		     mrem) {
383aadddd68SJiri Olsa 			if (snoop & P(SNOOP, HIT))
384aadddd68SJiri Olsa 				stats->rmt_hit++;
385aadddd68SJiri Olsa 			else if (snoop & P(SNOOP, HITM))
386dba8ab93SJiri Olsa 				HITM_INC(rmt_hitm);
387aadddd68SJiri Olsa 		}
388aadddd68SJiri Olsa 
389aadddd68SJiri Olsa 		if ((lvl & P(LVL, MISS)))
390aadddd68SJiri Olsa 			stats->ld_miss++;
391aadddd68SJiri Olsa 
392aadddd68SJiri Olsa 	} else if (op & P(OP, STORE)) {
393aadddd68SJiri Olsa 		/* store */
394aadddd68SJiri Olsa 		stats->store++;
395aadddd68SJiri Olsa 
396aadddd68SJiri Olsa 		if (!daddr) {
397aadddd68SJiri Olsa 			stats->st_noadrs++;
398aadddd68SJiri Olsa 			return -1;
399aadddd68SJiri Olsa 		}
400aadddd68SJiri Olsa 
401aadddd68SJiri Olsa 		if (lvl & P(LVL, HIT)) {
402aadddd68SJiri Olsa 			if (lvl & P(LVL, UNC)) stats->st_uncache++;
403aadddd68SJiri Olsa 			if (lvl & P(LVL, L1 )) stats->st_l1hit++;
404aadddd68SJiri Olsa 		}
405aadddd68SJiri Olsa 		if (lvl & P(LVL, MISS))
406aadddd68SJiri Olsa 			if (lvl & P(LVL, L1)) stats->st_l1miss++;
407aadddd68SJiri Olsa 	} else {
408aadddd68SJiri Olsa 		/* unparsable data_src? */
409aadddd68SJiri Olsa 		stats->noparse++;
410aadddd68SJiri Olsa 		return -1;
411aadddd68SJiri Olsa 	}
412aadddd68SJiri Olsa 
413aadddd68SJiri Olsa 	if (!mi->daddr.map || !mi->iaddr.map) {
414aadddd68SJiri Olsa 		stats->nomap++;
415aadddd68SJiri Olsa 		return -1;
416aadddd68SJiri Olsa 	}
417aadddd68SJiri Olsa 
418aadddd68SJiri Olsa #undef P
419dba8ab93SJiri Olsa #undef HITM_INC
420aadddd68SJiri Olsa 	return err;
421aadddd68SJiri Olsa }
4220a9a24ccSJiri Olsa 
4230a9a24ccSJiri Olsa void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
4240a9a24ccSJiri Olsa {
4250a9a24ccSJiri Olsa 	stats->nr_entries	+= add->nr_entries;
4260a9a24ccSJiri Olsa 
4270a9a24ccSJiri Olsa 	stats->locks		+= add->locks;
4280a9a24ccSJiri Olsa 	stats->store		+= add->store;
4290a9a24ccSJiri Olsa 	stats->st_uncache	+= add->st_uncache;
4300a9a24ccSJiri Olsa 	stats->st_noadrs	+= add->st_noadrs;
4310a9a24ccSJiri Olsa 	stats->st_l1hit		+= add->st_l1hit;
4320a9a24ccSJiri Olsa 	stats->st_l1miss	+= add->st_l1miss;
4330a9a24ccSJiri Olsa 	stats->load		+= add->load;
4340a9a24ccSJiri Olsa 	stats->ld_excl		+= add->ld_excl;
4350a9a24ccSJiri Olsa 	stats->ld_shared	+= add->ld_shared;
4360a9a24ccSJiri Olsa 	stats->ld_uncache	+= add->ld_uncache;
4370a9a24ccSJiri Olsa 	stats->ld_io		+= add->ld_io;
4380a9a24ccSJiri Olsa 	stats->ld_miss		+= add->ld_miss;
4390a9a24ccSJiri Olsa 	stats->ld_noadrs	+= add->ld_noadrs;
4400a9a24ccSJiri Olsa 	stats->ld_fbhit		+= add->ld_fbhit;
4410a9a24ccSJiri Olsa 	stats->ld_l1hit		+= add->ld_l1hit;
4420a9a24ccSJiri Olsa 	stats->ld_l2hit		+= add->ld_l2hit;
4430a9a24ccSJiri Olsa 	stats->ld_llchit	+= add->ld_llchit;
4440a9a24ccSJiri Olsa 	stats->lcl_hitm		+= add->lcl_hitm;
4450a9a24ccSJiri Olsa 	stats->rmt_hitm		+= add->rmt_hitm;
446dba8ab93SJiri Olsa 	stats->tot_hitm		+= add->tot_hitm;
4470a9a24ccSJiri Olsa 	stats->rmt_hit		+= add->rmt_hit;
4480a9a24ccSJiri Olsa 	stats->lcl_dram		+= add->lcl_dram;
4490a9a24ccSJiri Olsa 	stats->rmt_dram		+= add->rmt_dram;
4500a9a24ccSJiri Olsa 	stats->nomap		+= add->nomap;
4510a9a24ccSJiri Olsa 	stats->noparse		+= add->noparse;
4520a9a24ccSJiri Olsa }
453