aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-08 08:20:16 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-08 09:56:42 -0500
commit87b9cf4623ad4e5fc009e48c020593dffd5d3793 (patch)
treebd49f47b3fee4f4dc956e7db303fb1c20d53eee3 /arch
parent241771ef016b5c0c83cd7a4372a74321c973c1e6 (diff)
x86, perfcounters: read out MSR_CORE_PERF_GLOBAL_STATUS with counters disabled
Impact: make perfcounter NMI and IRQ sequence more robust Make __smp_perf_counter_interrupt() a bit more conservative: first disable all counters, then read out the status. Most invocations are because there are real events, so there's no performance impact. Code flow gets a bit simpler as well this way. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/cpu/perf_counter.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 82440cbed0e6..615e953208ef 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -383,18 +383,16 @@ static void __smp_perf_counter_interrupt(struct pt_regs *regs, int nmi)
383 struct cpu_hw_counters *cpuc; 383 struct cpu_hw_counters *cpuc;
384 u64 ack, status; 384 u64 ack, status;
385 385
386 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
387 if (!status) {
388 ack_APIC_irq();
389 return;
390 }
391
392 /* Disable counters globally */ 386 /* Disable counters globally */
393 wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0); 387 wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0);
394 ack_APIC_irq(); 388 ack_APIC_irq();
395 389
396 cpuc = &per_cpu(cpu_hw_counters, cpu); 390 cpuc = &per_cpu(cpu_hw_counters, cpu);
397 391
392 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
393 if (!status)
394 goto out;
395
398again: 396again:
399 ack = status; 397 ack = status;
400 for_each_bit(bit, (unsigned long *) &status, nr_hw_counters) { 398 for_each_bit(bit, (unsigned long *) &status, nr_hw_counters) {
@@ -440,7 +438,7 @@ again:
440 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); 438 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
441 if (status) 439 if (status)
442 goto again; 440 goto again;
443 441out:
444 /* 442 /*
445 * Do not reenable when global enable is off: 443 * Do not reenable when global enable is off:
446 */ 444 */