diff options
author | Robin Murphy <robin.murphy@arm.com> | 2019-08-01 16:22:44 +0100 |
---|---|---|
committer | Will Deacon <will@kernel.org> | 2019-08-27 19:37:04 +0100 |
commit | 33e84ea4330da8a16bda8a871d0cd3c872bcd89f (patch) | |
tree | 6e1daa55521a4ffcd8859f290f8ac3d71b52aeb2 /drivers/perf/arm_smmuv3_pmu.c | |
parent | d91cc2f46ad5bd8020902093385fedf7e9e9d755 (diff) | |
download | linux-rpi-33e84ea4330da8a16bda8a871d0cd3c872bcd89f.tar.gz linux-rpi-33e84ea4330da8a16bda8a871d0cd3c872bcd89f.tar.bz2 linux-rpi-33e84ea4330da8a16bda8a871d0cd3c872bcd89f.zip |
perf/smmuv3: Validate group size
Ensure that a group will actually fit into the available counters.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'drivers/perf/arm_smmuv3_pmu.c')
-rw-r--r-- | drivers/perf/arm_smmuv3_pmu.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c index da71c741cb46..c65c197b52a7 100644 --- a/drivers/perf/arm_smmuv3_pmu.c +++ b/drivers/perf/arm_smmuv3_pmu.c @@ -323,6 +323,7 @@ static int smmu_pmu_event_init(struct perf_event *event) struct smmu_pmu *smmu_pmu = to_smmu_pmu(event->pmu); struct device *dev = smmu_pmu->dev; struct perf_event *sibling; + int group_num_events = 1; u16 event_id; if (event->attr.type != event->pmu->type) @@ -347,18 +348,23 @@ static int smmu_pmu_event_init(struct perf_event *event) } /* Don't allow groups with mixed PMUs, except for s/w events */ - if (event->group_leader->pmu != event->pmu && - !is_software_event(event->group_leader)) { - dev_dbg(dev, "Can't create mixed PMU group\n"); - return -EINVAL; + if (!is_software_event(event->group_leader)) { + if (event->group_leader->pmu != event->pmu) + return -EINVAL; + + if (++group_num_events > smmu_pmu->num_counters) + return -EINVAL; } for_each_sibling_event(sibling, event->group_leader) { - if (sibling->pmu != event->pmu && - !is_software_event(sibling)) { - dev_dbg(dev, "Can't create mixed PMU group\n"); + if (is_software_event(sibling)) + continue; + + if (sibling->pmu != event->pmu) + return -EINVAL; + + if (++group_num_events > smmu_pmu->num_counters) return -EINVAL; - } } hwc->idx = -1; |