aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-06-12 07:53:16 -0400
committerIngo Molnar <mingo@kernel.org>2014-06-12 07:53:16 -0400
commit94eb153130ce2c5f5f4959c96ea8197475bd66b6 (patch)
tree452c7fd4bd5d494d8b170fd5e840a5ae004e65ba /tools/perf
parent82b897782d10fcc4930c9d4a15b175348fdd2871 (diff)
parent9b32ba71ba905b90610fc2aad77cb98a373c5624 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core
Pull perf/core improvements and fixes from Jiri Olsa: * Bitmask handling and plugin updates (Steven Rostedt) * Fix pipe check regression in attr event callback (Jiri Olsa) * Prettify the tags/TAGS/cscope targets output (Jiri Olsa) * Print array argument as string (Namhyung Kim) * Pass protection and flags bits through mmap2 interface (Peter Zijlstra) * Update perf tool mmap2 interface with protection and flag bits (Don Zickus) * Re-enable mmap interface (Don Zickus) * Add mem-mode documentation to report command (Don Zickus) * Add sort on dcacheline (Don Zickus) Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-report.txt23
-rw-r--r--tools/perf/Makefile.perf6
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/util/event.c57
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/hist.c9
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/machine.c4
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/sort.c107
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/util.c1
-rw-r--r--tools/perf/util/util.h1
19 files changed, 203 insertions, 27 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index cefdf430d1b4..d2b59af62bc0 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -117,6 +117,22 @@ OPTIONS
117 By default, every sort keys not specified in -F will be appended 117 By default, every sort keys not specified in -F will be appended
118 automatically. 118 automatically.
119 119
120 If --mem-mode option is used, following sort keys are also available
121 (incompatible with --branch-stack):
122 symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline.
123
124 - symbol_daddr: name of data symbol being executed on at the time of sample
125 - dso_daddr: name of library or module containing the data being executed
126 on at the time of sample
127 - locked: whether the bus was locked at the time of sample
128 - tlb: type of tlb access for the data at the time of sample
129 - mem: type of memory access for the data at the time of sample
130 - snoop: type of snoop (if any) for the data at the time of sample
131 - dcacheline: the cacheline the data address is on at the time of sample
132
133 And default sort keys are changed to local_weight, mem, sym, dso,
134 symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
135
120-p:: 136-p::
121--parent=<regex>:: 137--parent=<regex>::
122 A regex filter to identify parent. The parent is a caller of this 138 A regex filter to identify parent. The parent is a caller of this
@@ -260,6 +276,13 @@ OPTIONS
260 Demangle symbol names to human readable form. It's enabled by default, 276 Demangle symbol names to human readable form. It's enabled by default,
261 disable with --no-demangle. 277 disable with --no-demangle.
262 278
279--mem-mode::
280 Use the data addresses of samples in addition to instruction addresses
281 to build the histograms. To generate meaningful output, the perf.data
282 file must have been obtained using perf record -d -W and using a
283 special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
284 'perf mem' for simpler access.
285
263--percent-limit:: 286--percent-limit::
264 Do not show entries which have an overhead under that percent. 287 Do not show entries which have an overhead under that percent.
265 (Default: 0). 288 (Default: 0).
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index ae20edfcc3f7..9670a16fa577 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -819,15 +819,15 @@ TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol
819TAG_FILES= ../../include/uapi/linux/perf_event.h 819TAG_FILES= ../../include/uapi/linux/perf_event.h
820 820
821TAGS: 821TAGS:
822 $(RM) TAGS 822 $(QUIET_GEN)$(RM) TAGS; \
823 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs etags -a $(TAG_FILES) 823 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs etags -a $(TAG_FILES)
824 824
825tags: 825tags:
826 $(RM) tags 826 $(QUIET_GEN)$(RM) tags; \
827 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs ctags -a $(TAG_FILES) 827 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs ctags -a $(TAG_FILES)
828 828
829cscope: 829cscope:
830 $(RM) cscope* 830 $(QUIET_GEN)$(RM) cscope*; \
831 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) 831 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES)
832 832
833### Detect prefix changes 833### Detect prefix changes
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6a3af0013d68..16c7c11ad06e 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -72,7 +72,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
72 if (ret) 72 if (ret)
73 return ret; 73 return ret;
74 74
75 if (&inject->output.is_pipe) 75 if (!inject->output.is_pipe)
76 return 0; 76 return 0;
77 77
78 return perf_event__repipe_synth(tool, event); 78 return perf_event__repipe_synth(tool, event);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 78f7b920e548..95c58fc15284 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -458,6 +458,7 @@ int main(int argc, const char **argv)
458 458
459 /* The page_size is placed in util object. */ 459 /* The page_size is placed in util object. */
460 page_size = sysconf(_SC_PAGE_SIZE); 460 page_size = sysconf(_SC_PAGE_SIZE);
461 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
461 462
462 cmd = perf_extract_argv0_path(argv[0]); 463 cmd = perf_extract_argv0_path(argv[0]);
463 if (!cmd) 464 if (!cmd)
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 108f0cd49f4e..96adb730b744 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -15,7 +15,7 @@ static int mmap_handler(struct perf_tool *tool __maybe_unused,
15 struct perf_sample *sample __maybe_unused, 15 struct perf_sample *sample __maybe_unused,
16 struct machine *machine) 16 struct machine *machine)
17{ 17{
18 return machine__process_mmap_event(machine, event, NULL); 18 return machine__process_mmap2_event(machine, event, NULL);
19} 19}
20 20
21static int init_live_machine(struct machine *machine) 21static int init_live_machine(struct machine *machine)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 65795b835b39..d0281bdfa582 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,4 +1,5 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <sys/mman.h>
2#include "event.h" 3#include "event.h"
3#include "debug.h" 4#include "debug.h"
4#include "hist.h" 5#include "hist.h"
@@ -178,13 +179,14 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
178 return -1; 179 return -1;
179 } 180 }
180 181
181 event->header.type = PERF_RECORD_MMAP; 182 event->header.type = PERF_RECORD_MMAP2;
182 183
183 while (1) { 184 while (1) {
184 char bf[BUFSIZ]; 185 char bf[BUFSIZ];
185 char prot[5]; 186 char prot[5];
186 char execname[PATH_MAX]; 187 char execname[PATH_MAX];
187 char anonstr[] = "//anon"; 188 char anonstr[] = "//anon";
189 unsigned int ino;
188 size_t size; 190 size_t size;
189 ssize_t n; 191 ssize_t n;
190 192
@@ -195,15 +197,20 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
195 strcpy(execname, ""); 197 strcpy(execname, "");
196 198
197 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 199 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
198 n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n", 200 n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
199 &event->mmap.start, &event->mmap.len, prot, 201 &event->mmap2.start, &event->mmap2.len, prot,
200 &event->mmap.pgoff, 202 &event->mmap2.pgoff, &event->mmap2.maj,
201 execname); 203 &event->mmap2.min,
204 &ino, execname);
205
202 /* 206 /*
203 * Anon maps don't have the execname. 207 * Anon maps don't have the execname.
204 */ 208 */
205 if (n < 4) 209 if (n < 7)
206 continue; 210 continue;
211
212 event->mmap2.ino = (u64)ino;
213
207 /* 214 /*
208 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c 215 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
209 */ 216 */
@@ -212,6 +219,21 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
212 else 219 else
213 event->header.misc = PERF_RECORD_MISC_GUEST_USER; 220 event->header.misc = PERF_RECORD_MISC_GUEST_USER;
214 221
222 /* map protection and flags bits */
223 event->mmap2.prot = 0;
224 event->mmap2.flags = 0;
225 if (prot[0] == 'r')
226 event->mmap2.prot |= PROT_READ;
227 if (prot[1] == 'w')
228 event->mmap2.prot |= PROT_WRITE;
229 if (prot[2] == 'x')
230 event->mmap2.prot |= PROT_EXEC;
231
232 if (prot[3] == 's')
233 event->mmap2.flags |= MAP_SHARED;
234 else
235 event->mmap2.flags |= MAP_PRIVATE;
236
215 if (prot[2] != 'x') { 237 if (prot[2] != 'x') {
216 if (!mmap_data || prot[0] != 'r') 238 if (!mmap_data || prot[0] != 'r')
217 continue; 239 continue;
@@ -223,15 +245,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
223 strcpy(execname, anonstr); 245 strcpy(execname, anonstr);
224 246
225 size = strlen(execname) + 1; 247 size = strlen(execname) + 1;
226 memcpy(event->mmap.filename, execname, size); 248 memcpy(event->mmap2.filename, execname, size);
227 size = PERF_ALIGN(size, sizeof(u64)); 249 size = PERF_ALIGN(size, sizeof(u64));
228 event->mmap.len -= event->mmap.start; 250 event->mmap2.len -= event->mmap.start;
229 event->mmap.header.size = (sizeof(event->mmap) - 251 event->mmap2.header.size = (sizeof(event->mmap2) -
230 (sizeof(event->mmap.filename) - size)); 252 (sizeof(event->mmap2.filename) - size));
231 memset(event->mmap.filename + size, 0, machine->id_hdr_size); 253 memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
232 event->mmap.header.size += machine->id_hdr_size; 254 event->mmap2.header.size += machine->id_hdr_size;
233 event->mmap.pid = tgid; 255 event->mmap2.pid = tgid;
234 event->mmap.tid = pid; 256 event->mmap2.tid = pid;
235 257
236 if (process(tool, event, &synth_sample, machine) != 0) { 258 if (process(tool, event, &synth_sample, machine) != 0) {
237 rc = -1; 259 rc = -1;
@@ -612,12 +634,15 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
612size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) 634size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
613{ 635{
614 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 636 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
615 " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n", 637 " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n",
616 event->mmap2.pid, event->mmap2.tid, event->mmap2.start, 638 event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
617 event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, 639 event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
618 event->mmap2.min, event->mmap2.ino, 640 event->mmap2.min, event->mmap2.ino,
619 event->mmap2.ino_generation, 641 event->mmap2.ino_generation,
620 (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', 642 (event->mmap2.prot & PROT_READ) ? 'r' : '-',
643 (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
644 (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
645 (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
621 event->mmap2.filename); 646 event->mmap2.filename);
622} 647}
623 648
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index d970232cb270..9ba2eb3bdcfd 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -27,6 +27,8 @@ struct mmap2_event {
27 u32 min; 27 u32 min;
28 u64 ino; 28 u64 ino;
29 u64 ino_generation; 29 u64 ino_generation;
30 u32 prot;
31 u32 flags;
30 char filename[PATH_MAX]; 32 char filename[PATH_MAX];
31}; 33};
32 34
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 5c28d82b76c4..21154dabc5fa 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -659,6 +659,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
659 perf_evsel__set_sample_bit(evsel, WEIGHT); 659 perf_evsel__set_sample_bit(evsel, WEIGHT);
660 660
661 attr->mmap = track; 661 attr->mmap = track;
662 attr->mmap2 = track && !perf_missing_features.mmap2;
662 attr->comm = track; 663 attr->comm = track;
663 664
664 if (opts->sample_transaction) 665 if (opts->sample_transaction)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 5a0a4b2cadc4..30df6187ee02 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -128,6 +128,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
128 + unresolved_col_width + 2; 128 + unresolved_col_width + 2;
129 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, 129 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
130 symlen); 130 symlen);
131 hists__new_col_len(hists, HISTC_MEM_DCACHELINE,
132 symlen + 1);
131 } else { 133 } else {
132 symlen = unresolved_col_width + 4 + 2; 134 symlen = unresolved_col_width + 4 + 2;
133 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, 135 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
@@ -439,9 +441,10 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
439 .map = al->map, 441 .map = al->map,
440 .sym = al->sym, 442 .sym = al->sym,
441 }, 443 },
442 .cpu = al->cpu, 444 .cpu = al->cpu,
443 .ip = al->addr, 445 .cpumode = al->cpumode,
444 .level = al->level, 446 .ip = al->addr,
447 .level = al->level,
445 .stat = { 448 .stat = {
446 .nr_events = 1, 449 .nr_events = 1,
447 .period = period, 450 .period = period,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index d2bf03575d5f..742f49a85725 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -72,6 +72,7 @@ enum hist_column {
72 HISTC_MEM_TLB, 72 HISTC_MEM_TLB,
73 HISTC_MEM_LVL, 73 HISTC_MEM_LVL,
74 HISTC_MEM_SNOOP, 74 HISTC_MEM_SNOOP,
75 HISTC_MEM_DCACHELINE,
75 HISTC_TRANSACTION, 76 HISTC_TRANSACTION,
76 HISTC_NR_COLS, /* Last entry */ 77 HISTC_NR_COLS, /* Last entry */
77}; 78};
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 7409ac8de51c..0e5fea95d596 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1060,6 +1060,8 @@ int machine__process_mmap2_event(struct machine *machine,
1060 event->mmap2.pid, event->mmap2.maj, 1060 event->mmap2.pid, event->mmap2.maj,
1061 event->mmap2.min, event->mmap2.ino, 1061 event->mmap2.min, event->mmap2.ino,
1062 event->mmap2.ino_generation, 1062 event->mmap2.ino_generation,
1063 event->mmap2.prot,
1064 event->mmap2.flags,
1063 event->mmap2.filename, type); 1065 event->mmap2.filename, type);
1064 1066
1065 if (map == NULL) 1067 if (map == NULL)
@@ -1105,7 +1107,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1105 1107
1106 map = map__new(&machine->user_dsos, event->mmap.start, 1108 map = map__new(&machine->user_dsos, event->mmap.start,
1107 event->mmap.len, event->mmap.pgoff, 1109 event->mmap.len, event->mmap.pgoff,
1108 event->mmap.pid, 0, 0, 0, 0, 1110 event->mmap.pid, 0, 0, 0, 0, 0, 0,
1109 event->mmap.filename, 1111 event->mmap.filename,
1110 type); 1112 type);
1111 1113
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 8ccbb32eda25..25c571f4cba6 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -138,7 +138,7 @@ void map__init(struct map *map, enum map_type type,
138 138
139struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 139struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
140 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 140 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
141 u64 ino_gen, char *filename, 141 u64 ino_gen, u32 prot, u32 flags, char *filename,
142 enum map_type type) 142 enum map_type type)
143{ 143{
144 struct map *map = malloc(sizeof(*map)); 144 struct map *map = malloc(sizeof(*map));
@@ -157,6 +157,8 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
157 map->min = d_min; 157 map->min = d_min;
158 map->ino = ino; 158 map->ino = ino;
159 map->ino_generation = ino_gen; 159 map->ino_generation = ino_gen;
160 map->prot = prot;
161 map->flags = flags;
160 162
161 if ((anon || no_dso) && type == MAP__FUNCTION) { 163 if ((anon || no_dso) && type == MAP__FUNCTION) {
162 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 164 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index ae2d45110588..7758c72522ef 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -35,6 +35,8 @@ struct map {
35 bool referenced; 35 bool referenced;
36 bool erange_warned; 36 bool erange_warned;
37 u32 priv; 37 u32 priv;
38 u32 prot;
39 u32 flags;
38 u64 pgoff; 40 u64 pgoff;
39 u64 reloc; 41 u64 reloc;
40 u32 maj, min; /* only valid for MMAP2 record */ 42 u32 maj, min; /* only valid for MMAP2 record */
@@ -118,7 +120,7 @@ void map__init(struct map *map, enum map_type type,
118 u64 start, u64 end, u64 pgoff, struct dso *dso); 120 u64 start, u64 end, u64 pgoff, struct dso *dso);
119struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 121struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
120 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 122 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
121 u64 ino_gen, 123 u64 ino_gen, u32 prot, u32 flags,
122 char *filename, enum map_type type); 124 char *filename, enum map_type type);
123struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 125struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
124void map__delete(struct map *map); 126void map__delete(struct map *map);
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index e108207c5de0..af7da565a750 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -215,6 +215,7 @@ static void define_event_symbols(struct event_format *event,
215 case PRINT_BSTRING: 215 case PRINT_BSTRING:
216 case PRINT_DYNAMIC_ARRAY: 216 case PRINT_DYNAMIC_ARRAY:
217 case PRINT_STRING: 217 case PRINT_STRING:
218 case PRINT_BITMASK:
218 break; 219 break;
219 case PRINT_TYPE: 220 case PRINT_TYPE:
220 define_event_symbols(event, ev_name, args->typecast.item); 221 define_event_symbols(event, ev_name, args->typecast.item);
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cd9774df3750..1c419321f707 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -197,6 +197,7 @@ static void define_event_symbols(struct event_format *event,
197 case PRINT_BSTRING: 197 case PRINT_BSTRING:
198 case PRINT_DYNAMIC_ARRAY: 198 case PRINT_DYNAMIC_ARRAY:
199 case PRINT_FUNC: 199 case PRINT_FUNC:
200 case PRINT_BITMASK:
200 /* we should warn... */ 201 /* we should warn... */
201 return; 202 return;
202 } 203 }
@@ -622,6 +623,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
622 fprintf(ofp, "%s=", f->name); 623 fprintf(ofp, "%s=", f->name);
623 if (f->flags & FIELD_IS_STRING || 624 if (f->flags & FIELD_IS_STRING ||
624 f->flags & FIELD_IS_FLAG || 625 f->flags & FIELD_IS_FLAG ||
626 f->flags & FIELD_IS_ARRAY ||
625 f->flags & FIELD_IS_SYMBOLIC) 627 f->flags & FIELD_IS_SYMBOLIC)
626 fprintf(ofp, "%%s"); 628 fprintf(ofp, "%%s");
627 else if (f->flags & FIELD_IS_SIGNED) 629 else if (f->flags & FIELD_IS_SIGNED)
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 45512baaab67..1ec57dd82284 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,3 +1,4 @@
1#include <sys/mman.h>
1#include "sort.h" 2#include "sort.h"
2#include "hist.h" 3#include "hist.h"
3#include "comm.h" 4#include "comm.h"
@@ -784,6 +785,104 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
784 return repsep_snprintf(bf, size, "%-*s", width, out); 785 return repsep_snprintf(bf, size, "%-*s", width, out);
785} 786}
786 787
788static inline u64 cl_address(u64 address)
789{
790 /* return the cacheline of the address */
791 return (address & ~(cacheline_size - 1));
792}
793
794static int64_t
795sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
796{
797 u64 l, r;
798 struct map *l_map, *r_map;
799
800 if (!left->mem_info) return -1;
801 if (!right->mem_info) return 1;
802
803 /* group event types together */
804 if (left->cpumode > right->cpumode) return -1;
805 if (left->cpumode < right->cpumode) return 1;
806
807 l_map = left->mem_info->daddr.map;
808 r_map = right->mem_info->daddr.map;
809
810 /* if both are NULL, jump to sort on al_addr instead */
811 if (!l_map && !r_map)
812 goto addr;
813
814 if (!l_map) return -1;
815 if (!r_map) return 1;
816
817 if (l_map->maj > r_map->maj) return -1;
818 if (l_map->maj < r_map->maj) return 1;
819
820 if (l_map->min > r_map->min) return -1;
821 if (l_map->min < r_map->min) return 1;
822
823 if (l_map->ino > r_map->ino) return -1;
824 if (l_map->ino < r_map->ino) return 1;
825
826 if (l_map->ino_generation > r_map->ino_generation) return -1;
827 if (l_map->ino_generation < r_map->ino_generation) return 1;
828
829 /*
830 * Addresses with no major/minor numbers are assumed to be
831 * anonymous in userspace. Sort those on pid then address.
832 *
833 * The kernel and non-zero major/minor mapped areas are
834 * assumed to be unity mapped. Sort those on address.
835 */
836
837 if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
838 (!(l_map->flags & MAP_SHARED)) &&
839 !l_map->maj && !l_map->min && !l_map->ino &&
840 !l_map->ino_generation) {
841 /* userspace anonymous */
842
843 if (left->thread->pid_ > right->thread->pid_) return -1;
844 if (left->thread->pid_ < right->thread->pid_) return 1;
845 }
846
847addr:
848 /* al_addr does all the right addr - start + offset calculations */
849 l = cl_address(left->mem_info->daddr.al_addr);
850 r = cl_address(right->mem_info->daddr.al_addr);
851
852 if (l > r) return -1;
853 if (l < r) return 1;
854
855 return 0;
856}
857
858static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
859 size_t size, unsigned int width)
860{
861
862 uint64_t addr = 0;
863 struct map *map = NULL;
864 struct symbol *sym = NULL;
865 char level = he->level;
866
867 if (he->mem_info) {
868 addr = cl_address(he->mem_info->daddr.al_addr);
869 map = he->mem_info->daddr.map;
870 sym = he->mem_info->daddr.sym;
871
872 /* print [s] for shared data mmaps */
873 if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
874 map && (map->type == MAP__VARIABLE) &&
875 (map->flags & MAP_SHARED) &&
876 (map->maj || map->min || map->ino ||
877 map->ino_generation))
878 level = 's';
879 else if (!map)
880 level = 'X';
881 }
882 return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
883 width);
884}
885
787struct sort_entry sort_mispredict = { 886struct sort_entry sort_mispredict = {
788 .se_header = "Branch Mispredicted", 887 .se_header = "Branch Mispredicted",
789 .se_cmp = sort__mispredict_cmp, 888 .se_cmp = sort__mispredict_cmp,
@@ -876,6 +975,13 @@ struct sort_entry sort_mem_snoop = {
876 .se_width_idx = HISTC_MEM_SNOOP, 975 .se_width_idx = HISTC_MEM_SNOOP,
877}; 976};
878 977
978struct sort_entry sort_mem_dcacheline = {
979 .se_header = "Data Cacheline",
980 .se_cmp = sort__dcacheline_cmp,
981 .se_snprintf = hist_entry__dcacheline_snprintf,
982 .se_width_idx = HISTC_MEM_DCACHELINE,
983};
984
879static int64_t 985static int64_t
880sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 986sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
881{ 987{
@@ -1043,6 +1149,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
1043 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), 1149 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1044 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), 1150 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1045 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), 1151 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1152 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
1046}; 1153};
1047 1154
1048#undef DIM 1155#undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 5bf0098d6b06..041f0c9cea2b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -89,6 +89,7 @@ struct hist_entry {
89 u64 ip; 89 u64 ip;
90 u64 transaction; 90 u64 transaction;
91 s32 cpu; 91 s32 cpu;
92 u8 cpumode;
92 93
93 struct hist_entry_diff diff; 94 struct hist_entry_diff diff;
94 95
@@ -185,6 +186,7 @@ enum sort_type {
185 SORT_MEM_TLB, 186 SORT_MEM_TLB,
186 SORT_MEM_LVL, 187 SORT_MEM_LVL,
187 SORT_MEM_SNOOP, 188 SORT_MEM_SNOOP,
189 SORT_MEM_DCACHELINE,
188}; 190};
189 191
190/* 192/*
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 7fff6be07f07..95aefa78bb07 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,6 +17,7 @@
17 * XXX We need to find a better place for these things... 17 * XXX We need to find a better place for these things...
18 */ 18 */
19unsigned int page_size; 19unsigned int page_size;
20int cacheline_size;
20 21
21bool test_attr__enabled; 22bool test_attr__enabled;
22 23
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b03da44e94e4..66864364ccb4 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -304,6 +304,7 @@ char *rtrim(char *s);
304void dump_stack(void); 304void dump_stack(void);
305 305
306extern unsigned int page_size; 306extern unsigned int page_size;
307extern int cacheline_size;
307 308
308void get_term_dimensions(struct winsize *ws); 309void get_term_dimensions(struct winsize *ws);
309 310