summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Fay <pfay@codeaurora.org>2016-11-03 17:07:16 -0700
committerPatrick Fay <pfay@codeaurora.org>2017-01-16 11:52:33 -0800
commit377c09d738d74ee059c100e4834fdc5c6736636d (patch)
tree0ab4c025a681d7cd45b70d9a8ab7ae00990bd608
parent573979dee2a76e4d7f61cb867c12afbaed7e1eb5 (diff)
perf: Fix NULL pointer ref in exclude_idle update
Commit 573979dee2a7 ("perf: Add support for exclude_idle attribute") registers an idle callback routine armv8pmu_idle_update. Currently the idle update routine might be called before the pmu has allocated all the per_cpu structures. This can result in a null pointer reference. Change arm_pmu_device_probe to allocate the structures via cpu_pmu_init() before the init_fn() call (which eventually does the idle_notify_register call). Change a branch to out_free to out_destroy as out_free doesn't cleanup what was allocated in cpu_pmu_init(). Also have armv8pmu_idle_update check that the structure is not null before using it. Change-Id: Ie1198fc1783804c61467889c68656d6e8c9c9edf Signed-off-by: Patrick Fay <pfay@codeaurora.org>
-rw-r--r--arch/arm64/kernel/perf_event.c3
-rw-r--r--drivers/perf/arm_pmu.c10
2 files changed, 8 insertions, 5 deletions
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 10db9cbaf49e..e8f5a17707d4 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -590,6 +590,9 @@ static void armv8pmu_idle_update(struct arm_pmu *cpu_pmu)
hw_events = this_cpu_ptr(cpu_pmu->hw_events);
+ if (!hw_events)
+ return;
+
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
if (!test_bit(idx, hw_events->used_mask))
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 71154ec99d3c..13b79438af1c 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -1051,6 +1051,10 @@ int arm_pmu_device_probe(struct platform_device *pdev,
pmu->plat_device = pdev;
+ ret = cpu_pmu_init(pmu);
+ if (ret)
+ goto out_free;
+
if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
init_fn = of_id->data;
@@ -1073,13 +1077,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
if (ret) {
pr_info("%s: failed to probe PMU!\n", of_node_full_name(node));
- goto out_free;
+ goto out_destroy;
}
- ret = cpu_pmu_init(pmu);
- if (ret)
- goto out_free;
-
ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
if (ret)
goto out_destroy;