Pull perf events fixes from Ingo Molnar: - Fix lock ordering bug found by lockdep in perf_event_wakeup() - Fix uncore counter enumeration on Granite Rapids and Sierra Forest - Fix perf_mmap() refcount bug found by Syzkaller - Fix __perf_event_overflow() vs perf_remove_from_context() race * tag 'perf-urgent-2026-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf: Fix __perf_event_overflow() vs perf_remove_from_context() race perf/core: Fix refcount bug and potential UAF in perf_mmap perf/x86/intel/uncore: Add per-scheduler IMC CAS count events perf/core: Fix invalid wait context in ctx_sched_in()
Unified · Split
| @@ -6497,6 +6497,32 @@ static struct intel_uncore_type gnr_uncore_ubox = { · 6496 unmodified lines | |||
| 6497 | .attr_update = uncore_alias_groups, | 6497 | .attr_update = uncore_alias_groups, |
| 6498 | }; | 6498 | }; |
| 6499 | 6499 | ||
| 6500 | static struct uncore_event_desc gnr_uncore_imc_events[] = { | ||
| 6501 | INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x01,umask=0x00"), | ||
| 6502 | INTEL_UNCORE_EVENT_DESC(cas_count_read_sch0, "event=0x05,umask=0xcf"), | ||
| 6503 | INTEL_UNCORE_EVENT_DESC(cas_count_read_sch0.scale, "6.103515625e-5"), | ||
| 6504 | INTEL_UNCORE_EVENT_DESC(cas_count_read_sch0.unit, "MiB"), | ||
| 6505 | INTEL_UNCORE_EVENT_DESC(cas_count_read_sch1, "event=0x06,umask=0xcf"), | ||
| 6506 | INTEL_UNCORE_EVENT_DESC(cas_count_read_sch1.scale, "6.103515625e-5"), | ||
| 6507 | INTEL_UNCORE_EVENT_DESC(cas_count_read_sch1.unit, "MiB"), | ||
| 6508 | INTEL_UNCORE_EVENT_DESC(cas_count_write_sch0, "event=0x05,umask=0xf0"), | ||
| 6509 | INTEL_UNCORE_EVENT_DESC(cas_count_write_sch0.scale, "6.103515625e-5"), | ||
| 6510 | INTEL_UNCORE_EVENT_DESC(cas_count_write_sch0.unit, "MiB"), | ||
| 6511 | INTEL_UNCORE_EVENT_DESC(cas_count_write_sch1, "event=0x06,umask=0xf0"), | ||
| 6512 | INTEL_UNCORE_EVENT_DESC(cas_count_write_sch1.scale, "6.103515625e-5"), | ||
| 6513 | INTEL_UNCORE_EVENT_DESC(cas_count_write_sch1.unit, "MiB"), | ||
| 6514 | { /* end: all zeroes */ }, | ||
| 6515 | }; | ||
| 6516 | |||
| 6517 | static struct intel_uncore_type gnr_uncore_imc = { | ||
| 6518 | SPR_UNCORE_MMIO_COMMON_FORMAT(), | ||
| 6519 | .name = "imc", | ||
| 6520 | .fixed_ctr_bits = 48, | ||
| 6521 | .fixed_ctr = SNR_IMC_MMIO_PMON_FIXED_CTR, | ||
| 6522 | .fixed_ctl = SNR_IMC_MMIO_PMON_FIXED_CTL, | ||
| 6523 | .event_descs = gnr_uncore_imc_events, | ||
| 6524 | }; | ||
| 6525 | |||
| 6500 | static struct intel_uncore_type gnr_uncore_pciex8 = { | 6526 | static struct intel_uncore_type gnr_uncore_pciex8 = { |
| 6501 | SPR_UNCORE_PCI_COMMON_FORMAT(), | 6527 | SPR_UNCORE_PCI_COMMON_FORMAT(), |
| 6502 | .name = "pciex8", | 6528 | .name = "pciex8", |
| @@ -6544,7 +6570,7 @@ static struct intel_uncore_type *gnr_uncores[UNCORE_GNR_NUM_UNCORE_TYPES] = { · 41 unmodified lines | |||
| 6544 | NULL, | 6570 | NULL, |
| 6545 | &spr_uncore_pcu, | 6571 | &spr_uncore_pcu, |
| 6546 | &gnr_uncore_ubox, | 6572 | &gnr_uncore_ubox, |
| 6547 | &spr_uncore_imc, | 6573 | &gnr_uncore_imc, |
| 6548 | NULL, | 6574 | NULL, |
| 6549 | &gnr_uncore_upi, | 6575 | &gnr_uncore_upi, |
| 6550 | NULL, | 6576 | NULL, |
| @@ -4138,7 +4138,8 @@ static int merge_sched_in(struct perf_event *event, void *data) · 4137 unmodified lines | |||
| 4138 | if (*perf_event_fasync(event)) | 4138 | if (*perf_event_fasync(event)) |
| 4139 | event->pending_kill = POLL_ERR; | 4139 | event->pending_kill = POLL_ERR; |
| 4140 | 4140 | ||
| 4141 | perf_event_wakeup(event); | 4141 | event->pending_wakeup = 1; |
| 4142 | irq_work_queue(&event->pending_irq); | ||
| 4142 | } else { | 4143 | } else { |
| 4143 | struct perf_cpu_pmu_context *cpc = this_cpc(event->pmu_ctx->pmu); | 4144 | struct perf_cpu_pmu_context *cpc = this_cpc(event->pmu_ctx->pmu); |
| 4144 | 4145 | ||
| @@ -7464,28 +7465,28 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) · 3319 unmodified lines | |||
| 7464 | ret = perf_mmap_aux(vma, event, nr_pages); | 7465 | ret = perf_mmap_aux(vma, event, nr_pages); |
| 7465 | if (ret) | 7466 | if (ret) |
| 7466 | return ret; | 7467 | return ret; |
| 7467 | } | ||
| 7468 | 7468 | ||
| 7469 | /* | 7469 | /* |
| 7470 | * Since pinned accounting is per vm we cannot allow fork() to copy our | 7470 | * Since pinned accounting is per vm we cannot allow fork() to copy our |
| 7471 | * vma. | 7471 | * vma. |
| 7472 | */ | 7472 | */ |
| 7473 | vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP); | 7473 | vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP); |
| 7474 | vma->vm_ops = &perf_mmap_vmops; | 7474 | vma->vm_ops = &perf_mmap_vmops; |
| 7475 | 7475 | ||
| 7476 | mapped = get_mapped(event, event_mapped); | 7476 | mapped = get_mapped(event, event_mapped); |
| 7477 | if (mapped) | 7477 | if (mapped) |
| 7478 | mapped(event, vma->vm_mm); | 7478 | mapped(event, vma->vm_mm); |
| 7479 | 7479 | ||
| 7480 | /* | 7480 | /* |
| 7481 | * Try to map it into the page table. On fail, invoke | 7481 | * Try to map it into the page table. On fail, invoke |
| 7482 | * perf_mmap_close() to undo the above, as the callsite expects | 7482 | * perf_mmap_close() to undo the above, as the callsite expects |
| 7483 | * full cleanup in this case and therefore does not invoke | 7483 | * full cleanup in this case and therefore does not invoke |
| 7484 | * vmops::close(). | 7484 | * vmops::close(). |
| 7485 | */ | 7485 | */ |
| 7486 | ret = map_range(event->rb, vma); | 7486 | ret = map_range(event->rb, vma); |
| 7487 | if (ret) | 7487 | if (ret) |
| 7488 | perf_mmap_close(vma); | 7488 | perf_mmap_close(vma); |
| 7489 | } | ||
| 7489 | 7490 | ||
| 7490 | return ret; | 7491 | return ret; |
| 7491 | } | 7492 | } |
| @@ -10776,6 +10777,13 @@ int perf_event_overflow(struct perf_event *event, · 3284 unmodified lines | |||
| 10776 | struct perf_sample_data *data, | 10777 | struct perf_sample_data *data, |
| 10777 | struct pt_regs *regs) | 10778 | struct pt_regs *regs) |
| 10778 | { | 10779 | { |
| 10780 | /* | ||
| 10781 | * Entry point from hardware PMI, interrupts should be disabled here. | ||
| 10782 | * This serializes us against perf_event_remove_from_context() in | ||
| 10783 | * things like perf_event_release_kernel(). | ||
| 10784 | */ | ||
| 10785 | lockdep_assert_irqs_disabled(); | ||
| 10786 | |||
| 10779 | return __perf_event_overflow(event, 1, data, regs); | 10787 | return __perf_event_overflow(event, 1, data, regs); |
| 10780 | } | 10788 | } |
| 10781 | 10789 | ||
| @@ -10852,6 +10860,19 @@ static void perf_swevent_event(struct perf_event *event, u64 nr, · 70 unmodified lines | |||
| 10852 | { | 10860 | { |
| 10853 | struct hw_perf_event *hwc = &event->hw; | 10861 | struct hw_perf_event *hwc = &event->hw; |
| 10854 | 10862 | ||
| 10863 | /* | ||
| 10864 | * This is: | ||
| 10865 | * - software preempt | ||
| 10866 | * - tracepoint preempt | ||
| 10867 | * - tp_target_task irq (ctx->lock) | ||
| 10868 | * - uprobes preempt/irq | ||
| 10869 | * - kprobes preempt/irq | ||
| 10870 | * - hw_breakpoint irq | ||
| 10871 | * | ||
| 10872 | * Any of these are sufficient to hold off RCU and thus ensure @event | ||
| 10873 | * exists. | ||
| 10874 | */ | ||
| 10875 | lockdep_assert_preemption_disabled(); | ||
| 10855 | local64_add(nr, &event->count); | 10876 | local64_add(nr, &event->count); |
| 10856 | 10877 | ||
| 10857 | if (!regs) | 10878 | if (!regs) |
| @@ -10860,6 +10881,16 @@ static void perf_swevent_event(struct perf_event *event, u64 nr, · 2 unmodified lines | |||
| 10860 | if (!is_sampling_event(event)) | 10881 | if (!is_sampling_event(event)) |
| 10861 | return; | 10882 | return; |
| 10862 | 10883 | ||
| 10884 | /* | ||
| 10885 | * Serialize against event_function_call() IPIs like normal overflow | ||
| 10886 | * event handling. Specifically, must not allow | ||
| 10887 | * perf_event_release_kernel() -> perf_remove_from_context() to make | ||
| 10888 | * progress and 'release' the event from under us. | ||
| 10889 | */ | ||
| 10890 | guard(irqsave)(); | ||
| 10891 | if (event->state != PERF_EVENT_STATE_ACTIVE) | ||
| 10892 | return; | ||
| 10893 | |||
| 10863 | if ((event->attr.sample_type & PERF_SAMPLE_PERIOD) && !event->attr.freq) { | 10894 | if ((event->attr.sample_type & PERF_SAMPLE_PERIOD) && !event->attr.freq) { |
| 10864 | data->period = nr; | 10895 | data->period = nr; |
| 10865 | return perf_swevent_overflow(event, 1, data, regs); | 10896 | return perf_swevent_overflow(event, 1, data, regs); |
| @@ -11358,6 +11389,11 @@ void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, · 492 unmodified lines | |||
| 11358 | struct perf_sample_data data; | 11389 | struct perf_sample_data data; |
| 11359 | struct perf_event *event; | 11390 | struct perf_event *event; |
| 11360 | 11391 | ||
| 11392 | /* | ||
| 11393 | * Per being a tracepoint, this runs with preemption disabled. | ||
| 11394 | */ | ||
| 11395 | lockdep_assert_preemption_disabled(); | ||
| 11396 | |||
| 11361 | struct perf_raw_record raw = { | 11397 | struct perf_raw_record raw = { |
| 11362 | .frag = { | 11398 | .frag = { |
| 11363 | .size = entry_size, | 11399 | .size = entry_size, |
| @@ -11690,6 +11726,11 @@ void perf_bp_event(struct perf_event *bp, void *data) · 326 unmodified lines | |||
| 11690 | struct perf_sample_data sample; | 11726 | struct perf_sample_data sample; |
| 11691 | struct pt_regs *regs = data; | 11727 | struct pt_regs *regs = data; |
| 11692 | 11728 | ||
| 11729 | /* | ||
| 11730 | * Exception context, will have interrupts disabled. | ||
| 11731 | */ | ||
| 11732 | lockdep_assert_irqs_disabled(); | ||
| 11733 | |||
| 11693 | perf_sample_data_init(&sample, bp->attr.bp_addr, 0); | 11734 | perf_sample_data_init(&sample, bp->attr.bp_addr, 0); |
| 11694 | 11735 | ||
| 11695 | if (!bp->hw.state && !perf_exclude_event(bp, regs)) | 11736 | if (!bp->hw.state && !perf_exclude_event(bp, regs)) |
| @@ -12154,7 +12195,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) · 458 unmodified lines | |||
| 12154 | 12195 | ||
| 12155 | if (regs && !perf_exclude_event(event, regs)) { | 12196 | if (regs && !perf_exclude_event(event, regs)) { |
| 12156 | if (!(event->attr.exclude_idle && is_idle_task(current))) | 12197 | if (!(event->attr.exclude_idle && is_idle_task(current))) |
| 12157 | if (__perf_event_overflow(event, 1, &data, regs)) | 12198 | if (perf_event_overflow(event, &data, regs)) |
| 12158 | ret = HRTIMER_NORESTART; | 12199 | ret = HRTIMER_NORESTART; |
| 12159 | } | 12200 | } |
| 12160 | 12201 | ||