Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Support MIPS unwinding and dwarf-regs

Map perf APIs (perf_reg_name/get_arch_regstr/unwind__arch_reg_id) with
MIPS specific registers.

[ayan@wavecomp.com: repick this patch for unwinding userstack backtrace
by perf and libunwind on MIPS based CPU.]

[yangtiezhu@loongson.cn: Add sample_reg_masks[] to fix build error,
silence some checkpatch errors and warnings, and also separate the
original patches into two parts (MIPS kernel and perf tools) to merge
easily.]

The original patches:

https://lore.kernel.org/patchwork/patch/1126521/
https://lore.kernel.org/patchwork/patch/1126520/

Committer notes:

Do it as __perf_reg_name() to cope with:

067012974c8ae31a ("perf tools: Fix arm64 build error with gcc-11")

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Archer Yan <ayan@wavecomp.com>
Cc: David Daney <david.daney@cavium.com>
Cc: Jianlin Lv <Jianlin.Lv@arm.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Juxin Gao <gaojuxin@loongson.cn>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Xuefeng Li <lixuefeng@loongson.cn>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
Link: http://lore.kernel.org/lkml/1612409724-3516-3-git-send-email-yangtiezhu@loongson.cn
Signed-off-by: Archer Yan <ayan@wavecomp.com>
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Tiezhu Yang and committed by
Arnaldo Carvalho de Melo
b5f184fb 84b77255

