FAILED: patch "[PATCH] perf/x86: Fix RDPMC vs. mm_struct tracking" failed to apply to 4.9-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
bfe334924ccd9f4a53f30240c03cf2f43f5b2df1Mon Sep 17 00:00:00 2001
From: Peter Zijlstra <[email protected]>
Date: Wed, 2 Aug 2017 19:39:30 +0200
Subject: [PATCH] perf/x86: Fix RDPMC vs. mm_struct tracking
Vince reported the following rdpmc() testcase failure:
Quoted 8 lines
Failing test case:
fd=perf_event_open(); addr=mmap(fd); exec() // without closing or unmapping the event fd=perf_event_open(); addr=mmap(fd); rdpmc() // GPFs due to rdpmc being disabled
The problem is of course that exec() plays tricks with what is current->mm, only destroying the old mappings after having installed the new mm.
Fix this confusion by passing along vma->vm_mm instead of relying on current->mm.
arch/x86/events/core.c +7 -9
@@ -2114,7 +2114,7 @@ static void refresh_pce(void *ignored)load_mm_cr4 (this_cpu_read (cpu_tlbstate.loaded_mm)); } -static void x86_pmu_event_mapped (struct perf_event *event) +static void x86_pmu_event_mapped (struct perf_event *event,struct mm_struct *mm) {if (!(event->hw.flags &PERF_X86_EVENT_RDPMC_ALLOWED ))return ;
@@ -2129,22 +2129,20 @@ static void x86_pmu_event_mapped(struct perf_event *event)* For now, this can't happen because all callers hold mmap_sem * for write. If this changes, we'll need a different solution. */ -lockdep_assert_held_exclusive (¤t->mm->mmap_sem); +lockdep_assert_held_exclusive (&mm->mmap_sem); -if (atomic_inc_return (¤t->mm->context.perf_rdpmc_allowed) ==1 ) -on_each_cpu_mask (mm_cpumask (current->mm), refresh_pce,NULL ,1 ); +if (atomic_inc_return (&mm->context.perf_rdpmc_allowed) ==1 ) +on_each_cpu_mask (mm_cpumask (mm), refresh_pce,NULL ,1 ); } -static void x86_pmu_event_unmapped (struct perf_event *event) +static void x86_pmu_event_unmapped (struct perf_event *event,struct mm_struct *mm) { -if (!current->mm) -return ;if (!(event->hw.flags &PERF_X86_EVENT_RDPMC_ALLOWED ))return ; -if (atomic_dec_and_test (¤t->mm->context.perf_rdpmc_allowed)) -on_each_cpu_mask (mm_cpumask (current->mm), refresh_pce,NULL ,1 ); +if (atomic_dec_and_test (&mm->context.perf_rdpmc_allowed)) +on_each_cpu_mask (mm_cpumask (mm), refresh_pce,NULL ,1 ); }static int x86_pmu_event_idx (struct perf_event *event)
include/linux/perf_event.h +2 -2
@@ -310,8 +310,8 @@ struct pmu {* Notification that the event was mapped or unmapped. Called * in the context of the mapping task. */ -void (*event_mapped) (struct perf_event *event);/*optional*/ -void (*event_unmapped) (struct perf_event *event);/*optional*/ +void (*event_mapped) (struct perf_event *event,struct mm_struct *mm);/* optional */ +void (*event_unmapped) (struct perf_event *event,struct mm_struct *mm);/* optional */ /* * Flags for ->add()/->del()/ ->start()/->stop(). There are
kernel/events/core.c +3 -3
@@ -5090,7 +5090,7 @@ static void perf_mmap_open(struct vm_area_struct *vma)atomic_inc (&event->rb->aux_mmap_count);if (event->pmu->event_mapped) - event->pmu->event_mapped (event); + event->pmu->event_mapped (event, vma->vm_mm); }static void perf_pmu_output_stop (struct perf_event *event);
@@ -5113,7 +5113,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)unsigned long size =perf_data_size (rb);if (event->pmu->event_unmapped) - event->pmu->event_unmapped (event); + event->pmu->event_unmapped (event, vma->vm_mm);/* * rb->aux_mmap_count will always drop before rb->mmap_count and
@@ -5411,7 +5411,7 @@ aux_unlock: vma->vm_ops = &perf_mmap_vmops;if (event->pmu->event_mapped) - event->pmu->event_mapped (event); + event->pmu->event_mapped (event, vma->vm_mm);return ret; }