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:
parent
9e35ad388b
commit
a4016a79fc
|
@ -783,6 +783,10 @@ static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)
|
|||
|
||||
counter = cpuc->counters[idx];
|
||||
hwc = &counter->hw;
|
||||
|
||||
if (counter->hw_event.nmi != nmi)
|
||||
goto next;
|
||||
|
||||
val = x86_perf_counter_update(counter, hwc, idx);
|
||||
if (val & (1ULL << (x86_pmu.counter_bits - 1)))
|
||||
goto next;
|
||||
|
@ -869,7 +873,6 @@ perf_counter_nmi_handler(struct notifier_block *self,
|
|||
{
|
||||
struct die_args *args = __args;
|
||||
struct pt_regs *regs;
|
||||
int ret;
|
||||
|
||||
if (!atomic_read(&active_counters))
|
||||
return NOTIFY_DONE;
|
||||
|
@ -886,9 +889,16 @@ perf_counter_nmi_handler(struct notifier_block *self,
|
|||
regs = args->regs;
|
||||
|
||||
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 = {
|
||||
|
|
Loading…
Reference in New Issue