summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2022-04-08 23:33:30 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-04-27 14:53:55 +0300
commitc55327bc3712ca96dc05bc4c6aab805b6fa8bb74 (patch)
tree9a38e5a9f7b7cae7a4f8266fcc94d25ec43f0b99
parent5580b974a84b30f6da90a3a562ea0dbfb0038110 (diff)
downloadlinux-c55327bc3712ca96dc05bc4c6aab805b6fa8bb74.tar.xz
arm_pmu: Validate single/group leader events
commit e5c23779f93d45e39a52758ca593bd7e62e9b4be upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 cb2f55f450e4..7fd11ef5cb8a 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -398,6 +398,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;
@@ -487,12 +490,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)