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
;