perf_counter: x86: Robustify interrupt handling
Two consecutive NMIs could daze and confuse the machine when the first would handle the overflow of both counters. [ Impact: fix false-positive syslog messages under multi-session profiling ] Signed-off-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:
committed by
Ingo Molnar
parent
9e35ad388b
commit
a4016a79fc
@@ -783,6 +783,10 @@ static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)
|
|||||||
|
|
||||||
counter = cpuc->counters[idx];
|
counter = cpuc->counters[idx];
|
||||||
hwc = &counter->hw;
|
hwc = &counter->hw;
|
||||||
|
|
||||||
|
if (counter->hw_event.nmi != nmi)
|
||||||
|
goto next;
|
||||||
|
|
||||||
val = x86_perf_counter_update(counter, hwc, idx);
|
val = x86_perf_counter_update(counter, hwc, idx);
|
||||||
if (val & (1ULL << (x86_pmu.counter_bits - 1)))
|
if (val & (1ULL << (x86_pmu.counter_bits - 1)))
|
||||||
goto next;
|
goto next;
|
||||||
@@ -869,7 +873,6 @@ perf_counter_nmi_handler(struct notifier_block *self,
|
|||||||
{
|
{
|
||||||
struct die_args *args = __args;
|
struct die_args *args = __args;
|
||||||
struct pt_regs *regs;
|
struct pt_regs *regs;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!atomic_read(&active_counters))
|
if (!atomic_read(&active_counters))
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
@@ -886,9 +889,16 @@ perf_counter_nmi_handler(struct notifier_block *self,
|
|||||||
regs = args->regs;
|
regs = args->regs;
|
||||||
|
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
ret = x86_pmu.handle_irq(regs, 1);
|
/*
|
||||||
|
* Can't rely on the handled return value to say it was our NMI, two
|
||||||
|
* counters could trigger 'simultaneously' raising two back-to-back NMIs.
|
||||||
|
*
|
||||||
|
* If the first NMI handles both, the latter will be empty and daze
|
||||||
|
* the CPU.
|
||||||
|
*/
|
||||||
|
x86_pmu.handle_irq(regs, 1);
|
||||||
|
|
||||||
return ret ? NOTIFY_STOP : NOTIFY_OK;
|
return NOTIFY_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
|
static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
|
||||||
|
Reference in New Issue
Block a user