summaryrefslogtreecommitdiff
path: root/tools/perf/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/arch/powerpc')
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/annotate/instructions.c317
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/Kbuild3
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls6
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/syscall.tbl5
-rw-r--r--tools/perf/arch/powerpc/include/dwarf-regs-table.h1
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h2
-rw-r--r--tools/perf/arch/powerpc/include/syscall_table.h8
-rw-r--r--tools/perf/arch/powerpc/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/arch/powerpc/util/Build6
-rw-r--r--tools/perf/arch/powerpc/util/auxtrace.c110
-rw-r--r--tools/perf/arch/powerpc/util/book3s_hcalls.h124
-rw-r--r--tools/perf/arch/powerpc/util/book3s_hv_exits.h33
-rw-r--r--tools/perf/arch/powerpc/util/event.c60
-rw-r--r--tools/perf/arch/powerpc/util/header.c4
-rw-r--r--tools/perf/arch/powerpc/util/kvm-stat.c219
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c240
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c52
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libdw.c76
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libunwind.c92
20 files changed, 132 insertions, 1229 deletions
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index a295a80ea078..44cc3f023318 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
-HAVE_KVM_STAT_SUPPORT := 1
PERF_HAVE_JITDUMP := 1
diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/arch/powerpc/annotate/instructions.c
deleted file mode 100644
index ca567cfdcbdb..000000000000
--- a/tools/perf/arch/powerpc/annotate/instructions.c
+++ /dev/null
@@ -1,317 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/compiler.h>
-
-static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
-{
- int i;
- struct ins_ops *ops;
-
- /*
- * - Interested only if instruction starts with 'b'.
- * - Few start with 'b', but aren't branch instructions.
- */
- if (name[0] != 'b' ||
- !strncmp(name, "bcd", 3) ||
- !strncmp(name, "brinc", 5) ||
- !strncmp(name, "bper", 4))
- return NULL;
-
- ops = &jump_ops;
-
- i = strlen(name) - 1;
- if (i < 0)
- return NULL;
-
- /* ignore optional hints at the end of the instructions */
- if (name[i] == '+' || name[i] == '-')
- i--;
-
- if (name[i] == 'l' || (name[i] == 'a' && name[i-1] == 'l')) {
- /*
- * if the instruction ends up with 'l' or 'la', then
- * those are considered 'calls' since they update LR.
- * ... except for 'bnl' which is branch if not less than
- * and the absolute form of the same.
- */
- if (strcmp(name, "bnl") && strcmp(name, "bnl+") &&
- strcmp(name, "bnl-") && strcmp(name, "bnla") &&
- strcmp(name, "bnla+") && strcmp(name, "bnla-"))
- ops = &call_ops;
- }
- if (name[i] == 'r' && name[i-1] == 'l')
- /*
- * instructions ending with 'lr' are considered to be
- * return instructions
- */
- ops = &ret_ops;
-
- arch__associate_ins_ops(arch, name, ops);
- return ops;
-}
-
-#define PPC_OP(op) (((op) >> 26) & 0x3F)
-#define PPC_21_30(R) (((R) >> 1) & 0x3ff)
-#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
-
-struct insn_offset {
- const char *name;
- int value;
-};
-
-/*
- * There are memory instructions with opcode 31 which are
- * of X Form, Example:
- * ldx RT,RA,RB
- * ______________________________________
- * | 31 | RT | RA | RB | 21 |/|
- * --------------------------------------
- * 0 6 11 16 21 30 31
- *
- * But all instructions with opcode 31 are not memory.
- * Example: add RT,RA,RB
- *
- * Use bits 21 to 30 to check memory insns with 31 as opcode.
- * In ins_array below, for ldx instruction:
- * name => OP_31_XOP_LDX
- * value => 21
- */
-
-static struct insn_offset ins_array[] = {
- { .name = "OP_31_XOP_LXSIWZX", .value = 12, },
- { .name = "OP_31_XOP_LWARX", .value = 20, },
- { .name = "OP_31_XOP_LDX", .value = 21, },
- { .name = "OP_31_XOP_LWZX", .value = 23, },
- { .name = "OP_31_XOP_LDUX", .value = 53, },
- { .name = "OP_31_XOP_LWZUX", .value = 55, },
- { .name = "OP_31_XOP_LXSIWAX", .value = 76, },
- { .name = "OP_31_XOP_LDARX", .value = 84, },
- { .name = "OP_31_XOP_LBZX", .value = 87, },
- { .name = "OP_31_XOP_LVX", .value = 103, },
- { .name = "OP_31_XOP_LBZUX", .value = 119, },
- { .name = "OP_31_XOP_STXSIWX", .value = 140, },
- { .name = "OP_31_XOP_STDX", .value = 149, },
- { .name = "OP_31_XOP_STWX", .value = 151, },
- { .name = "OP_31_XOP_STDUX", .value = 181, },
- { .name = "OP_31_XOP_STWUX", .value = 183, },
- { .name = "OP_31_XOP_STBX", .value = 215, },
- { .name = "OP_31_XOP_STVX", .value = 231, },
- { .name = "OP_31_XOP_STBUX", .value = 247, },
- { .name = "OP_31_XOP_LHZX", .value = 279, },
- { .name = "OP_31_XOP_LHZUX", .value = 311, },
- { .name = "OP_31_XOP_LXVDSX", .value = 332, },
- { .name = "OP_31_XOP_LWAX", .value = 341, },
- { .name = "OP_31_XOP_LHAX", .value = 343, },
- { .name = "OP_31_XOP_LWAUX", .value = 373, },
- { .name = "OP_31_XOP_LHAUX", .value = 375, },
- { .name = "OP_31_XOP_STHX", .value = 407, },
- { .name = "OP_31_XOP_STHUX", .value = 439, },
- { .name = "OP_31_XOP_LXSSPX", .value = 524, },
- { .name = "OP_31_XOP_LDBRX", .value = 532, },
- { .name = "OP_31_XOP_LSWX", .value = 533, },
- { .name = "OP_31_XOP_LWBRX", .value = 534, },
- { .name = "OP_31_XOP_LFSUX", .value = 567, },
- { .name = "OP_31_XOP_LXSDX", .value = 588, },
- { .name = "OP_31_XOP_LSWI", .value = 597, },
- { .name = "OP_31_XOP_LFDX", .value = 599, },
- { .name = "OP_31_XOP_LFDUX", .value = 631, },
- { .name = "OP_31_XOP_STXSSPX", .value = 652, },
- { .name = "OP_31_XOP_STDBRX", .value = 660, },
- { .name = "OP_31_XOP_STXWX", .value = 661, },
- { .name = "OP_31_XOP_STWBRX", .value = 662, },
- { .name = "OP_31_XOP_STFSX", .value = 663, },
- { .name = "OP_31_XOP_STFSUX", .value = 695, },
- { .name = "OP_31_XOP_STXSDX", .value = 716, },
- { .name = "OP_31_XOP_STSWI", .value = 725, },
- { .name = "OP_31_XOP_STFDX", .value = 727, },
- { .name = "OP_31_XOP_STFDUX", .value = 759, },
- { .name = "OP_31_XOP_LXVW4X", .value = 780, },
- { .name = "OP_31_XOP_LHBRX", .value = 790, },
- { .name = "OP_31_XOP_LXVD2X", .value = 844, },
- { .name = "OP_31_XOP_LFIWAX", .value = 855, },
- { .name = "OP_31_XOP_LFIWZX", .value = 887, },
- { .name = "OP_31_XOP_STXVW4X", .value = 908, },
- { .name = "OP_31_XOP_STHBRX", .value = 918, },
- { .name = "OP_31_XOP_STXVD2X", .value = 972, },
- { .name = "OP_31_XOP_STFIWX", .value = 983, },
-};
-
-/*
- * Arithmetic instructions which are having opcode as 31.
- * These instructions are tracked to save the register state
- * changes. Example:
- *
- * lwz r10,264(r3)
- * add r31, r3, r3
- * lwz r9, 0(r31)
- *
- * Here instruction tracking needs to identify the "add"
- * instruction and save data type of r3 to r31. If a sample
- * is hit at next "lwz r9, 0(r31)", by this instruction tracking,
- * data type of r31 can be resolved.
- */
-static struct insn_offset arithmetic_ins_op_31[] = {
- { .name = "SUB_CARRY_XO_FORM", .value = 8, },
- { .name = "MUL_HDW_XO_FORM1", .value = 9, },
- { .name = "ADD_CARRY_XO_FORM", .value = 10, },
- { .name = "MUL_HW_XO_FORM1", .value = 11, },
- { .name = "SUB_XO_FORM", .value = 40, },
- { .name = "MUL_HDW_XO_FORM", .value = 73, },
- { .name = "MUL_HW_XO_FORM", .value = 75, },
- { .name = "SUB_EXT_XO_FORM", .value = 136, },
- { .name = "ADD_EXT_XO_FORM", .value = 138, },
- { .name = "SUB_ZERO_EXT_XO_FORM", .value = 200, },
- { .name = "ADD_ZERO_EXT_XO_FORM", .value = 202, },
- { .name = "SUB_EXT_XO_FORM2", .value = 232, },
- { .name = "MUL_DW_XO_FORM", .value = 233, },
- { .name = "ADD_EXT_XO_FORM2", .value = 234, },
- { .name = "MUL_W_XO_FORM", .value = 235, },
- { .name = "ADD_XO_FORM", .value = 266, },
- { .name = "DIV_DW_XO_FORM1", .value = 457, },
- { .name = "DIV_W_XO_FORM1", .value = 459, },
- { .name = "DIV_DW_XO_FORM", .value = 489, },
- { .name = "DIV_W_XO_FORM", .value = 491, },
-};
-
-static struct insn_offset arithmetic_two_ops[] = {
- { .name = "mulli", .value = 7, },
- { .name = "subfic", .value = 8, },
- { .name = "addic", .value = 12, },
- { .name = "addic.", .value = 13, },
- { .name = "addi", .value = 14, },
- { .name = "addis", .value = 15, },
-};
-
-static int cmp_offset(const void *a, const void *b)
-{
- const struct insn_offset *val1 = a;
- const struct insn_offset *val2 = b;
-
- return (val1->value - val2->value);
-}
-
-static struct ins_ops *check_ppc_insn(struct disasm_line *dl)
-{
- int raw_insn = dl->raw.raw_insn;
- int opcode = PPC_OP(raw_insn);
- int mem_insn_31 = PPC_21_30(raw_insn);
- struct insn_offset *ret;
- struct insn_offset mem_insns_31_opcode = {
- "OP_31_INSN",
- mem_insn_31
- };
- char name_insn[32];
-
- /*
- * Instructions with opcode 32 to 63 are memory
- * instructions in powerpc
- */
- if ((opcode & 0x20)) {
- /*
- * Set name in case of raw instruction to
- * opcode to be used in insn-stat
- */
- if (!strlen(dl->ins.name)) {
- sprintf(name_insn, "%d", opcode);
- dl->ins.name = strdup(name_insn);
- }
- return &load_store_ops;
- } else if (opcode == 31) {
- /* Check for memory instructions with opcode 31 */
- ret = bsearch(&mem_insns_31_opcode, ins_array, ARRAY_SIZE(ins_array), sizeof(ins_array[0]), cmp_offset);
- if (ret) {
- if (!strlen(dl->ins.name))
- dl->ins.name = strdup(ret->name);
- return &load_store_ops;
- } else {
- mem_insns_31_opcode.value = PPC_22_30(raw_insn);
- ret = bsearch(&mem_insns_31_opcode, arithmetic_ins_op_31, ARRAY_SIZE(arithmetic_ins_op_31),
- sizeof(arithmetic_ins_op_31[0]), cmp_offset);
- if (ret != NULL)
- return &arithmetic_ops;
- /* Bits 21 to 30 has value 444 for "mr" insn ie, OR X form */
- if (PPC_21_30(raw_insn) == 444)
- return &arithmetic_ops;
- }
- } else {
- mem_insns_31_opcode.value = opcode;
- ret = bsearch(&mem_insns_31_opcode, arithmetic_two_ops, ARRAY_SIZE(arithmetic_two_ops),
- sizeof(arithmetic_two_ops[0]), cmp_offset);
- if (ret != NULL)
- return &arithmetic_ops;
- }
-
- return NULL;
-}
-
-/*
- * Instruction tracking function to track register state moves.
- * Example sequence:
- * ld r10,264(r3)
- * mr r31,r3
- * <<after some sequence>
- * ld r9,312(r31)
- *
- * Previous instruction sequence shows that register state of r3
- * is moved to r31. update_insn_state_powerpc tracks these state
- * changes
- */
-#ifdef HAVE_LIBDW_SUPPORT
-static void update_insn_state_powerpc(struct type_state *state,
- struct data_loc_info *dloc, Dwarf_Die * cu_die __maybe_unused,
- struct disasm_line *dl)
-{
- struct annotated_insn_loc loc;
- struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE];
- struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET];
- struct type_state_reg *tsr;
- u32 insn_offset = dl->al.offset;
-
- if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0)
- return;
-
- /*
- * Value 444 for bits 21:30 is for "mr"
- * instruction. "mr" is extended OR. So set the
- * source and destination reg correctly
- */
- if (PPC_21_30(dl->raw.raw_insn) == 444) {
- int src_reg = src->reg1;
-
- src->reg1 = dst->reg1;
- dst->reg1 = src_reg;
- }
-
- if (!has_reg_type(state, dst->reg1))
- return;
-
- tsr = &state->regs[dst->reg1];
-
- if (!has_reg_type(state, src->reg1) ||
- !state->regs[src->reg1].ok) {
- tsr->ok = false;
- return;
- }
-
- tsr->type = state->regs[src->reg1].type;
- tsr->kind = state->regs[src->reg1].kind;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] reg%d -> reg%d",
- insn_offset, src->reg1, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
-}
-#endif /* HAVE_LIBDW_SUPPORT */
-
-static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = powerpc__associate_instruction_ops;
- arch->objdump.comment_char = '#';
- annotate_opts.show_asm_raw = true;
- arch->e_machine = EM_PPC;
- arch->e_flags = 0;
- }
-
- return 0;
-}
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Kbuild b/tools/perf/arch/powerpc/entry/syscalls/Kbuild
deleted file mode 100644
index 84c6599b4ea6..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Kbuild
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-syscall-y += syscalls_32.h
-syscall-y += syscalls_64.h
diff --git a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls b/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
deleted file mode 100644
index e35afbc57c79..000000000000
--- a/tools/perf/arch/powerpc/entry/syscalls/Makefile.syscalls
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-syscall_abis_32 += nospu
-syscall_abis_64 += nospu
-
-syscalltbl = $(srctree)/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index d8b4ab78bef0..4fcc7c58a105 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -557,3 +557,8 @@
464 common getxattrat sys_getxattrat
465 common listxattrat sys_listxattrat
466 common removexattrat sys_removexattrat
+467 common open_tree_attr sys_open_tree_attr
+468 common file_getattr sys_file_getattr
+469 common file_setattr sys_file_setattr
+470 common listns sys_listns
+471 nospu rseq_slice_yield sys_rseq_slice_yield
diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
index 66dc015a733d..7e746cb31b66 100644
--- a/tools/perf/arch/powerpc/include/dwarf-regs-table.h
+++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
@@ -7,6 +7,7 @@
* http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
* http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
*/
+#undef REG_DWARFNUM_NAME
#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
static const char * const powerpc_regstr_tbl[] = {
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
index 1c66f6ba6773..22b492a3dd58 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <linux/types.h>
-#include <asm/perf_regs.h>
+#include "../../../../arch/powerpc/include/uapi/asm/perf_regs.h"
void perf_regs_load(u64 *regs);
diff --git a/tools/perf/arch/powerpc/include/syscall_table.h b/tools/perf/arch/powerpc/include/syscall_table.h
deleted file mode 100644
index 7ff51b783000..000000000000
--- a/tools/perf/arch/powerpc/include/syscall_table.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/bitsperlong.h>
-
-#if __BITS_PER_LONG == 64
-#include <asm/syscalls_64.h>
-#else
-#include <asm/syscalls_32.h>
-#endif
diff --git a/tools/perf/arch/powerpc/tests/dwarf-unwind.c b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
index 5ecf82893b84..66af884baa66 100644
--- a/tools/perf/arch/powerpc/tests/dwarf-unwind.c
+++ b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
@@ -45,7 +45,7 @@ static int sample_ustack(struct perf_sample *sample,
int test__arch_unwind_sample(struct perf_sample *sample,
struct thread *thread)
{
- struct regs_dump *regs = &sample->user_regs;
+ struct regs_dump *regs = perf_sample__user_regs(sample);
u64 *buf;
buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index ed82715080f9..ae928050e07a 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,13 +1,9 @@
perf-util-y += header.o
-perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o
-perf-util-y += perf_regs.o
perf-util-y += mem-events.o
perf-util-y += pmu.o
perf-util-y += sym-handling.o
perf-util-y += evsel.o
-perf-util-y += event.o
perf-util-$(CONFIG_LIBDW) += skip-callchain-idx.o
-perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
-perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-util-y += auxtrace.o
diff --git a/tools/perf/arch/powerpc/util/auxtrace.c b/tools/perf/arch/powerpc/util/auxtrace.c
new file mode 100644
index 000000000000..4600a1661b4f
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/auxtrace.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VPA support
+ */
+#include <errno.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/zalloc.h>
+
+#include "../../util/evlist.h"
+#include "../../util/debug.h"
+#include "../../util/auxtrace.h"
+#include "../../util/powerpc-vpadtl.h"
+#include "../../util/record.h"
+#include <internal/lib.h> // page_size
+
+#define KiB(x) ((x) * 1024)
+
+static int
+powerpc_vpadtl_recording_options(struct auxtrace_record *ar __maybe_unused,
+ struct evlist *evlist __maybe_unused,
+ struct record_opts *opts)
+{
+ opts->full_auxtrace = true;
+
+ /*
+ * Set auxtrace_mmap_pages to minimum
+ * two pages
+ */
+ if (!opts->auxtrace_mmap_pages) {
+ opts->auxtrace_mmap_pages = KiB(128) / page_size;
+ if (opts->mmap_pages == UINT_MAX)
+ opts->mmap_pages = KiB(256) / page_size;
+ }
+
+ return 0;
+}
+
+static size_t powerpc_vpadtl_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+ struct evlist *evlist __maybe_unused)
+{
+ return VPADTL_AUXTRACE_PRIV_SIZE;
+}
+
+static int
+powerpc_vpadtl_info_fill(struct auxtrace_record *itr __maybe_unused,
+ struct perf_session *session __maybe_unused,
+ struct perf_record_auxtrace_info *auxtrace_info,
+ size_t priv_size __maybe_unused)
+{
+ auxtrace_info->type = PERF_AUXTRACE_VPA_DTL;
+
+ return 0;
+}
+
+static void powerpc_vpadtl_free(struct auxtrace_record *itr)
+{
+ free(itr);
+}
+
+static u64 powerpc_vpadtl_reference(struct auxtrace_record *itr __maybe_unused)
+{
+ return 0;
+}
+
+struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
+ int *err)
+{
+ struct auxtrace_record *aux;
+ struct evsel *pos;
+ int found = 0;
+
+ /*
+ * Set err value to zero here. Any fail later
+ * will set appropriate return code to err.
+ */
+ *err = 0;
+
+ evlist__for_each_entry(evlist, pos) {
+ if (strstarts(pos->name, "vpa_dtl")) {
+ found = 1;
+ pos->needs_auxtrace_mmap = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return NULL;
+
+ /*
+ * To obtain the auxtrace buffer file descriptor, the auxtrace event
+ * must come first.
+ */
+ evlist__to_front(pos->evlist, pos);
+
+ aux = zalloc(sizeof(*aux));
+ if (aux == NULL) {
+ pr_debug("aux record is NULL\n");
+ *err = -ENOMEM;
+ return NULL;
+ }
+
+ aux->recording_options = powerpc_vpadtl_recording_options;
+ aux->info_priv_size = powerpc_vpadtl_info_priv_size;
+ aux->info_fill = powerpc_vpadtl_info_fill;
+ aux->free = powerpc_vpadtl_free;
+ aux->reference = powerpc_vpadtl_reference;
+ return aux;
+}
diff --git a/tools/perf/arch/powerpc/util/book3s_hcalls.h b/tools/perf/arch/powerpc/util/book3s_hcalls.h
deleted file mode 100644
index 488f4339b83c..000000000000
--- a/tools/perf/arch/powerpc/util/book3s_hcalls.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH_PERF_BOOK3S_HV_HCALLS_H
-#define ARCH_PERF_BOOK3S_HV_HCALLS_H
-
-/*
- * PowerPC HCALL codes : hcall code to name mapping
- */
-#define kvm_trace_symbol_hcall \
- {0x4, "H_REMOVE"}, \
- {0x8, "H_ENTER"}, \
- {0xc, "H_READ"}, \
- {0x10, "H_CLEAR_MOD"}, \
- {0x14, "H_CLEAR_REF"}, \
- {0x18, "H_PROTECT"}, \
- {0x1c, "H_GET_TCE"}, \
- {0x20, "H_PUT_TCE"}, \
- {0x24, "H_SET_SPRG0"}, \
- {0x28, "H_SET_DABR"}, \
- {0x2c, "H_PAGE_INIT"}, \
- {0x30, "H_SET_ASR"}, \
- {0x34, "H_ASR_ON"}, \
- {0x38, "H_ASR_OFF"}, \
- {0x3c, "H_LOGICAL_CI_LOAD"}, \
- {0x40, "H_LOGICAL_CI_STORE"}, \
- {0x44, "H_LOGICAL_CACHE_LOAD"}, \
- {0x48, "H_LOGICAL_CACHE_STORE"}, \
- {0x4c, "H_LOGICAL_ICBI"}, \
- {0x50, "H_LOGICAL_DCBF"}, \
- {0x54, "H_GET_TERM_CHAR"}, \
- {0x58, "H_PUT_TERM_CHAR"}, \
- {0x5c, "H_REAL_TO_LOGICAL"}, \
- {0x60, "H_HYPERVISOR_DATA"}, \
- {0x64, "H_EOI"}, \
- {0x68, "H_CPPR"}, \
- {0x6c, "H_IPI"}, \
- {0x70, "H_IPOLL"}, \
- {0x74, "H_XIRR"}, \
- {0x78, "H_MIGRATE_DMA"}, \
- {0x7c, "H_PERFMON"}, \
- {0xdc, "H_REGISTER_VPA"}, \
- {0xe0, "H_CEDE"}, \
- {0xe4, "H_CONFER"}, \
- {0xe8, "H_PROD"}, \
- {0xec, "H_GET_PPP"}, \
- {0xf0, "H_SET_PPP"}, \
- {0xf4, "H_PURR"}, \
- {0xf8, "H_PIC"}, \
- {0xfc, "H_REG_CRQ"}, \
- {0x100, "H_FREE_CRQ"}, \
- {0x104, "H_VIO_SIGNAL"}, \
- {0x108, "H_SEND_CRQ"}, \
- {0x110, "H_COPY_RDMA"}, \
- {0x114, "H_REGISTER_LOGICAL_LAN"}, \
- {0x118, "H_FREE_LOGICAL_LAN"}, \
- {0x11c, "H_ADD_LOGICAL_LAN_BUFFER"}, \
- {0x120, "H_SEND_LOGICAL_LAN"}, \
- {0x124, "H_BULK_REMOVE"}, \
- {0x130, "H_MULTICAST_CTRL"}, \
- {0x134, "H_SET_XDABR"}, \
- {0x138, "H_STUFF_TCE"}, \
- {0x13c, "H_PUT_TCE_INDIRECT"}, \
- {0x14c, "H_CHANGE_LOGICAL_LAN_MAC"}, \
- {0x150, "H_VTERM_PARTNER_INFO"}, \
- {0x154, "H_REGISTER_VTERM"}, \
- {0x158, "H_FREE_VTERM"}, \
- {0x15c, "H_RESET_EVENTS"}, \
- {0x160, "H_ALLOC_RESOURCE"}, \
- {0x164, "H_FREE_RESOURCE"}, \
- {0x168, "H_MODIFY_QP"}, \
- {0x16c, "H_QUERY_QP"}, \
- {0x170, "H_REREGISTER_PMR"}, \
- {0x174, "H_REGISTER_SMR"}, \
- {0x178, "H_QUERY_MR"}, \
- {0x17c, "H_QUERY_MW"}, \
- {0x180, "H_QUERY_HCA"}, \
- {0x184, "H_QUERY_PORT"}, \
- {0x188, "H_MODIFY_PORT"}, \
- {0x18c, "H_DEFINE_AQP1"}, \
- {0x190, "H_GET_TRACE_BUFFER"}, \
- {0x194, "H_DEFINE_AQP0"}, \
- {0x198, "H_RESIZE_MR"}, \
- {0x19c, "H_ATTACH_MCQP"}, \
- {0x1a0, "H_DETACH_MCQP"}, \
- {0x1a4, "H_CREATE_RPT"}, \
- {0x1a8, "H_REMOVE_RPT"}, \
- {0x1ac, "H_REGISTER_RPAGES"}, \
- {0x1b0, "H_DISABLE_AND_GET"}, \
- {0x1b4, "H_ERROR_DATA"}, \
- {0x1b8, "H_GET_HCA_INFO"}, \
- {0x1bc, "H_GET_PERF_COUNT"}, \
- {0x1c0, "H_MANAGE_TRACE"}, \
- {0x1d4, "H_FREE_LOGICAL_LAN_BUFFER"}, \
- {0x1d8, "H_POLL_PENDING"}, \
- {0x1e4, "H_QUERY_INT_STATE"}, \
- {0x244, "H_ILLAN_ATTRIBUTES"}, \
- {0x250, "H_MODIFY_HEA_QP"}, \
- {0x254, "H_QUERY_HEA_QP"}, \
- {0x258, "H_QUERY_HEA"}, \
- {0x25c, "H_QUERY_HEA_PORT"}, \
- {0x260, "H_MODIFY_HEA_PORT"}, \
- {0x264, "H_REG_BCMC"}, \
- {0x268, "H_DEREG_BCMC"}, \
- {0x26c, "H_REGISTER_HEA_RPAGES"}, \
- {0x270, "H_DISABLE_AND_GET_HEA"}, \
- {0x274, "H_GET_HEA_INFO"}, \
- {0x278, "H_ALLOC_HEA_RESOURCE"}, \
- {0x284, "H_ADD_CONN"}, \
- {0x288, "H_DEL_CONN"}, \
- {0x298, "H_JOIN"}, \
- {0x2a4, "H_VASI_STATE"}, \
- {0x2b0, "H_ENABLE_CRQ"}, \
- {0x2b8, "H_GET_EM_PARMS"}, \
- {0x2d0, "H_SET_MPP"}, \
- {0x2d4, "H_GET_MPP"}, \
- {0x2ec, "H_HOME_NODE_ASSOCIATIVITY"}, \
- {0x2f4, "H_BEST_ENERGY"}, \
- {0x2fc, "H_XIRR_X"}, \
- {0x300, "H_RANDOM"}, \
- {0x304, "H_COP"}, \
- {0x314, "H_GET_MPP_X"}, \
- {0x31c, "H_SET_MODE"}, \
- {0xf000, "H_RTAS"} \
-
-#endif
diff --git a/tools/perf/arch/powerpc/util/book3s_hv_exits.h b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
deleted file mode 100644
index 2011376c7ab5..000000000000
--- a/tools/perf/arch/powerpc/util/book3s_hv_exits.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH_PERF_BOOK3S_HV_EXITS_H
-#define ARCH_PERF_BOOK3S_HV_EXITS_H
-
-/*
- * PowerPC Interrupt vectors : exit code to name mapping
- */
-
-#define kvm_trace_symbol_exit \
- {0x0, "RETURN_TO_HOST"}, \
- {0x100, "SYSTEM_RESET"}, \
- {0x200, "MACHINE_CHECK"}, \
- {0x300, "DATA_STORAGE"}, \
- {0x380, "DATA_SEGMENT"}, \
- {0x400, "INST_STORAGE"}, \
- {0x480, "INST_SEGMENT"}, \
- {0x500, "EXTERNAL"}, \
- {0x502, "EXTERNAL_HV"}, \
- {0x600, "ALIGNMENT"}, \
- {0x700, "PROGRAM"}, \
- {0x800, "FP_UNAVAIL"}, \
- {0x900, "DECREMENTER"}, \
- {0x980, "HV_DECREMENTER"}, \
- {0xc00, "SYSCALL"}, \
- {0xd00, "TRACE"}, \
- {0xe00, "H_DATA_STORAGE"}, \
- {0xe20, "H_INST_STORAGE"}, \
- {0xe40, "H_EMUL_ASSIST"}, \
- {0xf00, "PERFMON"}, \
- {0xf20, "ALTIVEC"}, \
- {0xf40, "VSX"}
-
-#endif
diff --git a/tools/perf/arch/powerpc/util/event.c b/tools/perf/arch/powerpc/util/event.c
deleted file mode 100644
index 77d8cc2b5691..000000000000
--- a/tools/perf/arch/powerpc/util/event.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/zalloc.h>
-
-#include "../../../util/event.h"
-#include "../../../util/synthetic-events.h"
-#include "../../../util/machine.h"
-#include "../../../util/tool.h"
-#include "../../../util/map.h"
-#include "../../../util/debug.h"
-#include "../../../util/sample.h"
-
-void arch_perf_parse_sample_weight(struct perf_sample *data,
- const __u64 *array, u64 type)
-{
- union perf_sample_weight weight;
-
- weight.full = *array;
- if (type & PERF_SAMPLE_WEIGHT)
- data->weight = weight.full;
- else {
- data->weight = weight.var1_dw;
- data->ins_lat = weight.var2_w;
- data->p_stage_cyc = weight.var3_w;
- }
-}
-
-void arch_perf_synthesize_sample_weight(const struct perf_sample *data,
- __u64 *array, u64 type)
-{
- *array = data->weight;
-
- if (type & PERF_SAMPLE_WEIGHT_STRUCT) {
- *array &= 0xffffffff;
- *array |= ((u64)data->ins_lat << 32);
- }
-}
-
-const char *arch_perf_header_entry(const char *se_header)
-{
- if (!strcmp(se_header, "Local INSTR Latency"))
- return "Finish Cyc";
- else if (!strcmp(se_header, "INSTR Latency"))
- return "Global Finish_cyc";
- else if (!strcmp(se_header, "Local Pipeline Stage Cycle"))
- return "Dispatch Cyc";
- else if (!strcmp(se_header, "Pipeline Stage Cycle"))
- return "Global Dispatch_cyc";
- return se_header;
-}
-
-int arch_support_sort_key(const char *sort_key)
-{
- if (!strcmp(sort_key, "p_stage_cyc"))
- return 1;
- if (!strcmp(sort_key, "local_p_stage_cyc"))
- return 1;
- return 0;
-}
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index c7df534dbf8f..0be74f048f96 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -14,8 +14,8 @@
static bool is_compat_mode(void)
{
- u64 base_platform = getauxval(AT_BASE_PLATFORM);
- u64 platform = getauxval(AT_PLATFORM);
+ unsigned long base_platform = getauxval(AT_BASE_PLATFORM);
+ unsigned long platform = getauxval(AT_PLATFORM);
if (!strcmp((char *)platform, (char *)base_platform))
return false;
diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c
deleted file mode 100644
index c8357b571ccf..000000000000
--- a/tools/perf/arch/powerpc/util/kvm-stat.c
+++ /dev/null
@@ -1,219 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <errno.h>
-#include "util/kvm-stat.h"
-#include "util/parse-events.h"
-#include "util/debug.h"
-#include "util/evsel.h"
-#include "util/evlist.h"
-#include "util/pmus.h"
-
-#include "book3s_hv_exits.h"
-#include "book3s_hcalls.h"
-#include <subcmd/parse-options.h>
-
-#define NR_TPS 4
-
-const char *vcpu_id_str = "vcpu_id";
-const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter";
-const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit";
-
-define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit);
-define_exit_reasons_table(hcall_reasons, kvm_trace_symbol_hcall);
-
-/* Tracepoints specific to ppc_book3s_hv */
-const char *ppc_book3s_hv_kvm_tp[] = {
- "kvm_hv:kvm_guest_enter",
- "kvm_hv:kvm_guest_exit",
- "kvm_hv:kvm_hcall_enter",
- "kvm_hv:kvm_hcall_exit",
- NULL,
-};
-
-/* 1 extra placeholder for NULL */
-const char *kvm_events_tp[NR_TPS + 1];
-const char *kvm_exit_reason;
-
-static void hcall_event_get_key(struct evsel *evsel,
- struct perf_sample *sample,
- struct event_key *key)
-{
- key->info = 0;
- key->key = evsel__intval(evsel, sample, "req");
-}
-
-static const char *get_hcall_exit_reason(u64 exit_code)
-{
- struct exit_reasons_table *tbl = hcall_reasons;
-
- while (tbl->reason != NULL) {
- if (tbl->exit_code == exit_code)
- return tbl->reason;
- tbl++;
- }
-
- pr_debug("Unknown hcall code: %lld\n",
- (unsigned long long)exit_code);
- return "UNKNOWN";
-}
-
-static bool hcall_event_end(struct evsel *evsel,
- struct perf_sample *sample __maybe_unused,
- struct event_key *key __maybe_unused)
-{
- return (evsel__name_is(evsel, kvm_events_tp[3]));
-}
-
-static bool hcall_event_begin(struct evsel *evsel,
- struct perf_sample *sample, struct event_key *key)
-{
- if (evsel__name_is(evsel, kvm_events_tp[2])) {
- hcall_event_get_key(evsel, sample, key);
- return true;
- }
-
- return false;
-}
-static void hcall_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
- struct event_key *key,
- char *decode)
-{
- const char *hcall_reason = get_hcall_exit_reason(key->key);
-
- scnprintf(decode, KVM_EVENT_NAME_LEN, "%s", hcall_reason);
-}
-
-static struct kvm_events_ops hcall_events = {
- .is_begin_event = hcall_event_begin,
- .is_end_event = hcall_event_end,
- .decode_key = hcall_event_decode_key,
- .name = "HCALL-EVENT",
-};
-
-static struct kvm_events_ops exit_events = {
- .is_begin_event = exit_event_begin,
- .is_end_event = exit_event_end,
- .decode_key = exit_event_decode_key,
- .name = "VM-EXIT"
-};
-
-struct kvm_reg_events_ops kvm_reg_events_ops[] = {
- { .name = "vmexit", .ops = &exit_events },
- { .name = "hcall", .ops = &hcall_events },
- { NULL, NULL },
-};
-
-const char * const kvm_skip_events[] = {
- NULL,
-};
-
-
-static int is_tracepoint_available(const char *str, struct evlist *evlist)
-{
- struct parse_events_error err;
- int ret;
-
- parse_events_error__init(&err);
- ret = parse_events(evlist, str, &err);
- if (ret)
- parse_events_error__print(&err, "tracepoint");
- parse_events_error__exit(&err);
- return ret;
-}
-
-static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm,
- struct evlist *evlist)
-{
- const char **events_ptr;
- int i, nr_tp = 0, err = -1;
-
- /* Check for book3s_hv tracepoints */
- for (events_ptr = ppc_book3s_hv_kvm_tp; *events_ptr; events_ptr++) {
- err = is_tracepoint_available(*events_ptr, evlist);
- if (err)
- return -1;
- nr_tp++;
- }
-
- for (i = 0; i < nr_tp; i++)
- kvm_events_tp[i] = ppc_book3s_hv_kvm_tp[i];
-
- kvm_events_tp[i] = NULL;
- kvm_exit_reason = "trap";
- kvm->exit_reasons = hv_exit_reasons;
- kvm->exit_reasons_isa = "HV";
-
- return 0;
-}
-
-/* Wrapper to setup kvm tracepoints */
-static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm)
-{
- struct evlist *evlist = evlist__new();
-
- if (evlist == NULL)
- return -ENOMEM;
-
- /* Right now, only supported on book3s_hv */
- return ppc__setup_book3s_hv(kvm, evlist);
-}
-
-int setup_kvm_events_tp(struct perf_kvm_stat *kvm)
-{
- return ppc__setup_kvm_tp(kvm);
-}
-
-int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
-{
- int ret;
-
- ret = ppc__setup_kvm_tp(kvm);
- if (ret) {
- kvm->exit_reasons = NULL;
- kvm->exit_reasons_isa = NULL;
- }
-
- return ret;
-}
-
-/*
- * In case of powerpc architecture, pmu registers are programmable
- * by guest kernel. So monitoring guest via host may not provide
- * valid samples with default 'cycles' event. It is better to use
- * 'trace_imc/trace_cycles' event for guest profiling, since it
- * can track the guest instruction pointer in the trace-record.
- *
- * Function to parse the arguments and return appropriate values.
- */
-int kvm_add_default_arch_event(int *argc, const char **argv)
-{
- const char **tmp;
- bool event = false;
- int i, j = *argc;
-
- const struct option event_options[] = {
- OPT_BOOLEAN('e', "event", &event, NULL),
- OPT_END()
- };
-
- tmp = calloc(j + 1, sizeof(char *));
- if (!tmp)
- return -EINVAL;
-
- for (i = 0; i < j; i++)
- tmp[i] = argv[i];
-
- parse_options(j, tmp, event_options, NULL, PARSE_OPT_KEEP_UNKNOWN);
- if (!event) {
- if (perf_pmus__have_event("trace_imc", "trace_cycles")) {
- argv[j++] = strdup("-e");
- argv[j++] = strdup("trace_imc/trace_cycles/");
- *argc += 2;
- } else {
- free(tmp);
- return -EINVAL;
- }
- }
-
- free(tmp);
- return 0;
-}
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
deleted file mode 100644
index bd36cfd420a2..000000000000
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ /dev/null
@@ -1,240 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <errno.h>
-#include <string.h>
-#include <regex.h>
-#include <linux/zalloc.h>
-
-#include "perf_regs.h"
-#include "../../../util/perf_regs.h"
-#include "../../../util/debug.h"
-#include "../../../util/event.h"
-#include "../../../util/header.h"
-#include "../../../perf-sys.h"
-#include "utils_header.h"
-
-#include <linux/kernel.h>
-
-#define PVR_POWER9 0x004E
-#define PVR_POWER10 0x0080
-#define PVR_POWER11 0x0082
-
-static const struct sample_reg sample_reg_masks[] = {
- SMPL_REG(r0, PERF_REG_POWERPC_R0),
- SMPL_REG(r1, PERF_REG_POWERPC_R1),
- SMPL_REG(r2, PERF_REG_POWERPC_R2),
- SMPL_REG(r3, PERF_REG_POWERPC_R3),
- SMPL_REG(r4, PERF_REG_POWERPC_R4),
- SMPL_REG(r5, PERF_REG_POWERPC_R5),
- SMPL_REG(r6, PERF_REG_POWERPC_R6),
- SMPL_REG(r7, PERF_REG_POWERPC_R7),
- SMPL_REG(r8, PERF_REG_POWERPC_R8),
- SMPL_REG(r9, PERF_REG_POWERPC_R9),
- SMPL_REG(r10, PERF_REG_POWERPC_R10),
- SMPL_REG(r11, PERF_REG_POWERPC_R11),
- SMPL_REG(r12, PERF_REG_POWERPC_R12),
- SMPL_REG(r13, PERF_REG_POWERPC_R13),
- SMPL_REG(r14, PERF_REG_POWERPC_R14),
- SMPL_REG(r15, PERF_REG_POWERPC_R15),
- SMPL_REG(r16, PERF_REG_POWERPC_R16),
- SMPL_REG(r17, PERF_REG_POWERPC_R17),
- SMPL_REG(r18, PERF_REG_POWERPC_R18),
- SMPL_REG(r19, PERF_REG_POWERPC_R19),
- SMPL_REG(r20, PERF_REG_POWERPC_R20),
- SMPL_REG(r21, PERF_REG_POWERPC_R21),
- SMPL_REG(r22, PERF_REG_POWERPC_R22),
- SMPL_REG(r23, PERF_REG_POWERPC_R23),
- SMPL_REG(r24, PERF_REG_POWERPC_R24),
- SMPL_REG(r25, PERF_REG_POWERPC_R25),
- SMPL_REG(r26, PERF_REG_POWERPC_R26),
- SMPL_REG(r27, PERF_REG_POWERPC_R27),
- SMPL_REG(r28, PERF_REG_POWERPC_R28),
- SMPL_REG(r29, PERF_REG_POWERPC_R29),
- SMPL_REG(r30, PERF_REG_POWERPC_R30),
- SMPL_REG(r31, PERF_REG_POWERPC_R31),
- SMPL_REG(nip, PERF_REG_POWERPC_NIP),
- SMPL_REG(msr, PERF_REG_POWERPC_MSR),
- SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
- SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
- SMPL_REG(link, PERF_REG_POWERPC_LINK),
- SMPL_REG(xer, PERF_REG_POWERPC_XER),
- SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
- SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
- SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
- SMPL_REG(dar, PERF_REG_POWERPC_DAR),
- SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
- SMPL_REG(sier, PERF_REG_POWERPC_SIER),
- SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
- SMPL_REG(mmcr0, PERF_REG_POWERPC_MMCR0),
- SMPL_REG(mmcr1, PERF_REG_POWERPC_MMCR1),
- SMPL_REG(mmcr2, PERF_REG_POWERPC_MMCR2),
- SMPL_REG(mmcr3, PERF_REG_POWERPC_MMCR3),
- SMPL_REG(sier2, PERF_REG_POWERPC_SIER2),
- SMPL_REG(sier3, PERF_REG_POWERPC_SIER3),
- SMPL_REG(pmc1, PERF_REG_POWERPC_PMC1),
- SMPL_REG(pmc2, PERF_REG_POWERPC_PMC2),
- SMPL_REG(pmc3, PERF_REG_POWERPC_PMC3),
- SMPL_REG(pmc4, PERF_REG_POWERPC_PMC4),
- SMPL_REG(pmc5, PERF_REG_POWERPC_PMC5),
- SMPL_REG(pmc6, PERF_REG_POWERPC_PMC6),
- SMPL_REG(sdar, PERF_REG_POWERPC_SDAR),
- SMPL_REG(siar, PERF_REG_POWERPC_SIAR),
- SMPL_REG_END
-};
-
-/* REG or %rREG */
-#define SDT_OP_REGEX1 "^(%r)?([1-2]?[0-9]|3[0-1])$"
-
-/* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
-#define SDT_OP_REGEX2 "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
-
-static regex_t sdt_op_regex1, sdt_op_regex2;
-
-static int sdt_init_op_regex(void)
-{
- static int initialized;
- int ret = 0;
-
- if (initialized)
- return 0;
-
- ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
- if (ret)
- goto error;
-
- ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
- if (ret)
- goto free_regex1;
-
- initialized = 1;
- return 0;
-
-free_regex1:
- regfree(&sdt_op_regex1);
-error:
- pr_debug4("Regex compilation error.\n");
- return ret;
-}
-
-/*
- * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
- * Possible variants of OP are:
- * Format Example
- * -------------------------
- * NUM(REG) 48(18)
- * -NUM(REG) -48(18)
- * NUM(%rREG) 48(%r18)
- * -NUM(%rREG) -48(%r18)
- * REG 18
- * %rREG %r18
- * iNUM i0
- * i-NUM i-1
- *
- * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
- * and REG form with -mno-regnames. Here REG is general purpose register,
- * which is in 0 to 31 range.
- */
-int arch_sdt_arg_parse_op(char *old_op, char **new_op)
-{
- int ret, new_len;
- regmatch_t rm[5];
- char prefix;
-
- /* Constant argument. Uprobe does not support it */
- if (old_op[0] == 'i') {
- pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
- return SDT_ARG_SKIP;
- }
-
- ret = sdt_init_op_regex();
- if (ret < 0)
- return ret;
-
- if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
- /* REG or %rREG --> %gprREG */
-
- new_len = 5; /* % g p r NULL */
- new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
-
- *new_op = zalloc(new_len);
- if (!*new_op)
- return -ENOMEM;
-
- scnprintf(*new_op, new_len, "%%gpr%.*s",
- (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
- } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
- /*
- * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
- * +/-NUM(%gprREG)
- */
- prefix = (rm[1].rm_so == -1) ? '+' : '-';
-
- new_len = 8; /* +/- ( % g p r ) NULL */
- new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
- new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
-
- *new_op = zalloc(new_len);
- if (!*new_op)
- return -ENOMEM;
-
- scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
- (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
- (int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
- } else {
- pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
- return SDT_ARG_SKIP;
- }
-
- return SDT_ARG_VALID;
-}
-
-uint64_t arch__intr_reg_mask(void)
-{
- struct perf_event_attr attr = {
- .type = PERF_TYPE_HARDWARE,
- .config = PERF_COUNT_HW_CPU_CYCLES,
- .sample_type = PERF_SAMPLE_REGS_INTR,
- .precise_ip = 1,
- .disabled = 1,
- .exclude_kernel = 1,
- };
- int fd;
- u32 version;
- u64 extended_mask = 0, mask = PERF_REGS_MASK;
-
- /*
- * Get the PVR value to set the extended
- * mask specific to platform.
- */
- version = (((mfspr(SPRN_PVR)) >> 16) & 0xFFFF);
- if (version == PVR_POWER9)
- extended_mask = PERF_REG_PMU_MASK_300;
- else if ((version == PVR_POWER10) || (version == PVR_POWER11))
- extended_mask = PERF_REG_PMU_MASK_31;
- else
- return mask;
-
- attr.sample_regs_intr = extended_mask;
- attr.sample_period = 1;
- event_attr_init(&attr);
-
- /*
- * check if the pmu supports perf extended regs, before
- * returning the register mask to sample.
- */
- fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
- if (fd != -1) {
- close(fd);
- mask |= extended_mask;
- }
- return mask;
-}
-
-uint64_t arch__user_reg_mask(void)
-{
- return PERF_REGS_MASK;
-}
-
-const struct sample_reg *arch__sample_reg_masks(void)
-{
- return sample_reg_masks;
-}
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index 356786432fd3..e57f10798fa6 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -30,14 +30,6 @@
* The libdwfl code in this file is based on code from elfutils
* (libdwfl/argp-std.c, libdwfl/tests/addrcfi.c, etc).
*/
-static char *debuginfo_path;
-
-static const Dwfl_Callbacks offline_callbacks = {
- .debuginfo_path = &debuginfo_path,
- .find_debuginfo = dwfl_standard_find_debuginfo,
- .section_address = dwfl_offline_section_address,
-};
-
/*
* Use the DWARF expression for the Call-frame-address and determine
@@ -149,44 +141,22 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
* yet used)
* -1 in case of errors
*/
-static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc)
+static int check_return_addr(struct dso *dso, Dwarf_Addr mapped_pc)
{
int rc = -1;
Dwfl *dwfl;
Dwfl_Module *mod;
Dwarf_Frame *frame;
int ra_regno;
- Dwarf_Addr start = pc;
- Dwarf_Addr end = pc;
+ Dwarf_Addr start = mapped_pc;
+ Dwarf_Addr end = mapped_pc;
bool signalp;
- const char *exec_file = dso__long_name(dso);
-
- dwfl = RC_CHK_ACCESS(dso)->dwfl;
-
- if (!dwfl) {
- dwfl = dwfl_begin(&offline_callbacks);
- if (!dwfl) {
- pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
- return -1;
- }
-
- mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1,
- map_start, false);
- if (!mod) {
- pr_debug("dwfl_report_elf() failed %s\n",
- dwarf_errmsg(-1));
- /*
- * We normally cache the DWARF debug info and never
- * call dwfl_end(). But to prevent fd leak, free in
- * case of error.
- */
- dwfl_end(dwfl);
- goto out;
- }
- RC_CHK_ACCESS(dso)->dwfl = dwfl;
- }
- mod = dwfl_addrmodule(dwfl, pc);
+ dwfl = dso__libdw_dwfl(dso);
+ if (!dwfl)
+ return -1;
+
+ mod = dwfl_addrmodule(dwfl, mapped_pc);
if (!mod) {
pr_debug("dwfl_addrmodule() failed, %s\n", dwarf_errmsg(-1));
goto out;
@@ -196,9 +166,9 @@ static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc)
* To work with split debug info files (eg: glibc), check both
* .eh_frame and .debug_frame sections of the ELF header.
*/
- frame = get_eh_frame(mod, pc);
+ frame = get_eh_frame(mod, mapped_pc);
if (!frame) {
- frame = get_dwarf_frame(mod, pc);
+ frame = get_dwarf_frame(mod, mapped_pc);
if (!frame)
goto out;
}
@@ -264,7 +234,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
return skip_slot;
}
- rc = check_return_addr(dso, map__start(al.map), ip);
+ rc = check_return_addr(dso, map__map_ip(al.map, ip));
pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n",
dso__long_name(dso), al.sym->name, ip, rc);
diff --git a/tools/perf/arch/powerpc/util/unwind-libdw.c b/tools/perf/arch/powerpc/util/unwind-libdw.c
deleted file mode 100644
index e9a5a8bb67d9..000000000000
--- a/tools/perf/arch/powerpc/util/unwind-libdw.c
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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"
-
-/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils. */
-static const int special_regs[3][2] = {
- { 65, PERF_REG_POWERPC_LINK },
- { 101, PERF_REG_POWERPC_XER },
- { 109, PERF_REG_POWERPC_CTR },
-};
-
-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[32], dwarf_nip;
- size_t i;
-
-#define REG(r) ({ \
- Dwarf_Word val = 0; \
- perf_reg_value(&val, user_regs, PERF_REG_POWERPC_##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, 32, dwarf_regs))
- return false;
-
- dwarf_nip = REG(NIP);
- dwfl_thread_state_register_pc(thread, dwarf_nip);
- for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
- Dwarf_Word val = 0;
- perf_reg_value(&val, user_regs, special_regs[i][1]);
- if (!dwfl_thread_state_registers(thread,
- special_regs[i][0], 1,
- &val))
- return false;
- }
-
- return true;
-}
diff --git a/tools/perf/arch/powerpc/util/unwind-libunwind.c b/tools/perf/arch/powerpc/util/unwind-libunwind.c
deleted file mode 100644
index 90a6beda20de..000000000000
--- a/tools/perf/arch/powerpc/util/unwind-libunwind.c
+++ /dev/null
@@ -1,92 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2016 Chandan Kumar, IBM Corporation.
- */
-
-#include <errno.h>
-#include <libunwind.h>
-#include <asm/perf_regs.h>
-#include "../../util/unwind.h"
-#include "../../util/debug.h"
-
-int libunwind__arch_reg_id(int regnum)
-{
- switch (regnum) {
- case UNW_PPC64_R0:
- return PERF_REG_POWERPC_R0;
- case UNW_PPC64_R1:
- return PERF_REG_POWERPC_R1;
- case UNW_PPC64_R2:
- return PERF_REG_POWERPC_R2;
- case UNW_PPC64_R3:
- return PERF_REG_POWERPC_R3;
- case UNW_PPC64_R4:
- return PERF_REG_POWERPC_R4;
- case UNW_PPC64_R5:
- return PERF_REG_POWERPC_R5;
- case UNW_PPC64_R6:
- return PERF_REG_POWERPC_R6;
- case UNW_PPC64_R7:
- return PERF_REG_POWERPC_R7;
- case UNW_PPC64_R8:
- return PERF_REG_POWERPC_R8;
- case UNW_PPC64_R9:
- return PERF_REG_POWERPC_R9;
- case UNW_PPC64_R10:
- return PERF_REG_POWERPC_R10;
- case UNW_PPC64_R11:
- return PERF_REG_POWERPC_R11;
- case UNW_PPC64_R12:
- return PERF_REG_POWERPC_R12;
- case UNW_PPC64_R13:
- return PERF_REG_POWERPC_R13;
- case UNW_PPC64_R14:
- return PERF_REG_POWERPC_R14;
- case UNW_PPC64_R15:
- return PERF_REG_POWERPC_R15;
- case UNW_PPC64_R16:
- return PERF_REG_POWERPC_R16;
- case UNW_PPC64_R17:
- return PERF_REG_POWERPC_R17;
- case UNW_PPC64_R18:
- return PERF_REG_POWERPC_R18;
- case UNW_PPC64_R19:
- return PERF_REG_POWERPC_R19;
- case UNW_PPC64_R20:
- return PERF_REG_POWERPC_R20;
- case UNW_PPC64_R21:
- return PERF_REG_POWERPC_R21;
- case UNW_PPC64_R22:
- return PERF_REG_POWERPC_R22;
- case UNW_PPC64_R23:
- return PERF_REG_POWERPC_R23;
- case UNW_PPC64_R24:
- return PERF_REG_POWERPC_R24;
- case UNW_PPC64_R25:
- return PERF_REG_POWERPC_R25;
- case UNW_PPC64_R26:
- return PERF_REG_POWERPC_R26;
- case UNW_PPC64_R27:
- return PERF_REG_POWERPC_R27;
- case UNW_PPC64_R28:
- return PERF_REG_POWERPC_R28;
- case UNW_PPC64_R29:
- return PERF_REG_POWERPC_R29;
- case UNW_PPC64_R30:
- return PERF_REG_POWERPC_R30;
- case UNW_PPC64_R31:
- return PERF_REG_POWERPC_R31;
- case UNW_PPC64_LR:
- return PERF_REG_POWERPC_LINK;
- case UNW_PPC64_CTR:
- return PERF_REG_POWERPC_CTR;
- case UNW_PPC64_XER:
- return PERF_REG_POWERPC_XER;
- case UNW_PPC64_NIP:
- return PERF_REG_POWERPC_NIP;
- default:
- pr_err("unwind: invalid reg id %d\n", regnum);
- return -EINVAL;
- }
- return -EINVAL;
-}