mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/1] alpha/perf: Enable duration-based sampling throttling
@ 2026-11-10 19:31 Magnus Lindholm
  2026-11-10 19:31 ` [PATCH v2 1/1] alpha/perf: Account for time spent handling PMU interrupts Magnus Lindholm
  0 siblings, 1 reply; 2+ messages in thread
From: Magnus Lindholm @ 2026-11-10 19:31 UTC (permalink / raw)
  To: richard.henderson, mattst88, linux-kernel, linux-alpha; +Cc: linmag7

Hi,

Changes in v2, following Matt's review:
- Describe the unresponsive-machine/RCU-starvation symptom in the commit.
- Include proto.h for est_cycle_freq and use cycles_t without the cast.
- Precompute the cycles-to-nanoseconds multiplier/shift and mark both
  __ro_after_init, removing division from the interrupt path.
- Add Matt's Reviewed-by.

Both v2 mainline and ES40 integration builds passed (vmlinux, boot image
and modules), with only the existing saved_config COMMON-symbol warning.
Disassembly confirms no division call in either interrupt wrapper.
The multiplier conversion checks cover rounding, overflow and RPCC wrap.
The historical hardware results below apply to v1's division-based
conversion. V2 also passed seven bounded tests on the ES40 with the
alpha-devel integration: the 1024/s and 4096/s CPU0 controls, 1024/s
controls on CPUs 1 and 2, and period-17 tests starting at 100000/s on
each CPU. Duration feedback reduced the limits to 7168/s, 5120/s and
5120/s respectively. All 26156 samples were recorded without reported
loss, and no new RCU stalls or kernel faults appeared, including a
30-second observation after the final run. This does not repeat the
full v1 stress matrix below. The selected-frequency cleanup remains
outside this patch.

While testing Matt's v7 ProfileMe series [1] on my EV67 AlphaServer ES40,
I found that short-period sampling could make the machine unresponsive.
Once serial logging was enabled, the console showed RCU grace-period
kthread starvation reports. The failure also reproduced without my
generic-entry follow-up patches.

Count-based throttling was working: at HZ=1024 and the default limit of
100000 samples/s, the observed cadence was approximately 98 interrupts
per throttle cycle. However, Alpha never called perf_sample_event_took(),
so perf could not reduce that limit based on interrupt handling cost.
Setting perf_cpu_time_max_percent to 25 did not provide that feedback.

Keeping period 17 but lowering the limit to 1024 or 4096 samples/s made
the tests pass while still exercising repeated stop/park/restart cycles.
Adding duration feedback also made the original high-rate test pass,
without changing those counter-state operations. The minimal fix measured
average handler costs of 24-26 us against a 2.5 us budget and reduced the
limit to 7168-8192 samples/s.

Reproducer
==========

The reproducer requires Matt's ProfileMe kernel series and matching perf
tools. On the ES40 I used the following one-second workload, built
natively as "busy":

  #include <stdint.h>
  #include <time.h>

  static double now(void)
  {
          struct timespec t;

          clock_gettime(CLOCK_MONOTONIC, &t);
          return t.tv_sec + t.tv_nsec * 1e-9;
  }

  int main(void)
  {
          uint64_t x = 1;
          double end = now() + 1;

          do {
                  for (int i = 0; i < 1000; i++)
                          asm volatile("mulq %0,3,%0" : "+r" (x));
          } while (now() < end);
          return 0;
  }

  cc -O2 -o busy busy.c

As root, with serial capture running:

  dmesg -n 7
  sysctl -w kernel.perf_event_max_sample_rate=100000
  sysctl -w kernel.perf_cpu_time_max_percent=25

The period-10007 control completed successfully:

  taskset -c 0 perf record -B -R \
      -e cpu/instructions,profileme,randomize/ -c 10007 \
      -o control.data -- ./busy

Changing only the period reproduced the failure:

  taskset -c 0 perf record -B -R \
      -e cpu/instructions,profileme,randomize/ -c 17 \
      -o period17.data -- ./busy

The unpatched runs required a manual reset; a userspace timeout did not
reliably recover the system. The commands above are the essential
recording commands from the controlled tests, which also used a timeout
supervisor and saved logs on another machine.

Validation and submission scope
===============================

The v1 minimal fix, without diagnostic instrumentation, passed three
repeats of the high-rate reproducer and the two low-rate controls.
Broader testing covered 21 cases on all three CPUs: randomized ProfileMe
instruction sampling at periods 16, 17 and 31, ProfileMe and Aggregate
cycle sampling, and concurrent ProfileMe and mixed-mode workloads.
All completed, with 1352488 samples, no recorded losses and no new RCU
stalls or kernel faults. This was bounded stress testing, not a long soak.

The missing feedback predates ProfileMe. This patch is therefore based
on mainline and can be reviewed and applied independently of Matt's
series. I cross-built vmlinux, the Alpha boot image and modules on
mainline d48723711bae with the ES40 configuration and GCC 15.0.1. The
only build warning was the existing saved_config COMMON-symbol warning.

The hardware results above used Matt's v7 series with the v1 fix applied;
the mainline-only build has not been boot-tested. RPCC supplies a short,
same-CPU interval because Alpha's tick-based sched_clock() is too coarse
for this measurement. Counter programming and event handling are unchanged.

[1] https://lore.kernel.org/linux-alpha/20261105-alpha-profileme-v7-0-c474e892abb0@gmail.com/


Magnus Lindholm (1):
  alpha/perf: Account for time spent handling PMU interrupts

 arch/alpha/kernel/perf_event.c | 35 ++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH v2 1/1] alpha/perf: Account for time spent handling PMU interrupts
  2026-11-10 19:31 [PATCH v2 0/1] alpha/perf: Enable duration-based sampling throttling Magnus Lindholm
@ 2026-11-10 19:31 ` Magnus Lindholm
  0 siblings, 0 replies; 2+ messages in thread
