* [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-06-12 12:02 ` [tip:perf/core] " tip-bot for Peter Zijlstra
2014-05-19 19:13 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
` (5 subsequent siblings)
6 siblings, 1 reply; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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] 18+ messages in thread* [tip:perf/core] perf: Pass protection and flags bits through mmap2 interface
2014-05-19 19:13 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
@ 2014-06-12 12:02 ` tip-bot for Peter Zijlstra
0 siblings, 0 replies; 18+ messages in thread
From: tip-bot for Peter Zijlstra @ 2014-06-12 12:02 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, jolsa, a.p.zijlstra, peterz, tglx,
dzickus
Commit-ID: f972eb63b1003fae68d7b7e9b674d4ba5db681c2
Gitweb: http://git.kernel.org/tip/f972eb63b1003fae68d7b7e9b674d4ba5db681c2
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
AuthorDate: Mon, 19 May 2014 15:13:47 -0400
Committer: Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 12:21:04 +0200
perf: Pass protection and flags bits through mmap2 interface
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>
Link: http://lkml.kernel.org/r/1400526833-141779-2-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
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 5312fae..9269de2 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -705,6 +705,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 7da5e56..eea1955 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"
@@ -5127,6 +5128,7 @@ struct perf_mmap_event {
int maj, min;
u64 ino;
u64 ino_generation;
+ u32 prot, flags;
struct {
struct perf_event_header header;
@@ -5168,6 +5170,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);
@@ -5186,6 +5190,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,
@@ -5204,6 +5210,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;
@@ -5234,6 +5241,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);
@@ -5274,6 +5303,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;
@@ -5314,6 +5345,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);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support"
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
2014-05-19 19:13 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-05-19 19:13 ` [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits Don Zickus
` (4 subsequent siblings)
6 siblings, 0 replies; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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] 18+ messages in thread* [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
2014-05-19 19:13 ` [PATCH 1/7] events, perf: Pass protection and flags bits through mmap2 interface Don Zickus
2014-05-19 19:13 ` [PATCH 2/7] Revert "perf: Disable PERF_RECORD_MMAP2 support" Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-06-12 12:02 ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
2014-05-19 19:13 ` [PATCH 4/7] perf report: Add mem-mode documentation to report command Don Zickus
` (3 subsequent siblings)
6 siblings, 1 reply; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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] 18+ messages in thread* [tip:perf/core] perf tools: Update mmap2 interface with protection and flag bits
2014-05-19 19:13 ` [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits Don Zickus
@ 2014-06-12 12:02 ` tip-bot for Don Zickus
0 siblings, 0 replies; 18+ 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: 7ef807034ef33f8afe33fa7957c73954e8e4f89c
Gitweb: http://git.kernel.org/tip/7ef807034ef33f8afe33fa7957c73954e8e4f89c
Author: Don Zickus <dzickus@redhat.com>
AuthorDate: Mon, 19 May 2014 15:13:49 -0400
Committer: Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 13:34:45 +0200
perf tools: Update mmap2 interface with protection and flag bits
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>
Link: http://lkml.kernel.org/r/1400526833-141779-4-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
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 65795b8..ce43cba 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"
@@ -212,6 +213,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;
@@ -612,12 +628,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 8ccbb32..25c571f 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,
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));
@@ -157,6 +157,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);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 4/7] perf report: Add mem-mode documentation to report command
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
` (2 preceding siblings ...)
2014-05-19 19:13 ` [PATCH 3/7] perf: Update mmap2 interface with protection and flag bits Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-06-12 12:02 ` [tip:perf/core] " tip-bot for Don Zickus
2014-05-19 19:13 ` [PATCH 5/7] perf: Add cpumode to struct hist_entry Don Zickus
` (2 subsequent siblings)
6 siblings, 1 reply; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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] 18+ messages in thread* [tip:perf/core] perf report: Add mem-mode documentation to report command
2014-05-19 19:13 ` [PATCH 4/7] perf report: Add mem-mode documentation to report command Don Zickus
@ 2014-06-12 12:02 ` tip-bot for Don Zickus
0 siblings, 0 replies; 18+ 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: 75e906c9601aee73b88d6e6dc02371f8c3ca24d7
Gitweb: http://git.kernel.org/tip/75e906c9601aee73b88d6e6dc02371f8c3ca24d7
Author: Don Zickus <dzickus@redhat.com>
AuthorDate: Fri, 23 May 2014 18:41:23 +0200
Committer: Jiri Olsa <jolsa@kernel.org>
CommitDate: Mon, 9 Jun 2014 13:34:47 +0200
perf report: Add mem-mode documentation to report command
Add mem-mode sorting types and mem-mode itself to perf-report documentation.
Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1400526833-141779-5-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
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 cefdf43..00fbfb6 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -117,6 +117,21 @@ OPTIONS
By default, every sort keys not specified in -F will be appended
automatically.
+ 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
@@ -260,6 +275,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).
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 5/7] perf: Add cpumode to struct hist_entry
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
` (3 preceding siblings ...)
2014-05-19 19:13 ` [PATCH 4/7] perf report: Add mem-mode documentation to report command Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-05-19 19:13 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
2014-05-19 19:13 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
6 siblings, 0 replies; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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] 18+ messages in thread* [PATCH 6/7] perf: Add support to dynamically get cacheline size
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
` (4 preceding siblings ...)
2014-05-19 19:13 ` [PATCH 5/7] perf: Add cpumode to struct hist_entry Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-05-23 16:54 ` Jiri Olsa
2014-05-23 17:09 ` Jiri Olsa
2014-05-19 19:13 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
6 siblings, 2 replies; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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>
---
tools/perf/util/cpumap.c | 31 +++++++++++++++++++++++++++++++
tools/perf/util/cpumap.h | 12 ++++++++++++
tools/perf/util/sort.c | 3 +++
3 files changed, 46 insertions(+)
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index c4e55b7..d833238 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -477,3 +477,34 @@ 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, ret, size;
+ FILE *fp;
+
+
+ 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;
+ }
+
+ fp = fopen(path, "r");
+ if (!fp)
+ return -1;
+ ret = fscanf(fp, "%d", &size);
+ fclose(fp);
+ if (ret != 1)
+ return -1;
+
+ cacheline_size = size;
+
+ return 0;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 61a6548..b3e7b22 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -81,4 +81,16 @@ static inline int cpu__get_node(int cpu)
return cpunode_map[cpu];
}
+int cacheline_size;
+
+int cpu__setup_cacheline_size(void);
+
+static inline int cpu__cacheline_size(void)
+{
+ if (unlikely(!cacheline_size))
+ pr_debug("cacheline size not initialized\n");
+
+ return cacheline_size;
+}
+
#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 635cd8f..50adbfb 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";
@@ -1117,6 +1118,8 @@ int setup_sorting(void)
return -ENOMEM;
}
+ cpu__setup_cacheline_size();
+
for (tok = strtok_r(str, ", ", &tmp);
tok; tok = strtok_r(NULL, ", ", &tmp)) {
ret = sort_dimension__add(tok);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 6/7] perf: Add support to dynamically get cacheline size
2014-05-19 19:13 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
@ 2014-05-23 16:54 ` Jiri Olsa
2014-05-23 17:18 ` Don Zickus
2014-05-23 17:09 ` Jiri Olsa
1 sibling, 1 reply; 18+ messages in thread
From: Jiri Olsa @ 2014-05-23 16:54 UTC (permalink / raw)
To: Don Zickus; +Cc: acme, peterz, LKML, namhyung, eranian, Andi Kleen
On Mon, May 19, 2014 at 03:13:52PM -0400, Don Zickus wrote:
> 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>
> ---
> tools/perf/util/cpumap.c | 31 +++++++++++++++++++++++++++++++
> tools/perf/util/cpumap.h | 12 ++++++++++++
> tools/perf/util/sort.c | 3 +++
> 3 files changed, 46 insertions(+)
>
> diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
> index c4e55b7..d833238 100644
> --- a/tools/perf/util/cpumap.c
> +++ b/tools/perf/util/cpumap.c
> @@ -477,3 +477,34 @@ 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, ret, size;
> + FILE *fp;
> +
> +
> + 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;
> + }
> +
> + fp = fopen(path, "r");
> + if (!fp)
> + return -1;
> + ret = fscanf(fp, "%d", &size);
> + fclose(fp);
> + if (ret != 1)
> + return -1;
you can use filename__read_int
jirka
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 6/7] perf: Add support to dynamically get cacheline size
2014-05-23 16:54 ` Jiri Olsa
@ 2014-05-23 17:18 ` Don Zickus
0 siblings, 0 replies; 18+ messages in thread
From: Don Zickus @ 2014-05-23 17:18 UTC (permalink / raw)
To: Jiri Olsa; +Cc: acme, peterz, LKML, namhyung, eranian, Andi Kleen
On Fri, May 23, 2014 at 06:54:06PM +0200, Jiri Olsa wrote:
> On Mon, May 19, 2014 at 03:13:52PM -0400, Don Zickus wrote:
> > 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>
> > ---
> > tools/perf/util/cpumap.c | 31 +++++++++++++++++++++++++++++++
> > tools/perf/util/cpumap.h | 12 ++++++++++++
> > tools/perf/util/sort.c | 3 +++
> > 3 files changed, 46 insertions(+)
> >
> > diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
> > index c4e55b7..d833238 100644
> > --- a/tools/perf/util/cpumap.c
> > +++ b/tools/perf/util/cpumap.c
> > @@ -477,3 +477,34 @@ 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, ret, size;
> > + FILE *fp;
> > +
> > +
> > + 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;
> > + }
> > +
> > + fp = fopen(path, "r");
> > + if (!fp)
> > + return -1;
> > + ret = fscanf(fp, "%d", &size);
> > + fclose(fp);
> > + if (ret != 1)
> > + return -1;
>
> you can use filename__read_int
Doh. I forgot about that. I can respin this patch or the whole series
for that. Perhaps on Tuesday when we come back from our US Holiday.
Cheers,
Don
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/7] perf: Add support to dynamically get cacheline size
2014-05-19 19:13 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
2014-05-23 16:54 ` Jiri Olsa
@ 2014-05-23 17:09 ` Jiri Olsa
2014-05-23 17:30 ` Don Zickus
1 sibling, 1 reply; 18+ messages in thread
From: Jiri Olsa @ 2014-05-23 17:09 UTC (permalink / raw)
To: Don Zickus; +Cc: acme, peterz, LKML, namhyung, eranian, Andi Kleen
On Mon, May 19, 2014 at 03:13:52PM -0400, Don Zickus wrote:
SNIP
> diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
> index 61a6548..b3e7b22 100644
> --- a/tools/perf/util/cpumap.h
> +++ b/tools/perf/util/cpumap.h
> @@ -81,4 +81,16 @@ static inline int cpu__get_node(int cpu)
> return cpunode_map[cpu];
> }
>
> +int cacheline_size;
hum, so cacheline_size does not need to be global, if you use
cpu__cacheline_size in your next patch, right?
> +
> +int cpu__setup_cacheline_size(void);
> +
> +static inline int cpu__cacheline_size(void)
> +{
> + if (unlikely(!cacheline_size))
> + pr_debug("cacheline size not initialized\n");
> +
> + return cacheline_size;
> +}
> +
> #endif /* __PERF_CPUMAP_H */
> diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> index 635cd8f..50adbfb 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";
> @@ -1117,6 +1118,8 @@ int setup_sorting(void)
> return -ENOMEM;
> }
>
> + cpu__setup_cacheline_size();
> +
I dont think this is the best place to call the setup,
on the other hand I can't think of any suitable ;-)
how about lazy initialization from cpu__cacheline_size?
We also have page_size variable which gets initialized
in main and is globaly accesable. I wonder we should
add the cacheline_size variable in the same way.
jirka
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 6/7] perf: Add support to dynamically get cacheline size
2014-05-23 17:09 ` Jiri Olsa
@ 2014-05-23 17:30 ` Don Zickus
0 siblings, 0 replies; 18+ messages in thread
From: Don Zickus @ 2014-05-23 17:30 UTC (permalink / raw)
To: Jiri Olsa; +Cc: acme, peterz, LKML, namhyung, eranian, Andi Kleen
On Fri, May 23, 2014 at 07:09:01PM +0200, Jiri Olsa wrote:
> On Mon, May 19, 2014 at 03:13:52PM -0400, Don Zickus wrote:
>
> SNIP
>
> > diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
> > index 61a6548..b3e7b22 100644
> > --- a/tools/perf/util/cpumap.h
> > +++ b/tools/perf/util/cpumap.h
> > @@ -81,4 +81,16 @@ static inline int cpu__get_node(int cpu)
> > return cpunode_map[cpu];
> > }
> >
> > +int cacheline_size;
>
> hum, so cacheline_size does not need to be global, if you use
> cpu__cacheline_size in your next patch, right?
I made cpu__cacheline_size an inline so I think it does. If I stick that
function in cpumap.c then yeah I would agree it would not need to be
global.
Being that is was going to be called repeatedly while processing each
event I opted to make it an inline. I guess I could change that if it
matters.
>
> > +
> > +int cpu__setup_cacheline_size(void);
> > +
> > +static inline int cpu__cacheline_size(void)
> > +{
> > + if (unlikely(!cacheline_size))
> > + pr_debug("cacheline size not initialized\n");
> > +
> > + return cacheline_size;
> > +}
> > +
> > #endif /* __PERF_CPUMAP_H */
> > diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> > index 635cd8f..50adbfb 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";
> > @@ -1117,6 +1118,8 @@ int setup_sorting(void)
> > return -ENOMEM;
> > }
> >
> > + cpu__setup_cacheline_size();
> > +
>
> I dont think this is the best place to call the setup,
> on the other hand I can't think of any suitable ;-)
>
> how about lazy initialization from cpu__cacheline_size?
>
> We also have page_size variable which gets initialized
> in main and is globaly accesable. I wonder we should
> add the cacheline_size variable in the same way.
That seems to make sense. I can stick the variable in util.c|h then?
Cheers,
Don
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 7/7] perf: Add dcacheline sort
2014-05-19 19:13 [PATCH 0/7 V3] x86, nmi: Various fixes and cleanups Don Zickus
` (5 preceding siblings ...)
2014-05-19 19:13 ` [PATCH 6/7] perf: Add support to dynamically get cacheline size Don Zickus
@ 2014-05-19 19:13 ` Don Zickus
2014-05-23 17:14 ` Jiri Olsa
6 siblings, 1 reply; 18+ messages in thread
From: Don Zickus @ 2014-05-19 19:13 UTC (permalink / raw)
To: jolsa; +Cc: acme, peterz, 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>
---
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 | 109 +++++++++++++++++++++++++++++++
tools/perf/util/sort.h | 1 +
6 files changed, 116 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 50adbfb..e1968bd 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,106 @@ 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)
+{
+ int size = cpu__cacheline_size();
+
+ /* return the cacheline of the address */
+ return (address & ~(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 +958,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 +1132,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] 18+ messages in thread* Re: [PATCH 7/7] perf: Add dcacheline sort
2014-05-19 19:13 ` [PATCH 7/7] perf: Add dcacheline sort Don Zickus
@ 2014-05-23 17:14 ` Jiri Olsa
0 siblings, 0 replies; 18+ messages in thread
From: Jiri Olsa @ 2014-05-23 17:14 UTC (permalink / raw)
To: Don Zickus; +Cc: acme, peterz, LKML, namhyung, eranian, Andi Kleen
On Mon, May 19, 2014 at 03:13:53PM -0400, Don Zickus wrote:
> 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.
I think thats the extra '+' sign ;-) so +1 seems ok
jirka
^ permalink raw reply [flat|nested] 18+ messages in thread