9 #include "mem-events.h"
14 unsigned int perf_mem_events__loads_ldlat = 30;
16 #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
18 struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
19 E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "mem-loads"),
20 E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"),
26 static char mem_loads_name[100];
27 static bool mem_loads_name__init;
29 char *perf_mem_events__name(int i)
31 if (i == PERF_MEM_EVENTS__LOAD) {
32 if (!mem_loads_name__init) {
33 mem_loads_name__init = true;
34 scnprintf(mem_loads_name, sizeof(mem_loads_name),
35 perf_mem_events[i].name,
36 perf_mem_events__loads_ldlat);
38 return mem_loads_name;
41 return (char *)perf_mem_events[i].name;
44 int perf_mem_events__parse(const char *str)
46 char *tok, *saveptr = NULL;
51 /* We need buffer that we know we can write to. */
52 buf = malloc(strlen(str) + 1);
58 tok = strtok_r((char *)buf, ",", &saveptr);
61 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
62 struct perf_mem_event *e = &perf_mem_events[j];
64 if (strstr(e->tag, tok))
65 e->record = found = true;
68 tok = strtok_r(NULL, ",", &saveptr);
76 pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
80 int perf_mem_events__init(void)
82 const char *mnt = sysfs__mount();
89 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
91 struct perf_mem_event *e = &perf_mem_events[j];
94 scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
98 e->supported = found = true;
101 return found ? 0 : -ENOENT;
104 static const char * const tlb_access[] = {
114 int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
117 u64 m = PERF_MEM_TLB_NA;
120 sz -= 1; /* -1 for null termination */
124 m = mem_info->data_src.mem_dtlb;
126 hit = m & PERF_MEM_TLB_HIT;
127 miss = m & PERF_MEM_TLB_MISS;
129 /* already taken care of */
130 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
132 for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
139 l += scnprintf(out + l, sz - l, tlb_access[i]);
142 l += scnprintf(out, sz - l, "N/A");
144 l += scnprintf(out + l, sz - l, " hit");
146 l += scnprintf(out + l, sz - l, " miss");
151 static const char * const mem_lvl[] = {
160 "Remote RAM (1 hop)",
161 "Remote RAM (2 hops)",
162 "Remote Cache (1 hop)",
163 "Remote Cache (2 hops)",
168 int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
171 u64 m = PERF_MEM_LVL_NA;
175 m = mem_info->data_src.mem_lvl;
177 sz -= 1; /* -1 for null termination */
180 hit = m & PERF_MEM_LVL_HIT;
181 miss = m & PERF_MEM_LVL_MISS;
183 /* already taken care of */
184 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
186 for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
193 l += scnprintf(out + l, sz - l, mem_lvl[i]);
196 l += scnprintf(out, sz - l, "N/A");
198 l += scnprintf(out + l, sz - l, " hit");
200 l += scnprintf(out + l, sz - l, " miss");
205 static const char * const snoop_access[] = {
213 int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
216 u64 m = PERF_MEM_SNOOP_NA;
218 sz -= 1; /* -1 for null termination */
222 m = mem_info->data_src.mem_snoop;
224 for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
231 l += scnprintf(out + l, sz - l, snoop_access[i]);
235 l += scnprintf(out, sz - l, "N/A");
240 int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
242 u64 mask = PERF_MEM_LOCK_NA;
246 mask = mem_info->data_src.mem_lock;
248 if (mask & PERF_MEM_LOCK_NA)
249 l = scnprintf(out, sz, "N/A");
250 else if (mask & PERF_MEM_LOCK_LOCKED)
251 l = scnprintf(out, sz, "Yes");
253 l = scnprintf(out, sz, "No");
258 int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
262 i += perf_mem__lvl_scnprintf(out, sz, mem_info);
263 i += scnprintf(out + i, sz - i, "|SNP ");
264 i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
265 i += scnprintf(out + i, sz - i, "|TLB ");
266 i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
267 i += scnprintf(out + i, sz - i, "|LCK ");
268 i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
273 int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
275 union perf_mem_data_src *data_src = &mi->data_src;
276 u64 daddr = mi->daddr.addr;
277 u64 op = data_src->mem_op;
278 u64 lvl = data_src->mem_lvl;
279 u64 snoop = data_src->mem_snoop;
280 u64 lock = data_src->mem_lock;
283 #define HITM_INC(__f) \
289 #define P(a, b) PERF_MEM_##a##_##b
293 if (lock & P(LOCK, LOCKED)) stats->locks++;
295 if (op & P(OP, LOAD)) {
304 if (lvl & P(LVL, HIT)) {
305 if (lvl & P(LVL, UNC)) stats->ld_uncache++;
306 if (lvl & P(LVL, IO)) stats->ld_io++;
307 if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
308 if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
309 if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
310 if (lvl & P(LVL, L3 )) {
311 if (snoop & P(SNOOP, HITM))
317 if (lvl & P(LVL, LOC_RAM)) {
319 if (snoop & P(SNOOP, HIT))
325 if ((lvl & P(LVL, REM_RAM1)) ||
326 (lvl & P(LVL, REM_RAM2))) {
328 if (snoop & P(SNOOP, HIT))
335 if ((lvl & P(LVL, REM_CCE1)) ||
336 (lvl & P(LVL, REM_CCE2))) {
337 if (snoop & P(SNOOP, HIT))
339 else if (snoop & P(SNOOP, HITM))
343 if ((lvl & P(LVL, MISS)))
346 } else if (op & P(OP, STORE)) {
355 if (lvl & P(LVL, HIT)) {
356 if (lvl & P(LVL, UNC)) stats->st_uncache++;
357 if (lvl & P(LVL, L1 )) stats->st_l1hit++;
359 if (lvl & P(LVL, MISS))
360 if (lvl & P(LVL, L1)) stats->st_l1miss++;
362 /* unparsable data_src? */
367 if (!mi->daddr.map || !mi->iaddr.map) {
377 void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
379 stats->nr_entries += add->nr_entries;
381 stats->locks += add->locks;
382 stats->store += add->store;
383 stats->st_uncache += add->st_uncache;
384 stats->st_noadrs += add->st_noadrs;
385 stats->st_l1hit += add->st_l1hit;
386 stats->st_l1miss += add->st_l1miss;
387 stats->load += add->load;
388 stats->ld_excl += add->ld_excl;
389 stats->ld_shared += add->ld_shared;
390 stats->ld_uncache += add->ld_uncache;
391 stats->ld_io += add->ld_io;
392 stats->ld_miss += add->ld_miss;
393 stats->ld_noadrs += add->ld_noadrs;
394 stats->ld_fbhit += add->ld_fbhit;
395 stats->ld_l1hit += add->ld_l1hit;
396 stats->ld_l2hit += add->ld_l2hit;
397 stats->ld_llchit += add->ld_llchit;
398 stats->lcl_hitm += add->lcl_hitm;
399 stats->rmt_hitm += add->rmt_hitm;
400 stats->tot_hitm += add->tot_hitm;
401 stats->rmt_hit += add->rmt_hit;
402 stats->lcl_dram += add->lcl_dram;
403 stats->rmt_dram += add->rmt_dram;
404 stats->nomap += add->nomap;
405 stats->noparse += add->noparse;