diff options
author | Dean Roe <roe@sgi.com> | 2005-10-27 15:41:04 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-10-27 14:44:58 -0700 |
commit | c1902aae322952f8726469a6657df7b9d5c794fe (patch) | |
tree | 5c78f21c19597b64faf06e0faee7726ae01f7bbb /arch/ia64/mm/tlb.c | |
parent | 72ab373a5688a78cbdaf3bf96012e597d5399bb7 (diff) | |
download | talos-obmc-linux-c1902aae322952f8726469a6657df7b9d5c794fe.tar.gz talos-obmc-linux-c1902aae322952f8726469a6657df7b9d5c794fe.zip |
[IA64] - Avoid slow TLB purges on SGI Altix systems
flush_tlb_all() can be a scaling issue on large SGI Altix systems
since it uses the global call_lock and always executes on all cpus.
When a process enters flush_tlb_range() to purge TLBs for another
process, it is possible to avoid flush_tlb_all() and instead allow
sn2_global_tlb_purge() to purge TLBs only where necessary.
This patch modifies flush_tlb_range() so that this case can be handled
by platform TLB purge functions and updates ia64_global_tlb_purge()
accordingly. sn2_global_tlb_purge() now calculates the region register
value from the mm argument introduced with this patch.
Signed-off-by: Dean Roe <roe@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/mm/tlb.c')
-rw-r--r-- | arch/ia64/mm/tlb.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 464557e4ed82..99ea8c70f408 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -86,10 +86,15 @@ wrap_mmu_context (struct mm_struct *mm) } void -ia64_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) +ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) { static DEFINE_SPINLOCK(ptcg_lock); + if (mm != current->active_mm) { + flush_tlb_all(); + return; + } + /* HW requires global serialization of ptc.ga. */ spin_lock(&ptcg_lock); { @@ -135,15 +140,12 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long unsigned long size = end - start; unsigned long nbits; +#ifndef CONFIG_SMP if (mm != current->active_mm) { - /* this does happen, but perhaps it's not worth optimizing for? */ -#ifdef CONFIG_SMP - flush_tlb_all(); -#else mm->context = 0; -#endif return; } +#endif nbits = ia64_fls(size + 0xfff); while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits)) @@ -153,7 +155,7 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long start &= ~((1UL << nbits) - 1); # ifdef CONFIG_SMP - platform_global_tlb_purge(start, end, nbits); + platform_global_tlb_purge(mm, start, end, nbits); # else do { ia64_ptcl(start, (nbits<<2)); |