mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-18 22:14:16 +00:00 
			
		
		
		
	ARM: 7356/1: perf: check that we have an event in the PMU IRQ handlers
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>
This commit is contained in:
		
							parent
							
								
									99c1745b9c
								
							
						
					
					
						commit
						f6f5a30c83
					
				
					 3 changed files with 12 additions and 18 deletions
				
			
		|  | @ -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) | ||||
|  | @ -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; | ||||
| 
 | ||||
| 		/*
 | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Will Deacon
						Will Deacon