[tip:perf/core] perf unwind: Support for powerpc

2017-06-21 Thread tip-bot for Paolo Bonzini
Commit-ID:  a7f0fda085870312ab694b19a1304ece161a1217
Gitweb: http://git.kernel.org/tip/a7f0fda085870312ab694b19a1304ece161a1217
Author: Paolo Bonzini 
AuthorDate: Thu, 1 Jun 2017 12:24:41 +0200
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 21 Jun 2017 11:35:42 -0300

perf unwind: Support for powerpc

Porting PPC to libdw only needs an architecture-specific hook to move
the register state from perf to libdw.

The ARM and x86 architectures already use libdw, and it is useful to
have as much common code for the unwinder as possible.  Mark Wielaard
has contributed a frame-based unwinder to libdw, so that unwinding works
even for binaries that do not have CFI information.  In addition,
libunwind is always preferred to libdw by the build machinery so this
cannot introduce regressions on machines that have both libunwind and
libdw installed.

Signed-off-by: Paolo Bonzini 
Acked-by: Jiri Olsa 
Acked-by: Milian Wolff 
Acked-by: Ravi Bangoria 
Cc: Naveen N. Rao 
Cc: linuxppc-...@lists.ozlabs.org
Link: 
http://lkml.kernel.org/r/1496312681-20133-1-git-send-email-pbonz...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/Makefile.config  |  2 +-
 tools/perf/arch/powerpc/util/Build  |  2 +
 tools/perf/arch/powerpc/util/unwind-libdw.c | 73 +
 3 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 1f4fbc9..bdf0e87 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -61,7 +61,7 @@ endif
 # Disable it on all other architectures in case libdw unwind
 # support is detected in system. Add supported architectures
 # to the check.
-ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm))
+ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc))
   NO_LIBDW_DWARF_UNWIND := 1
 endif
 
diff --git a/tools/perf/arch/powerpc/util/Build 
b/tools/perf/arch/powerpc/util/Build
index 90ad64b..2e659531 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -5,4 +5,6 @@ libperf-y += perf_regs.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
+
 libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
+libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c 
b/tools/perf/arch/powerpc/util/unwind-libdw.c
new file mode 100644
index 000..3a24b3c
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
@@ -0,0 +1,73 @@
+#include 
+#include "../../util/unwind-libdw.h"
+#include "../../util/perf_regs.h"
+#include "../../util/event.h"
+
+/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils.  */
+static const int special_regs[3][2] = {
+   { 65, PERF_REG_POWERPC_LINK },
+   { 101, PERF_REG_POWERPC_XER },
+   { 109, PERF_REG_POWERPC_CTR },
+};
+
+bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
+{
+   struct unwind_info *ui = arg;
+   struct regs_dump *user_regs = >sample->user_regs;
+   Dwarf_Word dwarf_regs[32], dwarf_nip;
+   size_t i;
+
+#define REG(r) ({  \
+   Dwarf_Word val = 0; \
+   perf_reg_value(, user_regs, PERF_REG_POWERPC_##r);  \
+   val;\
+})
+
+   dwarf_regs[0]  = REG(R0);
+   dwarf_regs[1]  = REG(R1);
+   dwarf_regs[2]  = REG(R2);
+   dwarf_regs[3]  = REG(R3);
+   dwarf_regs[4]  = REG(R4);
+   dwarf_regs[5]  = REG(R5);
+   dwarf_regs[6]  = REG(R6);
+   dwarf_regs[7]  = REG(R7);
+   dwarf_regs[8]  = REG(R8);
+   dwarf_regs[9]  = REG(R9);
+   dwarf_regs[10] = REG(R10);
+   dwarf_regs[11] = REG(R11);
+   dwarf_regs[12] = REG(R12);
+   dwarf_regs[13] = REG(R13);
+   dwarf_regs[14] = REG(R14);
+   dwarf_regs[15] = REG(R15);
+   dwarf_regs[16] = REG(R16);
+   dwarf_regs[17] = REG(R17);
+   dwarf_regs[18] = REG(R18);
+   dwarf_regs[19] = REG(R19);
+   dwarf_regs[20] = REG(R20);
+   dwarf_regs[21] = REG(R21);
+   dwarf_regs[22] = REG(R22);
+   dwarf_regs[23] = REG(R23);
+   dwarf_regs[24] = REG(R24);
+   dwarf_regs[25] = REG(R25);
+   dwarf_regs[26] = REG(R26);
+   dwarf_regs[27] = REG(R27);
+   dwarf_regs[28] = REG(R28);
+   dwarf_regs[29] = REG(R29);
+   dwarf_regs[30] = REG(R30);
+   dwarf_regs[31] = REG(R31);
+   if (!dwfl_thread_state_registers(thread, 0, 32, dwarf_regs))
+   return false;
+
+   dwarf_nip = REG(NIP);
+   dwfl_thread_state_register_pc(thread, dwarf_nip);
+   for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
+   Dwarf_Word val = 0;
+   perf_reg_value(, 

[tip:perf/core] perf unwind: Support for powerpc

2017-06-21 Thread tip-bot for Paolo Bonzini
Commit-ID:  a7f0fda085870312ab694b19a1304ece161a1217
Gitweb: http://git.kernel.org/tip/a7f0fda085870312ab694b19a1304ece161a1217
Author: Paolo Bonzini 
AuthorDate: Thu, 1 Jun 2017 12:24:41 +0200
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 21 Jun 2017 11:35:42 -0300

perf unwind: Support for powerpc

Porting PPC to libdw only needs an architecture-specific hook to move
the register state from perf to libdw.

The ARM and x86 architectures already use libdw, and it is useful to
have as much common code for the unwinder as possible.  Mark Wielaard
has contributed a frame-based unwinder to libdw, so that unwinding works
even for binaries that do not have CFI information.  In addition,
libunwind is always preferred to libdw by the build machinery so this
cannot introduce regressions on machines that have both libunwind and
libdw installed.

Signed-off-by: Paolo Bonzini 
Acked-by: Jiri Olsa 
Acked-by: Milian Wolff 
Acked-by: Ravi Bangoria 
Cc: Naveen N. Rao 
Cc: linuxppc-...@lists.ozlabs.org
Link: 
http://lkml.kernel.org/r/1496312681-20133-1-git-send-email-pbonz...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/Makefile.config  |  2 +-
 tools/perf/arch/powerpc/util/Build  |  2 +
 tools/perf/arch/powerpc/util/unwind-libdw.c | 73 +
 3 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 1f4fbc9..bdf0e87 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -61,7 +61,7 @@ endif
 # Disable it on all other architectures in case libdw unwind
 # support is detected in system. Add supported architectures
 # to the check.
-ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm))
+ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc))
   NO_LIBDW_DWARF_UNWIND := 1
 endif
 
