tools/perf: Add basic support for LoongArch
Add basic support for LoongArch, which is very similar to the MIPS version. Signed-off-by: Ming Wang <wangming01@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
Родитель
22f367a689
Коммит
2fa5ebe3bc
|
@ -0,0 +1,40 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _ASM_LOONGARCH_PERF_REGS_H
|
||||
#define _ASM_LOONGARCH_PERF_REGS_H
|
||||
|
||||
enum perf_event_loongarch_regs {
|
||||
PERF_REG_LOONGARCH_PC,
|
||||
PERF_REG_LOONGARCH_R1,
|
||||
PERF_REG_LOONGARCH_R2,
|
||||
PERF_REG_LOONGARCH_R3,
|
||||
PERF_REG_LOONGARCH_R4,
|
||||
PERF_REG_LOONGARCH_R5,
|
||||
PERF_REG_LOONGARCH_R6,
|
||||
PERF_REG_LOONGARCH_R7,
|
||||
PERF_REG_LOONGARCH_R8,
|
||||
PERF_REG_LOONGARCH_R9,
|
||||
PERF_REG_LOONGARCH_R10,
|
||||
PERF_REG_LOONGARCH_R11,
|
||||
PERF_REG_LOONGARCH_R12,
|
||||
PERF_REG_LOONGARCH_R13,
|
||||
PERF_REG_LOONGARCH_R14,
|
||||
PERF_REG_LOONGARCH_R15,
|
||||
PERF_REG_LOONGARCH_R16,
|
||||
PERF_REG_LOONGARCH_R17,
|
||||
PERF_REG_LOONGARCH_R18,
|
||||
PERF_REG_LOONGARCH_R19,
|
||||
PERF_REG_LOONGARCH_R20,
|
||||
PERF_REG_LOONGARCH_R21,
|
||||
PERF_REG_LOONGARCH_R22,
|
||||
PERF_REG_LOONGARCH_R23,
|
||||
PERF_REG_LOONGARCH_R24,
|
||||
PERF_REG_LOONGARCH_R25,
|
||||
PERF_REG_LOONGARCH_R26,
|
||||
PERF_REG_LOONGARCH_R27,
|
||||
PERF_REG_LOONGARCH_R28,
|
||||
PERF_REG_LOONGARCH_R29,
|
||||
PERF_REG_LOONGARCH_R30,
|
||||
PERF_REG_LOONGARCH_R31,
|
||||
PERF_REG_LOONGARCH_MAX,
|
||||
};
|
||||
#endif /* _ASM_LOONGARCH_PERF_REGS_H */
|
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
#define __ARCH_WANT_SYS_CLONE3
|
||||
|
||||
#include <asm-generic/unistd.h>
|
|
@ -38,7 +38,7 @@ ifneq ($(NO_SYSCALL_TABLE),1)
|
|||
NO_SYSCALL_TABLE := 0
|
||||
endif
|
||||
else
|
||||
ifeq ($(SRCARCH),$(filter $(SRCARCH),powerpc arm64 s390 mips))
|
||||
ifeq ($(SRCARCH),$(filter $(SRCARCH),powerpc arm64 s390 mips loongarch))
|
||||
NO_SYSCALL_TABLE := 0
|
||||
endif
|
||||
endif
|
||||
|
@ -80,6 +80,12 @@ ifeq ($(SRCARCH),arm64)
|
|||
LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
|
||||
endif
|
||||
|
||||
ifeq ($(SRCARCH),loongarch)
|
||||
NO_PERF_REGS := 0
|
||||
CFLAGS += -I$(OUTPUT)arch/loongarch/include/generated
|
||||
LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64
|
||||
endif
|
||||
|
||||
ifeq ($(SRCARCH),riscv)
|
||||
NO_PERF_REGS := 0
|
||||
endif
|
||||
|
@ -107,7 +113,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 arm64 powerpc s390 csky riscv))
|
||||
ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390 csky riscv loongarch))
|
||||
NO_LIBDW_DWARF_UNWIND := 1
|
||||
endif
|
||||
|
||||
|
@ -129,7 +135,7 @@ endef
|
|||
ifdef LIBUNWIND_DIR
|
||||
LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
|
||||
LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
|
||||
LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64
|
||||
LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64 loongarch
|
||||
$(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch)))
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
perf-y += util/
|
|
@ -0,0 +1,28 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
ifndef NO_DWARF
|
||||
PERF_HAVE_DWARF_REGS := 1
|
||||
endif
|
||||
PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
|
||||
PERF_HAVE_JITDUMP := 1
|
||||
|
||||
#
|
||||
# Syscall table generation for perf
|
||||
#
|
||||
|
||||
out := $(OUTPUT)arch/loongarch/include/generated/asm
|
||||
header := $(out)/syscalls.c
|
||||
incpath := $(srctree)/tools
|
||||
sysdef := $(srctree)/tools/arch/loongarch/include/uapi/asm/unistd.h
|
||||
sysprf := $(srctree)/tools/perf/arch/loongarch/entry/syscalls/
|
||||
systbl := $(sysprf)/mksyscalltbl
|
||||
|
||||
# Create output directory if not already present
|
||||
_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
|
||||
|
||||
$(header): $(sysdef) $(systbl)
|
||||
$(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(incpath) $(sysdef) > $@
|
||||
|
||||
clean::
|
||||
$(call QUIET_CLEAN, loongarch) $(RM) $(header)
|
||||
|
||||
archheaders: $(header)
|
|
@ -0,0 +1,45 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Perf annotate functions.
|
||||
*
|
||||
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
static
|
||||
struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char *name)
|
||||
{
|
||||
struct ins_ops *ops = NULL;
|
||||
|
||||
if (!strncmp(name, "beqz", 4) ||
|
||||
!strncmp(name, "bnez", 4) ||
|
||||
!strncmp(name, "beq", 3) ||
|
||||
!strncmp(name, "bne", 3) ||
|
||||
!strncmp(name, "blt", 3) ||
|
||||
!strncmp(name, "bge", 3) ||
|
||||
!strncmp(name, "bltu", 4) ||
|
||||
!strncmp(name, "bgeu", 4) ||
|
||||
!strncmp(name, "bl", 2))
|
||||
ops = &call_ops;
|
||||
else if (!strncmp(name, "jirl", 4))
|
||||
ops = &ret_ops;
|
||||
else if (name[0] == 'b')
|
||||
ops = &jump_ops;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
arch__associate_ins_ops(arch, name, ops);
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
static
|
||||
int loongarch__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
if (!arch->initialized) {
|
||||
arch->associate_instruction_ops = loongarch__associate_ins_ops;
|
||||
arch->initialized = true;
|
||||
arch->objdump.comment_char = '#';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Generate system call table for perf. Derived from
|
||||
# powerpc script.
|
||||
#
|
||||
# Author(s): Ming Wang <wangming01@loongson.cn>
|
||||
# Author(s): Huacai Chen <chenhuacai@loongson.cn>
|
||||
# Copyright (C) 2020-2023 Loongson Technology Corporation Limited
|
||||
|
||||
gcc=$1
|
||||
hostcc=$2
|
||||
incpath=$3
|
||||
input=$4
|
||||
|
||||
if ! test -r $input; then
|
||||
echo "Could not read input file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_table_from_c()
|
||||
{
|
||||
local sc nr last_sc
|
||||
|
||||
create_table_exe=`mktemp ${TMPDIR:-/tmp}/create-table-XXXXXX`
|
||||
|
||||
{
|
||||
|
||||
cat <<-_EoHEADER
|
||||
#include <stdio.h>
|
||||
#include "$input"
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
_EoHEADER
|
||||
|
||||
while read sc nr; do
|
||||
printf "%s\n" " printf(\"\\t[%d] = \\\"$sc\\\",\\n\", $nr);"
|
||||
last_sc=$nr
|
||||
done
|
||||
|
||||
printf "%s\n" " printf(\"#define SYSCALLTBL_LOONGARCH_MAX_ID %d\\n\", $last_sc);"
|
||||
printf "}\n"
|
||||
|
||||
} | $hostcc -I $incpath/include/uapi -o $create_table_exe -x c -
|
||||
|
||||
$create_table_exe
|
||||
|
||||
rm -f $create_table_exe
|
||||
}
|
||||
|
||||
create_table()
|
||||
{
|
||||
echo "static const char *syscalltbl_loongarch[] = {"
|
||||
create_table_from_c
|
||||
echo "};"
|
||||
}
|
||||
|
||||
$gcc -E -dM -x c -I $incpath/include/uapi $input \
|
||||
|sed -ne 's/^#define __NR_//p' \
|
||||
|sort -t' ' -k2 -n \
|
||||
|create_table
|
|
@ -0,0 +1,16 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* dwarf-regs-table.h : Mapping of DWARF debug register numbers into
|
||||
* register names.
|
||||
*
|
||||
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifdef DEFINE_DWARF_REGSTR_TABLE
|
||||
static const char * const loongarch_regstr_tbl[] = {
|
||||
"%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
|
||||
"%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
|
||||
"%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
/* 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_LOONGARCH_MAX
|
||||
#define PERF_REG_IP PERF_REG_LOONGARCH_PC
|
||||
#define PERF_REG_SP PERF_REG_LOONGARCH_R3
|
||||
|
||||
#define PERF_REGS_MASK ((1ULL << PERF_REG_LOONGARCH_MAX) - 1)
|
||||
|
||||
#endif /* ARCH_PERF_REGS_H */
|
|
@ -0,0 +1,5 @@
|
|||
perf-y += perf_regs.o
|
||||
|
||||
perf-$(CONFIG_DWARF) += dwarf-regs.o
|
||||
perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
|
||||
perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
|
|
@ -0,0 +1,44 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
|
||||
*
|
||||
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h> /* for EINVAL */
|
||||
#include <string.h> /* for strcmp */
|
||||
#include <dwarf-regs.h>
|
||||
|
||||
struct pt_regs_dwarfnum {
|
||||
const char *name;
|
||||
unsigned int dwarfnum;
|
||||
};
|
||||
|
||||
static struct pt_regs_dwarfnum loongarch_gpr_table[] = {
|
||||
{"%r0", 0}, {"%r1", 1}, {"%r2", 2}, {"%r3", 3},
|
||||
{"%r4", 4}, {"%r5", 5}, {"%r6", 6}, {"%r7", 7},
|
||||
{"%r8", 8}, {"%r9", 9}, {"%r10", 10}, {"%r11", 11},
|
||||
{"%r12", 12}, {"%r13", 13}, {"%r14", 14}, {"%r15", 15},
|
||||
{"%r16", 16}, {"%r17", 17}, {"%r18", 18}, {"%r19", 19},
|
||||
{"%r20", 20}, {"%r21", 21}, {"%r22", 22}, {"%r23", 23},
|
||||
{"%r24", 24}, {"%r25", 25}, {"%r26", 26}, {"%r27", 27},
|
||||
{"%r28", 28}, {"%r29", 29}, {"%r30", 30}, {"%r31", 31},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
const char *get_arch_regstr(unsigned int n)
|
||||
{
|
||||
n %= 32;
|
||||
return loongarch_gpr_table[n].name;
|
||||
}
|
||||
|
||||
int regs_query_register_offset(const char *name)
|
||||
{
|
||||
const struct pt_regs_dwarfnum *roff;
|
||||
|
||||
for (roff = loongarch_gpr_table; roff->name != NULL; roff++)
|
||||
if (!strcmp(roff->name, name))
|
||||
return roff->dwarfnum;
|
||||
return -EINVAL;
|
||||
}
|
|
@ -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,56 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2020-2023 Loongson Technology Corporation Limited */
|
||||
|
||||
#include <elfutils/libdwfl.h>
|
||||
#include "../../util/unwind-libdw.h"
|
||||
#include "../../util/perf_regs.h"
|
||||
#include "../../util/sample.h"
|
||||
|
||||
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[PERF_REG_LOONGARCH_MAX];
|
||||
|
||||
#define REG(r) ({ \
|
||||
Dwarf_Word val = 0; \
|
||||
perf_reg_value(&val, user_regs, PERF_REG_LOONGARCH_##r); \
|
||||
val; \
|
||||
})
|
||||
|
||||
dwarf_regs[0] = 0;
|
||||
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);
|
||||
dwfl_thread_state_register_pc(thread, REG(PC));
|
||||
|
||||
return dwfl_thread_state_registers(thread, 0, PERF_REG_LOONGARCH_MAX, dwarf_regs);
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
// 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_LOONGARCH64_R1:
|
||||
return PERF_REG_LOONGARCH_R1;
|
||||
case UNW_LOONGARCH64_R2:
|
||||
return PERF_REG_LOONGARCH_R2;
|
||||
case UNW_LOONGARCH64_R3:
|
||||
return PERF_REG_LOONGARCH_R3;
|
||||
case UNW_LOONGARCH64_R4:
|
||||
return PERF_REG_LOONGARCH_R4;
|
||||
case UNW_LOONGARCH64_R5:
|
||||
return PERF_REG_LOONGARCH_R5;
|
||||
case UNW_LOONGARCH64_R6:
|
||||
return PERF_REG_LOONGARCH_R6;
|
||||
case UNW_LOONGARCH64_R7:
|
||||
return PERF_REG_LOONGARCH_R7;
|
||||
case UNW_LOONGARCH64_R8:
|
||||
return PERF_REG_LOONGARCH_R8;
|
||||
case UNW_LOONGARCH64_R9:
|
||||
return PERF_REG_LOONGARCH_R9;
|
||||
case UNW_LOONGARCH64_R10:
|
||||
return PERF_REG_LOONGARCH_R10;
|
||||
case UNW_LOONGARCH64_R11:
|
||||
return PERF_REG_LOONGARCH_R11;
|
||||
case UNW_LOONGARCH64_R12:
|
||||
return PERF_REG_LOONGARCH_R12;
|
||||
case UNW_LOONGARCH64_R13:
|
||||
return PERF_REG_LOONGARCH_R13;
|
||||
case UNW_LOONGARCH64_R14:
|
||||
return PERF_REG_LOONGARCH_R14;
|
||||
case UNW_LOONGARCH64_R15:
|
||||
return PERF_REG_LOONGARCH_R15;
|
||||
case UNW_LOONGARCH64_R16:
|
||||
return PERF_REG_LOONGARCH_R16;
|
||||
case UNW_LOONGARCH64_R17:
|
||||
return PERF_REG_LOONGARCH_R17;
|
||||
case UNW_LOONGARCH64_R18:
|
||||
return PERF_REG_LOONGARCH_R18;
|
||||
case UNW_LOONGARCH64_R19:
|
||||
return PERF_REG_LOONGARCH_R19;
|
||||
case UNW_LOONGARCH64_R20:
|
||||
return PERF_REG_LOONGARCH_R20;
|
||||
case UNW_LOONGARCH64_R21:
|
||||
return PERF_REG_LOONGARCH_R21;
|
||||
case UNW_LOONGARCH64_R22:
|
||||
return PERF_REG_LOONGARCH_R22;
|
||||
case UNW_LOONGARCH64_R23:
|
||||
return PERF_REG_LOONGARCH_R23;
|
||||
case UNW_LOONGARCH64_R24:
|
||||
return PERF_REG_LOONGARCH_R24;
|
||||
case UNW_LOONGARCH64_R25:
|
||||
return PERF_REG_LOONGARCH_R25;
|
||||
case UNW_LOONGARCH64_R26:
|
||||
return PERF_REG_LOONGARCH_R26;
|
||||
case UNW_LOONGARCH64_R27:
|
||||
return PERF_REG_LOONGARCH_R27;
|
||||
case UNW_LOONGARCH64_R28:
|
||||
return PERF_REG_LOONGARCH_R28;
|
||||
case UNW_LOONGARCH64_R29:
|
||||
return PERF_REG_LOONGARCH_R29;
|
||||
case UNW_LOONGARCH64_R30:
|
||||
return PERF_REG_LOONGARCH_R30;
|
||||
case UNW_LOONGARCH64_R31:
|
||||
return PERF_REG_LOONGARCH_R31;
|
||||
case UNW_LOONGARCH64_PC:
|
||||
return PERF_REG_LOONGARCH_PC;
|
||||
default:
|
||||
pr_err("unwind: invalid reg id %d\n", regnum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
|
@ -40,6 +40,7 @@ arch/x86/lib/x86-opcode-map.txt
|
|||
arch/x86/tools/gen-insn-attr-x86.awk
|
||||
arch/arm/include/uapi/asm/perf_regs.h
|
||||
arch/arm64/include/uapi/asm/perf_regs.h
|
||||
arch/loongarch/include/uapi/asm/perf_regs.h
|
||||
arch/mips/include/uapi/asm/perf_regs.h
|
||||
arch/powerpc/include/uapi/asm/perf_regs.h
|
||||
arch/s390/include/uapi/asm/perf_regs.h
|
||||
|
|
|
@ -149,6 +149,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i
|
|||
#include "arch/arm/annotate/instructions.c"
|
||||
#include "arch/arm64/annotate/instructions.c"
|
||||
#include "arch/csky/annotate/instructions.c"
|
||||
#include "arch/loongarch/annotate/instructions.c"
|
||||
#include "arch/mips/annotate/instructions.c"
|
||||
#include "arch/x86/annotate/instructions.c"
|
||||
#include "arch/powerpc/annotate/instructions.c"
|
||||
|
@ -211,6 +212,13 @@ static struct arch architectures[] = {
|
|||
.comment_char = '#',
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "loongarch",
|
||||
.init = loongarch__annotate_init,
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static void ins__delete(struct ins_operands *ops)
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#define EM_AARCH64 183 /* ARM 64 bit */
|
||||
#endif
|
||||
|
||||
#ifndef EM_LOONGARCH
|
||||
#define EM_LOONGARCH 258 /* LoongArch */
|
||||
#endif
|
||||
|
||||
/* Define const char * {arch}_register_tbl[] */
|
||||
#define DEFINE_DWARF_REGSTR_TABLE
|
||||
#include "../arch/x86/include/dwarf-regs-table.h"
|
||||
|
@ -25,6 +29,7 @@
|
|||
#include "../arch/sparc/include/dwarf-regs-table.h"
|
||||
#include "../arch/xtensa/include/dwarf-regs-table.h"
|
||||
#include "../arch/mips/include/dwarf-regs-table.h"
|
||||
#include "../arch/loongarch/include/dwarf-regs-table.h"
|
||||
|
||||
#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
|
||||
|
||||
|
@ -56,6 +61,8 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
|
|||
return __get_dwarf_regstr(xtensa_regstr_tbl, n);
|
||||
case EM_MIPS:
|
||||
return __get_dwarf_regstr(mips_regstr_tbl, n);
|
||||
case EM_LOONGARCH:
|
||||
return __get_dwarf_regstr(loongarch_regstr_tbl, n);
|
||||
default:
|
||||
pr_err("ELF MACHINE %x is not supported.\n", machine);
|
||||
}
|
||||
|
|
|
@ -435,6 +435,8 @@ static const char *normalize_arch(char *arch)
|
|||
return "mips";
|
||||
if (!strncmp(arch, "sh", 2) && isdigit(arch[2]))
|
||||
return "sh";
|
||||
if (!strncmp(arch, "loongarch", 9))
|
||||
return "loongarch";
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
|
|||
#elif defined(__riscv) && __riscv_xlen == 64
|
||||
#define GEN_ELF_ARCH EM_RISCV
|
||||
#define GEN_ELF_CLASS ELFCLASS64
|
||||
#elif defined(__loongarch__)
|
||||
#define GEN_ELF_ARCH EM_LOONGARCH
|
||||
#define GEN_ELF_CLASS ELFCLASS64
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,7 @@ uint64_t __weak arch__user_reg_mask(void)
|
|||
|
||||
#include "../../arch/arm/include/uapi/asm/perf_regs.h"
|
||||
#include "../../arch/csky/include/uapi/asm/perf_regs.h"
|
||||
#include "../../arch/loongarch/include/uapi/asm/perf_regs.h"
|
||||
#include "../../arch/mips/include/uapi/asm/perf_regs.h"
|
||||
#include "../../arch/powerpc/include/uapi/asm/perf_regs.h"
|
||||
#include "../../arch/riscv/include/uapi/asm/perf_regs.h"
|
||||
|
@ -236,6 +237,79 @@ static const char *__perf_reg_name_csky(int id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char *__perf_reg_name_loongarch(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case PERF_REG_LOONGARCH_PC:
|
||||
return "PC";
|
||||
case PERF_REG_LOONGARCH_R1:
|
||||
return "%r1";
|
||||
case PERF_REG_LOONGARCH_R2:
|
||||
return "%r2";
|
||||
case PERF_REG_LOONGARCH_R3:
|
||||
return "%r3";
|
||||
case PERF_REG_LOONGARCH_R4:
|
||||
return "%r4";
|
||||
case PERF_REG_LOONGARCH_R5:
|
||||
return "%r5";
|
||||
case PERF_REG_LOONGARCH_R6:
|
||||
return "%r6";
|
||||
case PERF_REG_LOONGARCH_R7:
|
||||
return "%r7";
|
||||
case PERF_REG_LOONGARCH_R8:
|
||||
return "%r8";
|
||||
case PERF_REG_LOONGARCH_R9:
|
||||
return "%r9";
|
||||
case PERF_REG_LOONGARCH_R10:
|
||||
return "%r10";
|
||||
case PERF_REG_LOONGARCH_R11:
|
||||
return "%r11";
|
||||
case PERF_REG_LOONGARCH_R12:
|
||||
return "%r12";
|
||||
case PERF_REG_LOONGARCH_R13:
|
||||
return "%r13";
|
||||
case PERF_REG_LOONGARCH_R14:
|
||||
return "%r14";
|
||||
case PERF_REG_LOONGARCH_R15:
|
||||
return "%r15";
|
||||
case PERF_REG_LOONGARCH_R16:
|
||||
return "%r16";
|
||||
case PERF_REG_LOONGARCH_R17:
|
||||
return "%r17";
|
||||
case PERF_REG_LOONGARCH_R18:
|
||||
return "%r18";
|
||||
case PERF_REG_LOONGARCH_R19:
|
||||
return "%r19";
|
||||
case PERF_REG_LOONGARCH_R20:
|
||||
return "%r20";
|
||||
case PERF_REG_LOONGARCH_R21:
|
||||
return "%r21";
|
||||
case PERF_REG_LOONGARCH_R22:
|
||||
return "%r22";
|
||||
case PERF_REG_LOONGARCH_R23:
|
||||
return "%r23";
|
||||
case PERF_REG_LOONGARCH_R24:
|
||||
return "%r24";
|
||||
case PERF_REG_LOONGARCH_R25:
|
||||
return "%r25";
|
||||
case PERF_REG_LOONGARCH_R26:
|
||||
return "%r26";
|
||||
case PERF_REG_LOONGARCH_R27:
|
||||
return "%r27";
|
||||
case PERF_REG_LOONGARCH_R28:
|
||||
return "%r28";
|
||||
case PERF_REG_LOONGARCH_R29:
|
||||
return "%r29";
|
||||
case PERF_REG_LOONGARCH_R30:
|
||||
return "%r30";
|
||||
case PERF_REG_LOONGARCH_R31:
|
||||
return "%r31";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *__perf_reg_name_mips(int id)
|
||||
{
|
||||
switch (id) {
|
||||
|
@ -670,6 +744,8 @@ const char *perf_reg_name(int id, const char *arch)
|
|||
|
||||
if (!strcmp(arch, "csky"))
|
||||
reg_name = __perf_reg_name_csky(id);
|
||||
else if (!strcmp(arch, "loongarch"))
|
||||
reg_name = __perf_reg_name_loongarch(id);
|
||||
else if (!strcmp(arch, "mips"))
|
||||
reg_name = __perf_reg_name_mips(id);
|
||||
else if (!strcmp(arch, "powerpc"))
|
||||
|
|
|
@ -38,6 +38,10 @@ static const char **syscalltbl_native = syscalltbl_arm64;
|
|||
#include <asm/syscalls_n64.c>
|
||||
const int syscalltbl_native_max_id = SYSCALLTBL_MIPS_N64_MAX_ID;
|
||||
static const char **syscalltbl_native = syscalltbl_mips_n64;
|
||||
#elif defined(__loongarch__)
|
||||
#include <asm/syscalls.c>
|
||||
const int syscalltbl_native_max_id = SYSCALLTBL_LOONGARCH_MAX_ID;
|
||||
static const char **syscalltbl_native = syscalltbl_loongarch;
|
||||
#endif
|
||||
|
||||
struct syscall {
|
||||
|
|
Загрузка…
Ссылка в новой задаче