Patch "perf/x86/intel/bts: Fix DS area sharing with x86_pmu events" has been added to the 4.1-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
perf/x86/intel/bts: Fix DS area sharing with x86_pmu events
to the 4.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
perf-x86-intel-bts-fix-ds-area-sharing-with-x86_pmu-events.patch
and it can be found in the queue-4.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
6b099d9b040b0f3d0aec05b560d7caf879af5077Mon Sep 17 00:00:00 2001
From: Alexander Shishkin <[email protected]>
Date: Thu, 11 Jun 2015 15:13:56 +0300
Subject: perf/x86/intel/bts: Fix DS area sharing with x86_pmu events
From: Alexander Shishkin <[email protected]>
commit 6b099d9b040b0f3d0aec05b560d7caf879af5077 upstream.
Currently, the intel_bts driver relies on the DS area allocated by the x86_pmu code in its event_init() path, which is a bug: creating a BTS event while no x86_pmu events are present results in a NULL pointer dereference.
The same DS area is also used by PEBS sampling, which makes it quite a bit trickier to have a separate one for intel_bts' purposes.
This patch makes intel_bts driver use the same DS allocation and reference counting code as x86_pmu to make sure it is always present when either intel_bts or x86_pmu need it.
--- arch/x86/kernel/cpu/perf_event.c | 52 ++++++++++++++++++----------- arch/x86/kernel/cpu/perf_event.h | 4 ++ arch/x86/kernel/cpu/perf_event_intel_bts.c | 9 +++++ 3 files changed, 46 insertions(+), 19 deletions(-)
arch/x86/kernel/cpu/perf_event.c +33 -19
@@ -270,11 +270,7 @@ msr_fail:static void hw_perf_event_destroy (struct perf_event *event) { -if (atomic_dec_and_mutex_lock (&active_events, &pmc_reserve_mutex)) { -release_pmc_hardware (); -release_ds_buffers (); -mutex_unlock (&pmc_reserve_mutex); - } +x86_release_hardware (); }void hw_perf_lbr_event_destroy (struct perf_event *event)
@@ -324,6 +320,35 @@ set_ext_hw_attr(struct hw_perf_event *hwreturn x86_pmu_extra_regs (val, event); } +int x86_reserve_hardware (void ) +{ +int err =0 ; + +if (!atomic_inc_not_zero (&active_events)) { +mutex_lock (&pmc_reserve_mutex); +if (atomic_read (&active_events) ==0 ) { +if (!reserve_pmc_hardware ()) + err = -EBUSY ; +else +reserve_ds_buffers (); + } +if (!err) +atomic_inc (&active_events); +mutex_unlock (&pmc_reserve_mutex); + } + +return err; +} + +void x86_release_hardware (void ) +{ +if (atomic_dec_and_mutex_lock (&active_events, &pmc_reserve_mutex)) { +release_pmc_hardware (); +release_ds_buffers (); +mutex_unlock (&pmc_reserve_mutex); + } +} +/* * Check if we can create event of a certain type (that no conflicting events * are present).
@@ -336,9 +361,10 @@ int x86_add_exclusive(unsigned int what)return 0 ;mutex_lock (&pmc_reserve_mutex); -for (i =0 ; i <ARRAY_SIZE (x86_pmu.lbr_exclusive); i++) +for (i =0 ; i <ARRAY_SIZE (x86_pmu.lbr_exclusive); i++) {if (i != what &&atomic_read (&x86_pmu.lbr_exclusive[i])) goto out; + }atomic_inc (&x86_pmu.lbr_exclusive[what]); ret =0 ;
@@ -527,19 +553,7 @@ static int __x86_pmu_event_init(struct pif (!x86_pmu_initialized ())return -ENODEV ; - err =0 ; -if (!atomic_inc_not_zero (&active_events)) { -mutex_lock (&pmc_reserve_mutex); -if (atomic_read (&active_events) ==0 ) { -if (!reserve_pmc_hardware ()) - err = -EBUSY ; -else -reserve_ds_buffers (); - } -if (!err) -atomic_inc (&active_events); -mutex_unlock (&pmc_reserve_mutex); - } + err =x86_reserve_hardware ();if (err)return err;
arch/x86/kernel/cpu/perf_event.h +4 -0
@@ -703,6 +703,10 @@ int x86_add_exclusive(unsigned int what)void x86_del_exclusive (unsigned int what); +int x86_reserve_hardware (void ); + +void x86_release_hardware (void ); +void hw_perf_lbr_event_destroy (struct perf_event *event);int x86_setup_perfctr (struct perf_event *event);
arch/x86/kernel/cpu/perf_event_intel_bts.c +9 -0
@@ -483,17 +483,26 @@ static int bts_event_add(struct perf_evestatic void bts_event_destroy (struct perf_event *event) { +x86_release_hardware ();x86_del_exclusive (x86_lbr_exclusive_bts); }static int bts_event_init (struct perf_event *event) { +int ret; +if (event->attr.type != bts_pmu.type)return -ENOENT ;if (x86_add_exclusive (x86_lbr_exclusive_bts))return -EBUSY ; + ret =x86_reserve_hardware (); +if (ret) { +x86_del_exclusive (x86_lbr_exclusive_bts); +return ret; + } + event->destroy = bts_event_destroy;return 0 ;
Patches currently in stable-queue which might be from [email protected] are
queue-4.1/perf-x86-intel-bts-fix-ds-area-sharing-with-x86_pmu-events.patch queue-4.1/perf-fix-ring_buffer_attach-rcu-sync-again.patch