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
;