linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting
@ 2014-05-27 16:28 Don Zickus
  2014-05-27 16:28 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
                   ` (7 more replies)
  0 siblings, 8 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

These patches enable mmap2 support in the kernel and perf to
allow support for data cacheline sorting.

Note: I haven't been able to reproduce Jiri's perf hang yet, so I don't
have a patch for that particular problem yet.

V4: reworked setting up cacheline size (Jiri Olsa)

V3: added patch to get cacheline size at runtime
    updated some changelogs
    fix a test failure (after install libunwind-devel)
    fix header column length

V2: change cacheline to dcacheline (Namhyung Kim)
    change dcacheline alogorithm a bit
    re-order mmap2 patches (Namhyung Kim)
    provide documentation (Andi Kleen)

Don Zickus (7):
  events, perf: Pass protection and flags bits through mmap2 interface
  Revert "perf: Disable PERF_RECORD_MMAP2 support"
  perf: Update mmap2 interface with protection and flag bits
  perf report: Add mem-mode documentation to report command
  perf: Add cpumode to struct hist_entry
  perf: Add support to dynamically get cacheline size
  perf: Add dcacheline sort

 include/uapi/linux/perf_event.h          |   1 +
 kernel/events/core.c                     |  37 +++++++++--
 tools/perf/Documentation/perf-report.txt |  23 +++++++
 tools/perf/builtin-report.c              |   2 +-
 tools/perf/perf.c                        |   5 ++
 tools/perf/tests/dwarf-unwind.c          |   2 +-
 tools/perf/util/cpumap.c                 |  27 ++++++++
 tools/perf/util/cpumap.h                 |   3 +
 tools/perf/util/event.c                  |  59 +++++++++++------
 tools/perf/util/event.h                  |   2 +
 tools/perf/util/evsel.c                  |   1 +
 tools/perf/util/hist.c                   |   9 ++-
 tools/perf/util/hist.h                   |   1 +
 tools/perf/util/machine.c                |   4 +-
 tools/perf/util/map.c                    |   4 +-
 tools/perf/util/map.h                    |   4 +-
 tools/perf/util/sort.c                   | 108 +++++++++++++++++++++++++++++++
 tools/perf/util/sort.h                   |   2 +
 tools/perf/util/util.c                   |   1 +
 tools/perf/util/util.h                   |   1 +
 20 files changed, 265 insertions(+), 31 deletions(-)

-- 
1.7.11.7


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-05-27 16:28 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

From: Peter Zijlstra <a.p.zijlstra@chello.nl>

The mmap2 interface was missing the protection and flags bits needed to
accurately determine if a mmap memory area was shared or private and
if it was readable or not.

Signed-off-by: Peter Zijlstra <peterz@infradead.org>
[tweaked patch to compile and wrote changelog]
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
 include/uapi/linux/perf_event.h |  1 +
 kernel/events/core.c            | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 853bc1c..2ed502f 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -699,6 +699,7 @@ enum perf_event_type {
 	 *	u32				min;
 	 *	u64				ino;
 	 *	u64				ino_generation;
+	 *	u32				prot, flags;
 	 *	char				filename[];
 	 * 	struct sample_id		sample_id;
 	 * };
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 5129b12..0711cc9 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -40,6 +40,7 @@
 #include <linux/mm_types.h>
 #include <linux/cgroup.h>
 #include <linux/module.h>
+#include <linux/mman.h>
 
 #include "internal.h"
 
@@ -5089,6 +5090,7 @@ struct perf_mmap_event {
 	int			maj, min;
 	u64			ino;
 	u64			ino_generation;
+	u32			prot, flags;
 
 	struct {
 		struct perf_event_header	header;
@@ -5130,6 +5132,8 @@ static void perf_event_mmap_output(struct perf_event *event,
 		mmap_event->event_id.header.size += sizeof(mmap_event->min);
 		mmap_event->event_id.header.size += sizeof(mmap_event->ino);
 		mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
+		mmap_event->event_id.header.size += sizeof(mmap_event->prot);
+		mmap_event->event_id.header.size += sizeof(mmap_event->flags);
 	}
 
 	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
@@ -5148,6 +5152,8 @@ static void perf_event_mmap_output(struct perf_event *event,
 		perf_output_put(&handle, mmap_event->min);
 		perf_output_put(&handle, mmap_event->ino);
 		perf_output_put(&handle, mmap_event->ino_generation);
+		perf_output_put(&handle, mmap_event->prot);
+		perf_output_put(&handle, mmap_event->flags);
 	}
 
 	__output_copy(&handle, mmap_event->file_name,
@@ -5166,6 +5172,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 	struct file *file = vma->vm_file;
 	int maj = 0, min = 0;
 	u64 ino = 0, gen = 0;
+	u32 prot = 0, flags = 0;
 	unsigned int size;
 	char tmp[16];
 	char *buf = NULL;
@@ -5196,6 +5203,28 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 		gen = inode->i_generation;
 		maj = MAJOR(dev);
 		min = MINOR(dev);
+
+		if (vma->vm_flags & VM_READ)
+			prot |= PROT_READ;
+		if (vma->vm_flags & VM_WRITE)
+			prot |= PROT_WRITE;
+		if (vma->vm_flags & VM_EXEC)
+			prot |= PROT_EXEC;
+
+		if (vma->vm_flags & VM_MAYSHARE)
+			flags = MAP_SHARED;
+		else
+			flags = MAP_PRIVATE;
+
+		if (vma->vm_flags & VM_DENYWRITE)
+			flags |= MAP_DENYWRITE;
+		if (vma->vm_flags & VM_MAYEXEC)
+			flags |= MAP_EXECUTABLE;
+		if (vma->vm_flags & VM_LOCKED)
+			flags |= MAP_LOCKED;
+		if (vma->vm_flags & VM_HUGETLB)
+			flags |= MAP_HUGETLB;
+
 		goto got_name;
 	} else {
 		name = (char *)arch_vma_name(vma);
@@ -5236,6 +5265,8 @@ got_name:
 	mmap_event->min = min;
 	mmap_event->ino = ino;
 	mmap_event->ino_generation = gen;
+	mmap_event->prot = prot;
+	mmap_event->flags = flags;
 
 	if (!(vma->vm_flags & VM_EXEC))
 		mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
@@ -5276,6 +5307,8 @@ void perf_event_mmap(struct vm_area_struct *vma)
 		/* .min (attr_mmap2 only) */
 		/* .ino (attr_mmap2 only) */
 		/* .ino_generation (attr_mmap2 only) */
+		/* .prot (attr_mmap2 only) */
+		/* .flags (attr_mmap2 only) */
 	};
 
 	perf_event_mmap_event(&mmap_event);
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support"
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
  2014-05-27 16:28 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-05-30  7:05   ` Namhyung Kim
  2014-05-30 14:49   ` [PATCH 2/7 V2] " Don Zickus
  2014-05-27 16:28 ` [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits Don Zickus
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

This reverts commit 3090ffb5a2515990182f3f55b0688a7817325488.

Re-enable the mmap2 interface as we will have a user soon.

Since things have changed since perf disabled mmap2, small tweaks
to the revert had to be done:

o commit 9d4ecc88 forced (n!=8) to become (n<7)
o a new libunwind test needed updating to use mmap2 interface

Signed-off-by: Don Zickus <dzickus@redhat.com>
---
v2: added a better changelog
    fix a unwind test (thanks Jiri)
---
 kernel/events/core.c            |  4 ----
 tools/perf/tests/dwarf-unwind.c |  2 +-
 tools/perf/util/event.c         | 36 +++++++++++++++++++-----------------
 tools/perf/util/evsel.c         |  1 +
 4 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 0711cc9..c793cb0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6882,10 +6882,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
 	if (ret)
 		return -EFAULT;
 
-	/* disabled for now */
-	if (attr->mmap2)
-		return -EINVAL;
-
 	if (attr->__reserved_1)
 		return -EINVAL;
 
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 108f0cd..96adb73 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,
 			struct perf_sample *sample __maybe_unused,
 			struct machine *machine)
 {
-	return machine__process_mmap_event(machine, event, NULL);
+	return machine__process_mmap2_event(machine, event, NULL);
 }
 
 static int init_live_machine(struct machine *machine)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 65795b8..5e7c722 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -178,13 +178,14 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP;
