提交 4b935658 编写于 作者: G Gu Zitao 提交者: Zheng Zengkai

sw64: add perf userspace tool support for sw64

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4SPZD
CVE: NA

-------------------------------

Add perf support for hardware events with CPU PMU, and add more
user utils and features.

Signed-off-by: Gu Zitao <guzitao@wxiat.com> #openEuler_contributor
Signed-off-by: NLaibin Qiu <qiulaibin@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 bae092b4
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _TOOLS_LINUX_ASM_SW64_BARRIER_H
#define _TOOLS_LINUX_ASM_SW64_BARRIER_H
#define mb() __asm__ __volatile__("mb" : : : "memory")
#define rmb() __asm__ __volatile__("mb" : : : "memory")
#define wmb() __asm__ __volatile__("mb" : : : "memory")
#endif /* _TOOLS_LINUX_ASM_SW64_BARRIER_H */
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __ASM_SW64_BITSPERLONG_H
#define __ASM_SW64_BITSPERLONG_H
#define __BITS_PER_LONG 64
#include <asm-generic/bitsperlong.h>
#endif /* __ASM_SW64_BITSPERLONG_H */
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _SW64_ERRNO_H
#define _SW64_ERRNO_H
#include <asm-generic/errno-base.h>
#undef EAGAIN /* 11 in errno-base.h */
#define EDEADLK 11 /* Resource deadlock would occur */
#define EAGAIN 35 /* Try again */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define EINPROGRESS 36 /* Operation now in progress */
#define EALREADY 37 /* Operation already in progress */
#define ENOTSOCK 38 /* Socket operation on non-socket */
#define EDESTADDRREQ 39 /* Destination address required */
#define EMSGSIZE 40 /* Message too long */
#define EPROTOTYPE 41 /* Protocol wrong type for socket */
#define ENOPROTOOPT 42 /* Protocol not available */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
#define EOPNOTSUPP 45 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 46 /* Protocol family not supported */
#define EAFNOSUPPORT 47 /* Address family not supported by protocol */
#define EADDRINUSE 48 /* Address already in use */
#define EADDRNOTAVAIL 49 /* Cannot assign requested address */
#define ENETDOWN 50 /* Network is down */
#define ENETUNREACH 51 /* Network is unreachable */
#define ENETRESET 52 /* Network dropped connection because of reset */
#define ECONNABORTED 53 /* Software caused connection abort */
#define ECONNRESET 54 /* Connection reset by peer */
#define ENOBUFS 55 /* No buffer space available */
#define EISCONN 56 /* Transport endpoint is already connected */
#define ENOTCONN 57 /* Transport endpoint is not connected */
#define ESHUTDOWN 58 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 59 /* Too many references: cannot splice */
#define ETIMEDOUT 60 /* Connection timed out */
#define ECONNREFUSED 61 /* Connection refused */
#define ELOOP 62 /* Too many symbolic links encountered */
#define ENAMETOOLONG 63 /* File name too long */
#define EHOSTDOWN 64 /* Host is down */
#define EHOSTUNREACH 65 /* No route to host */
#define ENOTEMPTY 66 /* Directory not empty */
#define EUSERS 68 /* Too many users */
#define EDQUOT 69 /* Quota exceeded */
#define ESTALE 70 /* Stale file handle */
#define EREMOTE 71 /* Object is remote */
#define ENOLCK 77 /* No record locks available */
#define ENOSYS 78 /* Function not implemented */
#define ENOMSG 80 /* No message of desired type */
#define EIDRM 81 /* Identifier removed */
#define ENOSR 82 /* Out of streams resources */
#define ETIME 83 /* Timer expired */
#define EBADMSG 84 /* Not a data message */
#define EPROTO 85 /* Protocol error */
#define ENODATA 86 /* No data available */
#define ENOSTR 87 /* Device not a stream */
#define ENOPKG 92 /* Package not installed */
#define EILSEQ 116 /* Illegal byte sequence */
/* The following are just random noise.. */
#define ECHRNG 88 /* Channel number out of range */
#define EL2NSYNC 89 /* Level 2 not synchronized */
#define EL3HLT 90 /* Level 3 halted */
#define EL3RST 91 /* Level 3 reset */
#define ELNRNG 93 /* Link number out of range */
#define EUNATCH 94 /* Protocol driver not attached */
#define ENOCSI 95 /* No CSI structure available */
#define EL2HLT 96 /* Level 2 halted */
#define EBADE 97 /* Invalid exchange */
#define EBADR 98 /* Invalid request descriptor */
#define EXFULL 99 /* Exchange full */
#define ENOANO 100 /* No anode */
#define EBADRQC 101 /* Invalid request code */
#define EBADSLT 102 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 104 /* Bad font file format */
#define ENONET 105 /* Machine is not on the network */
#define ENOLINK 106 /* Link has been severed */
#define EADV 107 /* Advertise error */
#define ESRMNT 108 /* Srmount error */
#define ECOMM 109 /* Communication error on send */
#define EMULTIHOP 110 /* Multihop attempted */
#define EDOTDOT 111 /* RFS specific error */
#define EOVERFLOW 112 /* Value too large for defined data type */
#define ENOTUNIQ 113 /* Name not unique on network */
#define EBADFD 114 /* File descriptor in bad state */
#define EREMCHG 115 /* Remote address changed */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define ELIBACC 122 /* Can not access a needed shared library */
#define ELIBBAD 123 /* Accessing a corrupted shared library */
#define ELIBSCN 124 /* .lib section in a.out corrupted */
#define ELIBMAX 125 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 126 /* Cannot exec a shared library directly */
#define ERESTART 127 /* Interrupted system call should be restarted */
#define ESTRPIPE 128 /* Streams pipe error */
#define ENOMEDIUM 129 /* No medium found */
#define EMEDIUMTYPE 130 /* Wrong medium type */
#define ECANCELED 131 /* Operation Cancelled */
#define ENOKEY 132 /* Required key not available */
#define EKEYEXPIRED 133 /* Key has expired */
#define EKEYREVOKED 134 /* Key has been revoked */
#define EKEYREJECTED 135 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 136 /* Owner died */
#define ENOTRECOVERABLE 137 /* State not recoverable */
#define ERFKILL 138 /* Operation not possible due to RF-kill */
#define EHWPOISON 139 /* Memory page has hardware error */
#endif /* _SW64_ERRNO_H */
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef TOOLS_ARCH_SW64_UAPI_ASM_MMAN_FIX_H
#define TOOLS_ARCH_SW64_UAPI_ASM_MMAN_FIX_H
#define MADV_DODUMP 17
#define MADV_DOFORK 11
#define MADV_DONTDUMP 16
#define MADV_DONTFORK 10
#define MADV_DONTNEED 6
#define MADV_FREE 8
#define MADV_HUGEPAGE 14
#define MADV_MERGEABLE 12
#define MADV_NOHUGEPAGE 15
#define MADV_NORMAL 0
#define MADV_RANDOM 1
#define MADV_REMOVE 9
#define MADV_SEQUENTIAL 2
#define MADV_UNMERGEABLE 13
#define MADV_WILLNEED 3
#define MAP_ANONYMOUS 0x10
#define MAP_DENYWRITE 0x02000
#define MAP_EXECUTABLE 0x04000
#define MAP_FILE 0
#define MAP_FIXED 0x100
#define MAP_GROWSDOWN 0x01000
#define MAP_HUGETLB 0x100000
#define MAP_LOCKED 0x08000
#define MAP_NONBLOCK 0x40000
#define MAP_NORESERVE 0x10000
#define MAP_POPULATE 0x20000
#define MAP_STACK 0x80000
#define PROT_EXEC 0x4
#define PROT_GROWSDOWN 0x01000000
#define PROT_GROWSUP 0x02000000
#define PROT_NONE 0x0
#define PROT_READ 0x1
#define PROT_SEM 0x8
#define PROT_WRITE 0x2
/* MADV_HWPOISON is undefined on alpha, fix it for perf */
#define MADV_HWPOISON 100
/* MADV_SOFT_OFFLINE is undefined on alpha, fix it for perf */
#define MADV_SOFT_OFFLINE 101
/* MAP_32BIT is undefined on alpha, fix it for perf */
#define MAP_32BIT 0
/* MAP_UNINITIALIZED is undefined on alpha, fix it for perf */
#define MAP_UNINITIALIZED 0
#endif /* TOOLS_ARCH_SW64_UAPI_ASM_MMAN_FIX_H */
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_SW64_PERF_REGS_H
#define _ASM_SW64_PERF_REGS_H
enum perf_event_sw64_regs {
PERF_REG_SW64_R0,
PERF_REG_SW64_R1,
PERF_REG_SW64_R2,
PERF_REG_SW64_R3,
PERF_REG_SW64_R4,
PERF_REG_SW64_R5,
PERF_REG_SW64_R6,
PERF_REG_SW64_R7,
PERF_REG_SW64_R8,
PERF_REG_SW64_R19,
PERF_REG_SW64_R20,
PERF_REG_SW64_R21,
PERF_REG_SW64_R22,
PERF_REG_SW64_R23,
PERF_REG_SW64_R24,
PERF_REG_SW64_R25,
PERF_REG_SW64_R26,
PERF_REG_SW64_R27,
PERF_REG_SW64_R28,
PERF_REG_SW64_HAE,
PERF_REG_SW64_TRAP_A0,
PERF_REG_SW64_TRAP_A1,
PERF_REG_SW64_TRAP_A2,
PERF_REG_SW64_PS,
PERF_REG_SW64_PC,
PERF_REG_SW64_GP,
PERF_REG_SW64_R16,
PERF_REG_SW64_R17,
PERF_REG_SW64_R18,
PERF_REG_SW64_MAX,
};
#endif /* _ASM_SW64_PERF_REGS_H */
......@@ -53,6 +53,7 @@ FEATURE_TESTS_BASIC := \
libslang-include-subdir \
libcrypto \
libunwind \
libunwind-sw_64 \
pthread-attr-setaffinity-np \
pthread-barrier \
reallocarray \
......
......@@ -40,6 +40,7 @@ FILES= \
test-libunwind-x86_64.bin \
test-libunwind-arm.bin \
test-libunwind-aarch64.bin \
test-libunwind-sw64.bin \
test-libunwind-debug-frame-arm.bin \
test-libunwind-debug-frame-aarch64.bin \
test-pthread-attr-setaffinity-np.bin \
......@@ -180,6 +181,9 @@ $(OUTPUT)test-libunwind-arm.bin:
$(OUTPUT)test-libunwind-aarch64.bin:
$(BUILD) -lelf -lunwind-aarch64
$(OUTPUT)test-libunwind-sw64.bin:
$(BUILD) -lelf -lunwind-sw_64
$(OUTPUT)test-libunwind-debug-frame-arm.bin:
$(BUILD) -lelf -lunwind-arm
......
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-sw_64.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}
......@@ -9,6 +9,8 @@
#include "../../../arch/alpha/include/uapi/asm/errno.h"
#elif defined(__mips__)
#include "../../../arch/mips/include/uapi/asm/errno.h"
#elif defined(__sw_64__)
#include "../../../arch/sw_64/include/uapi/asm/errno.h"
#elif defined(__xtensa__)
#include "../../../arch/xtensa/include/uapi/asm/errno.h"
#else
......
......@@ -82,6 +82,12 @@ ifeq ($(SRCARCH),csky)
NO_PERF_REGS := 0
endif
ifeq ($(SRCARCH),sw_64)
NO_PERF_REGS := 0
CFLAGS += -mieee
LIBUNWIND_LIBS = -lunwind -lunwind-sw_64
endif
ifeq ($(ARCH),s390)
NO_PERF_REGS := 0
CFLAGS += -fPIC -I$(OUTPUT)arch/s390/include/generated
......@@ -597,6 +603,13 @@ ifndef NO_LIBUNWIND
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64
endif
endif
ifeq ($(feature-libunwind-sw_64), 1)
$(call detected,CONFIG_LIBUNWIND_SW64)
CFLAGS += -DHAVE_LIBUNWIND_SW_64_SUPPORT
LDFLAGS += -lunwind-sw_64
EXTLIBS_LIBUNWIND += -lunwind-sw_64
have_libunwind = 1
endif
ifneq ($(feature-libunwind), 1)
msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
......
perf-y += util/
perf-$(CONFIG_DWARF_UNWIND) += tests/
ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
endif
PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ARCH_TESTS_H
#define ARCH_TESTS_H
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
struct perf_sample;
#endif
extern struct test arch_tests[];
#endif
/* 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>
void perf_regs_load(u64 *regs);
#define PERF_REGS_MASK ((1ULL << PERF_REG_SW64_MAX) - 1)
#define PERF_REGS_MAX PERF_REG_SW64_MAX
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
#define PERF_REG_IP PERF_REG_SW64_PC
#define PERF_REG_SP PERF_REG_SW64_HAE
static inline const char *perf_reg_name(int id)
{
switch (id) {
case PERF_REG_SW64_R0:
return "r0";
default:
return NULL;
}
return NULL;
}
#endif /* ARCH_PERF_REGS_H */
perf-y += regs_load.o
perf-y += dwarf-unwind.o
perf-y += arch-tests.o
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
#include "tests/tests.h"
#include "arch-tests.h"
struct test arch_tests[] = {
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
.desc = "DWARF unwind",
.func = test__dwarf_unwind,
},
#endif
{
.func = NULL,
},
};
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
#include "perf_regs.h"
#include "thread.h"
#include "map.h"
#include "maps.h"
#include "event.h"
#include "debug.h"
#include "tests/tests.h"
#define STACK_SIZE 8192
static int sample_ustack(struct perf_sample *sample,
struct thread *thread, u64 *regs)
{
struct stack_dump *stack = &sample->user_stack;
struct map *map;
unsigned long sp;
u64 stack_size, *buf;
printf("enter %s\n", __func__);
buf = malloc(STACK_SIZE);
if (!buf) {
printf("failed to allocate sample uregs data\n");
return -1;
}
sp = (unsigned long) regs[30];
map = maps__find(thread->maps, (u64)sp);
if (!map) {
printf("failed to get stack map\n");
free(buf);
return -1;
}
stack_size = map->end - sp;
stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
memcpy(buf, (void *) sp, stack_size);
stack->data = (char *) buf;
stack->size = stack_size;
return 0;
}
int test__arch_unwind_sample(struct perf_sample *sample,
struct thread *thread)
{
struct regs_dump *regs = &sample->user_regs;
u64 *buf;
buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
if (!buf) {
printf("failed to allocate sample uregs data\n");
return -1;
}
perf_regs_load(buf);
regs->abi = PERF_SAMPLE_REGS_ABI;
regs->regs = buf;
regs->mask = PERF_REGS_MASK;
return sample_ustack(sample, thread, buf);
}
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
.text
.set noat
.type perf_regs_load,%function
SYM_FUNC_START(perf_regs_load)
stl $0, 0x0($16);
stl $1, 0x8($16);
stl $2, 0x10($16);
stl $3, 0x18($16);
stl $4, 0x20($16);
stl $5, 0x28($16);
stl $6, 0x30($16);
stl $7, 0x38($16);
stl $8, 0x40($16);
stl $19, 0x48($16);
stl $20, 0x50($16);
stl $21, 0x58($16);
stl $22, 0x60($16);
stl $23, 0x68($16);
stl $24, 0x70($16);
stl $25, 0x78($16);
stl $26, 0x80($16);
stl $27, 0x88($16);
stl $28, 0x90($16);
stl $30, 0x98($16);
stl $20, 0xa0($16);
stl $21, 0xa8($16);
stl $22, 0xb0($16);
stl $23, 0xb8($16);
stl $26, 0xc0($16);
stl $29, 0xc8($16);
stl $16, 0xd0($16);
stl $17, 0xd8($16);
stl $18, 0xe0($16);
ret
SYM_FUNC_END(perf_regs_load)
perf-y += perf_regs.o
perf-$(CONFIG_DWARF) += dwarf-regs.o
perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
// SPDX-License-Identifier: GPL-2.0
/*
* Mapping of DWARF debug register numbers into register names.
*
* Copyright (C) 2010 Will Deacon, ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <dwarf-regs.h>
#include <linux/ptrace.h> /* for struct user_pt_regs */
#include <linux/stringify.h>
#include "util.h"
struct pt_regs_dwarfnum {
const char *name;
unsigned int dwarfnum;
};
#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
REG_DWARFNUM_NAME("%v0", 0),
REG_DWARFNUM_NAME("%t0", 1),
REG_DWARFNUM_NAME("%t1", 2),
REG_DWARFNUM_NAME("%t2", 3),
REG_DWARFNUM_NAME("%t3", 4),
REG_DWARFNUM_NAME("%t4", 5),
REG_DWARFNUM_NAME("%t5", 6),
REG_DWARFNUM_NAME("%t6", 7),
REG_DWARFNUM_NAME("%t7", 8),
REG_DWARFNUM_NAME("%s0", 9),
REG_DWARFNUM_NAME("%s1", 10),
REG_DWARFNUM_NAME("%s2", 11),
REG_DWARFNUM_NAME("%s3", 12),
REG_DWARFNUM_NAME("%s4", 13),
REG_DWARFNUM_NAME("%s5", 14),
REG_DWARFNUM_NAME("%s6", 15),
REG_DWARFNUM_NAME("%a0", 16),
REG_DWARFNUM_NAME("%a1", 17),
REG_DWARFNUM_NAME("%a2", 18),
REG_DWARFNUM_NAME("%a3", 19),
REG_DWARFNUM_NAME("%a4", 20),
REG_DWARFNUM_NAME("%a5", 21),
REG_DWARFNUM_NAME("%t8", 22),
REG_DWARFNUM_NAME("%t9", 23),
REG_DWARFNUM_NAME("%t10", 24),
REG_DWARFNUM_NAME("%t11", 25),
REG_DWARFNUM_NAME("%ra", 26),
REG_DWARFNUM_NAME("%pv", 27),
REG_DWARFNUM_NAME("%at", 28),
REG_DWARFNUM_NAME("%gp", 29),
REG_DWARFNUM_NAME("%sp", 30),
REG_DWARFNUM_NAME("%zero", 31),
REG_DWARFNUM_END,
};
/**
* get_arch_regstr() - lookup register name from it's DWARF register number
* @n: the DWARF register number
*
* get_arch_regstr() returns the name of the register in struct
* regdwarfnum_table from it's DWARF register number. If the register is not
* found in the table, this returns NULL;
*/
const char *get_arch_regstr(unsigned int n)
{
const struct pt_regs_dwarfnum *roff;
for (roff = regdwarfnum_table; roff->name != NULL; roff++)
if (roff->dwarfnum == n)
return roff->name;
return NULL;
}
int regs_query_register_offset(const char *name)
{
const struct pt_regs_dwarfnum *roff;
for (roff = regdwarfnum_table; roff->name != NULL; roff++)
if (!strcmp(roff->name, name))
return roff->dwarfnum;
return -EINVAL;
}
// SPDX-License-Identifier: GPL-2.0
#include "../../../util/perf_regs.h"
const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};
// SPDX-License-Identifier: GPL-2.0
#include <elfutils/libdwfl.h>
#include "../../util/unwind-libdw.h"
#include "../../util/perf_regs.h"
#include "../../util/event.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_SW64_MAX], dwarf_pc;
#define REG(r) ({ \
Dwarf_Word val = 0; \
perf_reg_value(&val, user_regs, PERF_REG_SW64_##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, PERF_REG_SW64_MAX,
dwarf_regs))
return false;
dwarf_pc = REG(PC);
dwfl_thread_state_register_pc(thread, dwarf_pc);
return true;
}
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#ifndef REMOTE_UNWIND_LIBUNWIND
#include <libunwind.h>
#include "perf_regs.h"
#include "../../util/unwind.h"
#include "../../util/debug.h"
#endif
int LIBUNWIND__ARCH_REG_ID(int regnum)
{
switch (regnum) {
case UNW_SW_64_R26:
return PERF_REG_SW64_R26;
case UNW_SW_64_R30:
return PERF_REG_SW64_HAE;
case UNW_SW_64_PC:
return PERF_REG_SW64_PC;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return -EINVAL;
}
......@@ -91,7 +91,7 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
$(Q)echo ';' >> $@
ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc))
ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc sw_64))
perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
endif
......
......@@ -129,7 +129,7 @@ bool test__bp_signal_is_supported(void);
bool test__bp_account_is_supported(void);
bool test__wp_is_supported(void);
#if defined(__arm__) || defined(__aarch64__)
#if defined(__arm__) || defined(__aarch64__) || defined(__sw_64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
struct perf_sample;
......
......@@ -168,6 +168,7 @@ perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
perf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
perf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o
perf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o
perf-$(CONFIG_LIBUNWIND_SW64) += libunwind/sw64.o
perf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
......
......@@ -170,6 +170,9 @@ static struct arch architectures[] = {
.name = "arm64",
.init = arm64__annotate_init,
},
{
.name = "sw_64",
},
{
.name = "csky",
.init = csky__annotate_init,
......
......@@ -335,6 +335,8 @@ static const char *normalize_arch(char *arch)
return "arm64";
if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
return "arm";
if (!strncmp(arch, "sw_64", 5))
return "sw_64";
if (!strncmp(arch, "s390", 4))
return "s390";
if (!strncmp(arch, "parisc", 6))
......
// SPDX-License-Identifier: GPL-2.0
/*
* This file setups defines to compile arch specific binary from the
* generic one.
*
* The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch
* name and the defination of this function is included directly from
* 'arch/arm64/util/unwind-libunwind.c', to make sure that this function
* is defined no matter what arch the host is.
*
* Finally, the arch specific unwind methods are exported which will
* be assigned to each arm64 thread.
*/
#define REMOTE_UNWIND_LIBUNWIND
/* Define arch specific functions & regs for libunwind, should be
* defined before including "unwind.h"
*/
#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arm64_reg_id(regnum)
#define LIBUNWIND__ARCH_REG_IP PERF_REG_SW64_PC
#define LIBUNWIND__ARCH_REG_SP PERF_REG_SW64_HAE
#include "unwind.h"
#include "debug.h"
#include "libunwind-sw_64.h"
#include <../../../../arch/sw_64/include/uapi/asm/perf_regs.h>
#include "../../arch/sw_64/util/unwind-libunwind.c"
#include "util/unwind-libunwind-local.c"
struct unwind_libunwind_ops *
sw64_unwind_libunwind_ops = &_unwind_libunwind_ops;
......@@ -11,6 +11,7 @@
struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *sw64_unwind_libunwind_ops;
static void unwind__register_ops(struct maps *maps, struct unwind_libunwind_ops *ops)
{
......@@ -51,6 +52,9 @@ int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized
} else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) {
if (dso_type == DSO__TYPE_64BIT)
ops = arm64_unwind_libunwind_ops;
} else if (!strcmp(arch, "sw_64")) {
if (dso_type == DSO__TYPE_64BIT)
ops = sw64_unwind_libunwind_ops;
}
if (!ops) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册