2023-05-20 02:56:58

by Leo Yan

[permalink] [raw]
Subject: [PATCH v1 0/5] perf parse-regs: Refactor arch related functions

The register parsing have two levels: one level is under 'arch' folder,
another level is under 'util' folder. A good design is 'arch' folder
handles architecture specific operations and provides APIs for upper
layer, on the other hand, 'util' folder should be general and simply
calls APIs to talk to arch layer.

The current code mixes these two layers, e.g. util/perf_regs.h includes
architecture's perf_regs.h, so it implicitly couples with specific
architecture during building time. Furthermore, util/perf_regs.c
includes all architectures' perf_regs.h, this is easily to cause conflict
due to duplicated definitions from any two different archs.

So this patch series is to refactor arch related functions for register
parsing:

Firstly, it creates a new folder util/perf-regs-arch and uses dedicated
source file for every arch, note, all of these source files will be
built in tool to support cross analysis (e.g. we can run perf on x86
machine for parsing aarch64's perf data file).

Secondly, rather than directly referring macros, we introduce new
functions, these functions are provided by architecture and then will be
invoked by perf common code. At the end, we can generalize the register
parsing in 'util' folder.

This patch series has been compiled successfully on my Arm64 and x86
machine.


Leo Yan (5):
perf parse-regs: Refactor arch register parsing functions
perf parse-regs: Introduce functions arch__reg_{ip|sp}()
perf parse-regs: Remove unused macros PERF_REG_{IP|SP}
perf parse-regs: Remove PERF_REGS_{MAX|MASK} from common code
perf parse-regs: Move out arch specific header from util/perf_regs.h

tools/perf/arch/arm/include/perf_regs.h | 3 -
tools/perf/arch/arm/util/perf_regs.c | 21 +
tools/perf/arch/arm/util/unwind-libdw.c | 1 +
tools/perf/arch/arm64/include/perf_regs.h | 3 -
tools/perf/arch/arm64/util/machine.c | 1 +
tools/perf/arch/arm64/util/perf_regs.c | 16 +
tools/perf/arch/arm64/util/unwind-libdw.c | 1 +
tools/perf/arch/csky/include/perf_regs.h | 3 -
tools/perf/arch/csky/util/perf_regs.c | 21 +
tools/perf/arch/csky/util/unwind-libdw.c | 1 +
tools/perf/arch/mips/include/perf_regs.h | 2 -
tools/perf/arch/mips/util/perf_regs.c | 21 +
tools/perf/arch/powerpc/include/perf_regs.h | 3 -
tools/perf/arch/powerpc/util/perf_regs.c | 16 +
tools/perf/arch/powerpc/util/unwind-libdw.c | 1 +
tools/perf/arch/riscv/include/perf_regs.h | 3 -
tools/perf/arch/riscv/util/perf_regs.c | 21 +
tools/perf/arch/riscv/util/unwind-libdw.c | 1 +
tools/perf/arch/s390/include/perf_regs.h | 3 -
tools/perf/arch/s390/util/perf_regs.c | 21 +
tools/perf/arch/s390/util/unwind-libdw.c | 1 +
tools/perf/arch/x86/include/perf_regs.h | 2 -
tools/perf/arch/x86/util/perf_regs.c | 16 +
tools/perf/arch/x86/util/unwind-libdw.c | 1 +
tools/perf/util/Build | 1 +
tools/perf/util/evsel.c | 2 +-
tools/perf/util/perf-regs-arch/Build | 8 +
.../util/perf-regs-arch/perf_regs_aarch64.c | 86 +++
.../perf/util/perf-regs-arch/perf_regs_arm.c | 50 ++
.../perf/util/perf-regs-arch/perf_regs_csky.c | 90 +++
.../perf/util/perf-regs-arch/perf_regs_mips.c | 77 +++
.../util/perf-regs-arch/perf_regs_powerpc.c | 135 ++++
.../util/perf-regs-arch/perf_regs_riscv.c | 82 +++
.../perf/util/perf-regs-arch/perf_regs_s390.c | 86 +++
.../perf/util/perf-regs-arch/perf_regs_x86.c | 88 +++
tools/perf/util/perf_regs.c | 646 +-----------------
tools/perf/util/perf_regs.h | 18 +-
tools/perf/util/unwind-libdw.c | 2 +-
tools/perf/util/unwind.h | 4 +-
39 files changed, 887 insertions(+), 671 deletions(-)
create mode 100644 tools/perf/util/perf-regs-arch/Build
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_aarch64.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_arm.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_csky.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_mips.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_powerpc.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_riscv.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_s390.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_x86.c

--
2.39.2



2023-05-20 02:57:25

by Leo Yan

[permalink] [raw]
Subject: [PATCH v1 2/5] perf parse-regs: Introduce functions arch__reg_{ip|sp}()

Ideally, we want util/perf_regs.c to be general enough and doesn't bind
with specific architecture.

But since util/perf_regs.c uses the macros PERF_REG_IP and PERF_REG_SP
which are defined by architecture, thus util/perf_regs.c is dependent on
architecture header (see util/perf_regs.h includes "<perf_regs.h>", here
perf_regs.h is architecture specific header).

As a step to generalize util/perf_regs.c, this commit introduces weak
functions arch__reg_ip() and arch__reg_sp() and every architecture can
define their own functions; thus, util/perf_regs.c doesn't need to use
PERF_REG_IP and PERF_REG_SP anymore.

This is a preparation to get rid of architecture specific header from
util/perf_regs.h.

Signed-off-by: Leo Yan <[email protected]>
---
tools/perf/arch/arm/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/arm64/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/csky/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/mips/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/powerpc/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/riscv/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/s390/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/x86/util/perf_regs.c | 10 ++++++++++
tools/perf/util/perf_regs.c | 10 ++++++++++
tools/perf/util/perf_regs.h | 4 +++-
tools/perf/util/unwind-libdw.c | 2 +-
tools/perf/util/unwind.h | 4 ++--
12 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/arm/util/perf_regs.c b/tools/perf/arch/arm/util/perf_regs.c
index 2833e101a7c6..37aa3a2091bd 100644
--- a/tools/perf/arch/arm/util/perf_regs.c
+++ b/tools/perf/arch/arm/util/perf_regs.c
@@ -4,3 +4,13 @@
const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_ARM_PC;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_ARM_SP;
+}
diff --git a/tools/perf/arch/arm64/util/perf_regs.c b/tools/perf/arch/arm64/util/perf_regs.c
index 006692c9b040..dbe7f00b222b 100644
--- a/tools/perf/arch/arm64/util/perf_regs.c
+++ b/tools/perf/arch/arm64/util/perf_regs.c
@@ -169,3 +169,13 @@ uint64_t arch__user_reg_mask(void)
}
return PERF_REGS_MASK;
}
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_ARM64_PC;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_ARM64_SP;
+}
diff --git a/tools/perf/arch/csky/util/perf_regs.c b/tools/perf/arch/csky/util/perf_regs.c
index 2864e2e3776d..d230d7e640fd 100644
--- a/tools/perf/arch/csky/util/perf_regs.c
+++ b/tools/perf/arch/csky/util/perf_regs.c
@@ -4,3 +4,13 @@
const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_CSKY_PC;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_CSKY_SP;
+}
diff --git a/tools/perf/arch/mips/util/perf_regs.c b/tools/perf/arch/mips/util/perf_regs.c
index 2864e2e3776d..64882ebc9287 100644
--- a/tools/perf/arch/mips/util/perf_regs.c
+++ b/tools/perf/arch/mips/util/perf_regs.c
@@ -4,3 +4,13 @@
const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_MIPS_PC;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_MIPS_R29;
+}
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index 8d07a78e742a..c84cd79986a8 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -226,3 +226,13 @@ uint64_t arch__intr_reg_mask(void)
}
return mask;
}
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_POWERPC_NIP;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_POWERPC_R1;
+}
diff --git a/tools/perf/arch/riscv/util/perf_regs.c b/tools/perf/arch/riscv/util/perf_regs.c
index 2864e2e3776d..13bbddd139d0 100644
--- a/tools/perf/arch/riscv/util/perf_regs.c
+++ b/tools/perf/arch/riscv/util/perf_regs.c
@@ -4,3 +4,13 @@
const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_RISCV_PC;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_RISCV_SP;
+}
diff --git a/tools/perf/arch/s390/util/perf_regs.c b/tools/perf/arch/s390/util/perf_regs.c
index 2864e2e3776d..9b2297471090 100644
--- a/tools/perf/arch/s390/util/perf_regs.c
+++ b/tools/perf/arch/s390/util/perf_regs.c
@@ -4,3 +4,13 @@
const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_S390_PC;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_S390_R15;
+}
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index 0ed177991ad0..c752a6e9cba6 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -312,3 +312,13 @@ uint64_t arch__intr_reg_mask(void)

return PERF_REGS_MASK;
}
+
+uint64_t arch__reg_ip(void)
+{
+ return PERF_REG_X86_IP;
+}
+
+uint64_t arch__reg_sp(void)
+{
+ return PERF_REG_X86_SP;
+}
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 8720ec6cf147..334c9a2b785d 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -20,6 +20,16 @@ uint64_t __weak arch__user_reg_mask(void)
return PERF_REGS_MASK;
}

+uint64_t __weak arch__reg_ip(void)
+{
+ return 0;
+}
+
+uint64_t __weak arch__reg_sp(void)
+{
+ return 0;
+}
+
#ifdef HAVE_PERF_REGS_SUPPORT

const char *perf_reg_name(int id, const char *arch)
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index ab4ec3f2a170..0a1460aaad37 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -26,13 +26,15 @@ enum {
int arch_sdt_arg_parse_op(char *old_op, char **new_op);
uint64_t arch__intr_reg_mask(void);
uint64_t arch__user_reg_mask(void);
+uint64_t arch__reg_ip(void);
+uint64_t arch__reg_sp(void);

#ifdef HAVE_PERF_REGS_SUPPORT
extern const struct sample_reg sample_reg_masks[];

#include <perf_regs.h>

-#define DWARF_MINIMAL_REGS ((1ULL << PERF_REG_IP) | (1ULL << PERF_REG_SP))
+#define DWARF_MINIMAL_REGS ((1ULL << arch__reg_ip()) | (1ULL << arch__reg_sp()))

const char *perf_reg_name(int id, const char *arch);
int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index bdccfc511b7e..f308f2ea512b 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -252,7 +252,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
if (!ui->dwfl)
goto out;

- err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
+ err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip());
if (err)
goto out;

diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index b2a03fa5289b..0a98ea9d8c94 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -43,11 +43,11 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
#endif

#ifndef LIBUNWIND__ARCH_REG_SP
-#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP
+#define LIBUNWIND__ARCH_REG_SP arch__reg_sp()
#endif

#ifndef LIBUNWIND__ARCH_REG_IP
-#define LIBUNWIND__ARCH_REG_IP PERF_REG_IP
+#define LIBUNWIND__ARCH_REG_IP arch__reg_ip()
#endif

int LIBUNWIND__ARCH_REG_ID(int regnum);
--
2.39.2


2023-05-20 02:58:09

by Leo Yan

[permalink] [raw]
Subject: [PATCH v1 3/5] perf parse-regs: Remove unused macros PERF_REG_{IP|SP}

