summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-14 13:22:40 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-14 13:22:40 -0700
commit33c66eb5e9844429911bf5478c96c60f9f8af9d0 (patch)
treefaaf5e1d3d70215e9bf3bf86790cc8cbdef0b8b8 /kernel
parent4b2bdc22210e39a02b3dc984cb8eb6b3293a56a7 (diff)
parent5a84b600050c5f16b8bba25dd0e7aea845880407 (diff)
downloadlwn-33c66eb5e9844429911bf5478c96c60f9f8af9d0.tar.gz
lwn-33c66eb5e9844429911bf5478c96c60f9f8af9d0.zip
Merge tag 'perf-core-2026-04-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull performance events updates from Ingo Molnar: "Core updates: - Try to allocate task_ctx_data quickly, to optimize O(N^2) algorithm on large systems with O(100k) threads (Namhyung Kim) AMD PMU driver IBS support updates and fixes, by Ravi Bangoria: - Fix interrupt accounting for discarded samples - Fix a Zen5-specific quirk - Fix PhyAddrVal handling - Fix NMI-safety with perf_allow_kernel() - Fix a race between event add and NMIs Intel PMU driver updates: - Only check GP counters for PEBS constraints validation (Dapeng Mi) MSR driver: - Turn SMI_COUNT and PPERF on by default, instead of a long list of CPU models to enable them on (Kan Liang) ... and misc cleanups and fixes by Aldf Conte, Anshuman Khandual, Namhyung Kim, Ravi Bangoria and Yen-Hsiang Hsu" * tag 'perf-core-2026-04-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/events: Replace READ_ONCE() with standard pgtable accessors perf/x86/msr: Make SMI and PPERF on by default perf/x86/intel/p4: Fix unused variable warning in p4_pmu_init() perf/x86/intel: Only check GP counters for PEBS constraints validation perf/x86/amd/ibs: Fix comment typo in ibs_op_data perf/amd/ibs: Advertise remote socket capability perf/amd/ibs: Enable streaming store filter perf/amd/ibs: Enable RIP bit63 hardware filtering perf/amd/ibs: Enable fetch latency filtering perf/amd/ibs: Support IBS_{FETCH|OP}_CTL2[Dis] to eliminate RMW race perf/amd/ibs: Add new MSRs and CPUID bits definitions perf/amd/ibs: Define macro for ldlat mask and shift perf/amd/ibs: Avoid race between event add and NMI perf/amd/ibs: Avoid calling perf_allow_kernel() from the IBS NMI handler perf/amd/ibs: Preserve PhyAddrVal bit when clearing PhyAddr MSR perf/amd/ibs: Limit ldlat->l3missonly dependency to Zen5 perf/amd/ibs: Account interrupt for discarded samples perf/core: Simplify __detach_global_ctx_data() perf/core: Try to allocate task_ctx_data quickly perf/core: Pass GFP flags to attach_task_ctx_data()
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 89b40e439717..9e66fbee37f0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5368,15 +5368,15 @@ static void unaccount_freq_event(void)
static struct perf_ctx_data *
-alloc_perf_ctx_data(struct kmem_cache *ctx_cache, bool global)
+alloc_perf_ctx_data(struct kmem_cache *ctx_cache, bool global, gfp_t gfp_flags)
{
struct perf_ctx_data *cd;
- cd = kzalloc_obj(*cd);
+ cd = kzalloc_obj(*cd, gfp_flags);
if (!cd)
return NULL;
- cd->data = kmem_cache_zalloc(ctx_cache, GFP_KERNEL);
+ cd->data = kmem_cache_zalloc(ctx_cache, gfp_flags);
if (!cd->data) {
kfree(cd);
return NULL;
@@ -5410,11 +5410,11 @@ static inline void perf_free_ctx_data_rcu(struct perf_ctx_data *cd)
static int
attach_task_ctx_data(struct task_struct *task, struct kmem_cache *ctx_cache,
- bool global)
+ bool global, gfp_t gfp_flags)
{
struct perf_ctx_data *cd, *old = NULL;
- cd = alloc_perf_ctx_data(ctx_cache, global);
+ cd = alloc_perf_ctx_data(ctx_cache, global, gfp_flags);
if (!cd)
return -ENOMEM;
@@ -5487,6 +5487,12 @@ again:
cd = NULL;
}
if (!cd) {
+ /*
+ * Try to allocate context quickly before
+ * traversing the whole thread list again.
+ */
+ if (!attach_task_ctx_data(p, ctx_cache, true, GFP_NOWAIT))
+ continue;
get_task_struct(p);
goto alloc;
}
@@ -5497,7 +5503,7 @@ again:
return 0;
alloc:
- ret = attach_task_ctx_data(p, ctx_cache, true);
+ ret = attach_task_ctx_data(p, ctx_cache, true, GFP_KERNEL);
put_task_struct(p);
if (ret) {
__detach_global_ctx_data();
@@ -5517,7 +5523,7 @@ attach_perf_ctx_data(struct perf_event *event)
return -ENOMEM;
if (task)
- return attach_task_ctx_data(task, ctx_cache, false);
+ return attach_task_ctx_data(task, ctx_cache, false, GFP_KERNEL);
ret = attach_global_ctx_data(ctx_cache);
if (ret)
@@ -5552,22 +5558,15 @@ static void __detach_global_ctx_data(void)
struct task_struct *g, *p;
struct perf_ctx_data *cd;
-again:
scoped_guard (rcu) {
for_each_process_thread(g, p) {
cd = rcu_dereference(p->perf_ctx_data);
- if (!cd || !cd->global)
- continue;
- cd->global = 0;
- get_task_struct(p);
- goto detach;
+ if (cd && cd->global) {
+ cd->global = 0;
+ detach_task_ctx_data(p);
+ }
}
}
- return;
-detach:
- detach_task_ctx_data(p);
- put_task_struct(p);
- goto again;
}
static void detach_global_ctx_data(void)
@@ -8420,7 +8419,7 @@ static u64 perf_get_pgtable_size(struct mm_struct *mm, unsigned long addr)
pte_t *ptep, pte;
pgdp = pgd_offset(mm, addr);
- pgd = READ_ONCE(*pgdp);
+ pgd = pgdp_get(pgdp);
if (pgd_none(pgd))
return 0;
@@ -8428,7 +8427,7 @@ static u64 perf_get_pgtable_size(struct mm_struct *mm, unsigned long addr)
return pgd_leaf_size(pgd);
p4dp = p4d_offset_lockless(pgdp, pgd, addr);
- p4d = READ_ONCE(*p4dp);
+ p4d = p4dp_get(p4dp);
if (!p4d_present(p4d))
return 0;
@@ -8436,7 +8435,7 @@ static u64 perf_get_pgtable_size(struct mm_struct *mm, unsigned long addr)
return p4d_leaf_size(p4d);
pudp = pud_offset_lockless(p4dp, p4d, addr);
- pud = READ_ONCE(*pudp);
+ pud = pudp_get(pudp);
if (!pud_present(pud))
return 0;
@@ -9238,7 +9237,7 @@ perf_event_alloc_task_data(struct task_struct *child,
return;
attach:
- attach_task_ctx_data(child, ctx_cache, true);
+ attach_task_ctx_data(child, ctx_cache, true, GFP_KERNEL);
}
void perf_event_fork(struct task_struct *task)