From cada1d8d5107b95ef6be094bd663490652adfd4e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 14 May 2009 14:52:17 +0200 Subject: [PATCH] --- yaml --- r: 147455 b: refs/heads/master c: a4016a79fcbd139e7378944c0d86a39fdbc70ecc h: refs/heads/master i: 147453: 13407e6686b245a63aff59c4e461e380b5fc0e26 147451: dd80159656fc98216dd5c57b8e0c3f89db14096e 147447: df72c8ee150f7f789b502b1c38e61f8aa923a44a 147439: 335f59e2e19af0552c04ee067bef32af2f3f9716 147423: 26ac0b54945c79b8edb01abaeb776747dffa0a0d 147391: 63ffa2e237dc9f3a7b61642a2340ca8aa9bc2696 147327: db523527f7e036f89a5601f3e4a27cc09aa13886 147199: dd9b4770d2d761042403aa92d79655517c7be861 146943: 5d9e81e75e4d303065e6ebc3d299eb1b13be5a55 146431: 943ba7b8f6994e5aaef3e14ea8e01655525fc647 145407: 166de486808a60d90701b0818a1c9c31faaad02b 143359: 808b3c9e30989b03e7757567bebd8f8dadb0602a 139263: 78d0ae86fae40371c332f42aaab3a939df3e8856 131071: 5e1d55329a1e76f29215b146a22e31dd45999a04 v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/cpu/perf_counter.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 2350a88e96db..250cf050efb7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9e35ad388bea89f7d6f375af4c0ae98803688666 +refs/heads/master: a4016a79fcbd139e7378944c0d86a39fdbc70ecc diff --git a/trunk/arch/x86/kernel/cpu/perf_counter.c b/trunk/arch/x86/kernel/cpu/perf_counter.c index 313638cecbb5..1dcf67057f16 100644 --- a/trunk/arch/x86/kernel/cpu/perf_counter.c +++ b/trunk/arch/x86/kernel/cpu/perf_counter.c @@ -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 = {