9 #include <linux/kernel.h>
10 #include "mem-events.h"
15 unsigned int perf_mem_events__loads_ldlat = 30;
17 #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
19 struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
20 E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "mem-loads"),
21 E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"),
27 static char mem_loads_name[100];
28 static bool mem_loads_name__init;
30 char *perf_mem_events__name(int i)
32 if (i == PERF_MEM_EVENTS__LOAD) {
33 if (!mem_loads_name__init) {
34 mem_loads_name__init = true;
35 scnprintf(mem_loads_name, sizeof(mem_loads_name),
36 perf_mem_events[i].name,
37 perf_mem_events__loads_ldlat);
39 return mem_loads_name;
42 return (char *)perf_mem_events[i].name;
45 int perf_mem_events__parse(const char *str)
47 char *tok, *saveptr = NULL;
52 /* We need buffer that we know we can write to. */
53 buf = malloc(strlen(str) + 1);
59 tok = strtok_r((char *)buf, ",", &saveptr);
62 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
63 struct perf_mem_event *e = &perf_mem_events[j];
65 if (strstr(e->tag, tok))
66 e->record = found = true;
69 tok = strtok_r(NULL, ",", &saveptr);
77 pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
81 int perf_mem_events__init(void)
83 const char *mnt = sysfs__mount();
90 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
92 struct perf_mem_event *e = &perf_mem_events[j];
95 scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
99 e->supported = found = true;
102 return found ? 0 : -ENOENT;
105 static const char * const tlb_access[] = {
115 int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
118 u64 m = PERF_MEM_TLB_NA;
121 sz -= 1; /* -1 for null termination */
125 m = mem_info->data_src.mem_dtlb;
127 hit = m & PERF_MEM_TLB_HIT;
128 miss = m & PERF_MEM_TLB_MISS;
130 /* already taken care of */
131 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
133 for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
140 l += scnprintf(out + l, sz - l, tlb_access[i]);
143 l += scnprintf(out, sz - l, "N/A");
145 l += scnprintf(out + l, sz - l, " hit");
147 l += scnprintf(out + l, sz - l, " miss");
152 static const char * const mem_lvl[] = {
161 "Remote RAM (1 hop)",
162 "Remote RAM (2 hops)",
163 "Remote Cache (1 hop)",
164 "Remote Cache (2 hops)",
169 int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
172 u64 m = PERF_MEM_LVL_NA;
176 m = mem_info->data_src.mem_lvl;
178 sz -= 1; /* -1 for null termination */
181 hit = m & PERF_MEM_LVL_HIT;
182 miss = m & PERF_MEM_LVL_MISS;
184 /* already taken care of */
185 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
187 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
194 l += scnprintf(out + l, sz - l, mem_lvl[i]);
197 l += scnprintf(out, sz - l, "N/A");
199 l += scnprintf(out + l, sz - l, " hit");
201 l += scnprintf(out + l, sz - l, " miss");
206 static const char * const snoop_access[] = {
214 int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
217 u64 m = PERF_MEM_SNOOP_NA;
219 sz -= 1; /* -1 for null termination */
223 m = mem_info->data_src.mem_snoop;
225 for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
232 l += scnprintf(out + l, sz - l, snoop_access[i]);
236 l += scnprintf(out, sz - l, "N/A");
241 int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
243 u64 mask = PERF_MEM_LOCK_NA;
247 mask = mem_info->data_src.mem_lock;
249 if (mask & PERF_MEM_LOCK_NA)
250 l = scnprintf(out, sz, "N/A");
251 else if (mask & PERF_MEM_LOCK_LOCKED)
252 l = scnprintf(out, sz, "Yes");
254 l = scnprintf(out, sz, "No");
259 int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
263 i += perf_mem__lvl_scnprintf(out, sz, mem_info);
264 i += scnprintf(out + i, sz - i, "|SNP ");
265 i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
266 i += scnprintf(out + i, sz - i, "|TLB ");
267 i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
268 i += scnprintf(out + i, sz - i, "|LCK ");
269 i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
274 int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
276 union perf_mem_data_src *data_src = &mi->data_src;
277 u64 daddr = mi->daddr.addr;
278 u64 op = data_src->mem_op;
279 u64 lvl = data_src->mem_lvl;
280 u64 snoop = data_src->mem_snoop;
281 u64 lock = data_src->mem_lock;
284 #define HITM_INC(__f) \
290 #define P(a, b) PERF_MEM_##a##_##b
294 if (lock & P(LOCK, LOCKED)) stats->locks++;
296 if (op & P(OP, LOAD)) {
305 if (lvl & P(LVL, HIT)) {
306 if (lvl & P(LVL, UNC)) stats->ld_uncache++;
307 if (lvl & P(LVL, IO)) stats->ld_io++;
308 if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
309 if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
310 if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
311 if (lvl & P(LVL, L3 )) {
312 if (snoop & P(SNOOP, HITM))
318 if (lvl & P(LVL, LOC_RAM)) {
320 if (snoop & P(SNOOP, HIT))
326 if ((lvl & P(LVL, REM_RAM1)) ||
327 (lvl & P(LVL, REM_RAM2))) {
329 if (snoop & P(SNOOP, HIT))
336 if ((lvl & P(LVL, REM_CCE1)) ||
337 (lvl & P(LVL, REM_CCE2))) {
338 if (snoop & P(SNOOP, HIT))
340 else if (snoop & P(SNOOP, HITM))
344 if ((lvl & P(LVL, MISS)))
347 } else if (op & P(OP, STORE)) {
356 if (lvl & P(LVL, HIT)) {
357 if (lvl & P(LVL, UNC)) stats->st_uncache++;
358 if (lvl & P(LVL, L1 )) stats->st_l1hit++;
360 if (lvl & P(LVL, MISS))
361 if (lvl & P(LVL, L1)) stats->st_l1miss++;
363 /* unparsable data_src? */
368 if (!mi->daddr.map || !mi->iaddr.map) {
378 void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
380 stats->nr_entries += add->nr_entries;
382 stats->locks += add->locks;
383 stats->store += add->store;
384 stats->st_uncache += add->st_uncache;
385 stats->st_noadrs += add->st_noadrs;
386 stats->st_l1hit += add->st_l1hit;
387 stats->st_l1miss += add->st_l1miss;
388 stats->load += add->load;
389 stats->ld_excl += add->ld_excl;
390 stats->ld_shared += add->ld_shared;
391 stats->ld_uncache += add->ld_uncache;
392 stats->ld_io += add->ld_io;
393 stats->ld_miss += add->ld_miss;
394 stats->ld_noadrs += add->ld_noadrs;
395 stats->ld_fbhit += add->ld_fbhit;
396 stats->ld_l1hit += add->ld_l1hit;
397 stats->ld_l2hit += add->ld_l2hit;
398 stats->ld_llchit += add->ld_llchit;
399 stats->lcl_hitm += add->lcl_hitm;
400 stats->rmt_hitm += add->rmt_hitm;
401 stats->tot_hitm += add->tot_hitm;
402 stats->rmt_hit += add->rmt_hit;
403 stats->lcl_dram += add->lcl_dram;
404 stats->rmt_dram += add->rmt_dram;
405 stats->nomap += add->nomap;
406 stats->noparse += add->noparse;