[PATCH v6 11/13] alpha/perf: add ProfileMe sample filters
From: Matt Turner
Date: Wed Nov 04 2026 - 14:44:07 EST
ProfileMe samples any fetched instruction, including those killed on a
wrong path, and what happened to it is only in the PERF_SAMPLE_RAW data.
Add three config1 bits that keep only the samples of instructions that:
retired retired. VAL says so for an instruction that did not trap,
and the trap type for one that did.
mispredict were mispredicted conditional branches.
trapped trapped, mispredicts included, or caused an ITB miss,
Istream access violation or interrupt redirect.
A sample must match every bit that is set, as with Arm SPE's
event_filter. The driver drops the samples that do not, and they still
count as interrupts for throttling and frequency mode.
Suggested-by: Ian Rogers <irogers@xxxxxxxxxx>
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Matt Turner <mattst88@xxxxxxxxx>
---
arch/alpha/include/asm/wrperfmon.h | 10 +++++
arch/alpha/kernel/perf_event.c | 83 ++++++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+)
diff --git a/arch/alpha/include/asm/wrperfmon.h b/arch/alpha/include/asm/wrperfmon.h
index dc24c7cb45db..6526438e73ee 100644
--- a/arch/alpha/include/asm/wrperfmon.h
+++ b/arch/alpha/include/asm/wrperfmon.h
@@ -106,9 +106,14 @@
#define EV67_I_STAT_MIS (1UL<<40)
/* I_STAT[TRAP_TYPE] values */
+#define EV67_TRAP_REPLAY 0
#define EV67_TRAP_DTB_DOUBLE_3 2
#define EV67_TRAP_DTB_DOUBLE_4 3
+#define EV67_TRAP_FEN 4
+#define EV67_TRAP_UNALIGNED 5
#define EV67_TRAP_DTB_SINGLE 6
+#define EV67_TRAP_DFAULT 7
+#define EV67_TRAP_OPCDEC 8
#define EV67_PCTR_VAL (1UL<<1)
#define EV67_PCTR_PM_KILLED_BM (1UL<<26)
@@ -116,5 +121,10 @@
/* PMPC bits 63:2 hold the profiled PC. Bit 0 set means a PALmode address. */
#define EV67_PMPC_PAL (1UL<<0)
#define EV67_PMPC_PC_MASK (~3UL)
+/* PMPC[14:0] of the redirect traps, which do not set I_STAT[TRP] */
+#define EV67_PMPC_PAL_OFFSET_MASK 0x7fffUL
+#define EV67_PMPC_IACV 0x0481
+#define EV67_PMPC_ITB_MISS 0x0581
+#define EV67_PMPC_INTERRUPT 0x0681
#endif
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 0723e1042145..32a8b5c98381 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -39,6 +39,13 @@
#define ALPHA_PERF_CONFIG_EVENT 0xffULL
#define ALPHA_PERF_CONFIG_PROFILEME BIT_ULL(8)
#define ALPHA_PERF_CONFIG_RANDOMIZE BIT_ULL(9)
+/* attr.config1 of a ProfileMe event: keep only samples of these insns. */
+#define ALPHA_PERF_CONFIG1_RETIRED BIT_ULL(0)
+#define ALPHA_PERF_CONFIG1_MISPREDICT BIT_ULL(1)
+#define ALPHA_PERF_CONFIG1_TRAPPED BIT_ULL(2)
+#define ALPHA_PERF_CONFIG1_FILTERS (ALPHA_PERF_CONFIG1_RETIRED | \
+ ALPHA_PERF_CONFIG1_MISPREDICT | \
+ ALPHA_PERF_CONFIG1_TRAPPED)
/* hw_perf_event.flags */
#define ALPHA_PERF_FLAG_WRAPPED 0x1
@@ -258,11 +265,17 @@ static int ev67_raw_event_valid(u64 config)
PMU_FORMAT_ATTR(event, "config:0-7");
PMU_FORMAT_ATTR(profileme, "config:8");
PMU_FORMAT_ATTR(randomize, "config:9");
+PMU_FORMAT_ATTR(retired, "config1:0");
+PMU_FORMAT_ATTR(mispredict, "config1:1");
+PMU_FORMAT_ATTR(trapped, "config1:2");
static struct attribute *ev67_format_attrs[] = {
&format_attr_event.attr,
&format_attr_profileme.attr,
&format_attr_randomize.attr,
+ &format_attr_retired.attr,
+ &format_attr_mispredict.attr,
+ &format_attr_trapped.attr,
NULL,
};
@@ -819,6 +832,12 @@ static int __hw_perf_event_init(struct perf_event *event)
return -EINVAL;
hwc->flags = profileme ? ALPHA_PERF_FLAG_PROFILEME : 0;
+ if (attr->config1 & ~ALPHA_PERF_CONFIG1_FILTERS)
+ return -EINVAL;
+ if (attr->config1 && !profileme)
+ return -EINVAL;
+ hwc->config = attr->config1;
+
if (attr->type == PERF_TYPE_RAW &&
(attr->config & ALPHA_PERF_CONFIG_RANDOMIZE)) {
if (!profileme)
@@ -1060,6 +1079,62 @@ static bool alpha_profileme_trp(unsigned long i_stat, unsigned long pctr_ctl)
return !(pctr_ctl & EV67_PCTR_PM_KILLED_BM) && (i_stat & EV67_I_STAT_TRP);
}
+/*
+ * VAL says whether an instruction that did not trap retired. For one that
+ * did, the trap type decides: these faults abort it, to be replayed,
+ * refetched after a fill, or emulated. Other traps, mispredicts among
+ * them, are counted as retired.
+ */
+static bool alpha_profileme_retired(unsigned long i_stat,
+ unsigned long pctr_ctl)
+{
+ if (pctr_ctl & EV67_PCTR_PM_KILLED_BM)
+ return false;
+ if (!(i_stat & EV67_I_STAT_TRP))
+ return pctr_ctl & EV67_PCTR_VAL;
+ if (i_stat & EV67_I_STAT_MIS)
+ return true;
+
+ switch ((i_stat >> EV67_I_STAT_TRAP_TYPE_SHIFT) &
+ EV67_I_STAT_TRAP_TYPE_MASK) {
+ case EV67_TRAP_REPLAY:
+ case EV67_TRAP_DTB_DOUBLE_3:
+ case EV67_TRAP_DTB_DOUBLE_4:
+ case EV67_TRAP_FEN:
+ case EV67_TRAP_UNALIGNED:
+ case EV67_TRAP_DTB_SINGLE:
+ case EV67_TRAP_DFAULT:
+ case EV67_TRAP_OPCDEC:
+ return false;
+ default:
+ return true;
+ }
+}
+
+/* What the profiled instruction did, as config1 filter bits. */
+static u64 alpha_profileme_status(unsigned long i_stat,
+ unsigned long pctr_ctl, unsigned long pmpc)
+{
+ u64 status = 0;
+
+ if (alpha_profileme_retired(i_stat, pctr_ctl))
+ status |= ALPHA_PERF_CONFIG1_RETIRED;
+ if (alpha_profileme_trp(i_stat, pctr_ctl)) {
+ status |= ALPHA_PERF_CONFIG1_TRAPPED;
+ if (i_stat & EV67_I_STAT_MIS)
+ status |= ALPHA_PERF_CONFIG1_MISPREDICT;
+ } else if (pmpc & EV67_PMPC_PAL) {
+ switch (pmpc & EV67_PMPC_PAL_OFFSET_MASK) {
+ case EV67_PMPC_IACV:
+ case EV67_PMPC_ITB_MISS:
+ case EV67_PMPC_INTERRUPT:
+ status |= ALPHA_PERF_CONFIG1_TRAPPED;
+ break;
+ }
+ }
+ return status;
+}
+
/* What the memory instruction at pc does, or PERF_MEM_OP_NA. */
static u64 alpha_profileme_mem_op(unsigned long pc)
{
@@ -1170,6 +1245,14 @@ static void alpha_perf_event_profileme(struct perf_event *event,
local64_add(ovr, &hwc->period_left);
}
+ /* A dropped sample still counts, for throttling and frequency mode. */
+ if ((alpha_profileme_status(i_stat, pctr_ctl, pmpc) & hwc->config) !=
+ hwc->config) {
+ if (alpha_perf_event_set_period(event, hwc, 0))
+ perf_event_account_interrupt(event);
+ return;
+ }
+
/*
* Attribute the sample to the profiled instruction rather than to
* wherever the interrupt landed. perf takes the sample's mode,
--
2.55.0