From: Magnus Lindholm @ 2026-11-10 19:31 UTC (permalink / raw)
  To: richard.henderson, mattst88, linux-kernel, linux-alpha; +Cc: linmag7

Alpha does not report PMU interrupt duration to perf, preventing its
adaptive throttling from reducing an excessively costly sampling rate.
Short sampling periods can leave the machine unresponsive with RCU
grace-period kthread starvation reports.

Measure handler time with RPCC and report it to perf_sample_event_took().
Precompute a multiplier and shift using the frequency selected by
time_init(), avoiding division in the interrupt handler. Alpha's
tick-based sched_clock() is too coarse for this measurement.
Wrap the existing handler so all return paths are accounted for, without
changing counter programming or event handling.

Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
---
 arch/alpha/kernel/perf_event.c | 35 ++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index a3eaab094ece..09033c2d1f66 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -16,8 +16,11 @@
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
+#include <linux/math64.h>
+#include <linux/clocksource.h>
 
 #include <asm/hwrpb.h>
+#include <asm/timex.h>
 #include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
@@ -25,6 +28,10 @@
 #include <asm/wrperfmon.h>
 #include <asm/hw_irq.h>
 
+#include "proto.h"
+
+static u32 pmu_cycle_mult __ro_after_init;
+static u32 pmu_cycle_shift __ro_after_init;
 
 /* The maximum number of PMCs on any Alpha CPU whatsoever. */
 #define MAX_HWEVENTS 3
@@ -797,8 +804,8 @@ void perf_event_print_debug(void)
  * Performance Monitoring Interrupt Service Routine called when a PMC
  * overflows.  The PMC that overflowed is passed in la_ptr.
  */
-static void alpha_perf_event_irq_handler(unsigned long la_ptr,
-					struct pt_regs *regs)
+static void alpha_perf_event_irq_inner(unsigned long la_ptr,
+				       struct pt_regs *regs)
 {
 	struct cpu_hw_events *cpuc;
 	struct perf_sample_data data;
@@ -862,11 +869,28 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
 
 
 
+/* sched_clock() is tick-based on Alpha; measure a short same-CPU interval. */
+static void alpha_perf_event_irq_handler(unsigned long la_ptr,
+					 struct pt_regs *regs)
+{
+	cycles_t start = get_cycles();
+	cycles_t cycles;
+
+	alpha_perf_event_irq_inner(la_ptr, regs);
+	/* Unsigned subtraction handles a wrap of the low 32-bit counter. */
+	cycles = get_cycles() - start;
+	if (likely(pmu_cycle_mult))
+		perf_sample_event_took(mul_u64_u32_shr(cycles, pmu_cycle_mult,
+						       pmu_cycle_shift));
+}
+
 /*
  * Init call to initialise performance events at kernel startup.
  */
 static int __init init_hw_perf_events(void)
 {
+	unsigned long cycle_freq;
+
 	pr_info("Performance events: ");
 
 	if (!supported_cpu()) {
@@ -878,6 +902,13 @@ static int __init init_hw_perf_events(void)
 
 	/* Override performance counter IRQ vector */
 
+	/* Match the calibrated frequency selected by time_init(). */
+	cycle_freq = est_cycle_freq ? est_cycle_freq : hwrpb->cycle_freq;
+	if (cycle_freq && cycle_freq <= U32_MAX)
+		clocks_calc_mult_shift(&pmu_cycle_mult, &pmu_cycle_shift,
+				       cycle_freq, NSEC_PER_SEC, 1);
+	else
+		pr_warn("PMU interrupt duration accounting disabled: invalid cycle frequency\n");
 	perf_irq = alpha_perf_event_irq_handler;
 
 	/* And set up PMU specification */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-10 19:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10 19:31 [PATCH v2 0/1] alpha/perf: Enable duration-based sampling throttling Magnus Lindholm
2026-11-10 19:31 ` [PATCH v2 1/1] alpha/perf: Account for time spent handling PMU interrupts Magnus Lindholm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®