+197
+6
tools/perf/Makefile.config
··· 87 87 CFLAGS += -fPIC -I$(OUTPUT)arch/s390/include/generated 88 88 endif 89 89 90 + ifeq ($(ARCH),mips) 91 + NO_PERF_REGS := 0 92 + CFLAGS += -I../../arch/mips/include/uapi -I../../arch/mips/include/generated/uapi 93 + LIBUNWIND_LIBS = -lunwind -lunwind-mips 94 + endif 95 + 90 96 ifeq ($(NO_PERF_REGS),0) 91 97 $(call detected,CONFIG_PERF_REGS) 92 98 endif
+4
tools/perf/arch/mips/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + ifndef NO_DWARF 3 + PERF_HAVE_DWARF_REGS := 1 4 + endif
+31
tools/perf/arch/mips/include/dwarf-regs-table.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * dwarf-regs-table.h : Mapping of DWARF debug register numbers into 4 + * register names. 5 + * 6 + * Copyright (C) 2013 Cavium, Inc. 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + */ 19 + 20 + #ifdef DEFINE_DWARF_REGSTR_TABLE 21 + #undef REG_DWARFNUM_NAME 22 + #define REG_DWARFNUM_NAME(reg, idx) [idx] = "$" #reg 23 + static const char * const mips_regstr_tbl[] = { 24 + "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", 25 + "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", 26 + "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "%29", 27 + "$30", "$31", 28 + REG_DWARFNUM_NAME(hi, 64), 29 + REG_DWARFNUM_NAME(lo, 65), 30 + }; 31 + #endif
+84
tools/perf/arch/mips/include/perf_regs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef ARCH_PERF_REGS_H 3 + #define ARCH_PERF_REGS_H 4 + 5 + #include <stdlib.h> 6 + #include <linux/types.h> 7 + #include <asm/perf_regs.h> 8 + 9 + #define PERF_REGS_MAX PERF_REG_MIPS_MAX 10 + #define PERF_REG_IP PERF_REG_MIPS_PC 11 + #define PERF_REG_SP PERF_REG_MIPS_R29 12 + 13 + #define PERF_REGS_MASK ((1ULL << PERF_REG_MIPS_MAX) - 1) 14 + 15 + static inline const char *__perf_reg_name(int id) 16 + { 17 + switch (id) { 18 + case PERF_REG_MIPS_PC: 19 + return "PC"; 20 + case PERF_REG_MIPS_R1: 21 + return "$1"; 22 + case PERF_REG_MIPS_R2: 23 + return "$2"; 24 + case PERF_REG_MIPS_R3: 25 + return "$3"; 26 + case PERF_REG_MIPS_R4: 27 + return "$4"; 28 + case PERF_REG_MIPS_R5: 29 + return "$5"; 30 + case PERF_REG_MIPS_R6: 31 + return "$6"; 32 + case PERF_REG_MIPS_R7: 33 + return "$7"; 34 + case PERF_REG_MIPS_R8: 35 + return "$8"; 36 + case PERF_REG_MIPS_R9: 37 + return "$9"; 38 + case PERF_REG_MIPS_R10: 39 + return "$10"; 40 + case PERF_REG_MIPS_R11: 41 + return "$11"; 42 + case PERF_REG_MIPS_R12: 43 + return "$12"; 44 + case PERF_REG_MIPS_R13: 45 + return "$13"; 46 + case PERF_REG_MIPS_R14: 47 + return "$14"; 48 + case PERF_REG_MIPS_R15: 49 + return "$15"; 50 + case PERF_REG_MIPS_R16: 51 + return "$16"; 52 + case PERF_REG_MIPS_R17: 53 + return "$17"; 54 + case PERF_REG_MIPS_R18: 55 + return "$18"; 56 + case PERF_REG_MIPS_R19: 57 + return "$19"; 58 + case PERF_REG_MIPS_R20: 59 + return "$20"; 60 + case PERF_REG_MIPS_R21: 61 + return "$21"; 62 + case PERF_REG_MIPS_R22: 63 + return "$22"; 64 + case PERF_REG_MIPS_R23: 65 + return "$23"; 66 + case PERF_REG_MIPS_R24: 67 + return "$24"; 68 + case PERF_REG_MIPS_R25: 69 + return "$25"; 70 + case PERF_REG_MIPS_R28: 71 + return "$28"; 72 + case PERF_REG_MIPS_R29: 73 + return "$29"; 74 + case PERF_REG_MIPS_R30: 75 + return "$30"; 76 + case PERF_REG_MIPS_R31: 77 + return "$31"; 78 + default: 79 + break; 80 + } 81 + return NULL; 82 + } 83 + 84 + #endif /* ARCH_PERF_REGS_H */
+3
tools/perf/arch/mips/util/Build
··· 1 + perf-y += perf_regs.o 2 + perf-$(CONFIG_DWARF) += dwarf-regs.o 3 + perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
+38
tools/perf/arch/mips/util/dwarf-regs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. 4 + * 5 + * Copyright (C) 2013 Cavium, Inc. 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + */ 18 + 19 + #include <stdio.h> 20 + #include <dwarf-regs.h> 21 + 22 + static const char *mips_gpr_names[32] = { 23 + "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", 24 + "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", 25 + "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", 26 + "$30", "$31" 27 + }; 28 + 29 + const char *get_arch_regstr(unsigned int n) 30 + { 31 + if (n < 32) 32 + return mips_gpr_names[n]; 33 + if (n == 64) 34 + return "hi"; 35 + if (n == 65) 36 + return "lo"; 37 + return NULL; 38 + }
+6
tools/perf/arch/mips/util/perf_regs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include "../../util/perf_regs.h" 3 + 4 + const struct sample_reg sample_reg_masks[] = { 5 + SMPL_REG_END 6 + };
+22
tools/perf/arch/mips/util/unwind-libunwind.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <errno.h> 4 + #include <libunwind.h> 5 + #include "perf_regs.h" 6 + #include "../../util/unwind.h" 7 + #include "util/debug.h" 8 + 9 + int libunwind__arch_reg_id(int regnum) 10 + { 11 + switch (regnum) { 12 + case UNW_MIPS_R1 ... UNW_MIPS_R25: 13 + return regnum - UNW_MIPS_R1 + PERF_REG_MIPS_R1; 14 + case UNW_MIPS_R28 ... UNW_MIPS_R31: 15 + return regnum - UNW_MIPS_R28 + PERF_REG_MIPS_R28; 16 + case UNW_MIPS_PC: 17 + return PERF_REG_MIPS_PC; 18 + default: 19 + pr_err("unwind: invalid reg id %d\n", regnum); 20 + return -EINVAL; 21 + } 22 + }
+3
tools/perf/util/dwarf-regs.c
··· 24 24 #include "../arch/s390/include/dwarf-regs-table.h" 25 25 #include "../arch/sparc/include/dwarf-regs-table.h" 26 26 #include "../arch/xtensa/include/dwarf-regs-table.h" 27 + #include "../arch/mips/include/dwarf-regs-table.h" 27 28 28 29 #define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL) 29 30 ··· 54 53 return __get_dwarf_regstr(sparc_regstr_tbl, n); 55 54 case EM_XTENSA: 56 55 return __get_dwarf_regstr(xtensa_regstr_tbl, n); 56 + case EM_MIPS: 57 + return __get_dwarf_regstr(mips_regstr_tbl, n); 57 58 default: 58 59 pr_err("ELF MACHINE %x is not supported.\n", machine); 59 60 }