Skip to content

Commit

Permalink
perf/smmuv3: Don't trample existing events with global filter
Browse files Browse the repository at this point in the history
commit 4c1daba upstream.

With global filtering, we only allow an event to be scheduled if its
filter settings exactly match those of any existing events, therefore
it is pointless to reapply the filter in that case. Much worse, though,
is that in doing that we trample the event type of counter 0 if it's
already active, and never touch the appropriate PMEVTYPERn so the new
event is likely not counting the right thing either. Don't do that.

CC: stable@vger.kernel.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/32c80c0e46237f49ad8da0c9f8864e13c4a803aa.1623153312.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
rmurphy-arm authored and gregkh committed Jul 14, 2021
1 parent 562521b commit 283d80b
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions drivers/perf/arm_smmuv3_pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,25 +277,27 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
struct perf_event *event, int idx)
{
u32 span, sid;
unsigned int num_ctrs = smmu_pmu->num_counters;
unsigned int cur_idx, num_ctrs = smmu_pmu->num_counters;
bool filter_en = !!get_filter_enable(event);

span = filter_en ? get_filter_span(event) :
SMMU_PMCG_DEFAULT_FILTER_SPAN;
sid = filter_en ? get_filter_stream_id(event) :
SMMU_PMCG_DEFAULT_FILTER_SID;

/* Support individual filter settings */
if (!smmu_pmu->global_filter) {
cur_idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
/*
* Per-counter filtering, or scheduling the first globally-filtered
* event into an empty PMU so idx == 0 and it works out equivalent.
*/
if (!smmu_pmu->global_filter || cur_idx == num_ctrs) {
smmu_pmu_set_event_filter(event, idx, span, sid);
return 0;
}

/* Requested settings same as current global settings*/
idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
if (idx == num_ctrs ||
smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) {
smmu_pmu_set_event_filter(event, 0, span, sid);
/* Otherwise, must match whatever's currently scheduled */
if (smmu_pmu_check_global_filter(smmu_pmu->events[cur_idx], event)) {
smmu_pmu_set_evtyper(smmu_pmu, idx, get_event(event));
return 0;
}

Expand Down

0 comments on commit 283d80b

Please sign in to comment.