mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	perf, x86: Catch spurious interrupts after disabling counters
Some cpus still deliver spurious interrupts after disabling a
counter. This caused 'undelivered NMI' messages. This patch
fixes this. Introduced by:
  4177c42: perf, x86: Try to handle unknown nmis with an enabled PMU
Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: gorcunov@gmail.com <gorcunov@gmail.com>
Cc: fweisbec@gmail.com <fweisbec@gmail.com>
Cc: ying.huang@intel.com <ying.huang@intel.com>
Cc: ming.m.lin@intel.com <ming.m.lin@intel.com>
Cc: yinghai@kernel.org <yinghai@kernel.org>
Cc: andi@firstfloor.org <andi@firstfloor.org>
Cc: eranian@google.com <eranian@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
LKML-Reference: <20100915162034.GO13563@erda.amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
			
			
This commit is contained in:
		
							parent
							
								
									258af47479
								
							
						
					
					
						commit
						63e6be6d98
					
				
					 1 changed files with 11 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -102,6 +102,7 @@ struct cpu_hw_events {
 | 
			
		|||
	 */
 | 
			
		||||
	struct perf_event	*events[X86_PMC_IDX_MAX]; /* in counter order */
 | 
			
		||||
	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
 | 
			
		||||
	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
 | 
			
		||||
	int			enabled;
 | 
			
		||||
 | 
			
		||||
	int			n_events;
 | 
			
		||||
| 
						 | 
				
			
			@ -1010,6 +1011,7 @@ static int x86_pmu_start(struct perf_event *event)
 | 
			
		|||
	x86_perf_event_set_period(event);
 | 
			
		||||
	cpuc->events[idx] = event;
 | 
			
		||||
	__set_bit(idx, cpuc->active_mask);
 | 
			
		||||
	__set_bit(idx, cpuc->running);
 | 
			
		||||
	x86_pmu.enable(event);
 | 
			
		||||
	perf_event_update_userpage(event);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1141,8 +1143,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
 | 
			
		|||
	cpuc = &__get_cpu_var(cpu_hw_events);
 | 
			
		||||
 | 
			
		||||
	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
 | 
			
		||||
		if (!test_bit(idx, cpuc->active_mask))
 | 
			
		||||
		if (!test_bit(idx, cpuc->active_mask)) {
 | 
			
		||||
			/*
 | 
			
		||||
			 * Though we deactivated the counter some cpus
 | 
			
		||||
			 * might still deliver spurious interrupts still
 | 
			
		||||
			 * in flight. Catch them:
 | 
			
		||||
			 */
 | 
			
		||||
			if (__test_and_clear_bit(idx, cpuc->running))
 | 
			
		||||
				handled++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		event = cpuc->events[idx];
 | 
			
		||||
		hwc = &event->hw;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue