Commit 68d01416 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Inefficient TLB flush fix

From: Martin Hicks <mort@wildopensource.com>

This is a patch based on one that Jack Steiner sent to the ia64 list in
November.  The original thread can be found at:

http://marc.theaimsgroup.com/?l=linux-ia64&m=106869606922555&w=2

I created the little wrapper function that was requested.  I think the only
other arch, other than ia64, that doesn't at least include asm-generic/tlb.h
is arm.


Something appears broken in TLB flushing on IA64 (& possibly other
architectures).  Functionally, it works but performance is bad on systems
with large cpu counts.

The result is that TLB flushing in exit_mmap() is frequently being done via
IPIs to all cpus rather than with a "ptc" instruction or with a new
context..
parent 9d02772a
...@@ -70,6 +70,12 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) ...@@ -70,6 +70,12 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
check_pgt_cache(); check_pgt_cache();
} }
static inline unsigned int
tlb_is_full_mm(struct mmu_gather *tlb)
{
return tlb->fullmm;
}
#define tlb_remove_tlb_entry(tlb,ptep,address) do { } while (0) #define tlb_remove_tlb_entry(tlb,ptep,address) do { } while (0)
#define tlb_start_vma(tlb,vma) \ #define tlb_start_vma(tlb,vma) \
......
...@@ -98,6 +98,11 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) ...@@ -98,6 +98,11 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
check_pgt_cache(); check_pgt_cache();
} }
static inline unsigned int
tlb_is_full_mm(struct mmu_gather *tlb)
{
return tlb->fullmm;
}
/* tlb_remove_page /* tlb_remove_page
* Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while * Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while
......
...@@ -173,6 +173,12 @@ tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end) ...@@ -173,6 +173,12 @@ tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
check_pgt_cache(); check_pgt_cache();
} }
static inline unsigned int
tlb_is_full_mm(struct mmu_gather *tlb)
{
return tlb->fullmm;
}
/* /*
* Logically, this routine frees PAGE. On MP machines, the actual freeing of the page * Logically, this routine frees PAGE. On MP machines, the actual freeing of the page
* must be delayed until after the TLB has been flushed (see comments at the beginning of * must be delayed until after the TLB has been flushed (see comments at the beginning of
......
...@@ -574,9 +574,10 @@ int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm, ...@@ -574,9 +574,10 @@ int unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm,
if ((long)zap_bytes > 0) if ((long)zap_bytes > 0)
continue; continue;
if (need_resched()) { if (need_resched()) {
int fullmm = tlb_is_full_mm(*tlbp);
tlb_finish_mmu(*tlbp, tlb_start, start); tlb_finish_mmu(*tlbp, tlb_start, start);
cond_resched_lock(&mm->page_table_lock); cond_resched_lock(&mm->page_table_lock);
*tlbp = tlb_gather_mmu(mm, 0); *tlbp = tlb_gather_mmu(mm, fullmm);
tlb_start_valid = 0; tlb_start_valid = 0;
} }
zap_bytes = ZAP_BLOCK_SIZE; zap_bytes = ZAP_BLOCK_SIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment