Skip to content

Commit eb0ef8a

Browse files
committed
Merge tag 'perf_urgent_for_v6.1_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Borislav Petkov: - Fix an intel PT erratum where CPUs do not support single range output for more than 4K - Fix a NULL ptr dereference which can happen after an NMI interferes with the event enabling dance in amd_pmu_enable_all() - Free the events array too when freeing uncore contexts on CPU online, thereby fixing a memory leak - Improve the pending SIGTRAP check * tag 'perf_urgent_for_v6.1_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86/intel/pt: Fix sampling using single range output perf/x86/amd: Fix crash due to race between amd_pmu_enable_all, perf NMI and throttling perf/x86/amd/uncore: Fix memory leak for events array perf: Improve missing SIGTRAP checking
2 parents 6a211a7 + ce0d998 commit eb0ef8a

File tree

4 files changed

+31
-9
lines changed

4 files changed

+31
-9
lines changed

arch/x86/events/amd/core.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,7 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
861861
pmu_enabled = cpuc->enabled;
862862
cpuc->enabled = 0;
863863

864-
/* stop everything (includes BRS) */
865-
amd_pmu_disable_all();
864+
amd_brs_disable_all();
866865

867866
/* Drain BRS is in use (could be inactive) */
868867
if (cpuc->lbr_users)
@@ -873,7 +872,7 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
873872

874873
cpuc->enabled = pmu_enabled;
875874
if (pmu_enabled)
876-
amd_pmu_enable_all(0);
875+
amd_brs_enable_all();
877876

878877
return amd_pmu_adjust_nmi_window(handled);
879878
}

arch/x86/events/amd/uncore.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ static void uncore_clean_online(void)
553553

554554
hlist_for_each_entry_safe(uncore, n, &uncore_unused_list, node) {
555555
hlist_del(&uncore->node);
556+
kfree(uncore->events);
556557
kfree(uncore);
557558
}
558559
}

arch/x86/events/intel/pt.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,15 @@ static int pt_buffer_try_single(struct pt_buffer *buf, int nr_pages)
12631263
if (1 << order != nr_pages)
12641264
goto out;
12651265

1266+
/*
1267+
* Some processors cannot always support single range for more than
1268+
* 4KB - refer errata TGL052, ADL037 and RPL017. Future processors might
1269+
* also be affected, so for now rather than trying to keep track of
1270+
* which ones, just disable it for all.
1271+
*/
1272+
if (nr_pages > 1)
1273+
goto out;
1274+
12661275
buf->single = true;
12671276
buf->nr_pages = nr_pages;
12681277
ret = 0;

kernel/events/core.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9306,14 +9306,27 @@ static int __perf_event_overflow(struct perf_event *event,
93069306
}
93079307

93089308
if (event->attr.sigtrap) {
9309-
/*
9310-
* Should not be able to return to user space without processing
9311-
* pending_sigtrap (kernel events can overflow multiple times).
9312-
*/
9313-
WARN_ON_ONCE(event->pending_sigtrap && event->attr.exclude_kernel);
9309+
unsigned int pending_id = 1;
9310+
9311+
if (regs)
9312+
pending_id = hash32_ptr((void *)instruction_pointer(regs)) ?: 1;
93149313
if (!event->pending_sigtrap) {
9315-
event->pending_sigtrap = 1;
9314+
event->pending_sigtrap = pending_id;
93169315
local_inc(&event->ctx->nr_pending);
9316+
} else if (event->attr.exclude_kernel) {
9317+
/*
9318+
* Should not be able to return to user space without
9319+
* consuming pending_sigtrap; with exceptions:
9320+
*
9321+
* 1. Where !exclude_kernel, events can overflow again
9322+
* in the kernel without returning to user space.
9323+
*
9324+
* 2. Events that can overflow again before the IRQ-
9325+
* work without user space progress (e.g. hrtimer).
9326+
* To approximate progress (with false negatives),
9327+
* check 32-bit hash of the current IP.
9328+
*/
9329+
WARN_ON_ONCE(event->pending_sigtrap != pending_id);
93179330
}
93189331
event->pending_addr = data->addr;
93199332
irq_work_queue(&event->pending_irq);

0 commit comments

Comments
 (0)