summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Richter <tmricht@linux.ibm.com>2026-03-06 13:50:31 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-04-11 14:29:52 +0200
commite7813ea3cc6036c9657e811736387a2d09f6abde (patch)
tree01c1700b8e4010cdcfcdc721a0144a4e16f72d25
parentace37bfec3822033e59fff390f2ff99fc96ebe4f (diff)
s390/cpum_sf: Cap sampling rate to prevent lsctl exception
commit 57ad0d4a00f5d3e80f33ba2da8d560c73d83dc22 upstream. commit fcc43a7e294f ("s390/configs: Set HZ=1000") changed the interrupt frequency of the system. On machines with heavy load and many perf event overflows, this might lead to an exception. Dmesg displays these entries: [112.242542] cpum_sf: Loading sampling controls failed: op 1 err -22 One line per CPU online. The root cause is the CPU Measurement sampling facility overflow adjustment. Whenever an overflow (too much samples per tick) occurs, the sampling rate is adjusted and increased. This was done without observing the maximum sampling rate limit. When the current sampling interval is higher than the maximum sampling rate limit, the lsctl instruction raises an exception. The error messages is the result of such an exception. Observe the upper limit when the new sampling rate is recalculated. Cc: stable@vger.kernel.org Fixes: 39d4a501a9ef ("s390/cpum_sf: Adjust sampling interval to avoid hitting sample limits") Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/s390/kernel/perf_cpum_sf.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
index e8bd19ac82c7..26926cb077ae 100644
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -1168,6 +1168,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
static void hw_perf_event_update(struct perf_event *event, int flush_all)
{
unsigned long long event_overflow, sampl_overflow, num_sdb;
+ struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
struct hw_perf_event *hwc = &event->hw;
union hws_trailer_header prev, new;
struct hws_trailer_entry *te;
@@ -1247,8 +1248,11 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
* are dropped.
* Slightly increase the interval to avoid hitting this limit.
*/
- if (event_overflow)
+ if (event_overflow) {
SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
+ if (SAMPL_RATE(hwc) > cpuhw->qsi.max_sampl_rate)
+ SAMPL_RATE(hwc) = cpuhw->qsi.max_sampl_rate;
+ }
}
static inline unsigned long aux_sdb_index(struct aux_buffer *aux,