diff --git a/tools/perf/arch/powerpc/util/Build 
b/tools/perf/arch/powerpc/util/Build
index 90ad64b..2e659531 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -5,4 +5,6 @@ libperf-y += perf_regs.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
+
 libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
+libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c 
b/tools/perf/arch/powerpc/util/unwind-libdw.c
new file mode 100644
index 000..3a24b3c
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
@@ -0,0 +1,73 @@
+#include 
+#include "../../util/unwind-libdw.h"
+#include "../../util/perf_regs.h"
+#include "../../util/event.h"
+
+/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils.  */
+static const int special_regs[3][2] = {
+   { 65, PERF_REG_POWERPC_LINK },
+   { 101, PERF_REG_POWERPC_XER },
+   { 109, PERF_REG_POWERPC_CTR },
+};
+
+bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
+{
+   struct unwind_info *ui = arg;
+   struct regs_dump *user_regs = >sample->user_regs;
+   Dwarf_Word dwarf_regs[32], dwarf_nip;
+   size_t i;
+
+#define REG(r) ({  \
+   Dwarf_Word val = 0; \
+   perf_reg_value(, user_regs, PERF_REG_POWERPC_##r);  \
+   val;\
+})
+
+   dwarf_regs[0]  = REG(R0);
+   dwarf_regs[1]  = REG(R1);
+   dwarf_regs[2]  = REG(R2);
+   dwarf_regs[3]  = REG(R3);
+   dwarf_regs[4]  = REG(R4);
+   dwarf_regs[5]  = REG(R5);
+   dwarf_regs[6]  = REG(R6);
+   dwarf_regs[7]  = REG(R7);
+   dwarf_regs[8]  = REG(R8);
+   dwarf_regs[9]  = REG(R9);
+   dwarf_regs[10] = REG(R10);
+   dwarf_regs[11] = REG(R11);
+   dwarf_regs[12] = REG(R12);
+   dwarf_regs[13] = REG(R13);
+   dwarf_regs[14] = REG(R14);
+   dwarf_regs[15] = REG(R15);
+   dwarf_regs[16] = REG(R16);
+   dwarf_regs[17] = REG(R17);
+   dwarf_regs[18] = REG(R18);
+   dwarf_regs[19] = REG(R19);
+   dwarf_regs[20] = REG(R20);
+   dwarf_regs[21] = REG(R21);
+   dwarf_regs[22] = REG(R22);
+   dwarf_regs[23] = REG(R23);
+   dwarf_regs[24] = REG(R24);
+   dwarf_regs[25] = REG(R25);
+   dwarf_regs[26] = REG(R26);
+   dwarf_regs[27] = REG(R27);
+   dwarf_regs[28] = REG(R28);
+   dwarf_regs[29] = REG(R29);
+   dwarf_regs[30] = REG(R30);
+   dwarf_regs[31] = REG(R31);
+   if (!dwfl_thread_state_registers(thread, 0, 32, dwarf_regs))
+   return false;
+
+   dwarf_nip = REG(NIP);
+   dwfl_thread_state_register_pc(thread, dwarf_nip);
+   for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
+   Dwarf_Word val = 0;
+   perf_reg_value(, user_regs, special_regs[i][1]);
+   if (!dwfl_thread_state_registers(thread,
+special_regs[i][0], 1,
+