mirror of https://gitee.com/openkylin/linux.git
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:
067012974c
("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>
This commit is contained in:
parent
84b7725536
commit
b5f184fbdb
|
@ -87,6 +87,12 @@ ifeq ($(ARCH),s390)
|
||||||
CFLAGS += -fPIC -I$(OUTPUT)arch/s390/include/generated
|
CFLAGS += -fPIC -I$(OUTPUT)arch/s390/include/generated
|
||||||
endif
|
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
|
||||||
|
|
||||||
ifeq ($(NO_PERF_REGS),0)
|
ifeq ($(NO_PERF_REGS),0)
|
||||||
$(call detected,CONFIG_PERF_REGS)
|
$(call detected,CONFIG_PERF_REGS)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
ifndef NO_DWARF
|
||||||
|
PERF_HAVE_DWARF_REGS := 1
|
||||||
|
endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* 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 * const 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
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef ARCH_PERF_REGS_H
|
||||||
|
#define ARCH_PERF_REGS_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/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
|
||||||
|
|
||||||
|
#define PERF_REGS_MASK ((1ULL << PERF_REG_MIPS_MAX) - 1)
|
||||||
|
|
||||||
|
static inline const char *__perf_reg_name(int id)
|
||||||
|
{
|
||||||
|
switch (id) {
|
||||||
|
case PERF_REG_MIPS_PC:
|
||||||
|
return "PC";
|
||||||
|
case PERF_REG_MIPS_R1:
|
||||||
|
return "$1";
|
||||||
|
case PERF_REG_MIPS_R2:
|
||||||
|
return "$2";
|
||||||
|
case PERF_REG_MIPS_R3:
|
||||||
|
return "$3";
|
||||||
|
case PERF_REG_MIPS_R4:
|
||||||
|
return "$4";
|
||||||
|
case PERF_REG_MIPS_R5:
|
||||||
|
return "$5";
|
||||||
|
case PERF_REG_MIPS_R6:
|
||||||
|
return "$6";
|
||||||
|
case PERF_REG_MIPS_R7:
|
||||||
|
return "$7";
|
||||||
|
case PERF_REG_MIPS_R8:
|
||||||
|
return "$8";
|
||||||
|
case PERF_REG_MIPS_R9:
|
||||||
|
return "$9";
|
||||||
|
case PERF_REG_MIPS_R10:
|
||||||
|
return "$10";
|
||||||
|
case PERF_REG_MIPS_R11:
|
||||||
|
return "$11";
|
||||||
|
case PERF_REG_MIPS_R12:
|
||||||
|
return "$12";
|
||||||
|
case PERF_REG_MIPS_R13:
|
||||||
|
return "$13";
|
||||||
|
case PERF_REG_MIPS_R14:
|
||||||
|
return "$14";
|
||||||
|
case PERF_REG_MIPS_R15:
|
||||||
|
return "$15";
|
||||||
|
case PERF_REG_MIPS_R16:
|
||||||
|
return "$16";
|
||||||
|
case PERF_REG_MIPS_R17:
|
||||||
|
return "$17";
|
||||||
|
case PERF_REG_MIPS_R18:
|
||||||
|
return "$18";
|
||||||
|
case PERF_REG_MIPS_R19:
|
||||||
|
return "$19";
|
||||||
|
case PERF_REG_MIPS_R20:
|
||||||
|
return "$20";
|
||||||
|
case PERF_REG_MIPS_R21:
|
||||||
|
return "$21";
|
||||||
|
case PERF_REG_MIPS_R22:
|
||||||
|
return "$22";
|
||||||
|
case PERF_REG_MIPS_R23:
|
||||||
|
return "$23";
|
||||||
|
case PERF_REG_MIPS_R24:
|
||||||
|
return "$24";
|
||||||
|
case PERF_REG_MIPS_R25:
|
||||||
|
return "$25";
|
||||||
|
case PERF_REG_MIPS_R28:
|
||||||
|
return "$28";
|
||||||
|
case PERF_REG_MIPS_R29:
|
||||||
|
return "$29";
|
||||||
|
case PERF_REG_MIPS_R30:
|
||||||
|
return "$30";
|
||||||
|
case PERF_REG_MIPS_R31:
|
||||||
|
return "$31";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ARCH_PERF_REGS_H */
|
|
@ -0,0 +1,3 @@
|
||||||
|
perf-y += perf_regs.o
|
||||||
|
perf-$(CONFIG_DWARF) += dwarf-regs.o
|
||||||
|
perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
|
|
@ -0,0 +1,38 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* dwarf-regs.c : 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dwarf-regs.h>
|
||||||
|
|
||||||
|
static const char *mips_gpr_names[32] = {
|
||||||
|
"$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"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *get_arch_regstr(unsigned int n)
|
||||||
|
{
|
||||||
|
if (n < 32)
|
||||||
|
return mips_gpr_names[n];
|
||||||
|
if (n == 64)
|
||||||
|
return "hi";
|
||||||
|
if (n == 65)
|
||||||
|
return "lo";
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
#include "../../util/perf_regs.h"
|
||||||
|
|
||||||
|
const struct sample_reg sample_reg_masks[] = {
|
||||||
|
SMPL_REG_END
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libunwind.h>
|
||||||
|
#include "perf_regs.h"
|
||||||
|
#include "../../util/unwind.h"
|
||||||
|
#include "util/debug.h"
|
||||||
|
|
||||||
|
int libunwind__arch_reg_id(int regnum)
|
||||||
|
{
|
||||||
|
switch (regnum) {
|
||||||
|
case UNW_MIPS_R1 ... UNW_MIPS_R25:
|
||||||
|
return regnum - UNW_MIPS_R1 + PERF_REG_MIPS_R1;
|
||||||
|
case UNW_MIPS_R28 ... UNW_MIPS_R31:
|
||||||
|
return regnum - UNW_MIPS_R28 + PERF_REG_MIPS_R28;
|
||||||
|
case UNW_MIPS_PC:
|
||||||
|
return PERF_REG_MIPS_PC;
|
||||||
|
default:
|
||||||
|
pr_err("unwind: invalid reg id %d\n", regnum);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@
|
||||||
#include "../arch/s390/include/dwarf-regs-table.h"
|
#include "../arch/s390/include/dwarf-regs-table.h"
|
||||||
#include "../arch/sparc/include/dwarf-regs-table.h"
|
#include "../arch/sparc/include/dwarf-regs-table.h"
|
||||||
#include "../arch/xtensa/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)
|
#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
|
||||||
|
|
||||||
|
@ -53,6 +54,8 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
|
||||||
return __get_dwarf_regstr(sparc_regstr_tbl, n);
|
return __get_dwarf_regstr(sparc_regstr_tbl, n);
|
||||||
case EM_XTENSA:
|
case EM_XTENSA:
|
||||||
return __get_dwarf_regstr(xtensa_regstr_tbl, n);
|
return __get_dwarf_regstr(xtensa_regstr_tbl, n);
|
||||||
|
case EM_MIPS:
|
||||||
|
return __get_dwarf_regstr(mips_regstr_tbl, n);
|
||||||
default:
|
default:
|
||||||
pr_err("ELF MACHINE %x is not supported.\n", machine);
|
pr_err("ELF MACHINE %x is not supported.\n", machine);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue