9 #include "mem-events.h"
13 #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
15 struct perf_mem_event perf_mem_events
[PERF_MEM_EVENTS__MAX
] = {
16 E("ldlat-loads", "cpu/mem-loads,ldlat=30/P", "mem-loads"),
17 E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"),
23 char *perf_mem_events__name(int i
)
25 return (char *)perf_mem_events
[i
].name
;
28 int perf_mem_events__parse(const char *str
)
30 char *tok
, *saveptr
= NULL
;
35 /* We need buffer that we know we can write to. */
36 buf
= malloc(strlen(str
) + 1);
42 tok
= strtok_r((char *)buf
, ",", &saveptr
);
45 for (j
= 0; j
< PERF_MEM_EVENTS__MAX
; j
++) {
46 struct perf_mem_event
*e
= &perf_mem_events
[j
];
48 if (strstr(e
->tag
, tok
))
49 e
->record
= found
= true;
52 tok
= strtok_r(NULL
, ",", &saveptr
);
60 pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str
);
64 int perf_mem_events__init(void)
66 const char *mnt
= sysfs__mount();
73 for (j
= 0; j
< PERF_MEM_EVENTS__MAX
; j
++) {
75 struct perf_mem_event
*e
= &perf_mem_events
[j
];
78 scnprintf(path
, PATH_MAX
, "%s/devices/cpu/events/%s",
82 e
->supported
= found
= true;
85 return found
? 0 : -ENOENT
;
88 static const char * const tlb_access
[] = {
98 int perf_mem__tlb_scnprintf(char *out
, size_t sz
, struct mem_info
*mem_info
)
101 u64 m
= PERF_MEM_TLB_NA
;
104 sz
-= 1; /* -1 for null termination */
108 m
= mem_info
->data_src
.mem_dtlb
;
110 hit
= m
& PERF_MEM_TLB_HIT
;
111 miss
= m
& PERF_MEM_TLB_MISS
;
113 /* already taken care of */
114 m
&= ~(PERF_MEM_TLB_HIT
|PERF_MEM_TLB_MISS
);
116 for (i
= 0; m
&& i
< ARRAY_SIZE(tlb_access
); i
++, m
>>= 1) {
123 l
+= scnprintf(out
+ l
, sz
- l
, tlb_access
[i
]);
126 l
+= scnprintf(out
, sz
- l
, "N/A");
128 l
+= scnprintf(out
+ l
, sz
- l
, " hit");
130 l
+= scnprintf(out
+ l
, sz
- l
, " miss");
135 static const char * const mem_lvl
[] = {
144 "Remote RAM (1 hop)",
145 "Remote RAM (2 hops)",
146 "Remote Cache (1 hop)",
147 "Remote Cache (2 hops)",
152 int perf_mem__lvl_scnprintf(char *out
, size_t sz
, struct mem_info
*mem_info
)
155 u64 m
= PERF_MEM_LVL_NA
;
159 m
= mem_info
->data_src
.mem_lvl
;
161 sz
-= 1; /* -1 for null termination */
164 hit
= m
& PERF_MEM_LVL_HIT
;
165 miss
= m
& PERF_MEM_LVL_MISS
;
167 /* already taken care of */
168 m
&= ~(PERF_MEM_LVL_HIT
|PERF_MEM_LVL_MISS
);
170 for (i
= 0; m
&& i
< ARRAY_SIZE(mem_lvl
); i
++, m
>>= 1) {
177 l
+= scnprintf(out
+ l
, sz
- l
, mem_lvl
[i
]);
180 l
+= scnprintf(out
, sz
- l
, "N/A");
182 l
+= scnprintf(out
+ l
, sz
- l
, " hit");
184 l
+= scnprintf(out
+ l
, sz
- l
, " miss");
189 static const char * const snoop_access
[] = {
197 int perf_mem__snp_scnprintf(char *out
, size_t sz
, struct mem_info
*mem_info
)
200 u64 m
= PERF_MEM_SNOOP_NA
;
202 sz
-= 1; /* -1 for null termination */
206 m
= mem_info
->data_src
.mem_snoop
;
208 for (i
= 0; m
&& i
< ARRAY_SIZE(snoop_access
); i
++, m
>>= 1) {
215 l
+= scnprintf(out
+ l
, sz
- l
, snoop_access
[i
]);
219 l
+= scnprintf(out
, sz
- l
, "N/A");
224 int perf_mem__lck_scnprintf(char *out
, size_t sz
, struct mem_info
*mem_info
)
226 u64 mask
= PERF_MEM_LOCK_NA
;
230 mask
= mem_info
->data_src
.mem_lock
;
232 if (mask
& PERF_MEM_LOCK_NA
)
233 l
= scnprintf(out
, sz
, "N/A");
234 else if (mask
& PERF_MEM_LOCK_LOCKED
)
235 l
= scnprintf(out
, sz
, "Yes");
237 l
= scnprintf(out
, sz
, "No");
242 int perf_script__meminfo_scnprintf(char *out
, size_t sz
, struct mem_info
*mem_info
)
246 i
+= perf_mem__lvl_scnprintf(out
, sz
, mem_info
);
247 i
+= scnprintf(out
+ i
, sz
- i
, "|SNP ");
248 i
+= perf_mem__snp_scnprintf(out
+ i
, sz
- i
, mem_info
);
249 i
+= scnprintf(out
+ i
, sz
- i
, "|TLB ");
250 i
+= perf_mem__tlb_scnprintf(out
+ i
, sz
- i
, mem_info
);
251 i
+= scnprintf(out
+ i
, sz
- i
, "|LCK ");
252 i
+= perf_mem__lck_scnprintf(out
+ i
, sz
- i
, mem_info
);