| From 83d349f35e1ae72268c5104dbf9ab2ae635425d4 Mon Sep 17 00:00:00 2001 |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| Date: Fri, 21 Aug 2009 09:23:57 -0700 |
| Subject: x86: don't send an IPI to the empty set of CPU's |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| commit 83d349f35e1ae72268c5104dbf9ab2ae635425d4 upstream. |
| |
| The default_send_IPI_mask_logical() function uses the "flat" APIC mode |
| to send an IPI to a set of CPU's at once, but if that set happens to be |
| empty, some older local APIC's will apparently be rather unhappy. So |
| just warn if a caller gives us an empty mask, and ignore it. |
| |
| This fixes a regression in 2.6.30.x, due to commit 4595f9620 ("x86: |
| change flush_tlb_others to take a const struct cpumask"), documented |
| here: |
| |
| http://bugzilla.kernel.org/show_bug.cgi?id=13933 |
| |
| which causes a silent lock-up. It only seems to happen on PPro, P2, P3 |
| and Athlon XP cores. Most developers sadly (or not so sadly, if you're |
| a developer..) have more modern CPU's. Also, on x86-64 we don't use the |
| flat APIC mode, so it would never trigger there even if the APIC didn't |
| like sending an empty IPI mask. |
| |
| Reported-by: Pavel Vilim <wylda@volny.cz> |
| Reported-and-tested-by: Thomas Bjรถrnell <thomas.bjornell@gmail.com> |
| Reported-and-tested-by: Martin Rogge <marogge@onlinehome.de> |
| Cc: Mike Travis <travis@sgi.com> |
| Cc: Ingo Molnar <mingo@elte.hu> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/x86/kernel/apic/ipi.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/arch/x86/kernel/apic/ipi.c |
| +++ b/arch/x86/kernel/apic/ipi.c |
| @@ -106,6 +106,9 @@ void default_send_IPI_mask_logical(const |
| unsigned long mask = cpumask_bits(cpumask)[0]; |
| unsigned long flags; |
| |
| + if (WARN_ONCE(!mask, "empty IPI mask")) |
| + return; |
| + |
| local_irq_save(flags); |
| WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); |
| __default_send_IPI_dest_field(mask, vector, apic->dest_logical); |