[PATCH] s390/pai: Handle multiple PMU stop callback invocations
Thomas Richter <[email protected]>
| Newsgroups | org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
Handle the following scenario: The kernel protects itself against a very high sampling load and throttles the sampling using: perf_event_throttle() --> PMU->stop() Shortly later the scheduler may terminate the task and removes it from the CPU. It again calls PMU->stop() which results in two invocations of PMU->stop() called back to back. Protect against this and check the PERF_HES_STOPPED bit on function entry. If it is already set return. Clear bit PERF_HES_STOPPED in PMU->start(). Cc: [email protected] # v6.19+ Fixes: 9f66572f2889 ("s390/pai_crypto: Enable per-task and system-wide sampling event") Fixes: 582cc1b28e8c ("s390/pai_ext: Enable per-task and system-wide sampling event") Signed-off-by: Thomas Richter <[email protected]> Reviewed-by: Sumanth Korikkar <[email protected]> --- arch/s390/kernel/perf_pai.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index 1e5a1f1cc68a..f6790f658f21 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -484,6 +484,7 @@ static void pai_start(struct perf_event *event, int flags, cpump->event = event; } } + event->hw.state &= ~PERF_HES_STOPPED; } static void paicrypt_start(struct perf_event *event, int flags) @@ -530,6 +531,13 @@ static void pai_stop(struct perf_event *event, int flags) struct pai_mapptr *mp = this_cpu_ptr(pai_root[idx].mapptr); struct pai_map *cpump = mp->mapptr; + /* Cope with multiple invocations: + * 1. perf_event_throttle() --> PMU->stop() + * 2. task schedules out --> PMU->stop() + * Check for event already stopped. + */ + if (event->hw.state & PERF_HES_STOPPED) + return; if (!event->attr.sample_period) { /* Counting */ pai_pmu[idx].pmu->read(event); } else { /* Sampling */ -- 2.55.0