With the RAPL PMU addition, there is a recursive locking when CPU online callback function calls rapl_package_add_pmu(). Here cpu_hotplug_lock is already acquired by cpuhp_thread_fun() and rapl_package_add_pmu() tries to acquire again. <4>[ 8.197433] ============================================ <4>[ 8.197437] WARNING: possible recursive locking detected <4>[ 8.197440] 6.19.0-rc1-lgci-xe-xe-4242-05b7c58b3367dca84+ #1 Not tainted <4>[ 8.197444] -------------------------------------------- <4>[ 8.197447] cpuhp/0/20 is trying to acquire lock: <4>[ 8.197450] ffffffff83487870 (cpu_hotplug_lock){++++}-{0:0}, at: rapl_package_add_pmu+0x37/0x370 [intel_rapl_common] <4>[ 8.197463] but task is already holding lock: <4>[ 8.197466] ffffffff83487870 (cpu_hotplug_lock){++++}-{0:0}, at: cpuhp_thread_fun+0x6d/0x290 <4>[ 8.197477] other info that might help us debug this: <4>[ 8.197480] Possible unsafe locking scenario: <4>[ 8.197483] CPU0 <4>[ 8.197485] ---- <4>[ 8.197487] lock(cpu_hotplug_lock); <4>[ 8.197490] lock(cpu_hotplug_lock); <4>[ 8.197493] *** DEADLOCK *** .. .. <4>[ 8.197542] __lock_acquire+0x146e/0x2790 <4>[ 8.197548] lock_acquire+0xc4/0x2c0 <4>[ 8.197550] ? rapl_package_add_pmu+0x37/0x370 [intel_rapl_common] <4>[ 8.197556] cpus_read_lock+0x41/0x110 <4>[ 8.197558] ? rapl_package_add_pmu+0x37/0x370 [intel_rapl_common] <4>[ 8.197561] rapl_package_add_pmu+0x37/0x370 [intel_rapl_common] <4>[ 8.197565] rapl_cpu_online+0x85/0x87 [intel_rapl_msr] <4>[ 8.197568] ? __pfx_rapl_cpu_online+0x10/0x10 [intel_rapl_msr] <4>[ 8.197570] cpuhp_invoke_callback+0x41f/0x6c0 <4>[ 8.197573] ? cpuhp_thread_fun+0x6d/0x290 <4>[ 8.197575] cpuhp_thread_fun+0x1e2/0x290 <4>[ 8.197578] ? smpboot_thread_fn+0x26/0x290 <4>[ 8.197581] smpboot_thread_fn+0x12f/0x290 <4>[ 8.197584] ? __pfx_smpboot_thread_fn+0x10/0x10 <4>[ 8.197586] kthread+0x11f/0x250 <4>[ 8.197589] ? __pfx_kthread+0x10/0x10 <4>[ 8.197592] ret_from_fork+0x344/0x3a0 <4>[ 8.197595] ? __pfx_kthread+0x10/0x10 <4>[ 8.197597] ret_from_fork_asm+0x1a/0x30 <4>[ 8.197604] </TASK> Fix this issue in the same way as rapl powercap package domain is added from the same CPU online callback by introducing another interface which doesn't call cpus_read_lock(). Add rapl_package_add_pmu_locked() and rapl_package_remove_pmu_locked() which don't call cpus_read_lock().
Showing the changes to include/linux (1 of 3 files). Show all
Unified · Split
| @@ -214,10 +214,14 @@ void rapl_remove_package(struct rapl_package *rp); · 213 unmodified lines | |||
| 214 | 214 | ||
| 215 | #ifdef CONFIG_PERF_EVENTS | 215 | #ifdef CONFIG_PERF_EVENTS |
| 216 | int rapl_package_add_pmu(struct rapl_package *rp); | 216 | int rapl_package_add_pmu(struct rapl_package *rp); |
| 217 | int rapl_package_add_pmu_locked(struct rapl_package *rp); | ||
| 217 | void rapl_package_remove_pmu(struct rapl_package *rp); | 218 | void rapl_package_remove_pmu(struct rapl_package *rp); |
| 219 | void rapl_package_remove_pmu_locked(struct rapl_package *rp); | ||
| 218 | #else | 220 | #else |
| 219 | static inline int rapl_package_add_pmu(struct rapl_package *rp) { return 0; } | 221 | static inline int rapl_package_add_pmu(struct rapl_package *rp) { return 0; } |
| 222 | static inline int rapl_package_add_pmu_locked(struct rapl_package *rp) { return 0; } | ||
| 220 | static inline void rapl_package_remove_pmu(struct rapl_package *rp) { } | 223 | static inline void rapl_package_remove_pmu(struct rapl_package *rp) { } |
| 224 | static inline void rapl_package_remove_pmu_locked(struct rapl_package *rp) { } | ||
| 221 | #endif | 225 | #endif |
| 222 | 226 | ||
| 223 | #endif /* __INTEL_RAPL_H__ */ | 227 | #endif /* __INTEL_RAPL_H__ */ |