+	event->header.type = PERF_RECORD_MMAP2;
 
 	while (1) {
 		char bf[BUFSIZ];
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
+		unsigned int ino;
 		size_t size;
 		ssize_t n;
 
@@ -195,14 +196,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
-		       &event->mmap.start, &event->mmap.len, prot,
-		       &event->mmap.pgoff,
-		       execname);
-		/*
- 		 * Anon maps don't have the execname.
- 		 */
-		if (n < 4)
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+		       &event->mmap2.start, &event->mmap2.len, prot,
+		       &event->mmap2.pgoff, &event->mmap2.maj,
+		       &event->mmap2.min,
+		       &ino, execname);
+
+		event->mmap2.ino = (u64)ino;
+
+		if (n < 7)
 			continue;
 		/*
 		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
@@ -223,15 +225,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap.filename, execname, size);
+		memcpy(event->mmap2.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap.len -= event->mmap.start;
-		event->mmap.header.size = (sizeof(event->mmap) -
-					(sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
-		event->mmap.header.size += machine->id_hdr_size;
-		event->mmap.pid = tgid;
-		event->mmap.tid = pid;
+		event->mmap2.len -= event->mmap.start;
+		event->mmap2.header.size = (sizeof(event->mmap2) -
+					(sizeof(event->mmap2.filename) - size));
+		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
+		event->mmap2.header.size += machine->id_hdr_size;
+		event->mmap2.pid = tgid;
+		event->mmap2.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 5c28d82..21154da 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)
 		perf_evsel__set_sample_bit(evsel, WEIGHT);
 
 	attr->mmap  = track;
+	attr->mmap2 = track && !perf_missing_features.mmap2;
 	attr->comm  = track;
 
 	if (opts->sample_transaction)
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
  2014-05-27 16:28 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
  2014-05-27 16:28 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-05-27 16:28 ` [PATCH 4/7] perf report: Add mem-mode documentation to report command Don Zickus
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

The kernel piece passes more info now.  Update the perf tool to reflect
that and adjust the synthesized maps to play along.

Signed-off-by: Don Zickus <dzickus@redhat.com>
---
 tools/perf/util/event.c   | 23 +++++++++++++++++++++--
 tools/perf/util/event.h   |  2 ++
 tools/perf/util/machine.c |  4 +++-
 tools/perf/util/map.c     |  4 +++-
 tools/perf/util/map.h     |  4 +++-
 5 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 5e7c722..e91d28e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,4 +1,5 @@
 #include <linux/types.h>
+#include <sys/mman.h>
 #include "event.h"
 #include "debug.h"
 #include "hist.h"
@@ -214,6 +215,21 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		else
 			event->header.misc = PERF_RECORD_MISC_GUEST_USER;
 
+		/* map protection and flags bits */
+		event->mmap2.prot = 0;
+		event->mmap2.flags = 0;
+		if (prot[0] == 'r')
+			event->mmap2.prot |= PROT_READ;
+		if (prot[1] == 'w')
+			event->mmap2.prot |= PROT_WRITE;
+		if (prot[2] == 'x')
+			event->mmap2.prot |= PROT_EXEC;
+
+		if (prot[3] == 's')
+			event->mmap2.flags |= MAP_SHARED;
+		else
+			event->mmap2.flags |= MAP_PRIVATE;
+
 		if (prot[2] != 'x') {
 			if (!mmap_data || prot[0] != 'r')
 				continue;
@@ -614,12 +630,15 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
 {
 	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
-			   " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n",
+			   " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n",
 		       event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
 		       event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
 		       event->mmap2.min, event->mmap2.ino,
 		       event->mmap2.ino_generation,
-		       (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
+		       (event->mmap2.prot & PROT_READ) ? 'r' : '-',
+		       (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
+		       (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
+		       (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
 		       event->mmap2.filename);
 }
 
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index d970232..9ba2eb3 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -27,6 +27,8 @@ struct mmap2_event {
 	u32 min;
 	u64 ino;
 	u64 ino_generation;
+	u32 prot;
+	u32 flags;
 	char filename[PATH_MAX];
 };
 
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 7409ac8..0e5fea9 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,
 			event->mmap2.pid, event->mmap2.maj,
 			event->mmap2.min, event->mmap2.ino,
 			event->mmap2.ino_generation,
+			event->mmap2.prot,
+			event->mmap2.flags,
 			event->mmap2.filename, type);
 
 	if (map == NULL)
@@ -1105,7 +1107,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
 
 	map = map__new(&machine->user_dsos, event->mmap.start,
 			event->mmap.len, event->mmap.pgoff,
-			event->mmap.pid, 0, 0, 0, 0,
+			event->mmap.pid, 0, 0, 0, 0, 0, 0,
 			event->mmap.filename,
 			type);
 
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index ba5f5c0c..7ca1d7e 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -51,7 +51,7 @@ void map__init(struct map *map, enum map_type type,
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
 		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
-		     u64 ino_gen, char *filename,
+		     u64 ino_gen, u32 prot, u32 flags, char *filename,
 		     enum map_type type)
 {
 	struct map *map = malloc(sizeof(*map));
@@ -69,6 +69,8 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
 		map->min = d_min;
 		map->ino = ino;
 		map->ino_generation = ino_gen;
+		map->prot = prot;
+		map->flags = flags;
 
 		if ((anon || no_dso) && type == MAP__FUNCTION) {
 			snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index ae2d451..7758c72 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -35,6 +35,8 @@ struct map {
 	bool			referenced;
 	bool			erange_warned;
 	u32			priv;
+	u32			prot;
+	u32			flags;
 	u64			pgoff;
 	u64			reloc;
 	u32			maj, min; /* only valid for MMAP2 record */
@@ -118,7 +120,7 @@ void map__init(struct map *map, enum map_type type,
 	       u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
 		     u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
-		     u64 ino_gen,
+		     u64 ino_gen, u32 prot, u32 flags,
 		     char *filename, enum map_type type);
 struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 void map__delete(struct map *map);
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/7] perf report: Add mem-mode documentation to report command
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
                   ` (2 preceding siblings ...)
  2014-05-27 16:28 ` [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-05-27 16:28 ` [PATCH 5/7] perf: Add cpumode to struct hist_entry Don Zickus
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

Add mem-mode sorting types and mem-mode itself to perf-report documentation.

Signed-off-by: Don Zickus <dzickus@redhat.com>
---
 tools/perf/Documentation/perf-report.txt | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 09af662..bea1c83 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -98,6 +98,21 @@ OPTIONS
 	And default sort keys are changed to comm, dso_from, symbol_from, dso_to
 	and symbol_to, see '--branch-stack'.
 
+	If --mem-mode option is used, following sort keys are also available
+	(incompatible with --branch-stack):
+	symbol_daddr, dso_daddr, locked, tlb, mem, snoop.
+
+	- symbol_daddr: name of data symbol being executed on at the time of sample
+	- dso_daddr: name of library or module containing the data being executed
+	on at the time of sample
+	- locked: whether the bus was locked at the time of sample
+	- tlb: type of tlb access for the data at the time of sample
+	- mem: type of memory access for the data at the time of sample
+	- snoop: type of snoop (if any) for the data at the time of sample
+
+	And default sort keys are changed to local_weight, mem, sym, dso,
+	symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
+
 -p::
 --parent=<regex>::
         A regex filter to identify parent. The parent is a caller of this
@@ -236,6 +251,13 @@ OPTIONS
 	Demangle symbol names to human readable form. It's enabled by default,
 	disable with --no-demangle.
 
+--mem-mode::
+	Use the data addresses of samples in addition to instruction addresses
+	to build the histograms.  To generate meaningful output, the perf.data
+	file must have been obtained using perf record -d -W and using a 
+	special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
+	'perf mem' for simpler access.
+
 --percent-limit::
 	Do not show entries which have an overhead under that percent.
 	(Default: 0).
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 5/7] perf: Add cpumode to struct hist_entry
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
                   ` (3 preceding siblings ...)
  2014-05-27 16:28 ` [PATCH 4/7] perf report: Add mem-mode documentation to report command Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-06-12 12:03   ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
  2014-05-27 16:28 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

The next patch needs to sort on cpumode, so add it to hist_entry to be tracked.

Signed-off-by: Don Zickus <dzickus@redhat.com>
---
 tools/perf/util/hist.c | 7 ++++---
 tools/perf/util/sort.h | 1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 7f0236c..b7160b1c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -410,9 +410,10 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
 			.map	= al->map,
 			.sym	= al->sym,
 		},
-		.cpu	= al->cpu,
-		.ip	= al->addr,
-		.level	= al->level,
+		.cpu	 = al->cpu,
+		.cpumode = al->cpumode,
+		.ip	 = al->addr,
+		.level	 = al->level,
 		.stat = {
 			.nr_events = 1,
 			.period	= period,
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 43e5ff4..22cf912 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -87,6 +87,7 @@ struct hist_entry {
 	u64			ip;
 	u64			transaction;
 	s32			cpu;
+	u8			cpumode;
 
 	struct hist_entry_diff	diff;
 
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 6/7] perf: Add support to dynamically get cacheline size
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
                   ` (4 preceding siblings ...)
  2014-05-27 16:28 ` [PATCH 5/7] perf: Add cpumode to struct hist_entry Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-05-30  7:09   ` Namhyung Kim
                     ` (2 more replies)
  2014-05-27 16:28 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
  2014-05-30  7:15 ` [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Namhyung Kim
  7 siblings, 3 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

Different arches may have different cacheline sizes.  Look it up and set
a global variable for reference.

Signed-off-by: Don Zickus <dzickus@redhat.com>

---
V2: change to be global and setup in perf.c
    use filename__read_int for setup
---
 tools/perf/perf.c        |  5 +++++
 tools/perf/util/cpumap.c | 27 +++++++++++++++++++++++++++
 tools/perf/util/cpumap.h |  3 +++
 tools/perf/util/sort.c   |  1 +
 tools/perf/util/util.c   |  1 +
 tools/perf/util/util.h   |  1 +
 6 files changed, 38 insertions(+)

diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 431798a..dabf08b 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,6 +13,7 @@
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
+#include "util/cpumap.h"
 #include <api/fs/debugfs.h>
 #include <pthread.h>
 
@@ -459,6 +460,10 @@ int main(int argc, const char **argv)
 	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
 
+	/* The cacheline_size is placed in util objet */
+	if (cpu__setup_cacheline_size() < 0) 
+		goto out;
+
 	cmd = perf_extract_argv0_path(argv[0]);
 	if (!cmd)
 		cmd = "perf-help";
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index c4e55b7..1029982 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -477,3 +477,30 @@ int cpu__setup_cpunode_map(void)
 	closedir(dir1);
 	return 0;
 }
+
+int cpu__setup_cacheline_size(void)
+{
+	const char *mnt;
+	char path[PATH_MAX];
+	int n, size;
+	
+
+	mnt = sysfs__mountpoint();
+	if (!mnt)
+		return -1;
+
+	n = snprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu0/cache/index0/coherency_line_size", mnt);
+	if (n == PATH_MAX) {
+		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
+		return -1;
+	}
+
+	if (filename__read_int(path, &size)) {
+		pr_err("Can not read cacheline size\n");
+		return -1;
+	}
+
+	cacheline_size = size;
+
+	return 0;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 61a6548..507d7fd 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -5,6 +5,7 @@
 #include <stdbool.h>
 
 #include "perf.h"
+#include "util/util.h"
 #include "util/debug.h"
 
 struct cpu_map {
@@ -81,4 +82,6 @@ static inline int cpu__get_node(int cpu)
 	return cpunode_map[cpu];
 }
 
+int cpu__setup_cacheline_size(void);
+
 #endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 635cd8f..6e06567 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2,6 +2,7 @@
 #include "hist.h"
 #include "comm.h"
 #include "symbol.h"
+#include "cpumap.h"
 
 regex_t		parent_regex;
 const char	default_parent_pattern[] = "^sys_|^do_page_fault";
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 7fff6be..95aefa7 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,6 +17,7 @@
  * XXX We need to find a better place for these things...
  */
 unsigned int page_size;
+int cacheline_size;
 
 bool test_attr__enabled;
 
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b03da44..6686436 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -304,6 +304,7 @@ char *rtrim(char *s);
 void dump_stack(void);
 
 extern unsigned int page_size;
+extern int cacheline_size;
 
 void get_term_dimensions(struct winsize *ws);
 
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 7/7] perf: Add dcacheline sort
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
                   ` (5 preceding siblings ...)
  2014-05-27 16:28 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
@ 2014-05-27 16:28 ` Don Zickus
  2014-06-12 12:03   ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
  2014-05-30  7:15 ` [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Namhyung Kim
  7 siblings, 1 reply; 20+ messages in thread
From: Don Zickus @ 2014-05-27 16:28 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

In perf's 'mem-mode', one can get access to a whole bunch of details specific to a
particular sample instruction.  A bunch of those details relate to the data
address.

One interesting thing you can do with data addresses is to convert them into a unique
cacheline they belong too.  Organizing these data cachelines into similar groups and sorting
them can reveal cache contention.

This patch creates an alogorithm based on various sample details that can help group
entries together into data cachelines and allows 'perf report' to sort on it.

The algorithm relies on having proper mmap2 support in the kernel to help determine
if the memory map the data address belongs to is private to a pid or globally shared.

The alogortithm is as follows:

o group cpumodes together
o group entries with discovered maps together
o sort on major, minor, inode and inode generation numbers
o if userspace anon, then sort on pid
o sort on cachelines based on data addresses

The 'dcacheline' sort option in 'perf report' only works in 'mem-mode'.

Sample output:

 #
 # Samples: 206  of event 'cpu/mem-loads/pp'
 # Total weight : 2534
 # Sort order   : dcacheline,pid
 #
 # Overhead       Samples                                                          Data Cacheline       Command:  Pid
 # ........  ............  ......................................................................  ..................
 #
    13.22%             1  [k] 0xffff88042f08ebc0                                                       swapper:    0
     9.27%             1  [k] 0xffff88082e8cea80                                                       swapper:    0
     3.59%             2  [k] 0xffffffff819ba180                                                       swapper:    0
     0.32%             1  [k] arch_trigger_all_cpu_backtrace_handler_na.23901+0xffffffffffffffe0       swapper:    0
     0.32%             1  [k] timekeeper_seq+0xfffffffffffffff8                                        swapper:    0

Note:  Added a '+1' to symlen size in hists__calc_col_len to prevent the next column
from prematurely tabbing over and mis-aligning.  Not sure what the problem is.

Signed-off-by: Don Zickus <dzickus@redhat.com>
---
V4: call cacheline_size directly
v3: fix header column length
V2: update using cpu__cacheline_size()
---
 tools/perf/Documentation/perf-report.txt |   3 +-
 tools/perf/builtin-report.c              |   2 +-
 tools/perf/util/hist.c                   |   2 +
 tools/perf/util/hist.h                   |   1 +
 tools/perf/util/sort.c                   | 107 +++++++++++++++++++++++++++++++
 tools/perf/util/sort.h                   |   1 +
 6 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index bea1c83..9115d02 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -100,7 +100,7 @@ OPTIONS
 
 	If --mem-mode option is used, following sort keys are also available
 	(incompatible with --branch-stack):
-	symbol_daddr, dso_daddr, locked, tlb, mem, snoop.
+	symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline.
 
 	- symbol_daddr: name of data symbol being executed on at the time of sample
 	- dso_daddr: name of library or module containing the data being executed
@@ -109,6 +109,7 @@ OPTIONS
 	- tlb: type of tlb access for the data at the time of sample
 	- mem: type of memory access for the data at the time of sample
 	- snoop: type of snoop (if any) for the data at the time of sample
+	- dcacheline: the cacheline the data address is on at the time of sample
 
 	And default sort keys are changed to local_weight, mem, sym, dso,
 	symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 89c9528..387459f 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -702,7 +702,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 		   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
 		   " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
 		   " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, "
-		   "snoop, locked, abort, in_tx, transaction"),
+		   "snoop, locked, abort, in_tx, transaction, dcacheline"),
 	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
 		    "Show sample percentage for different cpu modes"),
 	OPT_STRING('p', "parent", &parent_pattern, "regex",
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b7160b1c..5df514c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -127,6 +127,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
 			       + unresolved_col_width + 2;
 			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
 					   symlen);
+			hists__new_col_len(hists, HISTC_MEM_DCACHELINE,
+					   symlen + 1);
 		} else {
 			symlen = unresolved_col_width + 4 + 2;
 			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 38c3e87..14d1dc1 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -72,6 +72,7 @@ enum hist_column {
 	HISTC_MEM_TLB,
 	HISTC_MEM_LVL,
 	HISTC_MEM_SNOOP,
+	HISTC_MEM_DCACHELINE,
 	HISTC_TRANSACTION,
 	HISTC_NR_COLS, /* Last entry */
 };
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 6e06567..f511c6f 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,3 +1,4 @@
+#include <sys/mman.h>
 #include "sort.h"
 #include "hist.h"
 #include "comm.h"
@@ -765,6 +766,104 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
 	return repsep_snprintf(bf, size, "%-*s", width, out);
 }
 
+static inline  u64 cl_address(u64 address)
+{
+	/* return the cacheline of the address */
+	return (address & ~(cacheline_size - 1));
+}
+
+static int64_t
+sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	u64 l, r;
+	struct map *l_map, *r_map;
+
+	if (!left->mem_info)  return -1;
+	if (!right->mem_info) return 1;
+
+	/* group event types together */
+	if (left->cpumode > right->cpumode) return -1;
+	if (left->cpumode < right->cpumode) return 1;
+
+	l_map = left->mem_info->daddr.map;
+	r_map = right->mem_info->daddr.map;
+
+	/* if both are NULL, jump to sort on al_addr instead */
+	if (!l_map && !r_map)
+		goto addr;
+
+	if (!l_map) return -1;
+	if (!r_map) return 1;
+
+	if (l_map->maj > r_map->maj) return -1;
+	if (l_map->maj < r_map->maj) return 1;
+
+	if (l_map->min > r_map->min) return -1;
+	if (l_map->min < r_map->min) return 1;
+
+	if (l_map->ino > r_map->ino) return -1;
+	if (l_map->ino < r_map->ino) return 1;
+
+	if (l_map->ino_generation > r_map->ino_generation) return -1;
+	if (l_map->ino_generation < r_map->ino_generation) return 1;
+
+	/*
+	 * Addresses with no major/minor numbers are assumed to be
+	 * anonymous in userspace.  Sort those on pid then address.
+	 *
+	 * The kernel and non-zero major/minor mapped areas are
+	 * assumed to be unity mapped.  Sort those on address.
+	 */
+
+	if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
+	    (!(l_map->flags & MAP_SHARED)) &&
+	    !l_map->maj && !l_map->min && !l_map->ino &&
+	    !l_map->ino_generation) {
+		/* userspace anonymous */
+
+		if (left->thread->pid_ > right->thread->pid_) return -1;
+		if (left->thread->pid_ < right->thread->pid_) return 1;
+	}
+
+addr:
+	/* al_addr does all the right addr - start + offset calculations */
+	l = cl_address(left->mem_info->daddr.al_addr);
+	r = cl_address(right->mem_info->daddr.al_addr);
+
+	if (l > r) return -1;
+	if (l < r) return 1;
+
+	return 0;
+}
+
+static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
+					  size_t size, unsigned int width)
+{
+
+	uint64_t addr = 0;
+	struct map *map = NULL;
+	struct symbol *sym = NULL;
+	char level = he->level;
+
+	if (he->mem_info) {
+		addr = cl_address(he->mem_info->daddr.al_addr);
+		map = he->mem_info->daddr.map;
+		sym = he->mem_info->daddr.sym;
+
+		/* print [s] for shared data mmaps */
+		if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
+		     map && (map->type == MAP__VARIABLE) &&
+		    (map->flags & MAP_SHARED) &&
+		    (map->maj || map->min || map->ino ||
+		     map->ino_generation))
+			level = 's';
+		else if (!map)
+			level = 'X';
+	}
+	return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
+					 width);
+}
+
 struct sort_entry sort_mispredict = {
 	.se_header	= "Branch Mispredicted",
 	.se_cmp		= sort__mispredict_cmp,
@@ -857,6 +956,13 @@ struct sort_entry sort_mem_snoop = {
 	.se_width_idx	= HISTC_MEM_SNOOP,
 };
 
+struct sort_entry sort_mem_dcacheline = {
+	.se_header	= "Data Cacheline",
+	.se_cmp		= sort__dcacheline_cmp,
+	.se_snprintf	= hist_entry__dcacheline_snprintf,
+	.se_width_idx	= HISTC_MEM_DCACHELINE,
+};
+
 static int64_t
 sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -1024,6 +1130,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
 	DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
 	DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
 	DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
+	DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
 };
 
 #undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 22cf912..460ec9c 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -167,6 +167,7 @@ enum sort_type {
 	SORT_MEM_TLB,
 	SORT_MEM_LVL,
 	SORT_MEM_SNOOP,
+	SORT_MEM_DCACHELINE,
 };
 
 /*
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support"
  2014-05-27 16:28 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
@ 2014-05-30  7:05   ` Namhyung Kim
  2014-05-30 14:49   ` [PATCH 2/7 V2] " Don Zickus
  1 sibling, 0 replies; 20+ messages in thread
From: Namhyung Kim @ 2014-05-30  7:05 UTC (permalink / raw)
  To: Don Zickus
  Cc: jolsa, Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, eranian,
	Andi Kleen

Hi Don,

On Tue, 27 May 2014 12:28:02 -0400, Don Zickus wrote:
> This reverts commit 3090ffb5a2515990182f3f55b0688a7817325488.
>
> Re-enable the mmap2 interface as we will have a user soon.
>
> Since things have changed since perf disabled mmap2, small tweaks
> to the revert had to be done:
>
> o commit 9d4ecc88 forced (n!=8) to become (n<7)
> o a new libunwind test needed updating to use mmap2 interface

Just few nitpicks..


[SNIP]
> @@ -195,14 +196,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
>  		strcpy(execname, "");
>  
>  		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
> -		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
> -		       &event->mmap.start, &event->mmap.len, prot,
> -		       &event->mmap.pgoff,
> -		       execname);
> -		/*
> - 		 * Anon maps don't have the execname.
> - 		 */

I think it's better to leave this comment as is.


> -		if (n < 4)
> +		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
> +		       &event->mmap2.start, &event->mmap2.len, prot,
> +		       &event->mmap2.pgoff, &event->mmap2.maj,
> +		       &event->mmap2.min,
> +		       &ino, execname);
> +
> +		event->mmap2.ino = (u64)ino;

And this can be moved below check..

Thanks,
Namhyung


> +
> +		if (n < 7)
>  			continue;
>  		/*
>  		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
> @@ -223,15 +225,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
>  			strcpy(execname, anonstr);
>  
>  		size = strlen(execname) + 1;
> -		memcpy(event->mmap.filename, execname, size);
> +		memcpy(event->mmap2.filename, execname, size);
>  		size = PERF_ALIGN(size, sizeof(u64));
> -		event->mmap.len -= event->mmap.start;
> -		event->mmap.header.size = (sizeof(event->mmap) -
> -					(sizeof(event->mmap.filename) - size));
> -		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
> -		event->mmap.header.size += machine->id_hdr_size;
> -		event->mmap.pid = tgid;
> -		event->mmap.tid = pid;
> +		event->mmap2.len -= event->mmap.start;
> +		event->mmap2.header.size = (sizeof(event->mmap2) -
> +					(sizeof(event->mmap2.filename) - size));
> +		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
> +		event->mmap2.header.size += machine->id_hdr_size;
> +		event->mmap2.pid = tgid;
> +		event->mmap2.tid = pid;
>  
>  		if (process(tool, event, &synth_sample, machine) != 0) {
>  			rc = -1;
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 5c28d82..21154da 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)
>  		perf_evsel__set_sample_bit(evsel, WEIGHT);
>  
>  	attr->mmap  = track;
> +	attr->mmap2 = track && !perf_missing_features.mmap2;
>  	attr->comm  = track;
>  
>  	if (opts->sample_transaction)

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 6/7] perf: Add support to dynamically get cacheline size
  2014-05-27 16:28 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
@ 2014-05-30  7:09   ` Namhyung Kim
  2014-05-30 14:50   ` [PATCH 6/7 V2] " Don Zickus
  2014-05-30 20:10   ` [PATCH 6/7 V3] " Don Zickus
  2 siblings, 0 replies; 20+ messages in thread
From: Namhyung Kim @ 2014-05-30  7:09 UTC (permalink / raw)
  To: Don Zickus
  Cc: jolsa, Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, eranian,
	Andi Kleen

On Tue, 27 May 2014 12:28:06 -0400, Don Zickus wrote:
> Different arches may have different cacheline sizes.  Look it up and set
> a global variable for reference.

[SNIP]
> diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> index 635cd8f..6e06567 100644
> --- a/tools/perf/util/sort.c
> +++ b/tools/perf/util/sort.c
> @@ -2,6 +2,7 @@
>  #include "hist.h"
>  #include "comm.h"
>  #include "symbol.h"
> +#include "cpumap.h"

It seems not needed anymore?

Thanks,
Namhyung

>  
>  regex_t		parent_regex;
>  const char	default_parent_pattern[] = "^sys_|^do_page_fault";

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting
  2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
                   ` (6 preceding siblings ...)
  2014-05-27 16:28 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
@ 2014-05-30  7:15 ` Namhyung Kim
  7 siblings, 0 replies; 20+ messages in thread
From: Namhyung Kim @ 2014-05-30  7:15 UTC (permalink / raw)
  To: Don Zickus
  Cc: jolsa, Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, eranian,
	Andi Kleen

On Tue, 27 May 2014 12:28:00 -0400, Don Zickus wrote:
> These patches enable mmap2 support in the kernel and perf to
> allow support for data cacheline sorting.
>
> Note: I haven't been able to reproduce Jiri's perf hang yet, so I don't
> have a patch for that particular problem yet.

I have no idea what the hang case is, but from a quick look, the code
for the tooling part (beside few nitpicks) looks good to me.

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 2/7 V2] Revert "perf: Disable PERF_RECORD_MMAP2 support"
  2014-05-27 16:28 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
  2014-05-30  7:05   ` Namhyung Kim
@ 2014-05-30 14:49   ` Don Zickus
  2014-06-12 12:02     ` [tip:perf/core] " tip-bot for Don Zickus
  1 sibling, 1 reply; 20+ messages in thread
From: Don Zickus @ 2014-05-30 14:49 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

This reverts commit 3090ffb5a2515990182f3f55b0688a7817325488.

Re-enable the mmap2 interface as we will have a user soon.

Since things have changed since perf disabled mmap2, small tweaks
to the revert had to be done:

o commit 9d4ecc88 forced (n!=8) to become (n<7)
o a new libunwind test needed updating to use mmap2 interface

Signed-off-by: Don Zickus <dzickus@redhat.com>
---
v3: restore comment (Namhyung Kim)
    move ino assignment (Namhyung Kim)
v2: added a better changelog
    fix a unwind test (thanks Jiri)
---
 kernel/events/core.c            |  4 ----
 tools/perf/tests/dwarf-unwind.c |  2 +-
 tools/perf/util/event.c         | 34 ++++++++++++++++++++--------------
 tools/perf/util/evsel.c         |  1 +
 4 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 0711cc9..c793cb0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6882,10 +6882,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
 	if (ret)
 		return -EFAULT;
 
-	/* disabled for now */
-	if (attr->mmap2)
-		return -EINVAL;
-
 	if (attr->__reserved_1)
 		return -EINVAL;
 
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 108f0cd..96adb73 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,
 			struct perf_sample *sample __maybe_unused,
 			struct machine *machine)
 {
-	return machine__process_mmap_event(machine, event, NULL);
+	return machine__process_mmap2_event(machine, event, NULL);
 }
 
 static int init_live_machine(struct machine *machine)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 65795b8..0a594fd 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -178,13 +178,14 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP;
+	event->header.type = PERF_RECORD_MMAP2;
 
 	while (1) {
 		char bf[BUFSIZ];
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
+		unsigned int ino;
 		size_t size;
 		ssize_t n;
 
@@ -195,15 +196,20 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
-		       &event->mmap.start, &event->mmap.len, prot,
-		       &event->mmap.pgoff,
-		       execname);
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+		       &event->mmap2.start, &event->mmap2.len, prot,
+		       &event->mmap2.pgoff, &event->mmap2.maj,
+		       &event->mmap2.min,
+		       &ino, execname);
+
 		/*
  		 * Anon maps don't have the execname.
  		 */
-		if (n < 4)
+		if (n < 7)
 			continue;
+
+		event->mmap2.ino = (u64)ino;
+
 		/*
 		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 		 */
@@ -223,15 +229,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap.filename, execname, size);
+		memcpy(event->mmap2.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap.len -= event->mmap.start;
-		event->mmap.header.size = (sizeof(event->mmap) -
-					(sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
-		event->mmap.header.size += machine->id_hdr_size;
-		event->mmap.pid = tgid;
-		event->mmap.tid = pid;
+		event->mmap2.len -= event->mmap.start;
+		event->mmap2.header.size = (sizeof(event->mmap2) -
+					(sizeof(event->mmap2.filename) - size));
+		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
+		event->mmap2.header.size += machine->id_hdr_size;
+		event->mmap2.pid = tgid;
+		event->mmap2.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 5c28d82..21154da 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)
 		perf_evsel__set_sample_bit(evsel, WEIGHT);
 
 	attr->mmap  = track;
+	attr->mmap2 = track && !perf_missing_features.mmap2;
 	attr->comm  = track;
 
 	if (opts->sample_transaction)
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 6/7 V2] perf: Add support to dynamically get cacheline size
  2014-05-27 16:28 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
  2014-05-30  7:09   ` Namhyung Kim
@ 2014-05-30 14:50   ` Don Zickus
  2014-05-30 15:28     ` Arnaldo Carvalho de Melo
  2014-05-30 20:10   ` [PATCH 6/7 V3] " Don Zickus
  2 siblings, 1 reply; 20+ messages in thread
From: Don Zickus @ 2014-05-30 14:50 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

Different arches may have different cacheline sizes.  Look it up and set
a global variable for reference.

Signed-off-by: Don Zickus <dzickus@redhat.com>

---
V3: remove unneeded cpumap.h (Namhyung Kim)
V2: change to be global and setup in perf.c
    use filename__read_int for setup
---
 tools/perf/perf.c        |  5 +++++
 tools/perf/util/cpumap.c | 27 +++++++++++++++++++++++++++
 tools/perf/util/cpumap.h |  3 +++
 tools/perf/util/util.c   |  1 +
 tools/perf/util/util.h   |  1 +
 5 files changed, 37 insertions(+)

diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 431798a..dabf08b 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,6 +13,7 @@
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
+#include "util/cpumap.h"
 #include <api/fs/debugfs.h>
 #include <pthread.h>
 
@@ -459,6 +460,10 @@ int main(int argc, const char **argv)
 	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
 
+	/* The cacheline_size is placed in util objet */
+	if (cpu__setup_cacheline_size() < 0) 
+		goto out;
+
 	cmd = perf_extract_argv0_path(argv[0]);
 	if (!cmd)
 		cmd = "perf-help";
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index c4e55b7..1029982 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -477,3 +477,30 @@ int cpu__setup_cpunode_map(void)
 	closedir(dir1);
 	return 0;
 }
+
+int cpu__setup_cacheline_size(void)
+{
+	const char *mnt;
+	char path[PATH_MAX];
+	int n, size;
+	
+
+	mnt = sysfs__mountpoint();
+	if (!mnt)
+		return -1;
+
+	n = snprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu0/cache/index0/coherency_line_size", mnt);
+	if (n == PATH_MAX) {
+		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
+		return -1;
+	}
+
+	if (filename__read_int(path, &size)) {
+		pr_err("Can not read cacheline size\n");
+		return -1;
+	}
+
+	cacheline_size = size;
+
+	return 0;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 61a6548..507d7fd 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -5,6 +5,7 @@
 #include <stdbool.h>
 
 #include "perf.h"
+#include "util/util.h"
 #include "util/debug.h"
 
 struct cpu_map {
@@ -81,4 +82,6 @@ static inline int cpu__get_node(int cpu)
 	return cpunode_map[cpu];
 }
 
+int cpu__setup_cacheline_size(void);
+
 #endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 7fff6be..95aefa7 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,6 +17,7 @@
  * XXX We need to find a better place for these things...
  */
 unsigned int page_size;
+int cacheline_size;
 
 bool test_attr__enabled;
 
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b03da44..6686436 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -304,6 +304,7 @@ char *rtrim(char *s);
 void dump_stack(void);
 
 extern unsigned int page_size;
+extern int cacheline_size;
 
 void get_term_dimensions(struct winsize *ws);
 
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 6/7 V2] perf: Add support to dynamically get cacheline size
  2014-05-30 14:50   ` [PATCH 6/7 V2] " Don Zickus
@ 2014-05-30 15:28     ` Arnaldo Carvalho de Melo
  2014-05-30 16:20       ` Don Zickus
  0 siblings, 1 reply; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-05-30 15:28 UTC (permalink / raw)
  To: Don Zickus; +Cc: jolsa, Peter Zijlstra, LKML, namhyung, eranian, Andi Kleen

Em Fri, May 30, 2014 at 10:50:25AM -0400, Don Zickus escreveu:
> Different arches may have different cacheline sizes.  Look it up and set
> a global variable for reference.

[acme@zoo linux]$ strings `which getconf` | grep LINESIZE
LEVEL1_ICACHE_LINESIZE
LEVEL1_DCACHE_LINESIZE
LEVEL2_CACHE_LINESIZE
LEVEL3_CACHE_LINESIZE
LEVEL4_CACHE_LINESIZE
[acme@zoo linux]$

man sysconf

That is what I use in pahole, for instance:

[acme@zoo pahole]$ grep sysconf *.c
dwarves_fprintf.c:		long sys_cacheline_size =
sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
[acme@zoo pahole]$

- Arnaldo
 
> Signed-off-by: Don Zickus <dzickus@redhat.com>
> 
> ---
> V3: remove unneeded cpumap.h (Namhyung Kim)
> V2: change to be global and setup in perf.c
>     use filename__read_int for setup
> ---
>  tools/perf/perf.c        |  5 +++++
>  tools/perf/util/cpumap.c | 27 +++++++++++++++++++++++++++
>  tools/perf/util/cpumap.h |  3 +++
>  tools/perf/util/util.c   |  1 +
>  tools/perf/util/util.h   |  1 +
>  5 files changed, 37 insertions(+)
> 
> diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> index 431798a..dabf08b 100644
> --- a/tools/perf/perf.c
> +++ b/tools/perf/perf.c
> @@ -13,6 +13,7 @@
>  #include "util/quote.h"
>  #include "util/run-command.h"
>  #include "util/parse-events.h"
> +#include "util/cpumap.h"
>  #include <api/fs/debugfs.h>
>  #include <pthread.h>
>  
> @@ -459,6 +460,10 @@ int main(int argc, const char **argv)
>  	/* The page_size is placed in util object. */
>  	page_size = sysconf(_SC_PAGE_SIZE);
>  
> +	/* The cacheline_size is placed in util objet */
> +	if (cpu__setup_cacheline_size() < 0) 
> +		goto out;
> +
>  	cmd = perf_extract_argv0_path(argv[0]);
>  	if (!cmd)
>  		cmd = "perf-help";
> diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
> index c4e55b7..1029982 100644
> --- a/tools/perf/util/cpumap.c
> +++ b/tools/perf/util/cpumap.c
> @@ -477,3 +477,30 @@ int cpu__setup_cpunode_map(void)
>  	closedir(dir1);
>  	return 0;
>  }
> +
> +int cpu__setup_cacheline_size(void)
> +{
> +	const char *mnt;
> +	char path[PATH_MAX];
> +	int n, size;
> +	
> +
> +	mnt = sysfs__mountpoint();
> +	if (!mnt)
> +		return -1;
> +
> +	n = snprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu0/cache/index0/coherency_line_size", mnt);
> +	if (n == PATH_MAX) {
> +		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
> +		return -1;
> +	}
> +
> +	if (filename__read_int(path, &size)) {
> +		pr_err("Can not read cacheline size\n");
> +		return -1;
> +	}
> +
> +	cacheline_size = size;
> +
> +	return 0;
> +}
> diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
> index 61a6548..507d7fd 100644
> --- a/tools/perf/util/cpumap.h
> +++ b/tools/perf/util/cpumap.h
> @@ -5,6 +5,7 @@
>  #include <stdbool.h>
>  
>  #include "perf.h"
> +#include "util/util.h"
>  #include "util/debug.h"
>  
>  struct cpu_map {
> @@ -81,4 +82,6 @@ static inline int cpu__get_node(int cpu)
>  	return cpunode_map[cpu];
>  }
>  
> +int cpu__setup_cacheline_size(void);
> +
>  #endif /* __PERF_CPUMAP_H */
> diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
> index 7fff6be..95aefa7 100644
> --- a/tools/perf/util/util.c
> +++ b/tools/perf/util/util.c
> @@ -17,6 +17,7 @@
>   * XXX We need to find a better place for these things...
>   */
>  unsigned int page_size;
> +int cacheline_size;
>  
>  bool test_attr__enabled;
>  
> diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
> index b03da44..6686436 100644
> --- a/tools/perf/util/util.h
> +++ b/tools/perf/util/util.h
> @@ -304,6 +304,7 @@ char *rtrim(char *s);
>  void dump_stack(void);
>  
>  extern unsigned int page_size;
> +extern int cacheline_size;
>  
>  void get_term_dimensions(struct winsize *ws);
>  
> -- 
> 1.7.11.7

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 6/7 V2] perf: Add support to dynamically get cacheline size
  2014-05-30 15:28     ` Arnaldo Carvalho de Melo
@ 2014-05-30 16:20       ` Don Zickus
  0 siblings, 0 replies; 20+ messages in thread
From: Don Zickus @ 2014-05-30 16:20 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: jolsa, Peter Zijlstra, LKML, namhyung, eranian, Andi Kleen

On Fri, May 30, 2014 at 12:28:30PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Fri, May 30, 2014 at 10:50:25AM -0400, Don Zickus escreveu:
> > Different arches may have different cacheline sizes.  Look it up and set
> > a global variable for reference.
> 
> [acme@zoo linux]$ strings `which getconf` | grep LINESIZE
> LEVEL1_ICACHE_LINESIZE
> LEVEL1_DCACHE_LINESIZE
> LEVEL2_CACHE_LINESIZE
> LEVEL3_CACHE_LINESIZE
> LEVEL4_CACHE_LINESIZE
> [acme@zoo linux]$
> 
> man sysconf
> 
> That is what I use in pahole, for instance:
> 
> [acme@zoo pahole]$ grep sysconf *.c
> dwarves_fprintf.c:		long sys_cacheline_size =
> sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
> [acme@zoo pahole]$

Well that does look easier.  I'll hack that up to see if it gives me the
same answer.

Thanks!

Cheers,
Don

> 
> - Arnaldo
>  
> > Signed-off-by: Don Zickus <dzickus@redhat.com>
> > 
> > ---
> > V3: remove unneeded cpumap.h (Namhyung Kim)
> > V2: change to be global and setup in perf.c
> >     use filename__read_int for setup
> > ---
> >  tools/perf/perf.c        |  5 +++++
> >  tools/perf/util/cpumap.c | 27 +++++++++++++++++++++++++++
> >  tools/perf/util/cpumap.h |  3 +++
> >  tools/perf/util/util.c   |  1 +
> >  tools/perf/util/util.h   |  1 +
> >  5 files changed, 37 insertions(+)
> > 
> > diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> > index 431798a..dabf08b 100644
> > --- a/tools/perf/perf.c
> > +++ b/tools/perf/perf.c
> > @@ -13,6 +13,7 @@
> >  #include "util/quote.h"
> >  #include "util/run-command.h"
> >  #include "util/parse-events.h"
> > +#include "util/cpumap.h"
> >  #include <api/fs/debugfs.h>
> >  #include <pthread.h>
> >  
> > @@ -459,6 +460,10 @@ int main(int argc, const char **argv)
> >  	/* The page_size is placed in util object. */
> >  	page_size = sysconf(_SC_PAGE_SIZE);
> >  
> > +	/* The cacheline_size is placed in util objet */
> > +	if (cpu__setup_cacheline_size() < 0) 
> > +		goto out;
> > +
> >  	cmd = perf_extract_argv0_path(argv[0]);
> >  	if (!cmd)
> >  		cmd = "perf-help";
> > diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
> > index c4e55b7..1029982 100644
> > --- a/tools/perf/util/cpumap.c
> > +++ b/tools/perf/util/cpumap.c
> > @@ -477,3 +477,30 @@ int cpu__setup_cpunode_map(void)
> >  	closedir(dir1);
> >  	return 0;
> >  }
> > +
> > +int cpu__setup_cacheline_size(void)
> > +{
> > +	const char *mnt;
> > +	char path[PATH_MAX];
> > +	int n, size;
> > +	
> > +
> > +	mnt = sysfs__mountpoint();
> > +	if (!mnt)
> > +		return -1;
> > +
> > +	n = snprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu0/cache/index0/coherency_line_size", mnt);
> > +	if (n == PATH_MAX) {
> > +		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
> > +		return -1;
> > +	}
> > +
> > +	if (filename__read_int(path, &size)) {
> > +		pr_err("Can not read cacheline size\n");
> > +		return -1;
> > +	}
> > +
> > +	cacheline_size = size;
> > +
> > +	return 0;
> > +}
> > diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
> > index 61a6548..507d7fd 100644
> > --- a/tools/perf/util/cpumap.h
> > +++ b/tools/perf/util/cpumap.h
> > @@ -5,6 +5,7 @@
> >  #include <stdbool.h>
> >  
> >  #include "perf.h"
> > +#include "util/util.h"
> >  #include "util/debug.h"
> >  
> >  struct cpu_map {
> > @@ -81,4 +82,6 @@ static inline int cpu__get_node(int cpu)
> >  	return cpunode_map[cpu];
> >  }
> >  
> > +int cpu__setup_cacheline_size(void);
> > +
> >  #endif /* __PERF_CPUMAP_H */
> > diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
> > index 7fff6be..95aefa7 100644
> > --- a/tools/perf/util/util.c
> > +++ b/tools/perf/util/util.c
> > @@ -17,6 +17,7 @@
> >   * XXX We need to find a better place for these things...
> >   */
> >  unsigned int page_size;
> > +int cacheline_size;
> >  
> >  bool test_attr__enabled;
> >  
> > diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
> > index b03da44..6686436 100644
> > --- a/tools/perf/util/util.h
> > +++ b/tools/perf/util/util.h
> > @@ -304,6 +304,7 @@ char *rtrim(char *s);
> >  void dump_stack(void);
> >  
> >  extern unsigned int page_size;
> > +extern int cacheline_size;
> >  
> >  void get_term_dimensions(struct winsize *ws);
> >  
> > -- 
> > 1.7.11.7

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 6/7 V3] perf: Add support to dynamically get cacheline size
  2014-05-27 16:28 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
  2014-05-30  7:09   ` Namhyung Kim
  2014-05-30 14:50   ` [PATCH 6/7 V2] " Don Zickus
@ 2014-05-30 20:10   ` Don Zickus
  2014-06-12 12:03     ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
  2 siblings, 1 reply; 20+ messages in thread
From: Don Zickus @ 2014-05-30 20:10 UTC (permalink / raw)
  To: jolsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, LKML, namhyung,
	eranian, Andi Kleen, Don Zickus

Different arches may have different cacheline sizes.  Look it up and set
a global variable for reference.

Signed-off-by: Don Zickus <dzickus@redhat.com>

---
V4: make it super simple using a sysconf (Arnaldo)
V3: remove unneeded cpumap.h (Namhyung Kim)
V2: change to be global and setup in perf.c
    use filename__read_int for setup

revert cacheline size stuff
---
 tools/perf/perf.c      | 1 +
 tools/perf/util/util.c | 1 +
 tools/perf/util/util.h | 1 +
 3 files changed, 3 insertions(+)

diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 431798a..d0374d4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -458,6 +458,7 @@ int main(int argc, const char **argv)
 
 	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
+	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
 
 	cmd = perf_extract_argv0_path(argv[0]);
 	if (!cmd)
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 7fff6be..95aefa7 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,6 +17,7 @@
  * XXX We need to find a better place for these things...
  */
 unsigned int page_size;
+int cacheline_size;
 
 bool test_attr__enabled;
 
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b03da44..6686436 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -304,6 +304,7 @@ char *rtrim(char *s);
 void dump_stack(void);
 
 extern unsigned int page_size;
+extern int cacheline_size;
 
 void get_term_dimensions(struct winsize *ws);
 
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] Revert "perf: Disable PERF_RECORD_MMAP2 support"
  2014-05-30 14:49   ` [PATCH 2/7 V2] " Don Zickus
@ 2014-06-12 12:02     ` tip-bot for Don Zickus
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Don Zickus @ 2014-06-12 12:02 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, jolsa, tglx, dzickus

Commit-ID:  a5a5ba72843dd05f991184d6cb9a4471acce1005
Gitweb:     http://git.kernel.org/tip/a5a5ba72843dd05f991184d6cb9a4471acce1005
Author:     Don Zickus <dzickus@redhat.com>
AuthorDate: Fri, 30 May 2014 10:49:42 -0400
Committer:  Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 13:34:46 +0200

Revert "perf: Disable PERF_RECORD_MMAP2 support"

This reverts commit 3090ffb5a2515990182f3f55b0688a7817325488.

Re-enable the mmap2 interface as we will have a user soon.

Since things have changed since perf disabled mmap2, small tweaks
to the revert had to be done:

o commit 9d4ecc88 forced (n!=8) to become (n<7)
o a new libunwind test needed updating to use mmap2 interface

Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1401461382-209586-1-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 kernel/events/core.c            |  4 ----
 tools/perf/tests/dwarf-unwind.c |  2 +-
 tools/perf/util/event.c         | 34 ++++++++++++++++++++--------------
 tools/perf/util/evsel.c         |  1 +
 4 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index eea1955..cd28335 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6929,10 +6929,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
 	if (ret)
 		return -EFAULT;
 
-	/* disabled for now */
-	if (attr->mmap2)
-		return -EINVAL;
-
 	if (attr->__reserved_1)
 		return -EINVAL;
 
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 108f0cd..96adb73 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,
 			struct perf_sample *sample __maybe_unused,
 			struct machine *machine)
 {
-	return machine__process_mmap_event(machine, event, NULL);
+	return machine__process_mmap2_event(machine, event, NULL);
 }
 
 static int init_live_machine(struct machine *machine)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ce43cba..d0281bd 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -179,13 +179,14 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP;
+	event->header.type = PERF_RECORD_MMAP2;
 
 	while (1) {
 		char bf[BUFSIZ];
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
+		unsigned int ino;
 		size_t size;
 		ssize_t n;
 
@@ -196,15 +197,20 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
-		       &event->mmap.start, &event->mmap.len, prot,
-		       &event->mmap.pgoff,
-		       execname);
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+		       &event->mmap2.start, &event->mmap2.len, prot,
+		       &event->mmap2.pgoff, &event->mmap2.maj,
+		       &event->mmap2.min,
+		       &ino, execname);
+
 		/*
  		 * Anon maps don't have the execname.
  		 */
-		if (n < 4)
+		if (n < 7)
 			continue;
+
+		event->mmap2.ino = (u64)ino;
+
 		/*
 		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 		 */
@@ -239,15 +245,15 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap.filename, execname, size);
+		memcpy(event->mmap2.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap.len -= event->mmap.start;
-		event->mmap.header.size = (sizeof(event->mmap) -
-					(sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
-		event->mmap.header.size += machine->id_hdr_size;
-		event->mmap.pid = tgid;
-		event->mmap.tid = pid;
+		event->mmap2.len -= event->mmap.start;
+		event->mmap2.header.size = (sizeof(event->mmap2) -
+					(sizeof(event->mmap2.filename) - size));
+		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
+		event->mmap2.header.size += machine->id_hdr_size;
+		event->mmap2.pid = tgid;
+		event->mmap2.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 5c28d82..21154da 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)
 		perf_evsel__set_sample_bit(evsel, WEIGHT);
 
 	attr->mmap  = track;
+	attr->mmap2 = track && !perf_missing_features.mmap2;
 	attr->comm  = track;
 
 	if (opts->sample_transaction)

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] perf tools: Add cpumode to struct hist_entry
  2014-05-27 16:28 ` [PATCH 5/7] perf: Add cpumode to struct hist_entry Don Zickus
@ 2014-06-12 12:03   ` tip-bot for Don Zickus
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Don Zickus @ 2014-06-12 12:03 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, jolsa, tglx, dzickus

Commit-ID:  7365be55eee37ddb4f487263b4ba5bc8beb9638f
Gitweb:     http://git.kernel.org/tip/7365be55eee37ddb4f487263b4ba5bc8beb9638f
Author:     Don Zickus <dzickus@redhat.com>
AuthorDate: Tue, 27 May 2014 12:28:05 -0400
Committer:  Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 13:34:48 +0200

perf tools: Add cpumode to struct hist_entry

The next patch needs to sort on cpumode, so add it to hist_entry to be tracked.

Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1401208087-181977-6-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/hist.c | 7 ++++---
 tools/perf/util/sort.h | 1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 5a0a4b2..d5f47a4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -439,9 +439,10 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
 			.map	= al->map,
 			.sym	= al->sym,
 		},
-		.cpu	= al->cpu,
-		.ip	= al->addr,
-		.level	= al->level,
+		.cpu	 = al->cpu,
+		.cpumode = al->cpumode,
+		.ip	 = al->addr,
+		.level	 = al->level,
 		.stat = {
 			.nr_events = 1,
 			.period	= period,
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 5bf0098..6de22f8 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -89,6 +89,7 @@ struct hist_entry {
 	u64			ip;
 	u64			transaction;
 	s32			cpu;
+	u8			cpumode;
 
 	struct hist_entry_diff	diff;
 

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] perf tools: Add support to dynamically get cacheline size
  2014-05-30 20:10   ` [PATCH 6/7 V3] " Don Zickus
@ 2014-06-12 12:03     ` tip-bot for Don Zickus
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Don Zickus @ 2014-06-12 12:03 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, jolsa, tglx, dzickus

Commit-ID:  2b1b71003ea809e619bd73e74dfc2a73069de66f
Gitweb:     http://git.kernel.org/tip/2b1b71003ea809e619bd73e74dfc2a73069de66f
Author:     Don Zickus <dzickus@redhat.com>
AuthorDate: Fri, 30 May 2014 16:10:05 -0400
Committer:  Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 13:34:48 +0200

perf tools: Add support to dynamically get cacheline size

Different arches may have different cacheline sizes.  Look it up and set
a global variable for reference.

Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1401480605-97442-1-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/perf.c      | 1 +
 tools/perf/util/util.c | 1 +
 tools/perf/util/util.h | 1 +
 3 files changed, 3 insertions(+)

diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 78f7b92..95c58fc 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -458,6 +458,7 @@ int main(int argc, const char **argv)
 
 	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
+	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
 
 	cmd = perf_extract_argv0_path(argv[0]);
 	if (!cmd)
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 7fff6be..95aefa7 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -17,6 +17,7 @@
  * XXX We need to find a better place for these things...
  */
 unsigned int page_size;
+int cacheline_size;
 
 bool test_attr__enabled;
 
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b03da44..6686436 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -304,6 +304,7 @@ char *rtrim(char *s);
 void dump_stack(void);
 
 extern unsigned int page_size;
+extern int cacheline_size;
 
 void get_term_dimensions(struct winsize *ws);
 

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] perf tools: Add dcacheline sort
  2014-05-27 16:28 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
@ 2014-06-12 12:03   ` tip-bot for Don Zickus
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Don Zickus @ 2014-06-12 12:03 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, jolsa, tglx, dzickus

Commit-ID:  9b32ba71ba905b90610fc2aad77cb98a373c5624
Gitweb:     http://git.kernel.org/tip/9b32ba71ba905b90610fc2aad77cb98a373c5624
Author:     Don Zickus <dzickus@redhat.com>
AuthorDate: Sun, 1 Jun 2014 15:38:29 +0200
Committer:  Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 13:34:49 +0200

perf tools: Add dcacheline sort

In perf's 'mem-mode', one can get access to a whole bunch of details specific to a
particular sample instruction.  A bunch of those details relate to the data
address.

One interesting thing you can do with data addresses is to convert them into a unique
cacheline they belong too.  Organizing these data cachelines into similar groups and sorting
them can reveal cache contention.

This patch creates an alogorithm based on various sample details that can help group
entries together into data cachelines and allows 'perf report' to sort on it.

The algorithm relies on having proper mmap2 support in the kernel to help determine
if the memory map the data address belongs to is private to a pid or globally shared.

The alogortithm is as follows:

o group cpumodes together
o group entries with discovered maps together
o sort on major, minor, inode and inode generation numbers
o if userspace anon, then sort on pid
o sort on cachelines based on data addresses

The 'dcacheline' sort option in 'perf report' only works in 'mem-mode'.

Sample output:

 #
 # Samples: 206  of event 'cpu/mem-loads/pp'
 # Total weight : 2534
 # Sort order   : dcacheline,pid
 #
 # Overhead       Samples                                                          Data Cacheline       Command:  Pid
 # ........  ............  ......................................................................  ..................
 #
    13.22%             1  [k] 0xffff88042f08ebc0                                                       swapper:    0
     9.27%             1  [k] 0xffff88082e8cea80                                                       swapper:    0
     3.59%             2  [k] 0xffffffff819ba180                                                       swapper:    0
     0.32%             1  [k] arch_trigger_all_cpu_backtrace_handler_na.23901+0xffffffffffffffe0       swapper:    0
     0.32%             1  [k] timekeeper_seq+0xfffffffffffffff8                                        swapper:    0

Note:  Added a '+1' to symlen size in hists__calc_col_len to prevent the next column
from prematurely tabbing over and mis-aligning.  Not sure what the problem is.

Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1401208087-181977-8-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-report.txt |   3 +-
 tools/perf/util/hist.c                   |   2 +
 tools/perf/util/hist.h                   |   1 +
 tools/perf/util/sort.c                   | 107 +++++++++++++++++++++++++++++++
 tools/perf/util/sort.h                   |   1 +
 5 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 00fbfb6..d2b59af 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -119,7 +119,7 @@ OPTIONS
 
 	If --mem-mode option is used, following sort keys are also available
 	(incompatible with --branch-stack):
-	symbol_daddr, dso_daddr, locked, tlb, mem, snoop.
+	symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline.
 
 	- symbol_daddr: name of data symbol being executed on at the time of sample
 	- dso_daddr: name of library or module containing the data being executed
@@ -128,6 +128,7 @@ OPTIONS
 	- tlb: type of tlb access for the data at the time of sample
 	- mem: type of memory access for the data at the time of sample
 	- snoop: type of snoop (if any) for the data at the time of sample
+	- dcacheline: the cacheline the data address is on at the time of sample
 
 	And default sort keys are changed to local_weight, mem, sym, dso,
 	symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index d5f47a4..30df618 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)
 			       + unresolved_col_width + 2;
 			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
 					   symlen);
+			hists__new_col_len(hists, HISTC_MEM_DCACHELINE,
+					   symlen + 1);
 		} else {
 			symlen = unresolved_col_width + 4 + 2;
 			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index d2bf035..742f49a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -72,6 +72,7 @@ enum hist_column {
 	HISTC_MEM_TLB,
 	HISTC_MEM_LVL,
 	HISTC_MEM_SNOOP,
+	HISTC_MEM_DCACHELINE,
 	HISTC_TRANSACTION,
 	HISTC_NR_COLS, /* Last entry */
 };
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 45512ba..1ec57dd 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,3 +1,4 @@
+#include <sys/mman.h>
 #include "sort.h"
 #include "hist.h"
 #include "comm.h"
@@ -784,6 +785,104 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
 	return repsep_snprintf(bf, size, "%-*s", width, out);
 }
 
+static inline  u64 cl_address(u64 address)
+{
+	/* return the cacheline of the address */
+	return (address & ~(cacheline_size - 1));
+}
+
+static int64_t
+sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	u64 l, r;
+	struct map *l_map, *r_map;
+
+	if (!left->mem_info)  return -1;
+	if (!right->mem_info) return 1;
+
+	/* group event types together */
+	if (left->cpumode > right->cpumode) return -1;
+	if (left->cpumode < right->cpumode) return 1;
+
+	l_map = left->mem_info->daddr.map;
+	r_map = right->mem_info->daddr.map;
+
+	/* if both are NULL, jump to sort on al_addr instead */
+	if (!l_map && !r_map)
+		goto addr;
+
+	if (!l_map) return -1;
+	if (!r_map) return 1;
+
+	if (l_map->maj > r_map->maj) return -1;
+	if (l_map->maj < r_map->maj) return 1;
+
+	if (l_map->min > r_map->min) return -1;
+	if (l_map->min < r_map->min) return 1;
+
+	if (l_map->ino > r_map->ino) return -1;
+	if (l_map->ino < r_map->ino) return 1;
+
+	if (l_map->ino_generation > r_map->ino_generation) return -1;
+	if (l_map->ino_generation < r_map->ino_generation) return 1;
+
+	/*
+	 * Addresses with no major/minor numbers are assumed to be
+	 * anonymous in userspace.  Sort those on pid then address.
+	 *
+	 * The kernel and non-zero major/minor mapped areas are
+	 * assumed to be unity mapped.  Sort those on address.
+	 */
+
+	if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
+	    (!(l_map->flags & MAP_SHARED)) &&
+	    !l_map->maj && !l_map->min && !l_map->ino &&
+	    !l_map->ino_generation) {
+		/* userspace anonymous */
+
+		if (left->thread->pid_ > right->thread->pid_) return -1;
+		if (left->thread->pid_ < right->thread->pid_) return 1;
+	}
+
+addr:
+	/* al_addr does all the right addr - start + offset calculations */
+	l = cl_address(left->mem_info->daddr.al_addr);
+	r = cl_address(right->mem_info->daddr.al_addr);
+
+	if (l > r) return -1;
+	if (l < r) return 1;
+
+	return 0;
+}
+
+static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
+					  size_t size, unsigned int width)
+{
+
+	uint64_t addr = 0;
+	struct map *map = NULL;
+	struct symbol *sym = NULL;
+	char level = he->level;
+
+	if (he->mem_info) {
+		addr = cl_address(he->mem_info->daddr.al_addr);
+		map = he->mem_info->daddr.map;
+		sym = he->mem_info->daddr.sym;
+
+		/* print [s] for shared data mmaps */
+		if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
+		     map && (map->type == MAP__VARIABLE) &&
+		    (map->flags & MAP_SHARED) &&
+		    (map->maj || map->min || map->ino ||
+		     map->ino_generation))
+			level = 's';
+		else if (!map)
+			level = 'X';
+	}
+	return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
+					 width);
+}
+
 struct sort_entry sort_mispredict = {
 	.se_header	= "Branch Mispredicted",
 	.se_cmp		= sort__mispredict_cmp,
@@ -876,6 +975,13 @@ struct sort_entry sort_mem_snoop = {
 	.se_width_idx	= HISTC_MEM_SNOOP,
 };
 
+struct sort_entry sort_mem_dcacheline = {
+	.se_header	= "Data Cacheline",
+	.se_cmp		= sort__dcacheline_cmp,
+	.se_snprintf	= hist_entry__dcacheline_snprintf,
+	.se_width_idx	= HISTC_MEM_DCACHELINE,
+};
+
 static int64_t
 sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -1043,6 +1149,7 @@ static struct sort_dimension memory_sort_dimensions[] = {
 	DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
 	DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
 	DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
+	DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
 };
 
 #undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 6de22f8..041f0c9 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -186,6 +186,7 @@ enum sort_type {
 	SORT_MEM_TLB,
 	SORT_MEM_LVL,
 	SORT_MEM_SNOOP,
+	SORT_MEM_DCACHELINE,
 };
 
 /*

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2014-06-12 12:03 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-27 16:28 [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Don Zickus
2014-05-27 16:28 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
2014-05-27 16:28 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
2014-05-30  7:05   ` Namhyung Kim
2014-05-30 14:49   ` [PATCH 2/7 V2] " Don Zickus
2014-06-12 12:02     ` [tip:perf/core] " tip-bot for Don Zickus
2014-05-27 16:28 ` [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits Don Zickus
2014-05-27 16:28 ` [PATCH 4/7] perf report: Add mem-mode documentation to report command Don Zickus
2014-05-27 16:28 ` [PATCH 5/7] perf: Add cpumode to struct hist_entry Don Zickus
2014-06-12 12:03   ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
2014-05-27 16:28 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
2014-05-30  7:09   ` Namhyung Kim
2014-05-30 14:50   ` [PATCH 6/7 V2] " Don Zickus
2014-05-30 15:28     ` Arnaldo Carvalho de Melo
2014-05-30 16:20       ` Don Zickus
2014-05-30 20:10   ` [PATCH 6/7 V3] " Don Zickus
2014-06-12 12:03     ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
2014-05-27 16:28 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
2014-06-12 12:03   ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
2014-05-30  7:15 ` [PATCH 0/7 V4] perf: Enable mmap2 and add dcacheline sorting Namhyung Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).