aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2016-01-19 05:23:38 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-11-16 09:06:12 -0500
commitf704ef44602fbf403e6722c7ed13f62d17e8cb20 (patch)
tree5addd8e06c1323a71b3e9caffa2d610d63a789ff /tools
parentc33eff600584ed493adfb42e3f130a6335f97750 (diff)
s390/perf: add support for perf_regs and libdw
With support for perf_regs and libdw, you can record and report call graphs for user space programs. Simply invoke perf with the --call-graph=dwarf command line option. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> [brueckner: added dwfl_thread_state_register_pc() call] Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Reviewed-and-tested-by: Thomas Richter <tmricht@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile.config6
-rw-r--r--tools/perf/arch/s390/include/perf_regs.h63
-rw-r--r--tools/perf/arch/s390/util/Build1
-rw-r--r--tools/perf/arch/s390/util/dwarf-regs.c4
-rw-r--r--tools/perf/arch/s390/util/unwind-libdw.c40
5 files changed, 113 insertions, 1 deletions
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 63f534a0902f..ed65e82f034e 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -53,6 +53,10 @@ ifeq ($(SRCARCH),arm64)
53 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 53 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
54endif 54endif
55 55
56ifeq ($(ARCH),s390)
57 NO_PERF_REGS := 0
58endif
59
56ifeq ($(NO_PERF_REGS),0) 60ifeq ($(NO_PERF_REGS),0)
57 $(call detected,CONFIG_PERF_REGS) 61 $(call detected,CONFIG_PERF_REGS)
58endif 62endif
@@ -61,7 +65,7 @@ endif
61# Disable it on all other architectures in case libdw unwind 65# Disable it on all other architectures in case libdw unwind
62# support is detected in system. Add supported architectures 66# support is detected in system. Add supported architectures
63# to the check. 67# to the check.
64ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc)) 68ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc s390))
65 NO_LIBDW_DWARF_UNWIND := 1 69 NO_LIBDW_DWARF_UNWIND := 1
66endif 70endif
67 71
diff --git a/tools/perf/arch/s390/include/perf_regs.h b/tools/perf/arch/s390/include/perf_regs.h
new file mode 100644
index 000000000000..ac4b8c8c49e2
--- /dev/null
+++ b/tools/perf/arch/s390/include/perf_regs.h
@@ -0,0 +1,63 @@
1#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H
3
4#include <stdlib.h>
5#include <linux/types.h>
6#include <../../../../arch/s390/include/uapi/asm/perf_regs.h>
7
8void perf_regs_load(u64 *regs);
9
10#define PERF_REGS_MASK ((1ULL << PERF_REG_S390_MAX) - 1)
11#define PERF_REGS_MAX PERF_REG_S390_MAX
12#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
13
14#define PERF_REG_IP PERF_REG_S390_PC
15#define PERF_REG_SP PERF_REG_S390_R15
16
17static inline const char *perf_reg_name(int id)
18{
19 switch (id) {
20 case PERF_REG_S390_R0:
21 return "R0";
22 case PERF_REG_S390_R1:
23 return "R1";
24 case PERF_REG_S390_R2:
25 return "R2";
26 case PERF_REG_S390_R3:
27 return "R3";
28 case PERF_REG_S390_R4:
29 return "R4";
30 case PERF_REG_S390_R5:
31 return "R5";
32 case PERF_REG_S390_R6:
33 return "R6";
34 case PERF_REG_S390_R7:
35 return "R7";
36 case PERF_REG_S390_R8:
37 return "R8";
38 case PERF_REG_S390_R9:
39 return "R9";
40 case PERF_REG_S390_R10:
41 return "R10";
42 case PERF_REG_S390_R11:
43 return "R11";
44 case PERF_REG_S390_R12:
45 return "R12";
46 case PERF_REG_S390_R13:
47 return "R13";
48 case PERF_REG_S390_R14:
49 return "R14";
50 case PERF_REG_S390_R15:
51 return "R15";
52 case PERF_REG_S390_MASK:
53 return "MASK";
54 case PERF_REG_S390_PC:
55 return "PC";
56 default:
57 return NULL;
58 }
59
60 return NULL;
61}
62
63#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
index 397084382b23..4a233683c684 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -2,6 +2,7 @@ libperf-y += header.o
2libperf-y += kvm-stat.o 2libperf-y += kvm-stat.o
3 3
4libperf-$(CONFIG_DWARF) += dwarf-regs.o 4libperf-$(CONFIG_DWARF) += dwarf-regs.o
5libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
5 6
6libperf-y += machine.o 7libperf-y += machine.o
7 8
diff --git a/tools/perf/arch/s390/util/dwarf-regs.c b/tools/perf/arch/s390/util/dwarf-regs.c
index 0dff5b2ed1e5..0cd7cba5d6ee 100644
--- a/tools/perf/arch/s390/util/dwarf-regs.c
+++ b/tools/perf/arch/s390/util/dwarf-regs.c
@@ -19,5 +19,9 @@ static const char *gpr_names[NUM_GPRS] = {
19 19
20const char *get_arch_regstr(unsigned int n) 20const char *get_arch_regstr(unsigned int n)
21{ 21{
22 if (n == 64)
23 return "mask";
24 if (n == 65)
25 return "pc";
22 return (n >= NUM_GPRS) ? NULL : gpr_names[n]; 26 return (n >= NUM_GPRS) ? NULL : gpr_names[n];
23} 27}
diff --git a/tools/perf/arch/s390/util/unwind-libdw.c b/tools/perf/arch/s390/util/unwind-libdw.c
new file mode 100644
index 000000000000..281bbb82402a
--- /dev/null
+++ b/tools/perf/arch/s390/util/unwind-libdw.c
@@ -0,0 +1,40 @@
1#include <elfutils/libdwfl.h>
2#include "../../util/unwind-libdw.h"
3#include "../../util/perf_regs.h"
4#include "../../util/event.h"
5
6
7bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
8{
9 struct unwind_info *ui = arg;
10 struct regs_dump *user_regs = &ui->sample->user_regs;
11 Dwarf_Word dwarf_regs[PERF_REG_S390_MAX];
12
13#define REG(r) ({ \
14 Dwarf_Word val = 0; \
15 perf_reg_value(&val, user_regs, PERF_REG_S390_##r); \
16 val; \
17})
18
19 dwarf_regs[0] = REG(R0);
20 dwarf_regs[1] = REG(R1);
21 dwarf_regs[2] = REG(R2);
22 dwarf_regs[3] = REG(R3);
23 dwarf_regs[4] = REG(R4);
24 dwarf_regs[5] = REG(R5);
25 dwarf_regs[6] = REG(R6);
26 dwarf_regs[7] = REG(R7);
27 dwarf_regs[8] = REG(R8);
28 dwarf_regs[9] = REG(R9);
29 dwarf_regs[10] = REG(R10);
30 dwarf_regs[11] = REG(R11);
31 dwarf_regs[12] = REG(R12);
32 dwarf_regs[13] = REG(R13);
33 dwarf_regs[14] = REG(R14);
34 dwarf_regs[15] = REG(R15);
35 dwarf_regs[16] = REG(MASK);
36 dwarf_regs[17] = REG(PC);
37
38 dwfl_thread_state_register_pc(thread, dwarf_regs[17]);
39 return dwfl_thread_state_registers(thread, 0, 16, dwarf_regs);
40}