]> git.karo-electronics.de Git - karo-tx-linux.git/commit
x86: don't call '->send_IPI_mask()' with an empty mask
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Aug 2009 16:48:10 +0000 (09:48 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 9 Sep 2009 03:33:16 +0000 (20:33 -0700)
commit5d884ca27c645691b20817c09a0e810f81975655
tree12fd07e0d54cfd11bc784bef70b6205a582f1c1a
parentff3d5a667d97fa518760f1492e0f3ed7f542770f
x86: don't call '->send_IPI_mask()' with an empty mask

commit b04e6373d694e977c95ae0ae000e2c1e2cf92d73 upstream.

As noted in 83d349f35e1ae72268c5104dbf9ab2ae635425d4 ("x86: don't send
an IPI to the empty set of CPU's"), some APIC's will be very unhappy
with an empty destination mask.  That commit added a WARN_ON() for that
case, and avoided the resulting problem, but didn't fix the underlying
reason for why those empty mask cases happened.

This fixes that, by checking the result of 'cpumask_andnot()' of the
current CPU actually has any other CPU's left in the set of CPU's to be
sent a TLB flush, and not calling down to the IPI code if the mask is
empty.

The reason this started happening at all is that we started passing just
the CPU mask pointers around in commit 4595f9620 ("x86: change
flush_tlb_others to take a const struct cpumask"), and when we did that,
the cpumask was no longer thread-local.

Before that commit, flush_tlb_mm() used to create it's own copy of
'mm->cpu_vm_mask' and pass that copy down to the low-level flush
routines after having tested that it was not empty.  But after changing
it to just pass down the CPU mask pointer, the lower level TLB flush
routines would now get a pointer to that 'mm->cpu_vm_mask', and that
could still change - and become empty - after the test due to other
CPU's having flushed their own TLB's.

See

http://bugzilla.kernel.org/show_bug.cgi?id=13933

for details.

Tested-by: Thomas Björnell <thomas.bjornell@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/mm/tlb.c