@@ -10,11 +10,25 @@
#include "../../util/auxtrace.h"
#include "../../util/debug.h"
+#include "../../util/env.h"
#include "../../util/evlist.h"
#include "../../util/pmu.h"
#include "cs-etm.h"
#include "arm-spe.h"
+#define SPE_ATTR_TS_ENABLE BIT(0)
+#define SPE_ATTR_PA_ENABLE BIT(1)
+#define SPE_ATTR_PCT_ENABLE BIT(2)
+#define SPE_ATTR_JITTER BIT(16)
+#define SPE_ATTR_BRANCH_FILTER BIT(32)
+#define SPE_ATTR_LOAD_FILTER BIT(33)
+#define SPE_ATTR_STORE_FILTER BIT(34)
+
+#define SPE_ATTR_EV_RETIRED BIT(1)
+#define SPE_ATTR_EV_CACHE BIT(3)
+#define SPE_ATTR_EV_TLB BIT(5)
+#define SPE_ATTR_EV_BRANCH BIT(7)
+
static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err)
{
struct perf_pmu **arm_spe_pmus = NULL;
@@ -108,3 +122,27 @@ struct auxtrace_record
*err = 0;
return NULL;
}
+
+void auxtrace__preprocess_evlist(struct evlist *evlist)
+{
+ struct evsel *evsel;
+ struct perf_pmu *pmu;
+
+ evlist__for_each_entry(evlist, evsel) {
+ /* Currently only supports precise_ip for branch-misses on arm64 */
+ if (!strcmp(perf_env__arch(evlist->env), "arm64")
+ && evsel->core.attr.config == PERF_COUNT_HW_BRANCH_MISSES
+ && evsel->core.attr.precise_ip)
+ {
+ pmu = perf_pmu__find("arm_spe_0");
+ if (pmu) {
+ evsel->pmu_name = pmu->name;
+ evsel->core.attr.type = pmu->type;
+ evsel->core.attr.config = SPE_ATTR_TS_ENABLE
+ | SPE_ATTR_BRANCH_FILTER;
+ evsel->core.attr.config1 = SPE_ATTR_EV_BRANCH;
+ evsel->core.attr.precise_ip = 0;
+ }
+ }
+ }
+}
\ No newline at end of file
@@ -2451,6 +2451,11 @@ int cmd_record(int argc, const char **argv)
argc = parse_options(argc, argv, record_options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+
+ if (auxtrace__preprocess_evlist) {
+ auxtrace__preprocess_evlist(rec->evlist);
+ }
+
if (quiet)
perf_quiet_option();
@@ -778,6 +778,15 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
attr.sample_id_all = evsel->core.attr.sample_id_all;
attr.read_format = evsel->core.attr.read_format;
+ /* If it is in the precise ip mode, there is no need to
+ * synthesize new events. */
+ if (!strncmp(evsel->name, "branch-misses", 13)) {
+ spe->sample_branch_miss = true;
+ spe->branch_miss_id = evsel->core.id[0];
+
+ return 0;
+ }
+
/* create new id val to be a fixed offset from evsel id */
id = evsel->core.id[0] + 1000000000;
@@ -20,6 +20,8 @@ enum {
union perf_event;
struct perf_session;
struct perf_pmu;
+struct evlist;
+struct evsel;
struct auxtrace_record *arm_spe_recording_init(int *err,
struct perf_pmu *arm_spe_pmu);
@@ -28,4 +30,5 @@ int arm_spe_process_auxtrace_info(union perf_event *event,
struct perf_session *session);
struct perf_event_attr *arm_spe_pmu_default_config(struct perf_pmu *arm_spe_pmu);
+void arm_spe_precise_ip_support(struct evlist *evlist, struct evsel *evsel);
#endif
@@ -584,6 +584,7 @@ void auxtrace__dump_auxtrace_sample(struct perf_session *session,
int auxtrace__flush_events(struct perf_session *session, struct perf_tool *tool);
void auxtrace__free_events(struct perf_session *session);
void auxtrace__free(struct perf_session *session);
+void auxtrace__preprocess_evlist(struct evlist *evlist) __attribute__((weak));
#define ITRACE_HELP \
" i: synthesize instructions events\n" \
@@ -728,6 +729,11 @@ void auxtrace__free(struct perf_session *session __maybe_unused)
{
}
+static inline
+void auxtrace__preprocess_evlist(struct evlist *evlist __maybe_unused)
+{
+}
+
static inline
int auxtrace_index__write(int fd __maybe_unused,
struct list_head *head __maybe_unused)
@@ -9,6 +9,7 @@
#include <errno.h>
#include <inttypes.h>
#include <poll.h>
+#include "arm-spe.h"
#include "cpumap.h"
#include "util/mmap.h"
#include "thread_map.h"
@@ -174,7 +174,6 @@ void perf_evsel__exit(struct evsel *evsel);
void evsel__delete(struct evsel *evsel);
struct callchain_param;
-
void perf_evsel__config(struct evsel *evsel,
struct record_opts *opts,
struct callchain_param *callchain);