The macros PERF_REG_{IP|SP} have been replaced by arch__reg_{ip|sp}()
respectively, remove them!

Signed-off-by: Leo Yan <[email protected]>
---
tools/perf/arch/arm/include/perf_regs.h | 3 ---
tools/perf/arch/arm64/include/perf_regs.h | 3 ---
tools/perf/arch/csky/include/perf_regs.h | 3 ---
tools/perf/arch/mips/include/perf_regs.h | 2 --
tools/perf/arch/powerpc/include/perf_regs.h | 3 ---
tools/perf/arch/riscv/include/perf_regs.h | 3 ---
tools/perf/arch/s390/include/perf_regs.h | 3 ---
tools/perf/arch/x86/include/perf_regs.h | 2 --
8 files changed, 22 deletions(-)

diff --git a/tools/perf/arch/arm/include/perf_regs.h b/tools/perf/arch/arm/include/perf_regs.h
index 99a06550e25d..75ce1c370114 100644
--- a/tools/perf/arch/arm/include/perf_regs.h
+++ b/tools/perf/arch/arm/include/perf_regs.h
@@ -12,7 +12,4 @@ void perf_regs_load(u64 *regs);
#define PERF_REGS_MAX PERF_REG_ARM_MAX
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32

-#define PERF_REG_IP PERF_REG_ARM_PC
-#define PERF_REG_SP PERF_REG_ARM_SP
-
#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index 35a3cc775b39..58639ee9f7ea 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -14,7 +14,4 @@ void perf_regs_load(u64 *regs);
#define PERF_REGS_MAX PERF_REG_ARM64_MAX
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64

-#define PERF_REG_IP PERF_REG_ARM64_PC
-#define PERF_REG_SP PERF_REG_ARM64_SP
-
#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/csky/include/perf_regs.h b/tools/perf/arch/csky/include/perf_regs.h
index 1afcc0e916c2..076c7746c8a2 100644
--- a/tools/perf/arch/csky/include/perf_regs.h
+++ b/tools/perf/arch/csky/include/perf_regs.h
@@ -12,7 +12,4 @@
#define PERF_REGS_MAX PERF_REG_CSKY_MAX
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32

-#define PERF_REG_IP PERF_REG_CSKY_PC
-#define PERF_REG_SP PERF_REG_CSKY_SP
-
#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/mips/include/perf_regs.h b/tools/perf/arch/mips/include/perf_regs.h
index b8cd8bbb37ba..7082e91e0ed1 100644
--- a/tools/perf/arch/mips/include/perf_regs.h
+++ b/tools/perf/arch/mips/include/perf_regs.h
@@ -7,8 +7,6 @@
#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)

diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
index 9bb17c3f370b..1c66f6ba6773 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -16,7 +16,4 @@ void perf_regs_load(u64 *regs);
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
#endif

-#define PERF_REG_IP PERF_REG_POWERPC_NIP
-#define PERF_REG_SP PERF_REG_POWERPC_R1
-
#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/riscv/include/perf_regs.h b/tools/perf/arch/riscv/include/perf_regs.h
index 6944bf0de53e..d482edb413e5 100644
--- a/tools/perf/arch/riscv/include/perf_regs.h
+++ b/tools/perf/arch/riscv/include/perf_regs.h
@@ -16,7 +16,4 @@
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
#endif

-#define PERF_REG_IP PERF_REG_RISCV_PC
-#define PERF_REG_SP PERF_REG_RISCV_SP
-
#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/s390/include/perf_regs.h b/tools/perf/arch/s390/include/perf_regs.h
index 52fcc0891da6..130dfad2b96a 100644
--- a/tools/perf/arch/s390/include/perf_regs.h
+++ b/tools/perf/arch/s390/include/perf_regs.h
@@ -11,7 +11,4 @@ void perf_regs_load(u64 *regs);
#define PERF_REGS_MAX PERF_REG_S390_MAX
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64

-#define PERF_REG_IP PERF_REG_S390_PC
-#define PERF_REG_SP PERF_REG_S390_R15
-
#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 16e23b722042..f209ce2c1dd9 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -20,7 +20,5 @@ void perf_regs_load(u64 *regs);
#define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT)
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
#endif
-#define PERF_REG_IP PERF_REG_X86_IP
-#define PERF_REG_SP PERF_REG_X86_SP

#endif /* ARCH_PERF_REGS_H */
--
2.39.2


2023-05-20 03:24:09

by Leo Yan

[permalink] [raw]
Subject: [PATCH v1 5/5] perf parse-regs: Move out arch specific header from util/perf_regs.h

util/perf_regs.h includes another perf_regs.h:

#include <perf_regs.h>

Here it includes architecture specific header, for example, if we build
arm64 target, the header tools/perf/arch/arm64/include/perf_regs.h is
included.

We use this implicit way to include architecture specific header, which
is not directive; furthermore, util/perf_regs.c is coupled with the
architecture specific definitions.

This patch moves out arch specific header from util/perf_regs.h for
generalizing the 'util' folder, as a result, the source files in 'arch'
folder explicitly include architecture's perf_regs.h.

Signed-off-by: Leo Yan <[email protected]>
---
tools/perf/arch/arm/util/perf_regs.c | 1 +
tools/perf/arch/arm/util/unwind-libdw.c | 1 +
tools/perf/arch/arm64/util/machine.c | 1 +
tools/perf/arch/arm64/util/perf_regs.c | 1 +
tools/perf/arch/arm64/util/unwind-libdw.c | 1 +
tools/perf/arch/csky/util/perf_regs.c | 1 +
tools/perf/arch/csky/util/unwind-libdw.c | 1 +
tools/perf/arch/mips/util/perf_regs.c | 1 +
tools/perf/arch/powerpc/util/perf_regs.c | 1 +
tools/perf/arch/powerpc/util/unwind-libdw.c | 1 +
tools/perf/arch/riscv/util/perf_regs.c | 1 +
tools/perf/arch/riscv/util/unwind-libdw.c | 1 +
tools/perf/arch/s390/util/perf_regs.c | 1 +
tools/perf/arch/s390/util/unwind-libdw.c | 1 +
tools/perf/arch/x86/util/perf_regs.c | 1 +
tools/perf/arch/x86/util/unwind-libdw.c | 1 +
tools/perf/util/perf_regs.h | 2 --
17 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/perf/arch/arm/util/perf_regs.c b/tools/perf/arch/arm/util/perf_regs.c
index 0d669dba08c4..244c1d0a46ac 100644
--- a/tools/perf/arch/arm/util/perf_regs.c
+++ b/tools/perf/arch/arm/util/perf_regs.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "perf_regs.h"
#include "../../../util/perf_regs.h"

