mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-25 07:29:24 -05:00
91 lines
3.3 KiB
Diff
91 lines
3.3 KiB
Diff
From d75be03af111fb5a31eba82f665242e6d8b07008 Mon Sep 17 00:00:00 2001
|
|
From: Arun KS <arunks@codeaurora.org>
|
|
Date: Wed, 11 May 2016 10:11:36 +0530
|
|
Subject: msm: perf: Do not allocate new hw_event if event is duplicate.
|
|
|
|
During a perf_event_enable, kernel/events/core.c calls pmu->add() which
|
|
is platform implementation(arch/arm/kernel/perf_event.c). Due to the
|
|
duplicate constraints, arch/arm/mach-msm/perf_event_msm_krait_l2.c
|
|
drivers marks the event as OFF but returns TRUE to perf_event.c which
|
|
goes ahead and allocates the hw_event and enables it.
|
|
|
|
Since event is marked OFF, kernel events core will try to enable this event
|
|
again during next perf_event_enable. Which results in same event enabled
|
|
on multiple hw_events. But during the perf_release, event struct is freed
|
|
and only one hw_event is released. This results in dereferencing the
|
|
invalid pointer and hence the crash.
|
|
|
|
Fix this by returning error in case of constraint event duplicate. Hence
|
|
avoiding the same event programmed on multiple hw event counters.
|
|
|
|
Change-Id: Ia3360be027dfe87ac753191ffe7e0bc947e72455
|
|
Signed-off-by: Arun KS <arunks@codeaurora.org>
|
|
---
|
|
arch/arm/kernel/perf_event.c | 1 +
|
|
arch/arm/mach-msm/perf_event_msm_krait_l2.c | 1 +
|
|
arch/arm/mach-msm/perf_event_msm_l2.c | 4 +++-
|
|
kernel/events/core.c | 7 -------
|
|
4 files changed, 5 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
|
|
index 1541a80..a1264ac 100644
|
|
--- a/arch/arm/kernel/perf_event.c
|
|
+++ b/arch/arm/kernel/perf_event.c
|
|
@@ -308,6 +308,7 @@ armpmu_add(struct perf_event *event, int flags)
|
|
pr_err("Event: %llx failed constraint check.\n",
|
|
event->attr.config);
|
|
event->state = PERF_EVENT_STATE_OFF;
|
|
+ err = -EPERM;
|
|
goto out;
|
|
}
|
|
|
|
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
|
|
index d816794..57f82d0 100644
|
|
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
|
|
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
|
|
@@ -463,6 +463,7 @@ static int msm_l2_test_set_ev_constraint(struct perf_event *event)
|
|
if (!(event->cpu < 0)) {
|
|
event->state = PERF_EVENT_STATE_OFF;
|
|
event->attr.constraint_duplicate = 1;
|
|
+ err = -EPERM;
|
|
}
|
|
}
|
|
out:
|
|
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
|
|
index f78487a..93695e2 100644
|
|
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
|
|
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
|
|
@@ -836,8 +836,10 @@ static int msm_l2_test_set_ev_constraint(struct perf_event *event)
|
|
* This sets the event OFF on all but one
|
|
* CPU.
|
|
*/
|
|
- if (!(event->cpu < 0))
|
|
+ if (!(event->cpu < 0)) {
|
|
event->state = PERF_EVENT_STATE_OFF;
|
|
+ err = -EPERM;
|
|
+ }
|
|
}
|
|
|
|
out:
|
|
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
|
index 33ad70a..7ebe09a 100644
|
|
--- a/kernel/events/core.c
|
|
+++ b/kernel/events/core.c
|
|
@@ -3030,13 +3030,6 @@ static void put_event(struct perf_event *event)
|
|
|
|
if (!atomic_long_dec_and_test(&event->refcount))
|
|
return;
|
|
- /*
|
|
- * Event can be in state OFF because of a constraint check.
|
|
- * Change to ACTIVE so that it gets cleaned up correctly.
|
|
- */
|
|
- if ((event->state == PERF_EVENT_STATE_OFF) &&
|
|
- event->attr.constraint_duplicate)
|
|
- event->state = PERF_EVENT_STATE_ACTIVE;
|
|
|
|
rcu_read_lock();
|
|
owner = ACCESS_ONCE(event->owner);
|
|
--
|
|
cgit v1.1
|
|
|