Skip to content

Commit

Permalink
ARM: 7356/1: perf: check that we have an event in the PMU IRQ handlers
Browse files Browse the repository at this point in the history
The PMU IRQ handlers in perf assume that if a counter has overflowed
then perf must be responsible. In the paranoid world of crazy hardware,
this could be false, so check that we do have a valid event before
attempting to dereference NULL in the interrupt path.

Cc: <stable@vger.kernel.org>
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Will Deacon authored and Russell King committed Mar 7, 2012
1 parent 99c1745 commit f6f5a30
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 18 deletions.
20 changes: 2 additions & 18 deletions arch/arm/kernel/perf_event_v6.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,23 +467,6 @@ armv6pmu_enable_event(struct hw_perf_event *hwc,
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
}

static int counter_is_active(unsigned long pmcr, int idx)
{
unsigned long mask = 0;
if (idx == ARMV6_CYCLE_COUNTER)
mask = ARMV6_PMCR_CCOUNT_IEN;
else if (idx == ARMV6_COUNTER0)
mask = ARMV6_PMCR_COUNT0_IEN;
else if (idx == ARMV6_COUNTER1)
mask = ARMV6_PMCR_COUNT1_IEN;

if (mask)
return pmcr & mask;

WARN_ONCE(1, "invalid counter number (%d)\n", idx);
return 0;
}

static irqreturn_t
armv6pmu_handle_irq(int irq_num,
void *dev)
Expand Down Expand Up @@ -513,7 +496,8 @@ armv6pmu_handle_irq(int irq_num,
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;

if (!counter_is_active(pmcr, idx))
/* Ignore if we don't have an event. */
if (!event)
continue;

/*
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/kernel/perf_event_v7.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,10 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;

/* Ignore if we don't have an event. */
if (!event)
continue;

/*
* We have a single interrupt for all counters. Check that
* each counter has overflowed before we process it.
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/kernel/perf_event_xscale.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;

if (!event)
continue;

if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
continue;

Expand Down Expand Up @@ -592,6 +595,9 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;

if (!event)
continue;

if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
continue;

Expand Down

0 comments on commit f6f5a30

Please sign in to comment.