const struct sample_reg sample_reg_masks[] = {
diff --git a/tools/perf/arch/arm/util/unwind-libdw.c b/tools/perf/arch/arm/util/unwind-libdw.c
index 1834a0cd9ce3..4e02cef461e3 100644
--- a/tools/perf/arch/arm/util/unwind-libdw.c
+++ b/tools/perf/arch/arm/util/unwind-libdw.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <elfutils/libdwfl.h>
+#include "perf_regs.h"
#include "../../../util/unwind-libdw.h"
#include "../../../util/perf_regs.h"
#include "../../../util/sample.h"
diff --git a/tools/perf/arch/arm64/util/machine.c b/tools/perf/arch/arm64/util/machine.c
index 235a0a1e1ec7..ba1144366e85 100644
--- a/tools/perf/arch/arm64/util/machine.c
+++ b/tools/perf/arch/arm64/util/machine.c
@@ -6,6 +6,7 @@
#include "debug.h"
#include "symbol.h"
#include "callchain.h"
+#include "perf_regs.h"
#include "record.h"
#include "util/perf_regs.h"

diff --git a/tools/perf/arch/arm64/util/perf_regs.c b/tools/perf/arch/arm64/util/perf_regs.c
index 4490c1b5ea51..34d957c750f7 100644
--- a/tools/perf/arch/arm64/util/perf_regs.c
+++ b/tools/perf/arch/arm64/util/perf_regs.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>

+#include "perf_regs.h"
#include "../../../perf-sys.h"
#include "../../../util/debug.h"
#include "../../../util/event.h"
diff --git a/tools/perf/arch/arm64/util/unwind-libdw.c b/tools/perf/arch/arm64/util/unwind-libdw.c
index 09385081bb03..e056d50ab42e 100644
--- a/tools/perf/arch/arm64/util/unwind-libdw.c
+++ b/tools/perf/arch/arm64/util/unwind-libdw.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <elfutils/libdwfl.h>
+#include "perf_regs.h"
#include "../../../util/unwind-libdw.h"
#include "../../../util/perf_regs.h"
#include "../../../util/sample.h"
diff --git a/tools/perf/arch/csky/util/perf_regs.c b/tools/perf/arch/csky/util/perf_regs.c
index 35755811316e..053ecbbc7b2f 100644
--- a/tools/perf/arch/csky/util/perf_regs.c
+++ b/tools/perf/arch/csky/util/perf_regs.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "perf_regs.h"
#include "../../util/perf_regs.h"

const struct sample_reg sample_reg_masks[] = {
diff --git a/tools/perf/arch/csky/util/unwind-libdw.c b/tools/perf/arch/csky/util/unwind-libdw.c
index 4bb4a06776e4..79df4374ab18 100644
--- a/tools/perf/arch/csky/util/unwind-libdw.c
+++ b/tools/perf/arch/csky/util/unwind-libdw.c
@@ -2,6 +2,7 @@
// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.

#include <elfutils/libdwfl.h>
+#include "perf_regs.h"
#include "../../util/unwind-libdw.h"
#include "../../util/perf_regs.h"
#include "../../util/event.h"
diff --git a/tools/perf/arch/mips/util/perf_regs.c b/tools/perf/arch/mips/util/perf_regs.c
index 2d2bfbb96182..751413b86ebf 100644
--- a/tools/perf/arch/mips/util/perf_regs.c
+++ b/tools/perf/arch/mips/util/perf_regs.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "perf_regs.h"
#include "../../util/perf_regs.h"

const struct sample_reg sample_reg_masks[] = {
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index e48622d1bc59..3d0f7c238a33 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -4,6 +4,7 @@
#include <regex.h>
#include <linux/zalloc.h>

+#include "perf_regs.h"
#include "../../../util/perf_regs.h"
#include "../../../util/debug.h"
#include "../../../util/event.h"
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c b/tools/perf/arch/powerpc/util/unwind-libdw.c
index e616642c754c..e9a5a8bb67d9 100644
--- a/tools/perf/arch/powerpc/util/unwind-libdw.c
+++ b/tools/perf/arch/powerpc/util/unwind-libdw.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <elfutils/libdwfl.h>
#include <linux/kernel.h>
+#include "perf_regs.h"
#include "../../../util/unwind-libdw.h"
#include "../../../util/perf_regs.h"
#include "../../../util/sample.h"
diff --git a/tools/perf/arch/riscv/util/perf_regs.c b/tools/perf/arch/riscv/util/perf_regs.c
index a2aaa46ef741..7b8fafd0598a 100644
--- a/tools/perf/arch/riscv/util/perf_regs.c
+++ b/tools/perf/arch/riscv/util/perf_regs.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "perf_regs.h"
#include "../../util/perf_regs.h"

const struct sample_reg sample_reg_masks[] = {
diff --git a/tools/perf/arch/riscv/util/unwind-libdw.c b/tools/perf/arch/riscv/util/unwind-libdw.c
index 54a198714eb8..5c98010d8b59 100644
--- a/tools/perf/arch/riscv/util/unwind-libdw.c
+++ b/tools/perf/arch/riscv/util/unwind-libdw.c
@@ -2,6 +2,7 @@
/* Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. */

#include <elfutils/libdwfl.h>
+#include "perf_regs.h"
#include "../../util/unwind-libdw.h"
#include "../../util/perf_regs.h"
#include "../../util/sample.h"
diff --git a/tools/perf/arch/s390/util/perf_regs.c b/tools/perf/arch/s390/util/perf_regs.c
index 8d79f8c50f4c..0a6358cedb93 100644
--- a/tools/perf/arch/s390/util/perf_regs.c
+++ b/tools/perf/arch/s390/util/perf_regs.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include "perf_regs.h"
#include "../../util/perf_regs.h"

const struct sample_reg sample_reg_masks[] = {
diff --git a/tools/perf/arch/s390/util/unwind-libdw.c b/tools/perf/arch/s390/util/unwind-libdw.c
index 7d92452d5287..f50fb6dbb35c 100644
--- a/tools/perf/arch/s390/util/unwind-libdw.c
+++ b/tools/perf/arch/s390/util/unwind-libdw.c
@@ -5,6 +5,7 @@
#include "../../util/event.h"
#include "../../util/sample.h"
#include "dwarf-regs-table.h"
+#include "perf_regs.h"


bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index a7e21f2a8964..aaf7f606606b 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -5,6 +5,7 @@
#include <linux/kernel.h>
#include <linux/zalloc.h>

+#include "perf_regs.h"
#include "../../../perf-sys.h"
#include "../../../util/perf_regs.h"
#include "../../../util/debug.h"
diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c
index ef71e8bf80bf..edb77e20e083 100644
--- a/tools/perf/arch/x86/util/unwind-libdw.c
+++ b/tools/perf/arch/x86/util/unwind-libdw.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <elfutils/libdwfl.h>
+#include "perf_regs.h"
#include "../../../util/unwind-libdw.h"
#include "../../../util/perf_regs.h"
#include "util/sample.h"
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 43b5a6d40e58..894d527edebe 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -32,8 +32,6 @@ uint64_t arch__reg_sp(void);
#ifdef HAVE_PERF_REGS_SUPPORT
extern const struct sample_reg sample_reg_masks[];

-#include <perf_regs.h>
-
#define DWARF_MINIMAL_REGS ((1ULL << arch__reg_ip()) | (1ULL << arch__reg_sp()))

const char *perf_reg_name(int id, const char *arch);
--
2.39.2


2023-05-20 03:24:12

by Leo Yan

[permalink] [raw]
Subject: [PATCH v1 4/5] perf parse-regs: Remove PERF_REGS_{MAX|MASK} from common code

The macros PERF_REGS_MAX and PERF_REGS_MASK are architecture specific,
let's remove them from the common file util/perf_regs.c.

As a side effect, the weak functions arch__intr_reg_mask() and
arch__user_reg_mask() just return zeros, every arch defines its own
functions in the 'arch' folder for returning right values.

Signed-off-by: Leo Yan <[email protected]>
---
tools/perf/arch/arm/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/arm64/util/perf_regs.c | 5 +++++
tools/perf/arch/csky/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/mips/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/powerpc/util/perf_regs.c | 5 +++++
tools/perf/arch/riscv/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/s390/util/perf_regs.c | 10 ++++++++++
tools/perf/arch/x86/util/perf_regs.c | 5 +++++
tools/perf/util/evsel.c | 2 +-
tools/perf/util/perf_regs.c | 4 ++--
tools/perf/util/perf_regs.h | 4 +---
11 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/tools/perf/arch/arm/util/perf_regs.c b/tools/perf/arch/arm/util/perf_regs.c
index 37aa3a2091bd..0d669dba08c4 100644
--- a/tools/perf/arch/arm/util/perf_regs.c
+++ b/tools/perf/arch/arm/util/perf_regs.c
@@ -5,6 +5,16 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};

+uint64_t arch__intr_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_ARM_PC;
diff --git a/tools/perf/arch/arm64/util/perf_regs.c b/tools/perf/arch/arm64/util/perf_regs.c
index dbe7f00b222b..4490c1b5ea51 100644
--- a/tools/perf/arch/arm64/util/perf_regs.c
+++ b/tools/perf/arch/arm64/util/perf_regs.c
@@ -139,6 +139,11 @@ int arch_sdt_arg_parse_op(char *old_op, char **new_op)
return SDT_ARG_VALID;
}

+uint64_t arch__intr_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__user_reg_mask(void)
{
struct perf_event_attr attr = {
diff --git a/tools/perf/arch/csky/util/perf_regs.c b/tools/perf/arch/csky/util/perf_regs.c
index d230d7e640fd..35755811316e 100644
--- a/tools/perf/arch/csky/util/perf_regs.c
+++ b/tools/perf/arch/csky/util/perf_regs.c
@@ -5,6 +5,16 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};

+uint64_t arch__intr_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_CSKY_PC;
diff --git a/tools/perf/arch/mips/util/perf_regs.c b/tools/perf/arch/mips/util/perf_regs.c
index 64882ebc9287..2d2bfbb96182 100644
--- a/tools/perf/arch/mips/util/perf_regs.c
+++ b/tools/perf/arch/mips/util/perf_regs.c
@@ -5,6 +5,16 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};

+uint64_t arch__intr_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_MIPS_PC;
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index c84cd79986a8..e48622d1bc59 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -227,6 +227,11 @@ uint64_t arch__intr_reg_mask(void)
return mask;
}

+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_POWERPC_NIP;
diff --git a/tools/perf/arch/riscv/util/perf_regs.c b/tools/perf/arch/riscv/util/perf_regs.c
index 13bbddd139d0..a2aaa46ef741 100644
--- a/tools/perf/arch/riscv/util/perf_regs.c
+++ b/tools/perf/arch/riscv/util/perf_regs.c
@@ -5,6 +5,16 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};

+uint64_t arch__intr_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_RISCV_PC;
diff --git a/tools/perf/arch/s390/util/perf_regs.c b/tools/perf/arch/s390/util/perf_regs.c
index 9b2297471090..8d79f8c50f4c 100644
--- a/tools/perf/arch/s390/util/perf_regs.c
+++ b/tools/perf/arch/s390/util/perf_regs.c
@@ -5,6 +5,16 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG_END
};

+uint64_t arch__intr_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_S390_PC;
diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c752a6e9cba6..a7e21f2a8964 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -313,6 +313,11 @@ uint64_t arch__intr_reg_mask(void)
return PERF_REGS_MASK;
}

