aboutsummaryrefslogtreecommitdiff
path: root/drivers/perf/arm_pmu.c
diff options
context:
space:
mode:
authorGravatar Rob Herring <robh@kernel.org> 2022-04-08 15:33:30 -0500
committerGravatar Will Deacon <will@kernel.org> 2022-04-13 11:48:45 +0100
commite5c23779f93d45e39a52758ca593bd7e62e9b4be (patch)
tree7ce2cf123703c332a9002a7cf7e542b7a4397b0f /drivers/perf/arm_pmu.c
parentperf/imx_ddr: Fix undefined behavior due to shift overflowing the constant (diff)
downloadlinux-e5c23779f93d45e39a52758ca593bd7e62e9b4be.tar.gz
linux-e5c23779f93d45e39a52758ca593bd7e62e9b4be.tar.bz2
linux-e5c23779f93d45e39a52758ca593bd7e62e9b4be.zip
arm_pmu: Validate single/group leader events
In the case where there is only a cycle counter available (i.e. PMCR_EL0.N is 0) and an event other than CPU cycles is opened, the open should fail as the event can never possibly be scheduled. However, the event validation when an event is opened is skipped when the group leader is opened. Fix this by always validating the group leader events. Reported-by: Al Grant <al.grant@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Rob Herring <robh@kernel.org> Acked-by: Mark Rutland <mark.rutland@arm.com> Link: https://lore.kernel.org/r/20220408203330.4014015-1-robh@kernel.org Cc: <stable@vger.kernel.org> Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'drivers/perf/arm_pmu.c')
-rw-r--r--drivers/perf/arm_pmu.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 9694370651fa..59d3980b8ca2 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -400,6 +400,9 @@ validate_group(struct perf_event *event)
if (!validate_event(event->pmu, &fake_pmu, leader))
return -EINVAL;
+ if (event == leader)
+ return 0;
+
for_each_sibling_event(sibling, leader) {
if (!validate_event(event->pmu, &fake_pmu, sibling))
return -EINVAL;
@@ -489,12 +492,7 @@ __hw_perf_event_init(struct perf_event *event)
local64_set(&hwc->period_left, hwc->sample_period);
}
- if (event->group_leader != event) {
- if (validate_group(event) != 0)
- return -EINVAL;
- }
-
- return 0;
+ return validate_group(event);
}
static int armpmu_event_init(struct perf_event *event)