[PATCH] perf: libdw support for powerpc
Naveen N. Rao
naveen.n.rao at linux.vnet.ibm.com
Fri May 19 04:19:45 AEST 2017
Paolo Bonzini wrote:
> The ARM and x86 architectures already use libdw, and it is useful to
> have as much common code for the unwinder as possible. Porting PPC
> to libdw only needs an architecture-specific hook to move the register
> state from perf to libdw.
Thanks. Ravi has had a similar patch locally, but from what I
understand, there are issues with libdw based unwinding on powerpc64. I
gave this a quick test and I don't see the user-space call trace being
unwinded properly with libdw.
With the same perf.data, with libunwind:
bswap 19286 134866.199717: 321955 cycles:
c0000000000b5e60 [unknown] ([unknown])
b31bc pSeries_lpar_hpte_invalidate (/boot/vmlinux)
76f10 flush_hash_page (/boot/vmlinux)
7ddec hpte_need_flush (/boot/vmlinux)
2d9f64 ptep_clear_flush (/boot/vmlinux)
2c24dc wp_page_copy (/boot/vmlinux)
2c5c44 do_wp_page (/boot/vmlinux)
2cabcc __handle_mm_fault (/boot/vmlinux)
2cbbe8 handle_mm_fault (/boot/vmlinux)
71074 do_page_fault (/boot/vmlinux)
1b078 handle_page_fault (/boot/vmlinux)
9958 _dl_map_object_from_fd (/lib/powerpc64le-linux-gnu/ld-2.24.so)
e70c _dl_map_object (/lib/powerpc64le-linux-gnu/ld-2.24.so)
18da4 openaux (/lib/powerpc64le-linux-gnu/ld-2.24.so)
1c068 _dl_catch_error (/lib/powerpc64le-linux-gnu/ld-2.24.so)
19430 _dl_map_object_deps (/lib/powerpc64le-linux-gnu/ld-2.24.so)
41dc dl_main (/lib/powerpc64le-linux-gnu/ld-2.24.so)
29954 _dl_sysdep_start (/lib/powerpc64le-linux-gnu/ld-2.24.so)
1be0 _dl_start_final (/lib/powerpc64le-linux-gnu/ld-2.24.so)
6080 _dl_start (/lib/powerpc64le-linux-gnu/ld-2.24.so)
1398 _start (/lib/powerpc64le-linux-gnu/ld-2.24.so)
... and with libdw:
bswap 19286 134866.199717: 321955 cycles:
c0000000000b5e60 [unknown] ([unknown])
b31bc pSeries_lpar_hpte_invalidate (/boot/vmlinux)
76f10 flush_hash_page (/boot/vmlinux)
7ddec hpte_need_flush (/boot/vmlinux)
2d9f64 ptep_clear_flush (/boot/vmlinux)
2c24dc wp_page_copy (/boot/vmlinux)
2c5c44 do_wp_page (/boot/vmlinux)
2cabcc __handle_mm_fault (/boot/vmlinux)
2cbbe8 handle_mm_fault (/boot/vmlinux)
71074 do_page_fault (/boot/vmlinux)
1b078 handle_page_fault (/boot/vmlinux)
Ravi is OOO currently can will have more to say on this once he is back
next week.
>
> Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
> ---
> 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(-)
> create mode 100644 tools/perf/arch/powerpc/util/unwind-libdw.c
>
> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
> index f67ae83..342c57c 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 ($(ARCH),$(filter $(ARCH),x86 arm))
> +ifneq ($(ARCH),$(filter $(ARCH),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..2e65953 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 0000000..c61e1d8
> --- /dev/null
> +++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
> @@ -0,0 +1,73 @@
> +#include <elfutils/libdwfl.h>
> +#include "../../util/util.h"
> +#include "../../util/unwind-libdw.h"
> +#include "../../util/perf_regs.h"
As an aside, we also need to include "event.h", without which there are
a few compile errors.
- Naveen
> +
> +/* 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 = &ui->sample->user_regs;
> + Dwarf_Word dwarf_regs[32], dwarf_nip;
> + size_t i;
> +
> +#define REG(r) ({ \
> + Dwarf_Word val = 0; \
> + perf_reg_value(&val, 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(&val, user_regs, special_regs[i][1]);
> + if (!dwfl_thread_state_registers(thread,
> + special_regs[i][0], 1,
> + &val))
> + return false;
> + }
> +
> + return true;
> +}
> --
> 1.8.3.1
>
>
>
More information about the Linuxppc-dev
mailing list