+uint64_t arch__user_reg_mask(void)
+{
+ return PERF_REGS_MASK;
+}
+
uint64_t arch__reg_ip(void)
{
return PERF_REG_X86_IP;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 356c07f03be6..bef415072a27 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -933,7 +933,7 @@ static void __evsel__config_callchain(struct evsel *evsel, struct record_opts *o
if (!function) {
evsel__set_sample_bit(evsel, REGS_USER);
evsel__set_sample_bit(evsel, STACK_USER);
- if (opts->sample_user_regs && DWARF_MINIMAL_REGS != PERF_REGS_MASK) {
+ if (opts->sample_user_regs && DWARF_MINIMAL_REGS != arch__user_reg_mask()) {
attr->sample_regs_user |= DWARF_MINIMAL_REGS;
pr_warning("WARNING: The use of --call-graph=dwarf may require all the user registers, "
"specifying a subset with --user-regs may render DWARF unwinding unreliable, "
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 334c9a2b785d..6698b9d2b32a 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -12,12 +12,12 @@ int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,

uint64_t __weak arch__intr_reg_mask(void)
{
- return PERF_REGS_MASK;
+ return 0;
}

uint64_t __weak arch__user_reg_mask(void)
{
- return PERF_REGS_MASK;
+ return 0;
}

uint64_t __weak arch__reg_ip(void)
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 0a1460aaad37..43b5a6d40e58 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -48,10 +48,8 @@ const char *__perf_reg_name_s390(int id);
const char *__perf_reg_name_x86(int id);

#else
-#define PERF_REGS_MASK 0
-#define PERF_REGS_MAX 0

-#define DWARF_MINIMAL_REGS PERF_REGS_MASK
+#define DWARF_MINIMAL_REGS 0

static inline const char *perf_reg_name(int id __maybe_unused, const char *arch __maybe_unused)
{
--
2.39.2


2023-05-20 03:24:56

by Leo Yan

[permalink] [raw]
Subject: [PATCH v1 1/5] perf parse-regs: Refactor arch register parsing functions

Every architecture has a specific register parsing function for
returning register name based on register index, to support cross
analysis (e.g. we use perf x86 binary to parse Arm64's perf data), we
build all these register parsing functions into the tool, this is why
we place all related functions into util/perf_regs.c.

Unfortunately, since util/perf_regs.c needs to include every arch's
perf_regs.h, this easily introduces duplicated definitions coming from
multiple headers, finally it's fragile for building and difficult for
maintenance.

We cannot simply move these register parsing functions into the
corresponding 'arch' folder, the folder is only conditionally built
based on the target architecture.

Therefore, this commit creates a new folder util/perf-regs-arch/ and
uses a dedicated source file to keep every architecture's register
parsing function to avoid definition conflicts.

This is only a refactoring, no functionality change is expected.

Signed-off-by: Leo Yan <[email protected]>
---
tools/perf/util/Build | 1 +
tools/perf/util/perf-regs-arch/Build | 8 +
.../util/perf-regs-arch/perf_regs_aarch64.c | 86 +++
.../perf/util/perf-regs-arch/perf_regs_arm.c | 50 ++
.../perf/util/perf-regs-arch/perf_regs_csky.c | 90 +++
.../perf/util/perf-regs-arch/perf_regs_mips.c | 77 +++
.../util/perf-regs-arch/perf_regs_powerpc.c | 135 ++++
.../util/perf-regs-arch/perf_regs_riscv.c | 82 +++
.../perf/util/perf-regs-arch/perf_regs_s390.c | 86 +++
.../perf/util/perf-regs-arch/perf_regs_x86.c | 88 +++
tools/perf/util/perf_regs.c | 642 ------------------
tools/perf/util/perf_regs.h | 8 +
12 files changed, 711 insertions(+), 642 deletions(-)
create mode 100644 tools/perf/util/perf-regs-arch/Build
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_aarch64.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_arm.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_csky.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_mips.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_powerpc.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_riscv.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_s390.c
create mode 100644 tools/perf/util/perf-regs-arch/perf_regs_x86.c

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index bd18fe5f2719..82b2d6b8d68c 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -28,6 +28,7 @@ perf-y += parse-events-hybrid.o
perf-y += print-events.o
perf-y += tracepoint.o
perf-y += perf_regs.o
+perf-y += perf-regs-arch/
perf-y += path.o
perf-y += print_binary.o
perf-y += rlimit.o
diff --git a/tools/perf/util/perf-regs-arch/Build b/tools/perf/util/perf-regs-arch/Build
new file mode 100644
index 000000000000..5f1ac8063548
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/Build
@@ -0,0 +1,8 @@
+perf-y += perf_regs_aarch64.o
+perf-y += perf_regs_arm.o
+perf-y += perf_regs_csky.o
+perf-y += perf_regs_mips.o
+perf-y += perf_regs_powerpc.o
+perf-y += perf_regs_riscv.o
+perf-y += perf_regs_s390.o
+perf-y += perf_regs_x86.o
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_aarch64.c b/tools/perf/util/perf-regs-arch/perf_regs_aarch64.c
new file mode 100644
index 000000000000..c02c045af46e
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_aarch64.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/arm64/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_arm64(int id)
+{
+ switch (id) {
+ case PERF_REG_ARM64_X0:
+ return "x0";
+ case PERF_REG_ARM64_X1:
+ return "x1";
+ case PERF_REG_ARM64_X2:
+ return "x2";
+ case PERF_REG_ARM64_X3:
+ return "x3";
+ case PERF_REG_ARM64_X4:
+ return "x4";
+ case PERF_REG_ARM64_X5:
+ return "x5";
+ case PERF_REG_ARM64_X6:
+ return "x6";
+ case PERF_REG_ARM64_X7:
+ return "x7";
+ case PERF_REG_ARM64_X8:
+ return "x8";
+ case PERF_REG_ARM64_X9:
+ return "x9";
+ case PERF_REG_ARM64_X10:
+ return "x10";
+ case PERF_REG_ARM64_X11:
+ return "x11";
+ case PERF_REG_ARM64_X12:
+ return "x12";
+ case PERF_REG_ARM64_X13:
+ return "x13";
+ case PERF_REG_ARM64_X14:
+ return "x14";
+ case PERF_REG_ARM64_X15:
+ return "x15";
+ case PERF_REG_ARM64_X16:
+ return "x16";
+ case PERF_REG_ARM64_X17:
+ return "x17";
+ case PERF_REG_ARM64_X18:
+ return "x18";
+ case PERF_REG_ARM64_X19:
+ return "x19";
+ case PERF_REG_ARM64_X20:
+ return "x20";
+ case PERF_REG_ARM64_X21:
+ return "x21";
+ case PERF_REG_ARM64_X22:
+ return "x22";
+ case PERF_REG_ARM64_X23:
+ return "x23";
+ case PERF_REG_ARM64_X24:
+ return "x24";
+ case PERF_REG_ARM64_X25:
+ return "x25";
+ case PERF_REG_ARM64_X26:
+ return "x26";
+ case PERF_REG_ARM64_X27:
+ return "x27";
+ case PERF_REG_ARM64_X28:
+ return "x28";
+ case PERF_REG_ARM64_X29:
+ return "x29";
+ case PERF_REG_ARM64_SP:
+ return "sp";
+ case PERF_REG_ARM64_LR:
+ return "lr";
+ case PERF_REG_ARM64_PC:
+ return "pc";
+ case PERF_REG_ARM64_VG:
+ return "vg";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_arm.c b/tools/perf/util/perf-regs-arch/perf_regs_arm.c
new file mode 100644
index 000000000000..e8b0fcd72f34
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_arm.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/arm/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_arm(int id)
+{
+ switch (id) {
+ case PERF_REG_ARM_R0:
+ return "r0";
+ case PERF_REG_ARM_R1:
+ return "r1";
+ case PERF_REG_ARM_R2:
+ return "r2";
+ case PERF_REG_ARM_R3:
+ return "r3";
+ case PERF_REG_ARM_R4:
+ return "r4";
+ case PERF_REG_ARM_R5:
+ return "r5";
+ case PERF_REG_ARM_R6:
+ return "r6";
+ case PERF_REG_ARM_R7:
+ return "r7";
+ case PERF_REG_ARM_R8:
+ return "r8";
+ case PERF_REG_ARM_R9:
+ return "r9";
+ case PERF_REG_ARM_R10:
+ return "r10";
+ case PERF_REG_ARM_FP:
+ return "fp";
+ case PERF_REG_ARM_IP:
+ return "ip";
+ case PERF_REG_ARM_SP:
+ return "sp";
+ case PERF_REG_ARM_LR:
+ return "lr";
+ case PERF_REG_ARM_PC:
+ return "pc";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_csky.c b/tools/perf/util/perf-regs-arch/perf_regs_csky.c
new file mode 100644
index 000000000000..e343b1cef7ba
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_csky.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../arch/csky/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_csky(int id)
+{
+ switch (id) {
+ case PERF_REG_CSKY_A0:
+ return "a0";
+ case PERF_REG_CSKY_A1:
+ return "a1";
+ case PERF_REG_CSKY_A2:
+ return "a2";
+ case PERF_REG_CSKY_A3:
+ return "a3";
+ case PERF_REG_CSKY_REGS0:
+ return "regs0";
+ case PERF_REG_CSKY_REGS1:
+ return "regs1";
+ case PERF_REG_CSKY_REGS2:
+ return "regs2";
+ case PERF_REG_CSKY_REGS3:
+ return "regs3";
+ case PERF_REG_CSKY_REGS4:
+ return "regs4";
+ case PERF_REG_CSKY_REGS5:
+ return "regs5";
+ case PERF_REG_CSKY_REGS6:
+ return "regs6";
+ case PERF_REG_CSKY_REGS7:
+ return "regs7";
+ case PERF_REG_CSKY_REGS8:
+ return "regs8";
+ case PERF_REG_CSKY_REGS9:
+ return "regs9";
+ case PERF_REG_CSKY_SP:
+ return "sp";
+ case PERF_REG_CSKY_LR:
+ return "lr";
+ case PERF_REG_CSKY_PC:
+ return "pc";
+#if defined(__CSKYABIV2__)
+ case PERF_REG_CSKY_EXREGS0:
+ return "exregs0";
+ case PERF_REG_CSKY_EXREGS1:
+ return "exregs1";
+ case PERF_REG_CSKY_EXREGS2:
+ return "exregs2";
+ case PERF_REG_CSKY_EXREGS3:
+ return "exregs3";
+ case PERF_REG_CSKY_EXREGS4:
+ return "exregs4";
+ case PERF_REG_CSKY_EXREGS5:
+ return "exregs5";
+ case PERF_REG_CSKY_EXREGS6:
+ return "exregs6";
+ case PERF_REG_CSKY_EXREGS7:
+ return "exregs7";
+ case PERF_REG_CSKY_EXREGS8:
+ return "exregs8";
+ case PERF_REG_CSKY_EXREGS9:
+ return "exregs9";
+ case PERF_REG_CSKY_EXREGS10:
+ return "exregs10";
+ case PERF_REG_CSKY_EXREGS11:
+ return "exregs11";
+ case PERF_REG_CSKY_EXREGS12:
+ return "exregs12";
+ case PERF_REG_CSKY_EXREGS13:
+ return "exregs13";
+ case PERF_REG_CSKY_EXREGS14:
+ return "exregs14";
+ case PERF_REG_CSKY_TLS:
+ return "tls";
+ case PERF_REG_CSKY_HI:
+ return "hi";
+ case PERF_REG_CSKY_LO:
+ return "lo";
+#endif
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_mips.c b/tools/perf/util/perf-regs-arch/perf_regs_mips.c
new file mode 100644
index 000000000000..f48fbca2f947
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_mips.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/mips/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_mips(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
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_powerpc.c b/tools/perf/util/perf-regs-arch/perf_regs_powerpc.c
new file mode 100644
index 000000000000..dda1b4b169fc
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_powerpc.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/powerpc/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_powerpc(int id)
+{
+ switch (id) {
+ case PERF_REG_POWERPC_R0:
+ return "r0";
+ case PERF_REG_POWERPC_R1:
+ return "r1";
+ case PERF_REG_POWERPC_R2:
+ return "r2";
+ case PERF_REG_POWERPC_R3:
+ return "r3";
+ case PERF_REG_POWERPC_R4:
+ return "r4";
+ case PERF_REG_POWERPC_R5:
+ return "r5";
+ case PERF_REG_POWERPC_R6:
+ return "r6";
+ case PERF_REG_POWERPC_R7:
+ return "r7";
+ case PERF_REG_POWERPC_R8:
+ return "r8";
+ case PERF_REG_POWERPC_R9:
+ return "r9";
+ case PERF_REG_POWERPC_R10:
+ return "r10";
+ case PERF_REG_POWERPC_R11:
+ return "r11";
+ case PERF_REG_POWERPC_R12:
+ return "r12";
+ case PERF_REG_POWERPC_R13:
+ return "r13";
+ case PERF_REG_POWERPC_R14:
+ return "r14";
+ case PERF_REG_POWERPC_R15:
+ return "r15";
+ case PERF_REG_POWERPC_R16:
+ return "r16";
+ case PERF_REG_POWERPC_R17:
+ return "r17";
+ case PERF_REG_POWERPC_R18:
+ return "r18";
+ case PERF_REG_POWERPC_R19:
+ return "r19";
+ case PERF_REG_POWERPC_R20:
+ return "r20";
+ case PERF_REG_POWERPC_R21:
+ return "r21";
+ case PERF_REG_POWERPC_R22:
+ return "r22";
+ case PERF_REG_POWERPC_R23:
+ return "r23";
+ case PERF_REG_POWERPC_R24:
+ return "r24";
+ case PERF_REG_POWERPC_R25:
+ return "r25";
+ case PERF_REG_POWERPC_R26:
+ return "r26";
+ case PERF_REG_POWERPC_R27:
+ return "r27";
+ case PERF_REG_POWERPC_R28:
+ return "r28";
+ case PERF_REG_POWERPC_R29:
+ return "r29";
+ case PERF_REG_POWERPC_R30:
+ return "r30";
+ case PERF_REG_POWERPC_R31:
+ return "r31";
+ case PERF_REG_POWERPC_NIP:
+ return "nip";
+ case PERF_REG_POWERPC_MSR:
+ return "msr";
+ case PERF_REG_POWERPC_ORIG_R3:
+ return "orig_r3";
+ case PERF_REG_POWERPC_CTR:
+ return "ctr";
+ case PERF_REG_POWERPC_LINK:
+ return "link";
+ case PERF_REG_POWERPC_XER:
+ return "xer";
+ case PERF_REG_POWERPC_CCR:
+ return "ccr";
+ case PERF_REG_POWERPC_SOFTE:
+ return "softe";
+ case PERF_REG_POWERPC_TRAP:
+ return "trap";
+ case PERF_REG_POWERPC_DAR:
+ return "dar";
+ case PERF_REG_POWERPC_DSISR:
+ return "dsisr";
+ case PERF_REG_POWERPC_SIER:
+ return "sier";
+ case PERF_REG_POWERPC_MMCRA:
+ return "mmcra";
+ case PERF_REG_POWERPC_MMCR0:
+ return "mmcr0";
+ case PERF_REG_POWERPC_MMCR1:
+ return "mmcr1";
+ case PERF_REG_POWERPC_MMCR2:
+ return "mmcr2";
+ case PERF_REG_POWERPC_MMCR3:
+ return "mmcr3";
+ case PERF_REG_POWERPC_SIER2:
+ return "sier2";
+ case PERF_REG_POWERPC_SIER3:
+ return "sier3";
+ case PERF_REG_POWERPC_PMC1:
+ return "pmc1";
+ case PERF_REG_POWERPC_PMC2:
+ return "pmc2";
+ case PERF_REG_POWERPC_PMC3:
+ return "pmc3";
+ case PERF_REG_POWERPC_PMC4:
+ return "pmc4";
+ case PERF_REG_POWERPC_PMC5:
+ return "pmc5";
+ case PERF_REG_POWERPC_PMC6:
+ return "pmc6";
+ case PERF_REG_POWERPC_SDAR:
+ return "sdar";
+ case PERF_REG_POWERPC_SIAR:
+ return "siar";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_riscv.c b/tools/perf/util/perf-regs-arch/perf_regs_riscv.c
new file mode 100644
index 000000000000..c504b047cac2
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_riscv.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/riscv/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_riscv(int id)
+{
+ switch (id) {
+ case PERF_REG_RISCV_PC:
+ return "pc";
+ case PERF_REG_RISCV_RA:
+ return "ra";
+ case PERF_REG_RISCV_SP:
+ return "sp";
+ case PERF_REG_RISCV_GP:
+ return "gp";
+ case PERF_REG_RISCV_TP:
+ return "tp";
+ case PERF_REG_RISCV_T0:
+ return "t0";
+ case PERF_REG_RISCV_T1:
+ return "t1";
+ case PERF_REG_RISCV_T2:
+ return "t2";
+ case PERF_REG_RISCV_S0:
+ return "s0";
+ case PERF_REG_RISCV_S1:
+ return "s1";
+ case PERF_REG_RISCV_A0:
+ return "a0";
+ case PERF_REG_RISCV_A1:
+ return "a1";
+ case PERF_REG_RISCV_A2:
+ return "a2";
+ case PERF_REG_RISCV_A3:
+ return "a3";
+ case PERF_REG_RISCV_A4:
+ return "a4";
+ case PERF_REG_RISCV_A5:
+ return "a5";
+ case PERF_REG_RISCV_A6:
+ return "a6";
+ case PERF_REG_RISCV_A7:
+ return "a7";
+ case PERF_REG_RISCV_S2:
+ return "s2";
+ case PERF_REG_RISCV_S3:
+ return "s3";
+ case PERF_REG_RISCV_S4:
+ return "s4";
+ case PERF_REG_RISCV_S5:
+ return "s5";
+ case PERF_REG_RISCV_S6:
+ return "s6";
+ case PERF_REG_RISCV_S7:
+ return "s7";
+ case PERF_REG_RISCV_S8:
+ return "s8";
+ case PERF_REG_RISCV_S9:
+ return "s9";
+ case PERF_REG_RISCV_S10:
+ return "s10";
+ case PERF_REG_RISCV_S11:
+ return "s11";
+ case PERF_REG_RISCV_T3:
+ return "t3";
+ case PERF_REG_RISCV_T4:
+ return "t4";
+ case PERF_REG_RISCV_T5:
+ return "t5";
+ case PERF_REG_RISCV_T6:
+ return "t6";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_s390.c b/tools/perf/util/perf-regs-arch/perf_regs_s390.c
new file mode 100644
index 000000000000..e71e2302394c
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_s390.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/s390/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_s390(int id)
+{
+ switch (id) {
+ case PERF_REG_S390_R0:
+ return "R0";
+ case PERF_REG_S390_R1:
+ return "R1";
+ case PERF_REG_S390_R2:
+ return "R2";
+ case PERF_REG_S390_R3:
+ return "R3";
+ case PERF_REG_S390_R4:
+ return "R4";
+ case PERF_REG_S390_R5:
+ return "R5";
+ case PERF_REG_S390_R6:
+ return "R6";
+ case PERF_REG_S390_R7:
+ return "R7";
+ case PERF_REG_S390_R8:
+ return "R8";
+ case PERF_REG_S390_R9:
+ return "R9";
+ case PERF_REG_S390_R10:
+ return "R10";
+ case PERF_REG_S390_R11:
+ return "R11";
+ case PERF_REG_S390_R12:
+ return "R12";
+ case PERF_REG_S390_R13:
+ return "R13";
+ case PERF_REG_S390_R14:
+ return "R14";
+ case PERF_REG_S390_R15:
+ return "R15";
+ case PERF_REG_S390_FP0:
+ return "FP0";
+ case PERF_REG_S390_FP1:
+ return "FP1";
+ case PERF_REG_S390_FP2:
+ return "FP2";
+ case PERF_REG_S390_FP3:
+ return "FP3";
+ case PERF_REG_S390_FP4:
+ return "FP4";
+ case PERF_REG_S390_FP5:
+ return "FP5";
+ case PERF_REG_S390_FP6:
+ return "FP6";
+ case PERF_REG_S390_FP7:
+ return "FP7";
+ case PERF_REG_S390_FP8:
+ return "FP8";
+ case PERF_REG_S390_FP9:
+ return "FP9";
+ case PERF_REG_S390_FP10:
+ return "FP10";
+ case PERF_REG_S390_FP11:
+ return "FP11";
+ case PERF_REG_S390_FP12:
+ return "FP12";
+ case PERF_REG_S390_FP13:
+ return "FP13";
+ case PERF_REG_S390_FP14:
+ return "FP14";
+ case PERF_REG_S390_FP15:
+ return "FP15";
+ case PERF_REG_S390_MASK:
+ return "MASK";
+ case PERF_REG_S390_PC:
+ return "PC";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf-regs-arch/perf_regs_x86.c b/tools/perf/util/perf-regs-arch/perf_regs_x86.c
new file mode 100644
index 000000000000..eb5d249afa70
--- /dev/null
+++ b/tools/perf/util/perf-regs-arch/perf_regs_x86.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifdef HAVE_PERF_REGS_SUPPORT
+
+#include "../perf_regs.h"
+#include "../../../arch/x86/include/uapi/asm/perf_regs.h"
+
+const char *__perf_reg_name_x86(int id)
+{
+ switch (id) {
+ case PERF_REG_X86_AX:
+ return "AX";
+ case PERF_REG_X86_BX:
+ return "BX";
+ case PERF_REG_X86_CX:
+ return "CX";
+ case PERF_REG_X86_DX:
+ return "DX";
+ case PERF_REG_X86_SI:
+ return "SI";
+ case PERF_REG_X86_DI:
+ return "DI";
+ case PERF_REG_X86_BP:
+ return "BP";
+ case PERF_REG_X86_SP:
+ return "SP";
+ case PERF_REG_X86_IP:
+ return "IP";
+ case PERF_REG_X86_FLAGS:
+ return "FLAGS";
+ case PERF_REG_X86_CS:
+ return "CS";
+ case PERF_REG_X86_SS:
+ return "SS";
+ case PERF_REG_X86_DS:
+ return "DS";
+ case PERF_REG_X86_ES:
+ return "ES";
+ case PERF_REG_X86_FS:
+ return "FS";
+ case PERF_REG_X86_GS:
+ return "GS";
+ case PERF_REG_X86_R8:
+ return "R8";
+ case PERF_REG_X86_R9:
+ return "R9";
+ case PERF_REG_X86_R10:
+ return "R10";
+ case PERF_REG_X86_R11:
+ return "R11";
+ case PERF_REG_X86_R12:
+ return "R12";
+ case PERF_REG_X86_R13:
+ return "R13";
+ case PERF_REG_X86_R14:
+ return "R14";
+ case PERF_REG_X86_R15:
+ return "R15";
+
+#define XMM(x) \
+ case PERF_REG_X86_XMM ## x: \
+ case PERF_REG_X86_XMM ## x + 1: \
+ return "XMM" #x;
+ XMM(0)
+ XMM(1)
+ XMM(2)
+ XMM(3)
+ XMM(4)
+ XMM(5)
+ XMM(6)
+ XMM(7)
+ XMM(8)
+ XMM(9)
+ XMM(10)
+ XMM(11)
+ XMM(12)
+ XMM(13)
+ XMM(14)
+ XMM(15)
+#undef XMM
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 57a567ee2cea..8720ec6cf147 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -22,648 +22,6 @@ uint64_t __weak arch__user_reg_mask(void)

#ifdef HAVE_PERF_REGS_SUPPORT

-#define perf_event_arm_regs perf_event_arm64_regs
-#include "../../arch/arm64/include/uapi/asm/perf_regs.h"
-#undef perf_event_arm_regs
-
-#include "../../arch/arm/include/uapi/asm/perf_regs.h"
-#include "../../arch/csky/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"
-#include "../../arch/s390/include/uapi/asm/perf_regs.h"
-#include "../../arch/x86/include/uapi/asm/perf_regs.h"
-
-static const char *__perf_reg_name_arm64(int id)
-{
- switch (id) {
- case PERF_REG_ARM64_X0:
- return "x0";
- case PERF_REG_ARM64_X1:
- return "x1";
- case PERF_REG_ARM64_X2:
- return "x2";
- case PERF_REG_ARM64_X3:
- return "x3";
- case PERF_REG_ARM64_X4:
- return "x4";
- case PERF_REG_ARM64_X5:
- return "x5";
- case PERF_REG_ARM64_X6:
- return "x6";
- case PERF_REG_ARM64_X7:
- return "x7";
- case PERF_REG_ARM64_X8:
- return "x8";
- case PERF_REG_ARM64_X9:
- return "x9";
- case PERF_REG_ARM64_X10:
- return "x10";
- case PERF_REG_ARM64_X11:
- return "x11";
- case PERF_REG_ARM64_X12:
- return "x12";
- case PERF_REG_ARM64_X13:
- return "x13";
- case PERF_REG_ARM64_X14:
- return "x14";
- case PERF_REG_ARM64_X15:
- return "x15";
- case PERF_REG_ARM64_X16:
- return "x16";
- case PERF_REG_ARM64_X17:
- return "x17";
- case PERF_REG_ARM64_X18:
- return "x18";
- case PERF_REG_ARM64_X19:
- return "x19";
- case PERF_REG_ARM64_X20:
- return "x20";
- case PERF_REG_ARM64_X21:
- return "x21";
- case PERF_REG_ARM64_X22:
- return "x22";
- case PERF_REG_ARM64_X23:
- return "x23";
- case PERF_REG_ARM64_X24:
- return "x24";
- case PERF_REG_ARM64_X25:
- return "x25";
- case PERF_REG_ARM64_X26:
- return "x26";
- case PERF_REG_ARM64_X27:
- return "x27";
- case PERF_REG_ARM64_X28:
- return "x28";
- case PERF_REG_ARM64_X29:
- return "x29";
- case PERF_REG_ARM64_SP:
- return "sp";
- case PERF_REG_ARM64_LR:
- return "lr";
- case PERF_REG_ARM64_PC:
- return "pc";
- case PERF_REG_ARM64_VG:
- return "vg";
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-static const char *__perf_reg_name_arm(int id)
-{
- switch (id) {
- case PERF_REG_ARM_R0:
- return "r0";
- case PERF_REG_ARM_R1:
- return "r1";
- case PERF_REG_ARM_R2:
- return "r2";
- case PERF_REG_ARM_R3:
- return "r3";
- case PERF_REG_ARM_R4:
- return "r4";
- case PERF_REG_ARM_R5:
- return "r5";
- case PERF_REG_ARM_R6:
- return "r6";
- case PERF_REG_ARM_R7:
- return "r7";
- case PERF_REG_ARM_R8:
- return "r8";
- case PERF_REG_ARM_R9:
- return "r9";
- case PERF_REG_ARM_R10:
- return "r10";
- case PERF_REG_ARM_FP:
- return "fp";
- case PERF_REG_ARM_IP:
- return "ip";
- case PERF_REG_ARM_SP:
- return "sp";
- case PERF_REG_ARM_LR:
- return "lr";
- case PERF_REG_ARM_PC:
- return "pc";
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-static const char *__perf_reg_name_csky(int id)
-{
- switch (id) {
- case PERF_REG_CSKY_A0:
- return "a0";
- case PERF_REG_CSKY_A1:
- return "a1";
- case PERF_REG_CSKY_A2:
- return "a2";
- case PERF_REG_CSKY_A3:
- return "a3";
- case PERF_REG_CSKY_REGS0:
- return "regs0";
- case PERF_REG_CSKY_REGS1:
- return "regs1";
- case PERF_REG_CSKY_REGS2:
- return "regs2";
- case PERF_REG_CSKY_REGS3:
- return "regs3";
- case PERF_REG_CSKY_REGS4:
- return "regs4";
- case PERF_REG_CSKY_REGS5:
- return "regs5";
- case PERF_REG_CSKY_REGS6:
- return "regs6";
- case PERF_REG_CSKY_REGS7:
- return "regs7";
- case PERF_REG_CSKY_REGS8:
- return "regs8";
- case PERF_REG_CSKY_REGS9:
- return "regs9";
- case PERF_REG_CSKY_SP:
- return "sp";
- case PERF_REG_CSKY_LR:
- return "lr";
- case PERF_REG_CSKY_PC:
- return "pc";
-#if defined(__CSKYABIV2__)
- case PERF_REG_CSKY_EXREGS0:
- return "exregs0";
- case PERF_REG_CSKY_EXREGS1:
- return "exregs1";
- case PERF_REG_CSKY_EXREGS2:
- return "exregs2";
- case PERF_REG_CSKY_EXREGS3:
- return "exregs3";
- case PERF_REG_CSKY_EXREGS4:
- return "exregs4";
- case PERF_REG_CSKY_EXREGS5:
- return "exregs5";
- case PERF_REG_CSKY_EXREGS6:
- return "exregs6";
- case PERF_REG_CSKY_EXREGS7:
- return "exregs7";
- case PERF_REG_CSKY_EXREGS8:
- return "exregs8";
- case PERF_REG_CSKY_EXREGS9:
- return "exregs9";
- case PERF_REG_CSKY_EXREGS10:
- return "exregs10";
- case PERF_REG_CSKY_EXREGS11:
- return "exregs11";
- case PERF_REG_CSKY_EXREGS12:
- return "exregs12";
- case PERF_REG_CSKY_EXREGS13:
- return "exregs13";
- case PERF_REG_CSKY_EXREGS14:
- return "exregs14";
- case PERF_REG_CSKY_TLS:
- return "tls";
- case PERF_REG_CSKY_HI:
- return "hi";
- case PERF_REG_CSKY_LO:
- return "lo";
-#endif
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-static const char *__perf_reg_name_mips(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;
-}
-
-static const char *__perf_reg_name_powerpc(int id)
-{
- switch (id) {
- case PERF_REG_POWERPC_R0:
- return "r0";
- case PERF_REG_POWERPC_R1:
- return "r1";
- case PERF_REG_POWERPC_R2:
- return "r2";
- case PERF_REG_POWERPC_R3:
- return "r3";
- case PERF_REG_POWERPC_R4:
- return "r4";
- case PERF_REG_POWERPC_R5:
- return "r5";
- case PERF_REG_POWERPC_R6:
- return "r6";
- case PERF_REG_POWERPC_R7:
- return "r7";
- case PERF_REG_POWERPC_R8:
- return "r8";
- case PERF_REG_POWERPC_R9:
- return "r9";
- case PERF_REG_POWERPC_R10:
- return "r10";
- case PERF_REG_POWERPC_R11:
- return "r11";
- case PERF_REG_POWERPC_R12:
- return "r12";
- case PERF_REG_POWERPC_R13:
- return "r13";
- case PERF_REG_POWERPC_R14:
- return "r14";
- case PERF_REG_POWERPC_R15:
- return "r15";
- case PERF_REG_POWERPC_R16:
- return "r16";
- case PERF_REG_POWERPC_R17:
- return "r17";
- case PERF_REG_POWERPC_R18:
- return "r18";
- case PERF_REG_POWERPC_R19:
- return "r19";
- case PERF_REG_POWERPC_R20:
- return "r20";
- case PERF_REG_POWERPC_R21:
- return "r21";
- case PERF_REG_POWERPC_R22:
- return "r22";
- case PERF_REG_POWERPC_R23:
- return "r23";
- case PERF_REG_POWERPC_R24:
- return "r24";
- case PERF_REG_POWERPC_R25:
- return "r25";
- case PERF_REG_POWERPC_R26:
- return "r26";
- case PERF_REG_POWERPC_R27:
- return "r27";
- case PERF_REG_POWERPC_R28:
- return "r28";
- case PERF_REG_POWERPC_R29:
- return "r29";
- case PERF_REG_POWERPC_R30:
- return "r30";
- case PERF_REG_POWERPC_R31:
- return "r31";
- case PERF_REG_POWERPC_NIP:
- return "nip";
- case PERF_REG_POWERPC_MSR:
- return "msr";
- case PERF_REG_POWERPC_ORIG_R3:
- return "orig_r3";
- case PERF_REG_POWERPC_CTR:
- return "ctr";
- case PERF_REG_POWERPC_LINK:
- return "link";
- case PERF_REG_POWERPC_XER:
- return "xer";
- case PERF_REG_POWERPC_CCR:
- return "ccr";
- case PERF_REG_POWERPC_SOFTE:
- return "softe";
- case PERF_REG_POWERPC_TRAP:
- return "trap";
- case PERF_REG_POWERPC_DAR:
- return "dar";
- case PERF_REG_POWERPC_DSISR:
- return "dsisr";
- case PERF_REG_POWERPC_SIER:
- return "sier";
- case PERF_REG_POWERPC_MMCRA:
- return "mmcra";
- case PERF_REG_POWERPC_MMCR0:
- return "mmcr0";
- case PERF_REG_POWERPC_MMCR1:
- return "mmcr1";
- case PERF_REG_POWERPC_MMCR2:
- return "mmcr2";
- case PERF_REG_POWERPC_MMCR3:
- return "mmcr3";
- case PERF_REG_POWERPC_SIER2:
- return "sier2";
- case PERF_REG_POWERPC_SIER3:
- return "sier3";
- case PERF_REG_POWERPC_PMC1:
- return "pmc1";
- case PERF_REG_POWERPC_PMC2:
- return "pmc2";
- case PERF_REG_POWERPC_PMC3:
- return "pmc3";
- case PERF_REG_POWERPC_PMC4:
- return "pmc4";
- case PERF_REG_POWERPC_PMC5:
- return "pmc5";
- case PERF_REG_POWERPC_PMC6:
- return "pmc6";
- case PERF_REG_POWERPC_SDAR:
- return "sdar";
- case PERF_REG_POWERPC_SIAR:
- return "siar";
- default:
- break;
- }
- return NULL;
-}
-
-static const char *__perf_reg_name_riscv(int id)
-{
- switch (id) {
- case PERF_REG_RISCV_PC:
- return "pc";
- case PERF_REG_RISCV_RA:
- return "ra";
- case PERF_REG_RISCV_SP:
- return "sp";
- case PERF_REG_RISCV_GP:
- return "gp";
- case PERF_REG_RISCV_TP:
- return "tp";
- case PERF_REG_RISCV_T0:
- return "t0";
- case PERF_REG_RISCV_T1:
- return "t1";
- case PERF_REG_RISCV_T2:
- return "t2";
- case PERF_REG_RISCV_S0:
- return "s0";
- case PERF_REG_RISCV_S1:
- return "s1";
- case PERF_REG_RISCV_A0:
- return "a0";
- case PERF_REG_RISCV_A1:
- return "a1";
- case PERF_REG_RISCV_A2:
- return "a2";
- case PERF_REG_RISCV_A3:
- return "a3";
- case PERF_REG_RISCV_A4:
- return "a4";
- case PERF_REG_RISCV_A5:
- return "a5";
- case PERF_REG_RISCV_A6:
- return "a6";
- case PERF_REG_RISCV_A7:
- return "a7";
- case PERF_REG_RISCV_S2:
- return "s2";
- case PERF_REG_RISCV_S3:
- return "s3";
- case PERF_REG_RISCV_S4:
- return "s4";
- case PERF_REG_RISCV_S5:
- return "s5";
- case PERF_REG_RISCV_S6:
- return "s6";
- case PERF_REG_RISCV_S7:
- return "s7";
- case PERF_REG_RISCV_S8:
- return "s8";
- case PERF_REG_RISCV_S9:
- return "s9";
- case PERF_REG_RISCV_S10:
- return "s10";
- case PERF_REG_RISCV_S11:
- return "s11";
- case PERF_REG_RISCV_T3:
- return "t3";
- case PERF_REG_RISCV_T4:
- return "t4";
- case PERF_REG_RISCV_T5:
- return "t5";
- case PERF_REG_RISCV_T6:
- return "t6";
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-static const char *__perf_reg_name_s390(int id)
-{
- switch (id) {
- case PERF_REG_S390_R0:
- return "R0";
- case PERF_REG_S390_R1:
- return "R1";
- case PERF_REG_S390_R2:
- return "R2";
- case PERF_REG_S390_R3:
- return "R3";
- case PERF_REG_S390_R4:
- return "R4";
- case PERF_REG_S390_R5:
- return "R5";
- case PERF_REG_S390_R6:
- return "R6";
- case PERF_REG_S390_R7:
- return "R7";
- case PERF_REG_S390_R8:
- return "R8";
- case PERF_REG_S390_R9:
- return "R9";
- case PERF_REG_S390_R10:
- return "R10";
- case PERF_REG_S390_R11:
- return "R11";
- case PERF_REG_S390_R12:
- return "R12";
- case PERF_REG_S390_R13:
- return "R13";
- case PERF_REG_S390_R14:
- return "R14";
- case PERF_REG_S390_R15:
- return "R15";
- case PERF_REG_S390_FP0:
- return "FP0";
- case PERF_REG_S390_FP1:
- return "FP1";
- case PERF_REG_S390_FP2:
- return "FP2";
- case PERF_REG_S390_FP3:
- return "FP3";
- case PERF_REG_S390_FP4:
- return "FP4";
- case PERF_REG_S390_FP5:
- return "FP5";
- case PERF_REG_S390_FP6:
- return "FP6";
- case PERF_REG_S390_FP7:
- return "FP7";
- case PERF_REG_S390_FP8:
- return "FP8";
- case PERF_REG_S390_FP9:
- return "FP9";
- case PERF_REG_S390_FP10:
- return "FP10";
- case PERF_REG_S390_FP11:
- return "FP11";
- case PERF_REG_S390_FP12:
- return "FP12";
- case PERF_REG_S390_FP13:
- return "FP13";
- case PERF_REG_S390_FP14:
- return "FP14";
- case PERF_REG_S390_FP15:
- return "FP15";
- case PERF_REG_S390_MASK:
- return "MASK";
- case PERF_REG_S390_PC:
- return "PC";
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-static const char *__perf_reg_name_x86(int id)
-{
- switch (id) {
- case PERF_REG_X86_AX:
- return "AX";
- case PERF_REG_X86_BX:
- return "BX";
- case PERF_REG_X86_CX:
- return "CX";
- case PERF_REG_X86_DX:
- return "DX";
- case PERF_REG_X86_SI:
- return "SI";
- case PERF_REG_X86_DI:
- return "DI";
- case PERF_REG_X86_BP:
- return "BP";
- case PERF_REG_X86_SP:
- return "SP";
- case PERF_REG_X86_IP:
- return "IP";
- case PERF_REG_X86_FLAGS:
- return "FLAGS";
- case PERF_REG_X86_CS:
- return "CS";
- case PERF_REG_X86_SS:
- return "SS";
- case PERF_REG_X86_DS:
- return "DS";
- case PERF_REG_X86_ES:
- return "ES";
- case PERF_REG_X86_FS:
- return "FS";
- case PERF_REG_X86_GS:
- return "GS";
- case PERF_REG_X86_R8:
- return "R8";
- case PERF_REG_X86_R9:
- return "R9";
- case PERF_REG_X86_R10:
- return "R10";
- case PERF_REG_X86_R11:
- return "R11";
- case PERF_REG_X86_R12:
- return "R12";
- case PERF_REG_X86_R13:
- return "R13";
- case PERF_REG_X86_R14:
- return "R14";
- case PERF_REG_X86_R15:
- return "R15";
-
-#define XMM(x) \
- case PERF_REG_X86_XMM ## x: \
- case PERF_REG_X86_XMM ## x + 1: \
- return "XMM" #x;
- XMM(0)
- XMM(1)
- XMM(2)
- XMM(3)
- XMM(4)
- XMM(5)
- XMM(6)
- XMM(7)
- XMM(8)
- XMM(9)
- XMM(10)
- XMM(11)
- XMM(12)
- XMM(13)
- XMM(14)
- XMM(15)
-#undef XMM
- default:
- return NULL;
- }
-
- return NULL;
-}
-
const char *perf_reg_name(int id, const char *arch)
{
const char *reg_name = NULL;
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index ce1127af05e4..ab4ec3f2a170 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -36,6 +36,14 @@ extern const struct sample_reg sample_reg_masks[];

const char *perf_reg_name(int id, const char *arch);
int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
+const char *__perf_reg_name_arm64(int id);
+const char *__perf_reg_name_arm(int id);
+const char *__perf_reg_name_csky(int id);
+const char *__perf_reg_name_mips(int id);
+const char *__perf_reg_name_powerpc(int id);
+const char *__perf_reg_name_riscv(int id);
+const char *__perf_reg_name_s390(int id);
+const char *__perf_reg_name_x86(int id);

#else
#define PERF_REGS_MASK 0
--
2.39.2


2023-05-22 09:03:38

by James Clark

[permalink] [raw]
Subject: Re: [PATCH v1 2/5] perf parse-regs: Introduce functions arch__reg_{ip|sp}()



On 20/05/2023 03:55, Leo Yan wrote:
> Ideally, we want util/perf_regs.c to be general enough and doesn't bind
> with specific architecture.
>
> But since util/perf_regs.c uses the macros PERF_REG_IP and PERF_REG_SP
> which are defined by architecture, thus util/perf_regs.c is dependent on
> architecture header (see util/perf_regs.h includes "<perf_regs.h>", here
> perf_regs.h is architecture specific header).
>
> As a step to generalize util/perf_regs.c, this commit introduces weak
> functions arch__reg_ip() and arch__reg_sp() and every architecture can
> define their own functions; thus, util/perf_regs.c doesn't need to use
> PERF_REG_IP and PERF_REG_SP anymore.
>
> This is a preparation to get rid of architecture specific header from
> util/perf_regs.h.
>
> Signed-off-by: Leo Yan <[email protected]>
> ---
[...]
>
> -#define DWARF_MINIMAL_REGS ((1ULL << PERF_REG_IP) | (1ULL << PERF_REG_SP))
> +#define DWARF_MINIMAL_REGS ((1ULL << arch__reg_ip()) | (1ULL << arch__reg_sp()))
>
> const char *perf_reg_name(int id, const char *arch);
> int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
> diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
> index bdccfc511b7e..f308f2ea512b 100644
> --- a/tools/perf/util/unwind-libdw.c
> +++ b/tools/perf/util/unwind-libdw.c
> @@ -252,7 +252,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
> if (!ui->dwfl)
> goto out;
>
> - err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
> + err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip());

Shouldn't it be more like this, because the weak symbols are a compile
time thing and it's supposed to support cross arch unwinding at runtime
(assuming something containing the arch from the file is passed down,
like we did with perf_reg_name()):

char *arch = perf_env__arch(evsel__env(evsel));
err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip(arch));

Now I'm wondering how cross unwinding ever worked because I see
libunwind also has something hard coded too:

#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP


2023-05-22 12:14:19

by Leo Yan

[permalink] [raw]
Subject: Re: [PATCH v1 2/5] perf parse-regs: Introduce functions arch__reg_{ip|sp}()

On Mon, May 22, 2023 at 09:57:25AM +0100, James Clark wrote:
>
>
> On 20/05/2023 03:55, Leo Yan wrote:
> > Ideally, we want util/perf_regs.c to be general enough and doesn't bind
> > with specific architecture.
> >
> > But since util/perf_regs.c uses the macros PERF_REG_IP and PERF_REG_SP
> > which are defined by architecture, thus util/perf_regs.c is dependent on
> > architecture header (see util/perf_regs.h includes "<perf_regs.h>", here
> > perf_regs.h is architecture specific header).
> >
> > As a step to generalize util/perf_regs.c, this commit introduces weak
> > functions arch__reg_ip() and arch__reg_sp() and every architecture can
> > define their own functions; thus, util/perf_regs.c doesn't need to use
> > PERF_REG_IP and PERF_REG_SP anymore.
> >
> > This is a preparation to get rid of architecture specific header from
> > util/perf_regs.h.
> >
> > Signed-off-by: Leo Yan <[email protected]>
> > ---
> [...]
> >
> > -#define DWARF_MINIMAL_REGS ((1ULL << PERF_REG_IP) | (1ULL << PERF_REG_SP))
> > +#define DWARF_MINIMAL_REGS ((1ULL << arch__reg_ip()) | (1ULL << arch__reg_sp()))
> >
> > const char *perf_reg_name(int id, const char *arch);
> > int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
> > diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
> > index bdccfc511b7e..f308f2ea512b 100644
> > --- a/tools/perf/util/unwind-libdw.c
> > +++ b/tools/perf/util/unwind-libdw.c
> > @@ -252,7 +252,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
> > if (!ui->dwfl)
> > goto out;
> >
> > - err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
> > + err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip());
>
> Shouldn't it be more like this, because the weak symbols are a compile
> time thing and it's supposed to support cross arch unwinding at runtime
> (assuming something containing the arch from the file is passed down,
> like we did with perf_reg_name()):
>
> char *arch = perf_env__arch(evsel__env(evsel));
> err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip(arch));

Thanks for pointing out, James.

Agreed that we need to return the IP and SP register based on the
arch. I will look into more details and spin for a new patch set for
this.

> Now I'm wondering how cross unwinding ever worked because I see
> libunwind also has something hard coded too:
>
> #define LIBUNWIND__ARCH_REG_SP PERF_REG_SP

Yeah, I also used arch__reg_sp() to replace PERF_REG_SP; but as you
suggestion, we should fix this with passing 'arch' parameter for
getting SP register based on arch.

Another important thing is to find a good test for cross unwinding.
Maybe I can use tools/perf/tests/shell/record.sh, function
test_register_capture() for testing registers, if you have any other
suggesion, please let me know.

Thanks,
Leo

2023-05-22 17:05:44

by James Clark

[permalink] [raw]
Subject: Re: [PATCH v1 2/5] perf parse-regs: Introduce functions arch__reg_{ip|sp}()



On 22/05/2023 13:07, Leo Yan wrote:
> On Mon, May 22, 2023 at 09:57:25AM +0100, James Clark wrote:
>>
>>
>> On 20/05/2023 03:55, Leo Yan wrote:
>>> Ideally, we want util/perf_regs.c to be general enough and doesn't bind
>>> with specific architecture.
>>>
>>> But since util/perf_regs.c uses the macros PERF_REG_IP and PERF_REG_SP
>>> which are defined by architecture, thus util/perf_regs.c is dependent on
>>> architecture header (see util/perf_regs.h includes "<perf_regs.h>", here
>>> perf_regs.h is architecture specific header).
>>>
>>> As a step to generalize util/perf_regs.c, this commit introduces weak
>>> functions arch__reg_ip() and arch__reg_sp() and every architecture can
>>> define their own functions; thus, util/perf_regs.c doesn't need to use
>>> PERF_REG_IP and PERF_REG_SP anymore.
>>>
>>> This is a preparation to get rid of architecture specific header from
>>> util/perf_regs.h.
>>>
>>> Signed-off-by: Leo Yan <[email protected]>
>>> ---
>> [...]
>>>
>>> -#define DWARF_MINIMAL_REGS ((1ULL << PERF_REG_IP) | (1ULL << PERF_REG_SP))
>>> +#define DWARF_MINIMAL_REGS ((1ULL << arch__reg_ip()) | (1ULL << arch__reg_sp()))
>>>
>>> const char *perf_reg_name(int id, const char *arch);
>>> int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
>>> diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
>>> index bdccfc511b7e..f308f2ea512b 100644
>>> --- a/tools/perf/util/unwind-libdw.c
>>> +++ b/tools/perf/util/unwind-libdw.c
>>> @@ -252,7 +252,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
>>> if (!ui->dwfl)
>>> goto out;
>>>
>>> - err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
>>> + err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip());
>>
>> Shouldn't it be more like this, because the weak symbols are a compile
>> time thing and it's supposed to support cross arch unwinding at runtime
>> (assuming something containing the arch from the file is passed down,
>> like we did with perf_reg_name()):
>>
>> char *arch = perf_env__arch(evsel__env(evsel));
>> err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip(arch));
>
> Thanks for pointing out, James.
>
> Agreed that we need to return the IP and SP register based on the
> arch. I will look into more details and spin for a new patch set for
> this.
>

You might be able to skip the extra work for now though, seeing as your
change is no worse than it was before and it fixes the duplicate
declaration issue.

>> Now I'm wondering how cross unwinding ever worked because I see
>> libunwind also has something hard coded too:
>>
>> #define LIBUNWIND__ARCH_REG_SP PERF_REG_SP
>
> Yeah, I also used arch__reg_sp() to replace PERF_REG_SP; but as you
> suggestion, we should fix this with passing 'arch' parameter for
> getting SP register based on arch.
>
> Another important thing is to find a good test for cross unwinding.
> Maybe I can use tools/perf/tests/shell/record.sh, function
> test_register_capture() for testing registers, if you have any other
> suggesion, please let me know.

The only way I can think is to have pre-recorded perf.data files in the
repo, but they'd also need the binary from the recording too. I think
this is probably not a very good idea because it's going to make the
repo huge if we keep changing them (which we will).

Some kind of third party perf test suite hosted somewhere might work but
I don't think this exists.

>
> Thanks,
> Leo

2023-05-22 18:19:17

by Ian Rogers

[permalink] [raw]
Subject: Re: [PATCH v1 2/5] perf parse-regs: Introduce functions arch__reg_{ip|sp}()

On Fri, May 19, 2023 at 7:56 PM Leo Yan <[email protected]> wrote:
>
> Ideally, we want util/perf_regs.c to be general enough and doesn't bind
> with specific architecture.
>
> But since util/perf_regs.c uses the macros PERF_REG_IP and PERF_REG_SP
> which are defined by architecture, thus util/perf_regs.c is dependent on
> architecture header (see util/perf_regs.h includes "<perf_regs.h>", here
> perf_regs.h is architecture specific header).
>
> As a step to generalize util/perf_regs.c, this commit introduces weak
> functions arch__reg_ip() and arch__reg_sp() and every architecture can
> define their own functions; thus, util/perf_regs.c doesn't need to use
> PERF_REG_IP and PERF_REG_SP anymore.
>
> This is a preparation to get rid of architecture specific header from
> util/perf_regs.h.
>
> Signed-off-by: Leo Yan <[email protected]>
> ---
> tools/perf/arch/arm/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/arm64/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/csky/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/mips/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/powerpc/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/riscv/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/s390/util/perf_regs.c | 10 ++++++++++
> tools/perf/arch/x86/util/perf_regs.c | 10 ++++++++++
> tools/perf/util/perf_regs.c | 10 ++++++++++
> tools/perf/util/perf_regs.h | 4 +++-
> tools/perf/util/unwind-libdw.c | 2 +-
> tools/perf/util/unwind.h | 4 ++--
> 12 files changed, 96 insertions(+), 4 deletions(-)
>
> diff --git a/tools/perf/arch/arm/util/perf_regs.c b/tools/perf/arch/arm/util/perf_regs.c
> index 2833e101a7c6..37aa3a2091bd 100644
> --- a/tools/perf/arch/arm/util/perf_regs.c
> +++ b/tools/perf/arch/arm/util/perf_regs.c
> @@ -4,3 +4,13 @@
> const struct sample_reg sample_reg_masks[] = {
> SMPL_REG_END
> };
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_ARM_PC;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_ARM_SP;
> +}
> diff --git a/tools/perf/arch/arm64/util/perf_regs.c b/tools/perf/arch/arm64/util/perf_regs.c
> index 006692c9b040..dbe7f00b222b 100644
> --- a/tools/perf/arch/arm64/util/perf_regs.c
> +++ b/tools/perf/arch/arm64/util/perf_regs.c
> @@ -169,3 +169,13 @@ uint64_t arch__user_reg_mask(void)
> }
> return PERF_REGS_MASK;
> }
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_ARM64_PC;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_ARM64_SP;
> +}
> diff --git a/tools/perf/arch/csky/util/perf_regs.c b/tools/perf/arch/csky/util/perf_regs.c
> index 2864e2e3776d..d230d7e640fd 100644
> --- a/tools/perf/arch/csky/util/perf_regs.c
> +++ b/tools/perf/arch/csky/util/perf_regs.c
> @@ -4,3 +4,13 @@
> const struct sample_reg sample_reg_masks[] = {
> SMPL_REG_END
> };
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_CSKY_PC;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_CSKY_SP;
> +}
> diff --git a/tools/perf/arch/mips/util/perf_regs.c b/tools/perf/arch/mips/util/perf_regs.c
> index 2864e2e3776d..64882ebc9287 100644
> --- a/tools/perf/arch/mips/util/perf_regs.c
> +++ b/tools/perf/arch/mips/util/perf_regs.c
> @@ -4,3 +4,13 @@
> const struct sample_reg sample_reg_masks[] = {
> SMPL_REG_END
> };
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_MIPS_PC;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_MIPS_R29;
> +}
> diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
> index 8d07a78e742a..c84cd79986a8 100644
> --- a/tools/perf/arch/powerpc/util/perf_regs.c
> +++ b/tools/perf/arch/powerpc/util/perf_regs.c
> @@ -226,3 +226,13 @@ uint64_t arch__intr_reg_mask(void)
> }
> return mask;
> }
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_POWERPC_NIP;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_POWERPC_R1;
> +}
> diff --git a/tools/perf/arch/riscv/util/perf_regs.c b/tools/perf/arch/riscv/util/perf_regs.c
> index 2864e2e3776d..13bbddd139d0 100644
> --- a/tools/perf/arch/riscv/util/perf_regs.c
> +++ b/tools/perf/arch/riscv/util/perf_regs.c
> @@ -4,3 +4,13 @@
> const struct sample_reg sample_reg_masks[] = {
> SMPL_REG_END
> };
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_RISCV_PC;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_RISCV_SP;
> +}
> diff --git a/tools/perf/arch/s390/util/perf_regs.c b/tools/perf/arch/s390/util/perf_regs.c
> index 2864e2e3776d..9b2297471090 100644
> --- a/tools/perf/arch/s390/util/perf_regs.c
> +++ b/tools/perf/arch/s390/util/perf_regs.c
> @@ -4,3 +4,13 @@
> const struct sample_reg sample_reg_masks[] = {
> SMPL_REG_END
> };
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_S390_PC;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_S390_R15;
> +}
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index 0ed177991ad0..c752a6e9cba6 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -312,3 +312,13 @@ uint64_t arch__intr_reg_mask(void)
>
> return PERF_REGS_MASK;
> }
> +
> +uint64_t arch__reg_ip(void)
> +{
> + return PERF_REG_X86_IP;
> +}
> +
> +uint64_t arch__reg_sp(void)
> +{
> + return PERF_REG_X86_SP;
> +}
> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index 8720ec6cf147..334c9a2b785d 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -20,6 +20,16 @@ uint64_t __weak arch__user_reg_mask(void)
> return PERF_REGS_MASK;
> }
>
> +uint64_t __weak arch__reg_ip(void)
> +{
> + return 0;
> +}
> +
> +uint64_t __weak arch__reg_sp(void)
> +{
> + return 0;
> +}
> +

Is there a need for the weak function if there is a definition for
every architecture? A problem with weak definitions is that they are
not part of the C standard, so strange things can happen such as
inlining - although I think this code is safe. Not having the weak
functions means that if someone tries to bring up a new architecture
they will get linker failures until they add the definitions. Failing
to link seems better than silently succeeding but then having to track
down runtime failures because these functions are returning 0.

Thanks,
Ian

> #ifdef HAVE_PERF_REGS_SUPPORT
>
> const char *perf_reg_name(int id, const char *arch)
> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index ab4ec3f2a170..0a1460aaad37 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -26,13 +26,15 @@ enum {
> int arch_sdt_arg_parse_op(char *old_op, char **new_op);
> uint64_t arch__intr_reg_mask(void);
> uint64_t arch__user_reg_mask(void);
> +uint64_t arch__reg_ip(void);
> +uint64_t arch__reg_sp(void);
>
> #ifdef HAVE_PERF_REGS_SUPPORT
> extern const struct sample_reg sample_reg_masks[];
>
> #include <perf_regs.h>
>
> -#define DWARF_MINIMAL_REGS ((1ULL << PERF_REG_IP) | (1ULL << PERF_REG_SP))
> +#define DWARF_MINIMAL_REGS ((1ULL << arch__reg_ip()) | (1ULL << arch__reg_sp()))
>
> const char *perf_reg_name(int id, const char *arch);
> int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
> diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
> index bdccfc511b7e..f308f2ea512b 100644
> --- a/tools/perf/util/unwind-libdw.c
> +++ b/tools/perf/util/unwind-libdw.c
> @@ -252,7 +252,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
> if (!ui->dwfl)
> goto out;
>
> - err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
> + err = perf_reg_value(&ip, &data->user_regs, arch__reg_ip());
> if (err)
> goto out;
>
> diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
> index b2a03fa5289b..0a98ea9d8c94 100644
> --- a/tools/perf/util/unwind.h
> +++ b/tools/perf/util/unwind.h
> @@ -43,11 +43,11 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
> #endif
>
> #ifndef LIBUNWIND__ARCH_REG_SP
> -#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP
> +#define LIBUNWIND__ARCH_REG_SP arch__reg_sp()
> #endif
>
> #ifndef LIBUNWIND__ARCH_REG_IP
> -#define LIBUNWIND__ARCH_REG_IP PERF_REG_IP
> +#define LIBUNWIND__ARCH_REG_IP arch__reg_ip()
> #endif
>
> int LIBUNWIND__ARCH_REG_ID(int regnum);
> --
> 2.39.2
>

2023-05-23 07:07:05

by Leo Yan

[permalink] [raw]
Subject: Re: [PATCH v1 2/5] perf parse-regs: Introduce functions arch__reg_{ip|sp}()

On Mon, May 22, 2023 at 11:08:12AM -0700, Ian Rogers wrote:

[...]

> > diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> > index 8720ec6cf147..334c9a2b785d 100644
> > --- a/tools/perf/util/perf_regs.c
> > +++ b/tools/perf/util/perf_regs.c
> > @@ -20,6 +20,16 @@ uint64_t __weak arch__user_reg_mask(void)
> > return PERF_REGS_MASK;
> > }
> >
> > +uint64_t __weak arch__reg_ip(void)
> > +{
> > + return 0;
> > +}
> > +
> > +uint64_t __weak arch__reg_sp(void)
> > +{
> > + return 0;
> > +}
> > +
>
> Is there a need for the weak function if there is a definition for
> every architecture?

In current code, some archs don't support register parsing (e.g.
arch/alpha, arch/parisc, arch/riscv64, etc), this is why I added weak
functions to avoid building breakage for these archs.

> A problem with weak definitions is that they are
> not part of the C standard, so strange things can happen such as
> inlining - although I think this code is safe.

Good to know this info, thanks for sharing.

> Not having the weak
> functions means that if someone tries to bring up a new architecture
> they will get linker failures until they add the definitions. Failing
> to link seems better than silently succeeding but then having to track
> down runtime failures because these functions are returning 0.

I agreed that removing weak functions is better way to move forward.

If removing the weak functions, we need to handle cases for below
archs which don't support register parsing:

arch/alpha/
arch/arc/
arch/parisc/
arch/riscv64/
arch/sh/
arch/sparc/
arch/xtensa/

As James pointed out perf fails to support cross unwinding, I will update
this patch, the new version's arch__reg_ip() / arch__reg_sp() will return
IP and SP registers based on the passed 'arch' parameter; for above
unsupported archs, arch__reg_ip() / arch__reg_sp() will return error and
architecture developers can extend register parsing in the future.

In this way, we also can remove weak definitions, this can give us an
extra benefit :)

Thanks,
Leo