* [PATCH 0/3 v2] Add CPU hotplug support for PAI PMU
@ 2026-08-24 12:23 Thomas Richter
2026-08-24 12:23 ` [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event Thomas Richter
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Thomas Richter @ 2026-08-24 12:23 UTC (permalink / raw)
To: linux-s390; +Cc: Thomas Richter
V4: Add findings from Sumanth and updated patch 3/3.
- Fix reference count for CPU hotplug remove while multiple
per-task events are active.
V3: Add findings from Sumanth and updated patch 3/3.
- Refined Fixes: commit id and messages
- Handle cpuhp_setup_state() failure
V2: Add findings from Sumanth and updated patch 3/3.
- handle possible NULL pointer dereference in pai_event_destroy_cpu()
- handle possibe memory allocation failure in pai_online_cpu()
- add Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
to patch 1/3 and patch 2/3.
Add support for CPU hotplug add and remove for PAI PMU.
Patch 1: Change function argument list
Patch 2: Move locking from CPU scope to event scope
Patch 3: Add CPU hotplug handler
Thomas Richter (3):
s390/pai: Use PAI PMU index as parameter replacing event
s390/pai: Move locking to event init and delete
s390/pai: Support CPU hotplug for PMU PAI
arch/s390/include/asm/pai.h | 1 -
arch/s390/kernel/perf_pai.c | 178 +++++++++++++++++++++++++-----------
2 files changed, 124 insertions(+), 55 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event 2026-08-24 12:23 [PATCH 0/3 v2] Add CPU hotplug support for PAI PMU Thomas Richter @ 2026-08-24 12:23 ` Thomas Richter 2026-08-24 12:32 ` sashiko-bot 2026-08-24 12:23 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter 2026-08-24 12:23 ` [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI Thomas Richter 2 siblings, 1 reply; 13+ messages in thread From: Thomas Richter @ 2026-08-24 12:23 UTC (permalink / raw) To: linux-s390; +Cc: Thomas Richter, Sumanth Korikkar Use PAI PMU index value as function argument instead of pointer to struct perf_event. Only that index value is used inside functions pai_alloc_cpu() and pai_event_destroy_cpu(). No functional change. Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> --- arch/s390/kernel/perf_pai.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index cdb8006220ca..7c13f5586c79 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -140,16 +140,14 @@ static void pai_free(struct pai_mapptr *mp) /* Adjust usage counters and remove allocated memory when all users are * gone. */ -static void pai_event_destroy_cpu(struct perf_event *event, int cpu) +static void pai_event_destroy_cpu(int idx, int cpu) { - int idx = PAI_PMU_IDX(event); struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); struct pai_map *cpump = mp->mapptr; mutex_lock(&pai_reserve_mutex); - debug_sprintf_event(paidbg, 5, "%s event %#llx idx %d cpu %d users %d " - "refcnt %u\n", __func__, event->attr.config, idx, - event->cpu, cpump->active_events, + debug_sprintf_event(paidbg, 5, "%s users %d refcnt %u\n", + __func__, cpump->active_events, refcount_read(&cpump->refcnt)); if (refcount_dec_and_test(&cpump->refcnt)) pai_free(mp); @@ -159,17 +157,17 @@ static void pai_event_destroy_cpu(struct perf_event *event, int cpu) static void pai_event_destroy(struct perf_event *event) { - int cpu; + int cpu = 0, idx = PAI_PMU_IDX(event); free_page(PAI_SAVE_AREA(event)); if (event->cpu == -1) { struct cpumask *mask = PAI_CPU_MASK(event); for_each_cpu(cpu, mask) - pai_event_destroy_cpu(event, cpu); + pai_event_destroy_cpu(idx, cpu); kfree(mask); } else { - pai_event_destroy_cpu(event, event->cpu); + pai_event_destroy_cpu(idx, event->cpu); } } @@ -241,12 +239,12 @@ static u64 paicrypt_getall(struct perf_event *event) * * Allocate the memory for the event. */ -static int pai_alloc_cpu(struct perf_event *event, int cpu) +static int pai_alloc_cpu(int idx, int cpu) { - int rc, idx = PAI_PMU_IDX(event); struct pai_map *cpump = NULL; bool need_paiext_cb = false; struct pai_mapptr *mp; + int rc; mutex_lock(&pai_reserve_mutex); /* Allocate root node */ @@ -318,6 +316,7 @@ static int pai_alloc_cpu(struct perf_event *event, int cpu) static int pai_alloc(struct perf_event *event) { + int idx = PAI_PMU_IDX(event); struct cpumask *maskptr; int cpu, rc = -ENOMEM; @@ -326,10 +325,10 @@ static int pai_alloc(struct perf_event *event) goto out; for_each_online_cpu(cpu) { - rc = pai_alloc_cpu(event, cpu); + rc = pai_alloc_cpu(idx, cpu); if (rc) { for_each_cpu(cpu, maskptr) - pai_event_destroy_cpu(event, cpu); + pai_event_destroy_cpu(idx, cpu); kfree(maskptr); goto out; } @@ -392,7 +391,7 @@ static int pai_event_init(struct perf_event *event, int idx) } if (event->cpu >= 0) - rc = pai_alloc_cpu(event, event->cpu); + rc = pai_alloc_cpu(idx, event->cpu); else rc = pai_alloc(event); if (rc) { -- 2.55.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event 2026-08-24 12:23 ` [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event Thomas Richter @ 2026-08-24 12:32 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-08-24 12:32 UTC (permalink / raw) To: Thomas Richter Cc: linux-s390, Vasily Gorbik, Alexander Gordeev, Christian Borntraeger, Heiko Carstens > Use PAI PMU index value as function argument instead of pointer > to struct perf_event. Only that index value is used inside > functions pai_alloc_cpu() and pai_event_destroy_cpu(). > No functional change. > > Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260824122307.86133-1-tmricht@linux.ibm.com?part=1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-24 12:23 [PATCH 0/3 v2] Add CPU hotplug support for PAI PMU Thomas Richter 2026-08-24 12:23 ` [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event Thomas Richter @ 2026-08-24 12:23 ` Thomas Richter 2026-08-24 12:43 ` sashiko-bot 2026-08-24 12:23 ` [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI Thomas Richter 2 siblings, 1 reply; 13+ messages in thread From: Thomas Richter @ 2026-08-24 12:23 UTC (permalink / raw) To: linux-s390; +Cc: Thomas Richter, Sumanth Korikkar Move mutex locking from per CPU allocation to event allocation. No functional change. Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> --- arch/s390/kernel/perf_pai.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index 7c13f5586c79..52d9f654346a 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -138,21 +138,19 @@ static void pai_free(struct pai_mapptr *mp) } /* Adjust usage counters and remove allocated memory when all users are - * gone. + * gone. Called under mutex_lock. */ static void pai_event_destroy_cpu(int idx, int cpu) { struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); struct pai_map *cpump = mp->mapptr; - mutex_lock(&pai_reserve_mutex); debug_sprintf_event(paidbg, 5, "%s users %d refcnt %u\n", __func__, cpump->active_events, refcount_read(&cpump->refcnt)); if (refcount_dec_and_test(&cpump->refcnt)) pai_free(mp); pai_root_free(idx); - mutex_unlock(&pai_reserve_mutex); } static void pai_event_destroy(struct perf_event *event) @@ -160,6 +158,7 @@ static void pai_event_destroy(struct perf_event *event) int cpu = 0, idx = PAI_PMU_IDX(event); free_page(PAI_SAVE_AREA(event)); + mutex_lock(&pai_reserve_mutex); if (event->cpu == -1) { struct cpumask *mask = PAI_CPU_MASK(event); @@ -169,6 +168,7 @@ static void pai_event_destroy(struct perf_event *event) } else { pai_event_destroy_cpu(idx, event->cpu); } + mutex_unlock(&pai_reserve_mutex); } static void paicrypt_event_destroy(struct perf_event *event) @@ -232,12 +232,10 @@ static u64 paicrypt_getall(struct perf_event *event) return sum; } -/* Check concurrent access of counting and sampling for crypto events. - * This function is called in process context and it is save to block. - * When the event initialization functions fails, no other call back will - * be invoked. - * - * Allocate the memory for the event. +/* Allocate all per-CPU data structures. This function is called in + * process context and can block. In case of error all partly allocated + * memory is released and the reference counters adjusted correctly. + * Called under mutex_lock. */ static int pai_alloc_cpu(int idx, int cpu) { @@ -246,11 +244,10 @@ static int pai_alloc_cpu(int idx, int cpu) struct pai_mapptr *mp; int rc; - mutex_lock(&pai_reserve_mutex); /* Allocate root node */ rc = pai_root_alloc(idx); if (rc) - goto unlock; + goto out; /* Allocate node for this event */ mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); @@ -308,12 +305,12 @@ static int pai_alloc_cpu(int idx, int cpu) */ pai_root_free(idx); } -unlock: - mutex_unlock(&pai_reserve_mutex); +out: /* If rc is non-zero, no increment of counter/sampler was done. */ return rc; } +/* Called under mutex_lock */ static int pai_alloc(struct perf_event *event) { int idx = PAI_PMU_IDX(event); @@ -390,10 +387,12 @@ static int pai_event_init(struct perf_event *event, int idx) } } + mutex_lock(&pai_reserve_mutex); if (event->cpu >= 0) rc = pai_alloc_cpu(idx, event->cpu); else rc = pai_alloc(event); + mutex_unlock(&pai_reserve_mutex); if (rc) { free_page(PAI_SAVE_AREA(event)); goto out; -- 2.55.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-24 12:23 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter @ 2026-08-24 12:43 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-08-24 12:43 UTC (permalink / raw) To: Thomas Richter Cc: Vasily Gorbik, linux-s390, Heiko Carstens, Alexander Gordeev, Christian Borntraeger > Move mutex locking from per CPU allocation to event allocation. > No functional change. > > Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260824122307.86133-1-tmricht@linux.ibm.com?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI 2026-08-24 12:23 [PATCH 0/3 v2] Add CPU hotplug support for PAI PMU Thomas Richter 2026-08-24 12:23 ` [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event Thomas Richter 2026-08-24 12:23 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter @ 2026-08-24 12:23 ` Thomas Richter 2026-08-24 12:53 ` sashiko-bot 2 siblings, 1 reply; 13+ messages in thread From: Thomas Richter @ 2026-08-24 12:23 UTC (permalink / raw) To: linux-s390; +Cc: Thomas Richter The command 'perf stat -e pai_crypto/CRYPTO_ALL/ -- <command>' crashes the kernel when CPUs are hotplug added during that run. Root cause is the missing allocation of per-CPU data structures for that new CPU. The allocation is dynamic and the first event that has task context creates such a structure for each online CPU. This is not sufficient. CPUs may be offline during event creation and can be set online during the perf run time. For example commands # echo 0 > /sys/devices/system/cpu/cpu1/online # perf stat -e cycles -i -- stress-ng -t10s --matrix X # sleep 1 # echo 1 > /sys/devices/system/cpu/cpu1/online Currently without a CPU hotplug handler, that new CPU has no per-CPU data infrastructure. The scheduler runs PMU call back function pai_add() to install the PMU support for that CPU before the task is being scheduled on that new CPU. In pai_add() instructions mp = this_cpu_ptr(pai_root[idx].mapptr); cpump = mp->mapptr; return a NULL pointer and the result is a kernel panic as variable cpump is used inside that function. Add CPU hotplug support for CPU add and delete and create the necessary per-CPU data infrastructure during CPU hotplug add processing. Same for CPU hotplug remove. This is done when the CPU is offline to ensure the data structures are available when CPU is made online and tasks are schedules on it. #Cc: stable@vger.kernel.org # v6.19 Fixes: 582cc1b28e8c ("s390/pai_ext: Enable per-task and system-wide sampling event") Fixes: 9f66572f2889 ("s390/pai_crypto: Enable per-task and system-wide sampling event") Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> --- arch/s390/include/asm/pai.h | 1 - arch/s390/kernel/perf_pai.c | 160 ++++++++++++++++++++++++++---------- 2 files changed, 116 insertions(+), 45 deletions(-) diff --git a/arch/s390/include/asm/pai.h b/arch/s390/include/asm/pai.h index 534d0320e2aa..a3456a36aaa7 100644 --- a/arch/s390/include/asm/pai.h +++ b/arch/s390/include/asm/pai.h @@ -76,7 +76,6 @@ static __always_inline void pai_kernel_exit(struct pt_regs *regs) } #define PAI_SAVE_AREA(x) ((x)->hw.event_base) -#define PAI_CPU_MASK(x) ((x)->hw.addr_filters) #define PAI_PMU_IDX(x) ((x)->hw.last_tag) #define PAI_SWLIST(x) (&(x)->hw.tp_list) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index 52d9f654346a..04a9dafa8f37 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -67,6 +67,7 @@ struct pai_mapptr { static struct pai_root { /* Anchor to per CPU data */ refcount_t refcnt; /* Overall active events */ + atomic_t tskctx; /* Overall per-task events */ struct pai_mapptr __percpu *mapptr; } pai_root[PAI_PMU_MAX]; @@ -93,14 +94,15 @@ struct pai_pmu { /* Define PAI PMU characteristics */ static struct pai_pmu pai_pmu[]; /* Forward declaration */ /* Free per CPU data when the last event is removed. */ -static void pai_root_free(int idx) +static void pai_root_free(int idx, int tasks) { - if (refcount_dec_and_test(&pai_root[idx].refcnt)) { + if (refcount_sub_and_test(tasks, &pai_root[idx].refcnt)) { free_percpu(pai_root[idx].mapptr); pai_root[idx].mapptr = NULL; } - debug_sprintf_event(paidbg, 5, "%s root[%d].refcount %d\n", __func__, - idx, refcount_read(&pai_root[idx].refcnt)); + debug_sprintf_event(paidbg, 5, "%s root[%d].refcount %d tskctx %d\n", + __func__, idx, refcount_read(&pai_root[idx].refcnt), + atomic_read(&pai_root[idx].tskctx)); } /* @@ -137,20 +139,36 @@ static void pai_free(struct pai_mapptr *mp) mp->mapptr = NULL; } -/* Adjust usage counters and remove allocated memory when all users are - * gone. Called under mutex_lock. - */ -static void pai_event_destroy_cpu(int idx, int cpu) +/* Called under mutex_lock */ +static void pai_event_destroy_cpu(int idx, int cpu, bool hotplug) { - struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); - struct pai_map *cpump = mp->mapptr; + struct pai_mapptr *mp; + struct pai_map *cpump; + int tasks = 1; - debug_sprintf_event(paidbg, 5, "%s users %d refcnt %u\n", - __func__, cpump->active_events, - refcount_read(&cpump->refcnt)); - if (refcount_dec_and_test(&cpump->refcnt)) + /* Check reference count and return when all gone. + * 1. An event is installed on online CPU X. + * 2. CPU x is offlined and the per-CPU data is removed. + * 3. Event is destroyed via close system call. + */ + if (!refcount_read(&pai_root[idx].refcnt)) + return; /* No events at all */ + mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); + if (!mp || !mp->mapptr) /* No events on that CPU */ + return; + + /* When hotplug is true, invocation is from CPU hotplug callback. + * Delete per-CPU resource and adjust refcnt when per-task events + * are currently active. This can be more than one. + * In this case adjust counters. + */ + if (hotplug) + tasks = atomic_read(&pai_root[idx].tskctx); + + cpump = mp->mapptr; + if (refcount_sub_and_test(tasks, &cpump->refcnt)) pai_free(mp); - pai_root_free(idx); + pai_root_free(idx, tasks); } static void pai_event_destroy(struct perf_event *event) @@ -160,13 +178,11 @@ static void pai_event_destroy(struct perf_event *event) free_page(PAI_SAVE_AREA(event)); mutex_lock(&pai_reserve_mutex); if (event->cpu == -1) { - struct cpumask *mask = PAI_CPU_MASK(event); - - for_each_cpu(cpu, mask) - pai_event_destroy_cpu(idx, cpu); - kfree(mask); + atomic_dec(&pai_root[idx].tskctx); + for_each_online_cpu(cpu) + pai_event_destroy_cpu(idx, cpu, false); } else { - pai_event_destroy_cpu(idx, event->cpu); + pai_event_destroy_cpu(idx, event->cpu, false); } mutex_unlock(&pai_reserve_mutex); } @@ -232,17 +248,25 @@ static u64 paicrypt_getall(struct perf_event *event) return sum; } -/* Allocate all per-CPU data structures. This function is called in - * process context and can block. In case of error all partly allocated - * memory is released and the reference counters adjusted correctly. - * Called under mutex_lock. - */ -static int pai_alloc_cpu(int idx, int cpu) +/* Called under mutex_lock */ +static int pai_alloc_cpu(int idx, int cpu, bool hotplug) { struct pai_map *cpump = NULL; bool need_paiext_cb = false; struct pai_mapptr *mp; - int rc; + int tasks = 1, rc = 0; + + /* When hotplug is true, invocation is from CPU hotplug callback. + * Allocate per-CPU resource when per-task events are currently active. + * This can be more than one. In this case adjust all reference + * counters. Otherwise return, this ensures memory is only allocated + * when needed. + */ + if (hotplug) { + tasks = atomic_read(&pai_root[idx].tskctx); + if (!tasks) + goto out; + } /* Allocate root node */ rc = pai_root_alloc(idx); @@ -291,26 +315,42 @@ static int pai_alloc_cpu(int idx, int cpu) goto undo; } INIT_LIST_HEAD(&cpump->syswide_list); - refcount_set(&cpump->refcnt, 1); + refcount_set(&cpump->refcnt, tasks); rc = 0; } else { - refcount_inc(&cpump->refcnt); + refcount_add(tasks, &cpump->refcnt); } + /* If tasks is greater than 1, we are called from CPU hotplug path + * and need to adjust the pai_root[idx].refcnt by the number of + * per-process events. Function pai_root_alloc(idx) already + * incremented by one. Adjust for the rest. + */ + if (tasks > 1) + refcount_add(tasks - 1, &pai_root[idx].refcnt); undo: if (rc) { /* Error in allocation of event, decrement anchor. Since * the event in not created, its destroy() function is never * invoked. Adjust the reference counter for the anchor. + * The failure happened in the case of variable + * cpump == NULL branch above. The pai_root[XXX].refcnt has + * been incremented by one. Then the per-CPU allocation + * failed, so decrement it by one, regardless of tasks. */ - pai_root_free(idx); + pai_root_free(idx, 1); } out: /* If rc is non-zero, no increment of counter/sampler was done. */ return rc; } -/* Called under mutex_lock */ +/* Check concurrent access of counting and sampling for PAI events. + * This function is called in process context and it is save to block. + * When the event initialization functions fails, no other call back will + * be invoked. + * Called under mutex_lock. + */ static int pai_alloc(struct perf_event *event) { int idx = PAI_PMU_IDX(event); @@ -322,24 +362,20 @@ static int pai_alloc(struct perf_event *event) goto out; for_each_online_cpu(cpu) { - rc = pai_alloc_cpu(idx, cpu); + rc = pai_alloc_cpu(idx, cpu, false); if (rc) { for_each_cpu(cpu, maskptr) - pai_event_destroy_cpu(idx, cpu); - kfree(maskptr); - goto out; + pai_event_destroy_cpu(idx, cpu, false); + goto undo; } cpumask_set_cpu(cpu, maskptr); } - /* - * On error all cpumask are freed and all events have been destroyed. - * Save of which CPUs data structures have been allocated for. - * Release them in pai_event_destroy call back function - * for this event. - */ - PAI_CPU_MASK(event) = maskptr; rc = 0; + /* Trace per-task events for CPU hotplug. */ + atomic_inc(&pai_root[idx].tskctx); +undo: + kfree(maskptr); out: return rc; } @@ -389,7 +425,7 @@ static int pai_event_init(struct perf_event *event, int idx) mutex_lock(&pai_reserve_mutex); if (event->cpu >= 0) - rc = pai_alloc_cpu(idx, event->cpu); + rc = pai_alloc_cpu(idx, event->cpu, false); else rc = pai_alloc(event); mutex_unlock(&pai_reserve_mutex); @@ -1216,8 +1252,34 @@ static int __init paipmu_setup(void) return install_ok; } +static int pai_online_cpu(unsigned int cpu) +{ + int rc; + + mutex_lock(&pai_reserve_mutex); + rc = pai_alloc_cpu(PAI_PMU_CRYPTO, cpu, true); + if (!rc) { + rc = pai_alloc_cpu(PAI_PMU_EXT, cpu, true); + if (rc) + pai_event_destroy_cpu(PAI_PMU_CRYPTO, cpu, true); + } + mutex_unlock(&pai_reserve_mutex); + return rc; +} + +static int pai_offline_cpu(unsigned int cpu) +{ + mutex_lock(&pai_reserve_mutex); + pai_event_destroy_cpu(PAI_PMU_CRYPTO, cpu, true); + pai_event_destroy_cpu(PAI_PMU_EXT, cpu, true); + mutex_unlock(&pai_reserve_mutex); + return 0; +} + static int __init pai_init(void) { + int rc; + /* Setup s390dbf facility */ paidbg = debug_register("pai", 32, 256, 128); if (!paidbg) { @@ -1226,7 +1288,17 @@ static int __init pai_init(void) } debug_register_view(paidbg, &debug_sprintf_view); + /* CPUHP_BP_PREPARE_DYN --> before CPU is brought online */ + rc = cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "perf/pai:prepare", + pai_online_cpu, pai_offline_cpu); + if (rc < 0) { + debug_unregister_view(paidbg, &debug_sprintf_view); + debug_unregister(paidbg); + return rc; + } + if (!paipmu_setup()) { + cpuhp_remove_state(rc); /* No PMU registration, no need for debug buffer */ debug_unregister_view(paidbg, &debug_sprintf_view); debug_unregister(paidbg); -- 2.55.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI 2026-08-24 12:23 ` [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI Thomas Richter @ 2026-08-24 12:53 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-08-24 12:53 UTC (permalink / raw) To: Thomas Richter Cc: Vasily Gorbik, Heiko Carstens, linux-s390, Alexander Gordeev, Christian Borntraeger Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Missing `cpus_read_lock()` during PAI event allocation and destruction causes race conditions with the new CPU hotplug callbacks, leading to NULL pointer dereferences or memory leaks. -- --- Patch [3]: [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI --- commit 91620cb7064d1e27822672c053b2886bba4751a9 Author: Thomas Richter <tmricht@linux.ibm.com> s390/pai: Support CPU hotplug for PMU PAI This commit adds CPU hotplug support for the PAI PMU, creating per-CPU data structures during CPU add/remove to prevent panics when CPUs are hotplugged during perf runs. > diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c > index 52d9f654346a2..04a9dafa8f371 100644 > --- a/arch/s390/kernel/perf_pai.c > +++ b/arch/s390/kernel/perf_pai.c [ ... ] > @@ -160,13 +178,11 @@ static void pai_event_destroy(struct perf_event *event) > free_page(PAI_SAVE_AREA(event)); > mutex_lock(&pai_reserve_mutex); > if (event->cpu == -1) { > - struct cpumask *mask = PAI_CPU_MASK(event); > - > - for_each_cpu(cpu, mask) > - pai_event_destroy_cpu(idx, cpu); > - kfree(mask); > + atomic_dec(&pai_root[idx].tskctx); > + for_each_online_cpu(cpu) > + pai_event_destroy_cpu(idx, cpu, false); [Severity: High] Does this code introduce a memory leak if a CPU is offlined concurrently? If a CPU is offlined, it is removed from cpu_online_mask at CPUHP_BRINGUP_CPU. If a concurrent perf event destruction runs, for_each_online_cpu() will skip the offlining CPU, failing to decrement its refcnt. When the offline process reaches pai_offline_cpu(), it reads tskctx as 0, so refcount_sub_and_test(0, ...) does not drop the reference, leaving the memory permanently leaked. Should cpus_read_lock() be held during pai_event_destroy() to prevent this? > } else { > - pai_event_destroy_cpu(idx, event->cpu); > + pai_event_destroy_cpu(idx, event->cpu, false); > } > mutex_unlock(&pai_reserve_mutex); > } [ ... ] > @@ -322,24 +362,20 @@ static int pai_alloc(struct perf_event *event) > goto out; > > for_each_online_cpu(cpu) { > - rc = pai_alloc_cpu(idx, cpu); > + rc = pai_alloc_cpu(idx, cpu, false); > if (rc) { > for_each_cpu(cpu, maskptr) > - pai_event_destroy_cpu(idx, cpu); > - kfree(maskptr); > - goto out; > + pai_event_destroy_cpu(idx, cpu, false); > + goto undo; > } > cpumask_set_cpu(cpu, maskptr); > } > > - /* > - * On error all cpumask are freed and all events have been destroyed. > - * Save of which CPUs data structures have been allocated for. > - * Release them in pai_event_destroy call back function > - * for this event. > - */ > - PAI_CPU_MASK(event) = maskptr; > rc = 0; > + /* Trace per-task events for CPU hotplug. */ > + atomic_inc(&pai_root[idx].tskctx); [Severity: High] Can this race with CPU hotplug and lead to a NULL pointer dereference? If CPU hotplug begins (e.g., via sysfs), pai_online_cpu() executes at CPUHP_BP_PREPARE_DYN. Since no per-task events exist (tskctx == 0), it skips allocation. If a concurrent system-wide perf event is created here, pai_alloc() iterates cpu_online_mask. Since the new CPU is not yet in the online mask (which happens later at CPUHP_BRINGUP_CPU), it skips allocation for the new CPU, and then increments tskctx to 1. When the CPU completes bring-up and a task schedules on it, will pai_add() dereference the unallocated per-CPU pointer and cause a kernel panic? > +undo: > + kfree(maskptr); > out: > return rc; > } [ ... ] > @@ -389,7 +425,7 @@ static int pai_event_init(struct perf_event *event, int idx) > > mutex_lock(&pai_reserve_mutex); > if (event->cpu >= 0) > - rc = pai_alloc_cpu(idx, event->cpu); > + rc = pai_alloc_cpu(idx, event->cpu, false); > else > rc = pai_alloc(event); > mutex_unlock(&pai_reserve_mutex); [Severity: High] Does pai_event_init() need to hold cpus_read_lock() here? Acquiring cpus_read_lock() before taking pai_reserve_mutex (to avoid ABBA deadlocks with the hotplug writer lock) would serialize event allocation with CPU hotplug operations, preventing the races mentioned above. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260824122307.86133-1-tmricht@linux.ibm.com?part=3 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/3 v6] Add CPU hotplug support for PAI PMU
@ 2026-08-25 7:29 Thomas Richter
2026-08-25 7:29 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter
0 siblings, 1 reply; 13+ messages in thread
From: Thomas Richter @ 2026-08-25 7:29 UTC (permalink / raw)
To: linux-s390; +Cc: Thomas Richter
V6: Add findings from Sashiko
- Remove cpus_read_lock() and cpus_read_unlock() invocations
from CPU hotplug handlers in patch 3.
V5: Add findings from Sashiko
- Add cpus_read_lock() and cpus_read_unlock() in patch 3.
V4: Add findings from Sumanth and updated patch 3/3.
- Fix reference count for CPU hotplug remove while multiple
per-task events are active.
V3: Add findings from Sumanth and updated patch 3/3.
- Refined Fixes: commit id and messages
- Handle cpuhp_setup_state() failure
V2: Add findings from Sumanth and updated patch 3/3.
- handle possible NULL pointer dereference in pai_event_destroy_cpu()
- handle possibe memory allocation failure in pai_online_cpu()
- add Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
to patch 1/3 and patch 2/3.
Add support for CPU hotplug add and remove for PAI PMU.
Patch 1: Change function argument list
Patch 2: Move locking from CPU scope to event scope
Patch 3: Add CPU hotplug handler
Thomas Richter (3):
s390/pai: Use PAI PMU index as parameter replacing event
s390/pai: Move locking to event init and delete
s390/pai: Support CPU hotplug for PMU PAI
arch/s390/include/asm/pai.h | 1 -
arch/s390/kernel/perf_pai.c | 182 +++++++++++++++++++++++++-----------
2 files changed, 128 insertions(+), 55 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-25 7:29 [PATCH 0/3 v6] Add CPU hotplug support for PAI PMU Thomas Richter @ 2026-08-25 7:29 ` Thomas Richter 2026-08-25 7:43 ` sashiko-bot 0 siblings, 1 reply; 13+ messages in thread From: Thomas Richter @ 2026-08-25 7:29 UTC (permalink / raw) To: linux-s390; +Cc: Thomas Richter, Sumanth Korikkar Move mutex locking from per CPU allocation to event allocation. No functional change. Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> --- arch/s390/kernel/perf_pai.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index 7c13f5586c79..52d9f654346a 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -138,21 +138,19 @@ static void pai_free(struct pai_mapptr *mp) } /* Adjust usage counters and remove allocated memory when all users are - * gone. + * gone. Called under mutex_lock. */ static void pai_event_destroy_cpu(int idx, int cpu) { struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); struct pai_map *cpump = mp->mapptr; - mutex_lock(&pai_reserve_mutex); debug_sprintf_event(paidbg, 5, "%s users %d refcnt %u\n", __func__, cpump->active_events, refcount_read(&cpump->refcnt)); if (refcount_dec_and_test(&cpump->refcnt)) pai_free(mp); pai_root_free(idx); - mutex_unlock(&pai_reserve_mutex); } static void pai_event_destroy(struct perf_event *event) @@ -160,6 +158,7 @@ static void pai_event_destroy(struct perf_event *event) int cpu = 0, idx = PAI_PMU_IDX(event); free_page(PAI_SAVE_AREA(event)); + mutex_lock(&pai_reserve_mutex); if (event->cpu == -1) { struct cpumask *mask = PAI_CPU_MASK(event); @@ -169,6 +168,7 @@ static void pai_event_destroy(struct perf_event *event) } else { pai_event_destroy_cpu(idx, event->cpu); } + mutex_unlock(&pai_reserve_mutex); } static void paicrypt_event_destroy(struct perf_event *event) @@ -232,12 +232,10 @@ static u64 paicrypt_getall(struct perf_event *event) return sum; } -/* Check concurrent access of counting and sampling for crypto events. - * This function is called in process context and it is save to block. - * When the event initialization functions fails, no other call back will - * be invoked. - * - * Allocate the memory for the event. +/* Allocate all per-CPU data structures. This function is called in + * process context and can block. In case of error all partly allocated + * memory is released and the reference counters adjusted correctly. + * Called under mutex_lock. */ static int pai_alloc_cpu(int idx, int cpu) { @@ -246,11 +244,10 @@ static int pai_alloc_cpu(int idx, int cpu) struct pai_mapptr *mp; int rc; - mutex_lock(&pai_reserve_mutex); /* Allocate root node */ rc = pai_root_alloc(idx); if (rc) - goto unlock; + goto out; /* Allocate node for this event */ mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); @@ -308,12 +305,12 @@ static int pai_alloc_cpu(int idx, int cpu) */ pai_root_free(idx); } -unlock: - mutex_unlock(&pai_reserve_mutex); +out: /* If rc is non-zero, no increment of counter/sampler was done. */ return rc; } +/* Called under mutex_lock */ static int pai_alloc(struct perf_event *event) { int idx = PAI_PMU_IDX(event); @@ -390,10 +387,12 @@ static int pai_event_init(struct perf_event *event, int idx) } } + mutex_lock(&pai_reserve_mutex); if (event->cpu >= 0) rc = pai_alloc_cpu(idx, event->cpu); else rc = pai_alloc(event); + mutex_unlock(&pai_reserve_mutex); if (rc) { free_page(PAI_SAVE_AREA(event)); goto out; -- 2.55.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-25 7:29 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter @ 2026-08-25 7:43 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-08-25 7:43 UTC (permalink / raw) To: Thomas Richter Cc: Vasily Gorbik, linux-s390, Heiko Carstens, Christian Borntraeger, Alexander Gordeev > Move mutex locking from per CPU allocation to event allocation. > No functional change. > > Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260825072931.3738180-1-tmricht@linux.ibm.com?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/3 v5] Add CPU hotplug support for PAI PMU
@ 2026-08-24 13:17 Thomas Richter
2026-08-24 13:17 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter
0 siblings, 1 reply; 13+ messages in thread
From: Thomas Richter @ 2026-08-24 13:17 UTC (permalink / raw)
To: linux-s390; +Cc: Thomas Richter
V5: Add findings from Sashiko
- Add cpus_read_lock() and cpus_read_unlock() in patch 3.
V4: Add findings from Sumanth and updated patch 3/3.
- Fix reference count for CPU hotplug remove while multiple
per-task events are active.
V3: Add findings from Sumanth and updated patch 3/3.
- Refined Fixes: commit id and messages
- Handle cpuhp_setup_state() failure
V2: Add findings from Sumanth and updated patch 3/3.
- handle possible NULL pointer dereference in pai_event_destroy_cpu()
- handle possibe memory allocation failure in pai_online_cpu()
- add Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
to patch 1/3 and patch 2/3.
Add support for CPU hotplug add and remove for PAI PMU.
Patch 1: Change function argument list
Patch 2: Move locking from CPU scope to event scope
Patch 3: Add CPU hotplug handler
Thomas Richter (3):
s390/pai: Use PAI PMU index as parameter replacing event
s390/pai: Move locking to event init and delete
s390/pai: Support CPU hotplug for PMU PAI
arch/s390/include/asm/pai.h | 1 -
arch/s390/kernel/perf_pai.c | 186 +++++++++++++++++++++++++-----------
2 files changed, 132 insertions(+), 55 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-24 13:17 [PATCH 0/3 v5] Add CPU hotplug support for PAI PMU Thomas Richter @ 2026-08-24 13:17 ` Thomas Richter 2026-08-24 13:29 ` sashiko-bot 0 siblings, 1 reply; 13+ messages in thread From: Thomas Richter @ 2026-08-24 13:17 UTC (permalink / raw) To: linux-s390; +Cc: Thomas Richter, Sumanth Korikkar Move mutex locking from per CPU allocation to event allocation. No functional change. Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> --- arch/s390/kernel/perf_pai.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index 7c13f5586c79..52d9f654346a 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -138,21 +138,19 @@ static void pai_free(struct pai_mapptr *mp) } /* Adjust usage counters and remove allocated memory when all users are - * gone. + * gone. Called under mutex_lock. */ static void pai_event_destroy_cpu(int idx, int cpu) { struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); struct pai_map *cpump = mp->mapptr; - mutex_lock(&pai_reserve_mutex); debug_sprintf_event(paidbg, 5, "%s users %d refcnt %u\n", __func__, cpump->active_events, refcount_read(&cpump->refcnt)); if (refcount_dec_and_test(&cpump->refcnt)) pai_free(mp); pai_root_free(idx); - mutex_unlock(&pai_reserve_mutex); } static void pai_event_destroy(struct perf_event *event) @@ -160,6 +158,7 @@ static void pai_event_destroy(struct perf_event *event) int cpu = 0, idx = PAI_PMU_IDX(event); free_page(PAI_SAVE_AREA(event)); + mutex_lock(&pai_reserve_mutex); if (event->cpu == -1) { struct cpumask *mask = PAI_CPU_MASK(event); @@ -169,6 +168,7 @@ static void pai_event_destroy(struct perf_event *event) } else { pai_event_destroy_cpu(idx, event->cpu); } + mutex_unlock(&pai_reserve_mutex); } static void paicrypt_event_destroy(struct perf_event *event) @@ -232,12 +232,10 @@ static u64 paicrypt_getall(struct perf_event *event) return sum; } -/* Check concurrent access of counting and sampling for crypto events. - * This function is called in process context and it is save to block. - * When the event initialization functions fails, no other call back will - * be invoked. - * - * Allocate the memory for the event. +/* Allocate all per-CPU data structures. This function is called in + * process context and can block. In case of error all partly allocated + * memory is released and the reference counters adjusted correctly. + * Called under mutex_lock. */ static int pai_alloc_cpu(int idx, int cpu) { @@ -246,11 +244,10 @@ static int pai_alloc_cpu(int idx, int cpu) struct pai_mapptr *mp; int rc; - mutex_lock(&pai_reserve_mutex); /* Allocate root node */ rc = pai_root_alloc(idx); if (rc) - goto unlock; + goto out; /* Allocate node for this event */ mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); @@ -308,12 +305,12 @@ static int pai_alloc_cpu(int idx, int cpu) */ pai_root_free(idx); } -unlock: - mutex_unlock(&pai_reserve_mutex); +out: /* If rc is non-zero, no increment of counter/sampler was done. */ return rc; } +/* Called under mutex_lock */ static int pai_alloc(struct perf_event *event) { int idx = PAI_PMU_IDX(event); @@ -390,10 +387,12 @@ static int pai_event_init(struct perf_event *event, int idx) } } + mutex_lock(&pai_reserve_mutex); if (event->cpu >= 0) rc = pai_alloc_cpu(idx, event->cpu); else rc = pai_alloc(event); + mutex_unlock(&pai_reserve_mutex); if (rc) { free_page(PAI_SAVE_AREA(event)); goto out; -- 2.55.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-24 13:17 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter @ 2026-08-24 13:29 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-08-24 13:29 UTC (permalink / raw) To: Thomas Richter Cc: Heiko Carstens, Alexander Gordeev, Christian Borntraeger, linux-s390, Vasily Gorbik > Move mutex locking from per CPU allocation to event allocation. > No functional change. > > Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260824131751.179275-1-tmricht@linux.ibm.com?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/3] Add CPU hotplug support for PAI PMU
@ 2026-08-24 9:20 Thomas Richter
2026-08-24 9:20 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter
0 siblings, 1 reply; 13+ messages in thread
From: Thomas Richter @ 2026-08-24 9:20 UTC (permalink / raw)
To: linux-s390; +Cc: Thomas Richter
V4: Add findings from Sumanth and updated patch 3/3.
- Fix reference count for CPU hotplug remove while multiple
per-task events are active.
V3: Add findings from Sumanth and updated patch 3/3.
- Refined Fixes: commit id and messages
- Handle cpuhp_setup_state() failure
V2: Add findings from Sumanth and updated patch 3/3.
- handle possible NULL pointer dereference in pai_event_destroy_cpu()
- handle possibe memory allocation failure in pai_online_cpu()
- add Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
to patch 1/3 and patch 2/3.
Add support for CPU hotplug add and remove for PAI PMU.
Patch 1: Change function argument list
Patch 2: Move locking from CPU scope to event scope
Patch 3: Add CPU hotplug handler
Thomas Richter (3):
s390/pai: Use PAI PMU index as parameter replacing event
s390/pai: Move locking to event init and delete
s390/pai: Support CPU hotplug for PMU PAI
arch/s390/include/asm/pai.h | 1 -
arch/s390/kernel/perf_pai.c | 178 +++++++++++++++++++++++++-----------
2 files changed, 124 insertions(+), 55 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-24 9:20 [PATCH 0/3] Add CPU hotplug support for PAI PMU Thomas Richter @ 2026-08-24 9:20 ` Thomas Richter 2026-08-24 9:31 ` sashiko-bot 0 siblings, 1 reply; 13+ messages in thread From: Thomas Richter @ 2026-08-24 9:20 UTC (permalink / raw) To: linux-s390; +Cc: Thomas Richter, Sumanth Korikkar Move mutex locking from per CPU allocation to event allocation. No functional change. Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> --- arch/s390/kernel/perf_pai.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c index 7c13f5586c79..52d9f654346a 100644 --- a/arch/s390/kernel/perf_pai.c +++ b/arch/s390/kernel/perf_pai.c @@ -138,21 +138,19 @@ static void pai_free(struct pai_mapptr *mp) } /* Adjust usage counters and remove allocated memory when all users are - * gone. + * gone. Called under mutex_lock. */ static void pai_event_destroy_cpu(int idx, int cpu) { struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); struct pai_map *cpump = mp->mapptr; - mutex_lock(&pai_reserve_mutex); debug_sprintf_event(paidbg, 5, "%s users %d refcnt %u\n", __func__, cpump->active_events, refcount_read(&cpump->refcnt)); if (refcount_dec_and_test(&cpump->refcnt)) pai_free(mp); pai_root_free(idx); - mutex_unlock(&pai_reserve_mutex); } static void pai_event_destroy(struct perf_event *event) @@ -160,6 +158,7 @@ static void pai_event_destroy(struct perf_event *event) int cpu = 0, idx = PAI_PMU_IDX(event); free_page(PAI_SAVE_AREA(event)); + mutex_lock(&pai_reserve_mutex); if (event->cpu == -1) { struct cpumask *mask = PAI_CPU_MASK(event); @@ -169,6 +168,7 @@ static void pai_event_destroy(struct perf_event *event) } else { pai_event_destroy_cpu(idx, event->cpu); } + mutex_unlock(&pai_reserve_mutex); } static void paicrypt_event_destroy(struct perf_event *event) @@ -232,12 +232,10 @@ static u64 paicrypt_getall(struct perf_event *event) return sum; } -/* Check concurrent access of counting and sampling for crypto events. - * This function is called in process context and it is save to block. - * When the event initialization functions fails, no other call back will - * be invoked. - * - * Allocate the memory for the event. +/* Allocate all per-CPU data structures. This function is called in + * process context and can block. In case of error all partly allocated + * memory is released and the reference counters adjusted correctly. + * Called under mutex_lock. */ static int pai_alloc_cpu(int idx, int cpu) { @@ -246,11 +244,10 @@ static int pai_alloc_cpu(int idx, int cpu) struct pai_mapptr *mp; int rc; - mutex_lock(&pai_reserve_mutex); /* Allocate root node */ rc = pai_root_alloc(idx); if (rc) - goto unlock; + goto out; /* Allocate node for this event */ mp = per_cpu_ptr(pai_root[idx].mapptr, cpu); @@ -308,12 +305,12 @@ static int pai_alloc_cpu(int idx, int cpu) */ pai_root_free(idx); } -unlock: - mutex_unlock(&pai_reserve_mutex); +out: /* If rc is non-zero, no increment of counter/sampler was done. */ return rc; } +/* Called under mutex_lock */ static int pai_alloc(struct perf_event *event) { int idx = PAI_PMU_IDX(event); @@ -390,10 +387,12 @@ static int pai_event_init(struct perf_event *event, int idx) } } + mutex_lock(&pai_reserve_mutex); if (event->cpu >= 0) rc = pai_alloc_cpu(idx, event->cpu); else rc = pai_alloc(event); + mutex_unlock(&pai_reserve_mutex); if (rc) { free_page(PAI_SAVE_AREA(event)); goto out; -- 2.55.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] s390/pai: Move locking to event init and delete 2026-08-24 9:20 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter @ 2026-08-24 9:31 ` sashiko-bot 0 siblings, 0 replies; 13+ messages in thread From: sashiko-bot @ 2026-08-24 9:31 UTC (permalink / raw) To: Thomas Richter Cc: Christian Borntraeger, linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev > Move mutex locking from per CPU allocation to event allocation. > No functional change. > > Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260824092036.3075553-1-tmricht@linux.ibm.com?part=2 ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-08-25 7:43 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-24 12:23 [PATCH 0/3 v2] Add CPU hotplug support for PAI PMU Thomas Richter 2026-08-24 12:23 ` [PATCH 1/3] s390/pai: Use PAI PMU index as parameter replacing event Thomas Richter 2026-08-24 12:32 ` sashiko-bot 2026-08-24 12:23 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter 2026-08-24 12:43 ` sashiko-bot 2026-08-24 12:23 ` [PATCH 3/3 v2] s390/pai: Support CPU hotplug for PMU PAI Thomas Richter 2026-08-24 12:53 ` sashiko-bot -- strict thread matches above, loose matches on Subject: below -- 2026-08-25 7:29 [PATCH 0/3 v6] Add CPU hotplug support for PAI PMU Thomas Richter 2026-08-25 7:29 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter 2026-08-25 7:43 ` sashiko-bot 2026-08-24 13:17 [PATCH 0/3 v5] Add CPU hotplug support for PAI PMU Thomas Richter 2026-08-24 13:17 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter 2026-08-24 13:29 ` sashiko-bot 2026-08-24 9:20 [PATCH 0/3] Add CPU hotplug support for PAI PMU Thomas Richter 2026-08-24 9:20 ` [PATCH 2/3] s390/pai: Move locking to event init and delete Thomas Richter 2026-08-24 9:31 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox