perf_counter: x86: Fix throttling
If counters are disabled globally when a perfcounter IRQ/NMI hits, and if we throttle in that case, we'll promote the '0' value to the next lapic IRQ and disable all perfcounters at that point, permanently ... Fix it. [ Impact: fix hung perfcounters under load ] Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@ -765,8 +765,13 @@ out:
|
|||||||
/*
|
/*
|
||||||
* Restore - do not reenable when global enable is off or throttled:
|
* Restore - do not reenable when global enable is off or throttled:
|
||||||
*/
|
*/
|
||||||
if (++cpuc->interrupts < PERFMON_MAX_INTERRUPTS)
|
if (cpuc->throttle_ctrl) {
|
||||||
|
if (++cpuc->interrupts < PERFMON_MAX_INTERRUPTS) {
|
||||||
intel_pmu_restore_all(cpuc->throttle_ctrl);
|
intel_pmu_restore_all(cpuc->throttle_ctrl);
|
||||||
|
} else {
|
||||||
|
pr_info("CPU#%d: perfcounters: max interrupt rate exceeded! Throttle on.\n", smp_processor_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -817,11 +822,16 @@ void perf_counter_unthrottle(void)
|
|||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_counters);
|
cpuc = &__get_cpu_var(cpu_hw_counters);
|
||||||
if (cpuc->interrupts >= PERFMON_MAX_INTERRUPTS) {
|
if (cpuc->interrupts >= PERFMON_MAX_INTERRUPTS) {
|
||||||
if (printk_ratelimit())
|
pr_info("CPU#%d: perfcounters: throttle off.\n", smp_processor_id());
|
||||||
printk(KERN_WARNING "perfcounters: max interrupts exceeded!\n");
|
|
||||||
hw_perf_restore(cpuc->throttle_ctrl);
|
/*
|
||||||
}
|
* Clear them before re-enabling irqs/NMIs again:
|
||||||
|
*/
|
||||||
cpuc->interrupts = 0;
|
cpuc->interrupts = 0;
|
||||||
|
hw_perf_restore(cpuc->throttle_ctrl);
|
||||||
|
} else {
|
||||||
|
cpuc->interrupts = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void smp_perf_counter_interrupt(struct pt_regs *regs)
|
void smp_perf_counter_interrupt(struct pt_regs *regs)
|
||||||
|
Reference in New Issue
Block a user