~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/mem-events.c

Version: ~ [ linux-5.15-rc1 ] ~ [ linux-5.14.5 ] ~ [ linux-5.13.18 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.66 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.147 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.206 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.246 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.282 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.283 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include <stddef.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <errno.h>
  5 #include <sys/types.h>
  6 #include <sys/stat.h>
  7 #include <unistd.h>
  8 #include <api/fs/fs.h>
  9 #include "mem-events.h"
 10 #include "debug.h"
 11 #include "symbol.h"
 12 
 13 unsigned int perf_mem_events__loads_ldlat = 30;
 14 
 15 #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
 16 
 17 struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
 18         E("ldlat-loads",        "cpu/mem-loads,ldlat=%u/P",     "mem-loads"),
 19         E("ldlat-stores",       "cpu/mem-stores/P",             "mem-stores"),
 20 };
 21 #undef E
 22 
 23 #undef E
 24 
 25 static char mem_loads_name[100];
 26 static bool mem_loads_name__init;
 27 
 28 char *perf_mem_events__name(int i)
 29 {
 30         if (i == PERF_MEM_EVENTS__LOAD) {
 31                 if (!mem_loads_name__init) {
 32                         mem_loads_name__init = true;
 33                         scnprintf(mem_loads_name, sizeof(mem_loads_name),
 34                                   perf_mem_events[i].name,
 35                                   perf_mem_events__loads_ldlat);
 36                 }
 37                 return mem_loads_name;
 38         }
 39 
 40         return (char *)perf_mem_events[i].name;
 41 }
 42 
 43 int perf_mem_events__parse(const char *str)
 44 {
 45         char *tok, *saveptr = NULL;
 46         bool found = false;
 47         char *buf;
 48         int j;
 49 
 50         /* We need buffer that we know we can write to. */
 51         buf = malloc(strlen(str) + 1);
 52         if (!buf)
 53                 return -ENOMEM;
 54 
 55         strcpy(buf, str);
 56 
 57         tok = strtok_r((char *)buf, ",", &saveptr);
 58 
 59         while (tok) {
 60                 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
 61                         struct perf_mem_event *e = &perf_mem_events[j];
 62 
 63                         if (strstr(e->tag, tok))
 64                                 e->record = found = true;
 65                 }
 66 
 67                 tok = strtok_r(NULL, ",", &saveptr);
 68         }
 69 
 70         free(buf);
 71 
 72         if (found)
 73                 return 0;
 74 
 75         pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
 76         return -1;
 77 }
 78 
 79 int perf_mem_events__init(void)
 80 {
 81         const char *mnt = sysfs__mount();
 82         bool found = false;
 83         int j;
 84 
 85         if (!mnt)
 86                 return -ENOENT;
 87 
 88         for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
 89                 char path[PATH_MAX];
 90                 struct perf_mem_event *e = &perf_mem_events[j];
 91                 struct stat st;
 92 
 93                 scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
 94                           mnt, e->sysfs_name);
 95 
 96                 if (!stat(path, &st))
 97                         e->supported = found = true;
 98         }
 99 
100         return found ? 0 : -ENOENT;
101 }
102 
103 static const char * const tlb_access[] = {
104         "N/A",
105         "HIT",
106         "MISS",
107         "L1",
108         "L2",
109         "Walker",
110         "Fault",
111 };
112 
113 int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
114 {
115         size_t l = 0, i;
116         u64 m = PERF_MEM_TLB_NA;
117         u64 hit, miss;
118 
119         sz -= 1; /* -1 for null termination */
120         out[0] = '\0';
121 
122         if (mem_info)
123                 m = mem_info->data_src.mem_dtlb;
124 
125         hit = m & PERF_MEM_TLB_HIT;
126         miss = m & PERF_MEM_TLB_MISS;
127 
128         /* already taken care of */
129         m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
130 
131         for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
132                 if (!(m & 0x1))
133                         continue;
134                 if (l) {
135                         strcat(out, " or ");
136                         l += 4;
137                 }
138                 l += scnprintf(out + l, sz - l, tlb_access[i]);
139         }
140         if (*out == '\0')
141                 l += scnprintf(out, sz - l, "N/A");
142         if (hit)
143                 l += scnprintf(out + l, sz - l, " hit");
144         if (miss)
145                 l += scnprintf(out + l, sz - l, " miss");
146 
147         return l;
148 }
149 
150 static const char * const mem_lvl[] = {
151         "N/A",
152         "HIT",
153         "MISS",
154         "L1",
155         "LFB",
156         "L2",
157         "L3",
158         "Local RAM",
159         "Remote RAM (1 hop)",
160         "Remote RAM (2 hops)",
161         "Remote Cache (1 hop)",
162         "Remote Cache (2 hops)",
163         "I/O",
164         "Uncached",
165 };
166 
167 int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
168 {
169         size_t i, l = 0;
170         u64 m =  PERF_MEM_LVL_NA;
171         u64 hit, miss;
172 
173         if (mem_info)
174                 m  = mem_info->data_src.mem_lvl;
175 
176         sz -= 1; /* -1 for null termination */
177         out[0] = '\0';
178 
179         hit = m & PERF_MEM_LVL_HIT;
180         miss = m & PERF_MEM_LVL_MISS;
181 
182         /* already taken care of */
183         m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
184 
185         for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
186                 if (!(m & 0x1))
187                         continue;
188                 if (l) {
189                         strcat(out, " or ");
190                         l += 4;
191                 }
192                 l += scnprintf(out + l, sz - l, mem_lvl[i]);
193         }
194         if (*out == '\0')
195                 l += scnprintf(out, sz - l, "N/A");
196         if (hit)
197                 l += scnprintf(out + l, sz - l, " hit");
198         if (miss)
199                 l += scnprintf(out + l, sz - l, " miss");
200 
201         return l;
202 }
203 
204 static const char * const snoop_access[] = {
205         "N/A",
206         "None",
207         "Miss",
208         "Hit",
209         "HitM",
210 };
211 
212 int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
213 {
214         size_t i, l = 0;
215         u64 m = PERF_MEM_SNOOP_NA;
216 
217         sz -= 1; /* -1 for null termination */
218         out[0] = '\0';
219 
220         if (mem_info)
221                 m = mem_info->data_src.mem_snoop;
222 
223         for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
224                 if (!(m & 0x1))
225                         continue;
226                 if (l) {
227                         strcat(out, " or ");
228                         l += 4;
229                 }
230                 l += scnprintf(out + l, sz - l, snoop_access[i]);
231         }
232 
233         if (*out == '\0')
234                 l += scnprintf(out, sz - l, "N/A");
235 
236         return l;
237 }
238 
239 int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
240 {
241         u64 mask = PERF_MEM_LOCK_NA;
242         int l;
243 
244         if (mem_info)
245                 mask = mem_info->data_src.mem_lock;
246 
247         if (mask & PERF_MEM_LOCK_NA)
248                 l = scnprintf(out, sz, "N/A");
249         else if (mask & PERF_MEM_LOCK_LOCKED)
250                 l = scnprintf(out, sz, "Yes");
251         else
252                 l = scnprintf(out, sz, "No");
253 
254         return l;
255 }
256 
257 int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
258 {
259         int i = 0;
260 
261         i += perf_mem__lvl_scnprintf(out, sz, mem_info);
262         i += scnprintf(out + i, sz - i, "|SNP ");
263         i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
264         i += scnprintf(out + i, sz - i, "|TLB ");
265         i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
266         i += scnprintf(out + i, sz - i, "|LCK ");
267         i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
268 
269         return i;
270 }
271 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp