Re: [PATCH 5/5] alpha/perf: optionally randomize the ProfileMe sampling interval

From: Magnus Lindholm

Date: Thu Oct 29 2026 - 11:04:12 EST


Hi Matt,

On Wed, Oct 28, 2026 at 7:09 PM Matt Turner <mattst88@xxxxxxxxx> wrote:
>
> A fixed sampling interval can phase-lock with a loop whose length divides
> it, so that the same few instructions are profiled over and over while
> the rest of the loop is never seen. DCPI avoided this by randomizing the
> interval.
>
> Add a randomize config bit that varies each interval by up to 1/16 of
> the period in either direction. Only ProfileMe events accept it, since
> Aggregate mode samples already land a variable distance from the
> instruction that overflowed. Counts are unaffected, because prev_count
> already records the value actually written to the counter.
>
> The jitter comes from a per-CPU prandom state rather than
> get_random_u32_below(), which takes the batched entropy local lock and
> triggers an invalid wait context report from lockdep in the PMI.
>
> Signed-off-by: Matt Turner <mattst88@xxxxxxxxx>
> ---
> arch/alpha/kernel/perf_event.c | 33 ++++++++++++++++++++++++++++++++-
> 1 file changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
> index 06c9afeb7c05..da8262c74d04 100644
> --- a/arch/alpha/kernel/perf_event.c
> +++ b/arch/alpha/kernel/perf_event.c
> @@ -16,6 +16,7 @@
> #include <linux/kdebug.h>
> #include <linux/mutex.h>
> #include <linux/init.h>
> +#include <linux/prandom.h>
>
> #include <asm/hwrpb.h>
> #include <linux/atomic.h>
> @@ -33,9 +34,11 @@
> /* Layout of attr.config for PERF_TYPE_RAW events; see format/ in sysfs. */
> #define ALPHA_PERF_CONFIG_EVENT 0xffULL
> #define ALPHA_PERF_CONFIG_PROFILEME BIT_ULL(8)
> +#define ALPHA_PERF_CONFIG_RANDOMIZE BIT_ULL(9)
>
> /* hw_perf_event.flags */
> #define ALPHA_PERF_FLAG_PROFILEME 0x1
> +#define ALPHA_PERF_FLAG_RANDOMIZE 0x2
>
> /* For tracking PMCs and the hw events they monitor on each CPU. */
> struct cpu_hw_events {
> @@ -59,6 +62,9 @@ struct cpu_hw_events {
> };
> DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
>
> +/* For randomizing sample intervals from the PMI, where locks are not allowed. */
> +static DEFINE_PER_CPU(struct rnd_state, alpha_perf_rnd);
> +
>
>
> /*
> @@ -246,10 +252,12 @@ 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");
>
> static struct attribute *ev67_format_attrs[] = {
> &format_attr_event.attr,
> &format_attr_profileme.attr,
> + &format_attr_randomize.attr,
> NULL,
> };
>
> @@ -360,6 +368,20 @@ static int alpha_perf_event_set_period(struct perf_event *event,
> ret = 1;
> }
>
> + /*
> + * Vary each new interval by up to 1/16 of the period either way, so
> + * the samples cannot phase-lock with a loop whose length divides the
> + * period. The count stays exact because prev_count records the value
> + * actually written.
> + */
> + if (ret && (hwc->flags & ALPHA_PERF_FLAG_RANDOMIZE) && period >= 8) {
> + long jitter = period / 8;
> + u32 r = prandom_u32_state(this_cpu_ptr(&alpha_perf_rnd));
> +
> + left += (long)((u64)r * jitter >> 32) - jitter / 2;
> + local64_set(&hwc->period_left, left);
> + }
> +

One minor corner case? This multiplication can overflow for very
large sample periods. I guess normal sampling periods are not
affected, is it worth using overflow-safe multiply/shift to avoid this
limitation?

> /*
> * Hardware restrictions require that the counters must not be
> * written with values that are too close to the maximum period.
> @@ -715,7 +737,8 @@ static int __hw_perf_event_init(struct perf_event *event)
> return -EOPNOTSUPP;
> } else if (attr->type == PERF_TYPE_RAW) {
> if (attr->config & ~(ALPHA_PERF_CONFIG_EVENT |
> - ALPHA_PERF_CONFIG_PROFILEME))
> + ALPHA_PERF_CONFIG_PROFILEME |
> + ALPHA_PERF_CONFIG_RANDOMIZE))
> return -EINVAL;
> ev = attr->config & ALPHA_PERF_CONFIG_EVENT;
> if (!alpha_pmu->raw_event_valid(ev))
> @@ -740,6 +763,14 @@ static int __hw_perf_event_init(struct perf_event *event)
> return -EINVAL;
> hwc->flags = profileme ? ALPHA_PERF_FLAG_PROFILEME : 0;
>
> + if (attr->type == PERF_TYPE_RAW &&
> + (attr->config & ALPHA_PERF_CONFIG_RANDOMIZE)) {
> + if (!profileme)
> + return -EINVAL;
> + prandom_init_once(&alpha_perf_rnd);
> + hwc->flags |= ALPHA_PERF_FLAG_RANDOMIZE;
> + }
> +
> /*
> * We place the event type in event_base here and leave calculation
> * of the codes to programme the PMU for alpha_pmu_enable() because
>
> --
> 2.55.0
>

I'll report back once I've done some testing on real hardware.

Thanks

Magnus