summaryrefslogtreecommitdiff
path: root/tools/perf/arch/arm64/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/arch/arm64/util')
-rw-r--r--tools/perf/arch/arm64/util/Build19
-rw-r--r--tools/perf/arch/arm64/util/arm-spe.c309
-rw-r--r--tools/perf/arch/arm64/util/dwarf-regs.c92
-rw-r--r--tools/perf/arch/arm64/util/header.c76
-rw-r--r--tools/perf/arch/arm64/util/hisi-ptt.c1
-rw-r--r--tools/perf/arch/arm64/util/pmu.c25
-rw-r--r--tools/perf/arch/arm64/util/unwind-libdw.c2
7 files changed, 282 insertions, 242 deletions
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index 78ef7115be3d..a74521b79eaa 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -1,14 +1,13 @@
-perf-y += header.o
-perf-y += machine.o
-perf-y += perf_regs.o
-perf-y += tsc.o
-perf-y += pmu.o
-perf-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o
-perf-$(CONFIG_DWARF) += dwarf-regs.o
-perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
-perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-util-y += header.o
+perf-util-y += machine.o
+perf-util-y += perf_regs.o
+perf-util-y += tsc.o
+perf-util-y += pmu.o
+perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o
+perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
+perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
-perf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
+perf-util-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
../../arm/util/auxtrace.o \
../../arm/util/cs-etm.o \
arm-spe.o mem-events.o hisi-ptt.o
diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c
index 51ccbfd3d246..4f2833b62ff5 100644
--- a/tools/perf/arch/arm64/util/arm-spe.c
+++ b/tools/perf/arch/arm64/util/arm-spe.c
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/log2.h>
+#include <linux/string.h>
#include <linux/zalloc.h>
#include <time.h>
@@ -22,9 +23,12 @@
#include "../../../util/debug.h"
#include "../../../util/auxtrace.h"
#include "../../../util/record.h"
+#include "../../../util/header.h"
#include "../../../util/arm-spe.h"
#include <tools/libc_compat.h> // reallocarray
+#define ARM_SPE_CPU_MAGIC 0x1010101010101010ULL
+
#define KiB(x) ((x) * 1024)
#define MiB(x) ((x) * 1024 * 1024)
@@ -36,11 +40,97 @@ struct arm_spe_recording {
bool *wrapped;
};
+/* Iterate config list to detect if the "freq" parameter is set */
+static bool arm_spe_is_set_freq(struct evsel *evsel)
+{
+ struct evsel_config_term *term;
+
+ list_for_each_entry(term, &evsel->config_terms, list) {
+ if (term->type == EVSEL__CONFIG_TERM_FREQ)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * arm_spe_find_cpus() returns a new cpu map, and the caller should invoke
+ * perf_cpu_map__put() to release the map after use.
+ */
+static struct perf_cpu_map *arm_spe_find_cpus(struct evlist *evlist)
+{
+ struct perf_cpu_map *event_cpus = evlist->core.user_requested_cpus;
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new_online_cpus();
+ struct perf_cpu_map *intersect_cpus;
+
+ /* cpu map is not "any" CPU , we have specific CPUs to work with */
+ if (!perf_cpu_map__has_any_cpu(event_cpus)) {
+ intersect_cpus = perf_cpu_map__intersect(event_cpus, online_cpus);
+ perf_cpu_map__put(online_cpus);
+ /* Event can be "any" CPU so count all CPUs. */
+ } else {
+ intersect_cpus = online_cpus;
+ }
+
+ return intersect_cpus;
+}
+
static size_t
arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused,
- struct evlist *evlist __maybe_unused)
+ struct evlist *evlist)
{
- return ARM_SPE_AUXTRACE_PRIV_SIZE;
+ struct perf_cpu_map *cpu_map = arm_spe_find_cpus(evlist);
+ size_t size;
+
+ if (!cpu_map)
+ return 0;
+
+ size = ARM_SPE_AUXTRACE_PRIV_MAX +
+ ARM_SPE_CPU_PRIV_MAX * perf_cpu_map__nr(cpu_map);
+ size *= sizeof(u64);
+
+ perf_cpu_map__put(cpu_map);
+ return size;
+}
+
+static int arm_spe_save_cpu_header(struct auxtrace_record *itr,
+ struct perf_cpu cpu, __u64 data[])
+{
+ struct arm_spe_recording *sper =
+ container_of(itr, struct arm_spe_recording, itr);
+ struct perf_pmu *pmu = NULL;
+ char *cpuid = NULL;
+ u64 val;
+
+ /* Read CPU MIDR */
+ cpuid = get_cpuid_allow_env_override(cpu);
+ if (!cpuid)
+ return -ENOMEM;
+ val = strtol(cpuid, NULL, 16);
+
+ data[ARM_SPE_MAGIC] = ARM_SPE_CPU_MAGIC;
+ data[ARM_SPE_CPU] = cpu.cpu;
+ data[ARM_SPE_CPU_NR_PARAMS] = ARM_SPE_CPU_PRIV_MAX - ARM_SPE_CPU_MIDR;
+ data[ARM_SPE_CPU_MIDR] = val;
+
+ /* Find the associate Arm SPE PMU for the CPU */
+ if (perf_cpu_map__has(sper->arm_spe_pmu->cpus, cpu))
+ pmu = sper->arm_spe_pmu;
+
+ if (!pmu) {
+ /* No Arm SPE PMU is found */
+ data[ARM_SPE_CPU_PMU_TYPE] = ULLONG_MAX;
+ data[ARM_SPE_CAP_MIN_IVAL] = 0;
+ } else {
+ data[ARM_SPE_CPU_PMU_TYPE] = pmu->type;
+
+ if (perf_pmu__scan_file(pmu, "caps/min_interval", "%lu", &val) != 1)
+ val = 0;
+ data[ARM_SPE_CAP_MIN_IVAL] = val;
+ }
+
+ free(cpuid);
+ return ARM_SPE_CPU_PRIV_MAX;
}
static int arm_spe_info_fill(struct auxtrace_record *itr,
@@ -48,20 +138,46 @@ static int arm_spe_info_fill(struct auxtrace_record *itr,
struct perf_record_auxtrace_info *auxtrace_info,
size_t priv_size)
{
+ int i, ret;
+ size_t offset;
struct arm_spe_recording *sper =
container_of(itr, struct arm_spe_recording, itr);
struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
+ struct perf_cpu_map *cpu_map;
+ struct perf_cpu cpu;
+ __u64 *data;
- if (priv_size != ARM_SPE_AUXTRACE_PRIV_SIZE)
+ if (priv_size != arm_spe_info_priv_size(itr, session->evlist))
return -EINVAL;
if (!session->evlist->core.nr_mmaps)
return -EINVAL;
+ cpu_map = arm_spe_find_cpus(session->evlist);
+ if (!cpu_map)
+ return -EINVAL;
+
auxtrace_info->type = PERF_AUXTRACE_ARM_SPE;
- auxtrace_info->priv[ARM_SPE_PMU_TYPE] = arm_spe_pmu->type;
+ auxtrace_info->priv[ARM_SPE_HEADER_VERSION] = ARM_SPE_HEADER_CURRENT_VERSION;
+ auxtrace_info->priv[ARM_SPE_HEADER_SIZE] =
+ ARM_SPE_AUXTRACE_PRIV_MAX - ARM_SPE_HEADER_VERSION;
+ auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2] = arm_spe_pmu->type;
+ auxtrace_info->priv[ARM_SPE_CPUS_NUM] = perf_cpu_map__nr(cpu_map);
+
+ offset = ARM_SPE_AUXTRACE_PRIV_MAX;
+ perf_cpu_map__for_each_cpu(cpu, i, cpu_map) {
+ assert(offset < priv_size);
+ data = &auxtrace_info->priv[offset];
+ ret = arm_spe_save_cpu_header(itr, cpu, data);
+ if (ret < 0)
+ goto out;
+ offset += ret;
+ }
- return 0;
+ ret = 0;
+out:
+ perf_cpu_map__put(cpu_map);
+ return ret;
}
static void
@@ -132,38 +248,48 @@ static __u64 arm_spe_pmu__sample_period(const struct perf_pmu *arm_spe_pmu)
return sample_period;
}
-static int arm_spe_recording_options(struct auxtrace_record *itr,
- struct evlist *evlist,
- struct record_opts *opts)
+static void arm_spe_setup_evsel(struct evsel *evsel, struct perf_cpu_map *cpus)
{
- struct arm_spe_recording *sper =
- container_of(itr, struct arm_spe_recording, itr);
- struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
- struct evsel *evsel, *arm_spe_evsel = NULL;
- struct perf_cpu_map *cpus = evlist->core.user_requested_cpus;
- bool privileged = perf_event_paranoid_check(-1);
- struct evsel *tracking_evsel;
- int err;
u64 bit;
- sper->evlist = evlist;
+ evsel->core.attr.freq = 0;
+ evsel->core.attr.sample_period = arm_spe_pmu__sample_period(evsel->pmu);
+ evsel->needs_auxtrace_mmap = true;
- evlist__for_each_entry(evlist, evsel) {
- if (evsel->core.attr.type == arm_spe_pmu->type) {
- if (arm_spe_evsel) {
- pr_err("There may be only one " ARM_SPE_PMU_NAME "x event\n");
- return -EINVAL;
- }
- evsel->core.attr.freq = 0;
- evsel->core.attr.sample_period = arm_spe_pmu__sample_period(arm_spe_pmu);
- evsel->needs_auxtrace_mmap = true;
- arm_spe_evsel = evsel;
- opts->full_auxtrace = true;
- }
+ /*
+ * To obtain the auxtrace buffer file descriptor, the auxtrace event
+ * must come first.
+ */
+ evlist__to_front(evsel->evlist, evsel);
+
+ /*
+ * In the case of per-cpu mmaps, sample CPU for AUX event;
+ * also enable the timestamp tracing for samples correlation.
+ */
+ if (!perf_cpu_map__is_any_cpu_or_is_empty(cpus)) {
+ evsel__set_sample_bit(evsel, CPU);
+ evsel__set_config_if_unset(evsel->pmu, evsel, "ts_enable", 1);
}
- if (!opts->full_auxtrace)
- return 0;
+ /*
+ * Set this only so that perf report knows that SPE generates memory info. It has no effect
+ * on the opening of the event or the SPE data produced.
+ */
+ evsel__set_sample_bit(evsel, DATA_SRC);
+
+ /*
+ * The PHYS_ADDR flag does not affect the driver behaviour, it is used to
+ * inform that the resulting output's SPE samples contain physical addresses
+ * where applicable.
+ */
+ bit = perf_pmu__format_bits(evsel->pmu, "pa_enable");
+ if (evsel->core.attr.config & bit)
+ evsel__set_sample_bit(evsel, PHYS_ADDR);
+}
+
+static int arm_spe_setup_aux_buffer(struct record_opts *opts)
+{
+ bool privileged = perf_event_paranoid_check(-1);
/*
* we are in snapshot mode.
@@ -193,6 +319,9 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
return -EINVAL;
}
+
+ pr_debug2("%sx snapshot size: %zu\n", ARM_SPE_PMU_NAME,
+ opts->auxtrace_snapshot_size);
}
/* We are in full trace mode but '-m,xyz' wasn't specified */
@@ -218,40 +347,15 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
}
}
- if (opts->auxtrace_snapshot_mode)
- pr_debug2("%sx snapshot size: %zu\n", ARM_SPE_PMU_NAME,
- opts->auxtrace_snapshot_size);
-
- /*
- * To obtain the auxtrace buffer file descriptor, the auxtrace event
- * must come first.
- */
- evlist__to_front(evlist, arm_spe_evsel);
-
- /*
- * In the case of per-cpu mmaps, sample CPU for AUX event;
- * also enable the timestamp tracing for samples correlation.
- */
- if (!perf_cpu_map__has_any_cpu_or_is_empty(cpus)) {
- evsel__set_sample_bit(arm_spe_evsel, CPU);
- evsel__set_config_if_unset(arm_spe_pmu, arm_spe_evsel,
- "ts_enable", 1);
- }
-
- /*
- * Set this only so that perf report knows that SPE generates memory info. It has no effect
- * on the opening of the event or the SPE data produced.
- */
- evsel__set_sample_bit(arm_spe_evsel, DATA_SRC);
+ return 0;
+}
- /*
- * The PHYS_ADDR flag does not affect the driver behaviour, it is used to
- * inform that the resulting output's SPE samples contain physical addresses
- * where applicable.
- */
- bit = perf_pmu__format_bits(arm_spe_pmu, "pa_enable");
- if (arm_spe_evsel->core.attr.config & bit)
- evsel__set_sample_bit(arm_spe_evsel, PHYS_ADDR);
+static int arm_spe_setup_tracking_event(struct evlist *evlist,
+ struct record_opts *opts)
+{
+ int err;
+ struct evsel *tracking_evsel;
+ struct perf_cpu_map *cpus = evlist->core.user_requested_cpus;
/* Add dummy event to keep tracking */
err = parse_event(evlist, "dummy:u");
@@ -265,7 +369,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
tracking_evsel->core.attr.sample_period = 1;
/* In per-cpu case, always need the time of mmap events etc */
- if (!perf_cpu_map__has_any_cpu_or_is_empty(cpus)) {
+ if (!perf_cpu_map__is_any_cpu_or_is_empty(cpus)) {
evsel__set_sample_bit(tracking_evsel, TIME);
evsel__set_sample_bit(tracking_evsel, CPU);
@@ -277,6 +381,60 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
return 0;
}
+static int arm_spe_recording_options(struct auxtrace_record *itr,
+ struct evlist *evlist,
+ struct record_opts *opts)
+{
+ struct arm_spe_recording *sper =
+ container_of(itr, struct arm_spe_recording, itr);
+ struct evsel *evsel, *tmp;
+ struct perf_cpu_map *cpus = evlist->core.user_requested_cpus;
+ bool discard = false;
+ int err;
+
+ sper->evlist = evlist;
+
+ evlist__for_each_entry(evlist, evsel) {
+ if (evsel__is_aux_event(evsel)) {
+ if (!strstarts(evsel->pmu->name, ARM_SPE_PMU_NAME)) {
+ pr_err("Found unexpected auxtrace event: %s\n",
+ evsel->pmu->name);
+ return -EINVAL;
+ }
+ opts->full_auxtrace = true;
+
+ if (opts->user_freq != UINT_MAX ||
+ arm_spe_is_set_freq(evsel)) {
+ pr_err("Arm SPE: Frequency is not supported. "
+ "Set period with -c option or PMU parameter (-e %s/period=NUM/).\n",
+ evsel->pmu->name);
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (!opts->full_auxtrace)
+ return 0;
+
+ evlist__for_each_entry_safe(evlist, tmp, evsel) {
+ if (evsel__is_aux_event(evsel)) {
+ arm_spe_setup_evsel(evsel, cpus);
+ if (evsel->core.attr.config &
+ perf_pmu__format_bits(evsel->pmu, "discard"))
+ discard = true;
+ }
+ }
+
+ if (discard)
+ return 0;
+
+ err = arm_spe_setup_aux_buffer(opts);
+ if (err)
+ return err;
+
+ return arm_spe_setup_tracking_event(evlist, opts);
+}
+
static int arm_spe_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
struct record_opts *opts,
const char *str)
@@ -301,12 +459,16 @@ static int arm_spe_snapshot_start(struct auxtrace_record *itr)
struct arm_spe_recording *ptr =
container_of(itr, struct arm_spe_recording, itr);
struct evsel *evsel;
+ int ret = -EINVAL;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->core.attr.type == ptr->arm_spe_pmu->type)
- return evsel__disable(evsel);
+ if (evsel__is_aux_event(evsel)) {
+ ret = evsel__disable(evsel);
+ if (ret < 0)
+ return ret;
+ }
}
- return -EINVAL;
+ return ret;
}
static int arm_spe_snapshot_finish(struct auxtrace_record *itr)
@@ -314,12 +476,16 @@ static int arm_spe_snapshot_finish(struct auxtrace_record *itr)
struct arm_spe_recording *ptr =
container_of(itr, struct arm_spe_recording, itr);
struct evsel *evsel;
+ int ret = -EINVAL;
evlist__for_each_entry(ptr->evlist, evsel) {
- if (evsel->core.attr.type == ptr->arm_spe_pmu->type)
- return evsel__enable(evsel);
+ if (evsel__is_aux_event(evsel)) {
+ ret = evsel__enable(evsel);
+ if (ret < 0)
+ return ret;
+ }
}
- return -EINVAL;
+ return ret;
}
static int arm_spe_alloc_wrapped_array(struct arm_spe_recording *ptr, int idx)
@@ -497,7 +663,6 @@ struct auxtrace_record *arm_spe_recording_init(int *err,
}
sper->arm_spe_pmu = arm_spe_pmu;
- sper->itr.pmu = arm_spe_pmu;
sper->itr.snapshot_start = arm_spe_snapshot_start;
sper->itr.snapshot_finish = arm_spe_snapshot_finish;
sper->itr.find_snapshot = arm_spe_find_snapshot;
diff --git a/tools/perf/arch/arm64/util/dwarf-regs.c b/tools/perf/arch/arm64/util/dwarf-regs.c
deleted file mode 100644
index 917b97d7c5d3..000000000000
--- a/tools/perf/arch/arm64/util/dwarf-regs.c
+++ /dev/null
@@ -1,92 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Mapping of DWARF debug register numbers into register names.
- *
- * Copyright (C) 2010 Will Deacon, ARM Ltd.
- */
-
-#include <errno.h>
-#include <stddef.h>
-#include <string.h>
-#include <dwarf-regs.h>
-#include <linux/ptrace.h> /* for struct user_pt_regs */
-#include <linux/stringify.h>
-
-struct pt_regs_dwarfnum {
- const char *name;
- unsigned int dwarfnum;
-};
-
-#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
-#define GPR_DWARFNUM_NAME(num) \
- {.name = __stringify(%x##num), .dwarfnum = num}
-#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
-#define DWARFNUM2OFFSET(index) \
- (index * sizeof((struct user_pt_regs *)0)->regs[0])
-
-/*
- * Reference:
- * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
- */
-static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
- GPR_DWARFNUM_NAME(0),
- GPR_DWARFNUM_NAME(1),
- GPR_DWARFNUM_NAME(2),
- GPR_DWARFNUM_NAME(3),
- GPR_DWARFNUM_NAME(4),
- GPR_DWARFNUM_NAME(5),
- GPR_DWARFNUM_NAME(6),
- GPR_DWARFNUM_NAME(7),
- GPR_DWARFNUM_NAME(8),
- GPR_DWARFNUM_NAME(9),
- GPR_DWARFNUM_NAME(10),
- GPR_DWARFNUM_NAME(11),
- GPR_DWARFNUM_NAME(12),
- GPR_DWARFNUM_NAME(13),
- GPR_DWARFNUM_NAME(14),
- GPR_DWARFNUM_NAME(15),
- GPR_DWARFNUM_NAME(16),
- GPR_DWARFNUM_NAME(17),
- GPR_DWARFNUM_NAME(18),
- GPR_DWARFNUM_NAME(19),
- GPR_DWARFNUM_NAME(20),
- GPR_DWARFNUM_NAME(21),
- GPR_DWARFNUM_NAME(22),
- GPR_DWARFNUM_NAME(23),
- GPR_DWARFNUM_NAME(24),
- GPR_DWARFNUM_NAME(25),
- GPR_DWARFNUM_NAME(26),
- GPR_DWARFNUM_NAME(27),
- GPR_DWARFNUM_NAME(28),
- GPR_DWARFNUM_NAME(29),
- REG_DWARFNUM_NAME("%lr", 30),
- REG_DWARFNUM_NAME("%sp", 31),
- REG_DWARFNUM_END,
-};
-
-/**
- * get_arch_regstr() - lookup register name from it's DWARF register number
- * @n: the DWARF register number
- *
- * get_arch_regstr() returns the name of the register in struct
- * regdwarfnum_table from it's DWARF register number. If the register is not
- * found in the table, this returns NULL;
- */
-const char *get_arch_regstr(unsigned int n)
-{
- const struct pt_regs_dwarfnum *roff;
- for (roff = regdwarfnum_table; roff->name != NULL; roff++)
- if (roff->dwarfnum == n)
- return roff->name;
- return NULL;
-}
-
-int regs_query_register_offset(const char *name)
-{
- const struct pt_regs_dwarfnum *roff;
-
- for (roff = regdwarfnum_table; roff->name != NULL; roff++)
- if (!strcmp(roff->name, name))
- return DWARFNUM2OFFSET(roff->dwarfnum);
- return -EINVAL;
-}
diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c
index 97037499152e..f445a2dd6293 100644
--- a/tools/perf/arch/arm64/util/header.c
+++ b/tools/perf/arch/arm64/util/header.c
@@ -4,8 +4,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <perf/cpumap.h>
-#include <util/cpumap.h>
-#include <internal/cpumap.h>
#include <api/fs/fs.h>
#include <errno.h>
#include "debug.h"
@@ -16,76 +14,66 @@
#define MIDR_REVISION_MASK GENMASK(3, 0)
#define MIDR_VARIANT_MASK GENMASK(23, 20)
-static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus)
+static int _get_cpuid(char *buf, size_t sz, struct perf_cpu cpu)
{
+ char path[PATH_MAX];
+ FILE *file;
const char *sysfs = sysfs__mountpoint();
- int cpu;
- int ret = EINVAL;
+ assert(cpu.cpu != -1);
if (!sysfs || sz < MIDR_SIZE)
return EINVAL;
- cpus = perf_cpu_map__get(cpus);
+ scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR, sysfs, cpu.cpu);
- for (cpu = 0; cpu < perf_cpu_map__nr(cpus); cpu++) {
- char path[PATH_MAX];
- FILE *file;
-
- scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR,
- sysfs, RC_CHK_ACCESS(cpus)->map[cpu].cpu);
-
- file = fopen(path, "r");
- if (!file) {
- pr_debug("fopen failed for file %s\n", path);
- continue;
- }
+ file = fopen(path, "r");
+ if (!file) {
+ pr_debug("fopen failed for file %s\n", path);
+ return EINVAL;
+ }
- if (!fgets(buf, MIDR_SIZE, file)) {
- fclose(file);
- continue;
- }
+ if (!fgets(buf, MIDR_SIZE, file)) {
+ pr_debug("Failed to read file %s\n", path);
fclose(file);
-
- /* got midr break loop */
- ret = 0;
- break;
+ return EINVAL;
}
-
- perf_cpu_map__put(cpus);
- return ret;
+ fclose(file);
+ return 0;
}
-int get_cpuid(char *buf, size_t sz)
+int get_cpuid(char *buf, size_t sz, struct perf_cpu cpu)
{
- struct perf_cpu_map *cpus = perf_cpu_map__new_online_cpus();
- int ret;
+ struct perf_cpu_map *cpus;
+ int idx;
+
+ if (cpu.cpu != -1)
+ return _get_cpuid(buf, sz, cpu);
+ cpus = perf_cpu_map__new_online_cpus();
if (!cpus)
return EINVAL;
- ret = _get_cpuid(buf, sz, cpus);
-
- perf_cpu_map__put(cpus);
+ perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
+ int ret = _get_cpuid(buf, sz, cpu);
- return ret;
+ if (ret == 0)
+ return 0;
+ }
+ return EINVAL;
}
-char *get_cpuid_str(struct perf_pmu *pmu)
+char *get_cpuid_str(struct perf_cpu cpu)
{
- char *buf = NULL;
+ char *buf = malloc(MIDR_SIZE);
int res;
- if (!pmu || !pmu->cpus)
- return NULL;
-
- buf = malloc(MIDR_SIZE);
if (!buf)
return NULL;
/* read midr from list of cpus mapped to this pmu */
- res = _get_cpuid(buf, MIDR_SIZE, pmu->cpus);
+ res = get_cpuid(buf, MIDR_SIZE, cpu);
if (res) {
- pr_err("failed to get cpuid string for PMU %s\n", pmu->name);
+ pr_err("failed to get cpuid string for CPU %d\n", cpu.cpu);
free(buf);
buf = NULL;
}
diff --git a/tools/perf/arch/arm64/util/hisi-ptt.c b/tools/perf/arch/arm64/util/hisi-ptt.c
index ba97c8a562a0..eac9739c87e6 100644
--- a/tools/perf/arch/arm64/util/hisi-ptt.c
+++ b/tools/perf/arch/arm64/util/hisi-ptt.c
@@ -174,7 +174,6 @@ struct auxtrace_record *hisi_ptt_recording_init(int *err,
}
pttr->hisi_ptt_pmu = hisi_ptt_pmu;
- pttr->itr.pmu = hisi_ptt_pmu;
pttr->itr.recording_options = hisi_ptt_recording_options;
pttr->itr.info_priv_size = hisi_ptt_info_priv_size;
pttr->itr.info_fill = hisi_ptt_info_fill;
diff --git a/tools/perf/arch/arm64/util/pmu.c b/tools/perf/arch/arm64/util/pmu.c
index 2a4eab2d160e..895fb0d0610c 100644
--- a/tools/perf/arch/arm64/util/pmu.c
+++ b/tools/perf/arch/arm64/util/pmu.c
@@ -1,30 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-#include <internal/cpumap.h>
-#include "../../../util/cpumap.h"
-#include "../../../util/header.h"
#include "../../../util/pmu.h"
#include "../../../util/pmus.h"
+#include "../../../util/tool_pmu.h"
#include <api/fs/fs.h>
-#include <math.h>
-const struct pmu_metrics_table *pmu_metrics_table__find(void)
-{
- struct perf_pmu *pmu;
-
- /* Metrics aren't currently supported on heterogeneous Arm systems */
- if (perf_pmus__num_core_pmus() > 1)
- return NULL;
-
- /* Doesn't matter which one here because they'll all be the same */
- pmu = perf_pmus__find_core_pmu();
- if (pmu)
- return perf_pmu__find_metrics_table(pmu);
-
- return NULL;
-}
-
-double perf_pmu__cpu_slots_per_cycle(void)
+u64 tool_pmu__cpu_slots_per_cycle(void)
{
char path[PATH_MAX];
unsigned long long slots = 0;
@@ -41,5 +22,5 @@ double perf_pmu__cpu_slots_per_cycle(void)
filename__read_ull(path, &slots);
}
- return slots ? (double)slots : NAN;
+ return slots;
}
diff --git a/tools/perf/arch/arm64/util/unwind-libdw.c b/tools/perf/arch/arm64/util/unwind-libdw.c
index e056d50ab42e..b89b0a7e5ad9 100644
--- a/tools/perf/arch/arm64/util/unwind-libdw.c
+++ b/tools/perf/arch/arm64/util/unwind-libdw.c
@@ -8,7 +8,7 @@
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;
+ struct regs_dump *user_regs = perf_sample__user_regs(ui->sample);
Dwarf_Word dwarf_regs[PERF_REG_ARM64_MAX], dwarf_pc;
#define REG(r) ({ \