sh: Flush only the needed range when unmapping a VMA.
authorPaul Mundt <lethal@linux-sh.org>
Tue, 17 Mar 2009 12:19:49 +0000 (21:19 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 17 Mar 2009 12:19:49 +0000 (21:19 +0900)
commitc20351846efcb755ba849d9fb701fbd9a1ffb7c2
tree8e8c0cdce372160fb2081d4e491550d1e8a8c99c
parent3a3b311ca375a37b29bb78b030f96bf97dee97f5
sh: Flush only the needed range when unmapping a VMA.

This follows the ARM change from Aaro Koskinen:

When unmapping N pages (e.g. shared memory) the amount of TLB
flushes done can be (N*PAGE_SIZE/ZAP_BLOCK_SIZE)*N although it
should be N at maximum. With PREEMPT kernel ZAP_BLOCK_SIZE is 8
pages, so there is a noticeable performance penalty when
unmapping a large VMA and the system is spending its time in
flush_tlb_range().

The problem is that tlb_end_vma() is always flushing the full VMA
range. The subrange that needs to be flushed can be calculated by
tlb_remove_tlb_entry(). This approach was suggested by Hugh
Dickins, and is also used by other arches.

The speed increase is roughly 3x for 8M mappings and for larger
mappings even more.

Bits and peices are taken from the ARM patch as well as the existing
arch/um implementation that is quite similar.

The end result is a significant reduction in both partial and full TLB
flushes initiated through flush_tlb_range().

At the same time, the nommu implementation was broken, had a superfluous
cache flush, and subsequently would have triggered a BUG_ON() if a
code-path had triggered it. Tidy this up for correctness and provide a
nopped-out implementation there.

More background on the initial discussion can be found at:

http://marc.info/?t=123609820900002&r=1&w=2
http://marc.info/?t=123660375800003&r=1&w=2

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/include/asm/tlb.h