[ayan@xxxxxxxxxxxx: Update this patch for the latest kernel] [ralf@xxxxxxxxxxxxxx: Add perf_get_regs_user() which is required after 'commit 88a7c26af8da ("perf: Move task_pt_regs sampling into arch code")' Signed-off-by: David Daney <david.daney@xxxxxxxxxx> Cc: linux-mips@xxxxxxxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx> Cc: Paul Mackerras <paulus@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxxxxxxxxxx> Signed-off-by: Ralf Baechle <ralf@xxxxxxxxxxxxxx> Signed-off-by: Archer Yan <ayan@xxxxxxxxxxxx> --- arch/mips/Kconfig | 2 + arch/mips/include/uapi/asm/perf_regs.h | 42 ++++++++++++ arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/perf_regs.c | 67 +++++++++++++++++++ tools/perf/Makefile.config | 6 ++ tools/perf/arch/mips/Build | 2 +- tools/perf/arch/mips/Makefile | 4 -- .../perf/arch/mips/include/dwarf-regs-table.h | 30 +++++++++ tools/perf/arch/mips/include/perf_regs.h | 2 +- tools/perf/arch/mips/util/Build | 4 +- tools/perf/arch/mips/util/dwarf-regs.c | 3 +- tools/perf/arch/mips/util/unwind-libunwind.c | 3 +- tools/perf/util/dwarf-regs.c | 3 + 13 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 arch/mips/include/uapi/asm/perf_regs.h create mode 100644 arch/mips/kernel/perf_regs.c create mode 100644 tools/perf/arch/mips/include/dwarf-regs-table.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4a5f5b0ee9a9..5e5b1719d9bf 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -69,6 +69,8 @@ config MIPS select HAVE_NMI select HAVE_OPROFILE select HAVE_PERF_EVENTS + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RSEQ select HAVE_STACKPROTECTOR diff --git a/arch/mips/include/uapi/asm/perf_regs.h b/arch/mips/include/uapi/asm/perf_regs.h new file mode 100644 index 000000000000..57382b0f1f52 --- /dev/null +++ b/arch/mips/include/uapi/asm/perf_regs.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_MIPS_PERF_REGS_H +#define _ASM_MIPS_PERF_REGS_H + +enum perf_event_mips_regs { + PERF_REG_MIPS_PC, + PERF_REG_MIPS_R1, + PERF_REG_MIPS_R2, + PERF_REG_MIPS_R3, + PERF_REG_MIPS_R4, + PERF_REG_MIPS_R5, + PERF_REG_MIPS_R6, + PERF_REG_MIPS_R7, + PERF_REG_MIPS_R8, + PERF_REG_MIPS_R9, + PERF_REG_MIPS_R10, + PERF_REG_MIPS_R11, + PERF_REG_MIPS_R12, + PERF_REG_MIPS_R13, + PERF_REG_MIPS_R14, + PERF_REG_MIPS_R15, + PERF_REG_MIPS_R16, + PERF_REG_MIPS_R17, + PERF_REG_MIPS_R18, + PERF_REG_MIPS_R19, + PERF_REG_MIPS_R20, + PERF_REG_MIPS_R21, + PERF_REG_MIPS_R22, + PERF_REG_MIPS_R23, + PERF_REG_MIPS_R24, + PERF_REG_MIPS_R25, + /* + * 26 and 27 are k0 and k1, they are always clobbered thus not + * stored. + */ + PERF_REG_MIPS_R28, + PERF_REG_MIPS_R29, + PERF_REG_MIPS_R30, + PERF_REG_MIPS_R31, + PERF_REG_MIPS_MAX = PERF_REG_MIPS_R31 + 1, +}; +#endif /* _ASM_MIPS_PERF_REGS_H */ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 89b07ea8d249..d8fb04540505 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -100,7 +100,7 @@ CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/n obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o -obj-$(CONFIG_PERF_EVENTS) += perf_event.o +obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o diff --git a/arch/mips/kernel/perf_regs.c b/arch/mips/kernel/perf_regs.c new file mode 100644 index 000000000000..2785c8407b3c --- /dev/null +++ b/arch/mips/kernel/perf_regs.c @@ -0,0 +1,67 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Some parts derived from x86 version of this file. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include <linux/perf_event.h> + +#include <asm/ptrace.h> + +#ifdef CONFIG_32BIT +u64 perf_reg_abi(struct task_struct *tsk) +{ + return PERF_SAMPLE_REGS_ABI_32; +} +#else /* Must be CONFIG_64BIT */ +u64 perf_reg_abi(struct task_struct *tsk) +{ + if (test_tsk_thread_flag(tsk, TIF_32BIT_REGS)) + return PERF_SAMPLE_REGS_ABI_32; + else + return PERF_SAMPLE_REGS_ABI_64; +} +#endif /* CONFIG_32BIT */ + +int perf_reg_validate(u64 mask) +{ + if (!mask) + return -EINVAL; + if (mask & ~((1ull << PERF_REG_MIPS_MAX) - 1)) + return -EINVAL; + return 0; +} + +u64 perf_reg_value(struct pt_regs *regs, int idx) +{ + long v; + + switch (idx) { + case PERF_REG_MIPS_PC: + v = regs->cp0_epc; + break; + case PERF_REG_MIPS_R1 ... PERF_REG_MIPS_R25: + v = regs->regs[idx - PERF_REG_MIPS_R1 + 1]; + break; + case PERF_REG_MIPS_R28 ... PERF_REG_MIPS_R31: + v = regs->regs[idx - PERF_REG_MIPS_R28 + 28]; + break; + + default: + WARN_ON_ONCE(1); + return 0; + } + + return (s64)v; /* Sign extend if 32-bit. */ +} + +void perf_get_regs_user(struct perf_regs *regs_user, + struct pt_regs *regs, struct pt_regs *regs_user_copy) +{ + regs_user->regs = task_pt_regs(current); + regs_user->abi = perf_reg_abi(current); +} diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index fe3f97e342fa..5ccb8b6fce7b 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -69,6 +69,12 @@ ifeq ($(NO_PERF_REGS),0) $(call detected,CONFIG_PERF_REGS) endif +ifeq ($(ARCH),mips) + NO_PERF_REGS := 0 + CFLAGS += -I../../arch/mips/include/uapi -I../../arch/mips/include/generated/uapi + LIBUNWIND_LIBS = -lunwind -lunwind-mips +endif + ifneq ($(NO_SYSCALL_TABLE),1) CFLAGS += -DHAVE_SYSCALL_TABLE_SUPPORT endif diff --git a/tools/perf/arch/mips/Build b/tools/perf/arch/mips/Build index 54afe4a467e7..e4e5f33c84d8 100644 --- a/tools/perf/arch/mips/Build +++ b/tools/perf/arch/mips/Build @@ -1 +1 @@ -libperf-y += util/ +perf-y += util/ diff --git a/tools/perf/arch/mips/Makefile b/tools/perf/arch/mips/Makefile index fe9b61e322a5..7fbca175099e 100644 --- a/tools/perf/arch/mips/Makefile +++ b/tools/perf/arch/mips/Makefile @@ -1,7 +1,3 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 -LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o -endif -ifndef NO_LIBUNWIND -LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o endif diff --git a/tools/perf/arch/mips/include/dwarf-regs-table.h b/tools/perf/arch/mips/include/dwarf-regs-table.h new file mode 100644 index 000000000000..ccd8ec66fb0c --- /dev/null +++ b/tools/perf/arch/mips/include/dwarf-regs-table.h @@ -0,0 +1,30 @@ +/* + * dwarf-regs-table.h : Mapping of DWARF debug register numbers into register names. + * + * Copyright (C) 2013 Cavium, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifdef DEFINE_DWARF_REGSTR_TABLE +#undef REG_DWARFNUM_NAME +#define REG_DWARFNUM_NAME(reg, idx) [idx] = "$" #reg +static const char *mips_regstr_tbl[] = { + "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", + "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", + "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", + "$30", "$31", + REG_DWARFNUM_NAME(hi, 64), + REG_DWARFNUM_NAME(lo, 65), + +}; +#endif diff --git a/tools/perf/arch/mips/include/perf_regs.h b/tools/perf/arch/mips/include/perf_regs.h index bc47b25d95dd..871bc6febe22 100644 --- a/tools/perf/arch/mips/include/perf_regs.h +++ b/tools/perf/arch/mips/include/perf_regs.h @@ -3,9 +3,9 @@ #define ARCH_PERF_REGS_H #include <stdlib.h> -#include "../../util/types.h" #include <asm/perf_regs.h> +#define PERF_REGS_MAX PERF_REG_MIPS_MAX #define PERF_REG_IP PERF_REG_MIPS_PC #define PERF_REG_SP PERF_REG_MIPS_R29 diff --git a/tools/perf/arch/mips/util/Build b/tools/perf/arch/mips/util/Build index 7da83b5ebc4c..678a68830ceb 100644 --- a/tools/perf/arch/mips/util/Build +++ b/tools/perf/arch/mips/util/Build @@ -1,2 +1,2 @@ -libperf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o +perf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o diff --git a/tools/perf/arch/mips/util/dwarf-regs.c b/tools/perf/arch/mips/util/dwarf-regs.c index 165e0179ea11..423abf158c99 100644 --- a/tools/perf/arch/mips/util/dwarf-regs.c +++ b/tools/perf/arch/mips/util/dwarf-regs.c @@ -14,8 +14,7 @@ * GNU General Public License for more details. * */ - -#include <libio.h> +#include <stdio.h> #include <dwarf-regs.h> static const char *mips_gpr_names[32] = { diff --git a/tools/perf/arch/mips/util/unwind-libunwind.c b/tools/perf/arch/mips/util/unwind-libunwind.c index 7af25427943f..0d8c99c29da6 100644 --- a/tools/perf/arch/mips/util/unwind-libunwind.c +++ b/tools/perf/arch/mips/util/unwind-libunwind.c @@ -4,8 +4,9 @@ #include <libunwind.h> #include "perf_regs.h" #include "../../util/unwind.h" +#include "util/debug.h" -int unwind__arch_reg_id(int regnum) +int libunwind__arch_reg_id(int regnum) { switch (regnum) { case UNW_MIPS_R1 ... UNW_MIPS_R25: diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c index db55eddce8cd..0bf60e6d28b5 100644 --- a/tools/perf/util/dwarf-regs.c +++ b/tools/perf/util/dwarf-regs.c @@ -25,6 +25,7 @@ #include "../arch/s390/include/dwarf-regs-table.h" #include "../arch/sparc/include/dwarf-regs-table.h" #include "../arch/xtensa/include/dwarf-regs-table.h" +#include "../arch/mips/include/dwarf-regs-table.h" #define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL) @@ -54,6 +55,8 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine) return __get_dwarf_regstr(sparc_regstr_tbl, n); case EM_XTENSA: return __get_dwarf_regstr(xtensa_regstr_tbl, n); + case EM_MIPS: + return __get_dwarf_regstr(mips_regstr_tbl, n); default: pr_err("ELF MACHINE %x is not supported.\n", machine); } -- 2.17.1