aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/include/asm
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2011-05-24 20:11:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 11:39:13 -0400
commit90f08e399d054d017c0e2c5089a0f44a76418271 (patch)
tree771d8a9ff675e3fe5deda53d0701e41f1f15e9a1 /arch/sparc/include/asm
parentd6bf29b44ddf3ca915f77b9383bee8b7a209f3fd (diff)
sparc: mmu_gather rework
Rework the sparc mmu_gather usage to conform to the new world order :-) Sparc mmu_gather does two things: - tracks vaddrs to unhash - tracks pages to free Split these two things like powerpc has done and keep the vaddrs in per-cpu data structures and flush them on context switch. The remaining bits can then use the generic mmu_gather. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: David Miller <davem@davemloft.net> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Jeff Dike <jdike@addtoit.com> Cc: Richard Weinberger <richard@nod.at> Cc: Tony Luck <tony.luck@intel.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Hugh Dickins <hughd@google.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Nick Piggin <npiggin@kernel.dk> Cc: Namhyung Kim <namhyung@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/sparc/include/asm')
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h3
-rw-r--r--arch/sparc/include/asm/pgtable_64.h15
-rw-r--r--arch/sparc/include/asm/tlb_64.h91
-rw-r--r--arch/sparc/include/asm/tlbflush_64.h12
4 files changed, 31 insertions, 90 deletions
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
index 5bdfa2c6e400..4e5e0878144f 100644
--- a/arch/sparc/include/asm/pgalloc_64.h
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -78,4 +78,7 @@ static inline void check_pgt_cache(void)
78 quicklist_trim(0, NULL, 25, 16); 78 quicklist_trim(0, NULL, 25, 16);
79} 79}
80 80
81#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
82#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
83
81#endif /* _SPARC64_PGALLOC_H */ 84#endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index b77128c80524..1e03c5a6b4f7 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -655,9 +655,11 @@ static inline int pte_special(pte_t pte)
655#define pte_unmap(pte) do { } while (0) 655#define pte_unmap(pte) do { } while (0)
656 656
657/* Actual page table PTE updates. */ 657/* Actual page table PTE updates. */
658extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig); 658extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
659 pte_t *ptep, pte_t orig, int fullmm);
659 660
660static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) 661static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
662 pte_t *ptep, pte_t pte, int fullmm)
661{ 663{
662 pte_t orig = *ptep; 664 pte_t orig = *ptep;
663 665
@@ -670,12 +672,19 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
670 * and SUN4V pte layout, so this inline test is fine. 672 * and SUN4V pte layout, so this inline test is fine.
671 */ 673 */
672 if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID)) 674 if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
673 tlb_batch_add(mm, addr, ptep, orig); 675 tlb_batch_add(mm, addr, ptep, orig, fullmm);
674} 676}
675 677
678#define set_pte_at(mm,addr,ptep,pte) \
679 __set_pte_at((mm), (addr), (ptep), (pte), 0)
680
676#define pte_clear(mm,addr,ptep) \ 681#define pte_clear(mm,addr,ptep) \
677 set_pte_at((mm), (addr), (ptep), __pte(0UL)) 682 set_pte_at((mm), (addr), (ptep), __pte(0UL))
678 683
684#define __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL
685#define pte_clear_not_present_full(mm,addr,ptep,fullmm) \
686 __set_pte_at((mm), (addr), (ptep), __pte(0UL), (fullmm))
687
679#ifdef DCACHE_ALIASING_POSSIBLE 688#ifdef DCACHE_ALIASING_POSSIBLE
680#define __HAVE_ARCH_MOVE_PTE 689#define __HAVE_ARCH_MOVE_PTE
681#define move_pte(pte, prot, old_addr, new_addr) \ 690#define move_pte(pte, prot, old_addr, new_addr) \
diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h
index dca406b9b6fc..190e18913cc6 100644
--- a/arch/sparc/include/asm/tlb_64.h
+++ b/arch/sparc/include/asm/tlb_64.h
@@ -7,66 +7,11 @@
7#include <asm/tlbflush.h> 7#include <asm/tlbflush.h>
8#include <asm/mmu_context.h> 8#include <asm/mmu_context.h>
9 9
10#define TLB_BATCH_NR 192
11
12/*
13 * For UP we don't need to worry about TLB flush
14 * and page free order so much..
15 */
16#ifdef CONFIG_SMP
17 #define FREE_PTE_NR 506
18 #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U)
19#else
20 #define FREE_PTE_NR 1
21 #define tlb_fast_mode(bp) 1
22#endif
23
24struct mmu_gather {
25 struct mm_struct *mm;
26 unsigned int pages_nr;
27 unsigned int need_flush;
28 unsigned int fullmm;
29 unsigned int tlb_nr;
30 unsigned long vaddrs[TLB_BATCH_NR];
31 struct page *pages[FREE_PTE_NR];
32};
33
34DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
35
36#ifdef CONFIG_SMP 10#ifdef CONFIG_SMP
37extern void smp_flush_tlb_pending(struct mm_struct *, 11extern void smp_flush_tlb_pending(struct mm_struct *,
38 unsigned long, unsigned long *); 12 unsigned long, unsigned long *);
39#endif 13#endif
40 14
41extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
42extern void flush_tlb_pending(void);
43
44static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
45{
46 struct mmu_gather *mp = &get_cpu_var(mmu_gathers);
47
48 BUG_ON(mp->tlb_nr);
49
50 mp->mm = mm;
51 mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U;
52 mp->fullmm = full_mm_flush;
53
54 return mp;
55}
56
57
58static inline void tlb_flush_mmu(struct mmu_gather *mp)
59{
60 if (!mp->fullmm)
61 flush_tlb_pending();
62 if (mp->need_flush) {
63 free_pages_and_swap_cache(mp->pages, mp->pages_nr);
64 mp->pages_nr = 0;
65 mp->need_flush = 0;
66 }
67
68}
69
70#ifdef CONFIG_SMP 15#ifdef CONFIG_SMP
71extern void smp_flush_tlb_mm(struct mm_struct *mm); 16extern void smp_flush_tlb_mm(struct mm_struct *mm);
72#define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm) 17#define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
@@ -74,38 +19,14 @@ extern void smp_flush_tlb_mm(struct mm_struct *mm);
74#define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT) 19#define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT)
75#endif 20#endif
76 21
77static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end) 22extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
78{ 23extern void flush_tlb_pending(void);
79 tlb_flush_mmu(mp);
80
81 if (mp->fullmm)
82 mp->fullmm = 0;
83
84 /* keep the page table cache within bounds */
85 check_pgt_cache();
86
87 put_cpu_var(mmu_gathers);
88}
89
90static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
91{
92 if (tlb_fast_mode(mp)) {
93 free_page_and_swap_cache(page);
94 return;
95 }
96 mp->need_flush = 1;
97 mp->pages[mp->pages_nr++] = page;
98 if (mp->pages_nr >= FREE_PTE_NR)
99 tlb_flush_mmu(mp);
100}
101
102#define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
103#define pte_free_tlb(mp, ptepage, addr) pte_free((mp)->mm, ptepage)
104#define pmd_free_tlb(mp, pmdp, addr) pmd_free((mp)->mm, pmdp)
105#define pud_free_tlb(tlb,pudp, addr) __pud_free_tlb(tlb,pudp,addr)
106 24
107#define tlb_migrate_finish(mm) do { } while (0)
108#define tlb_start_vma(tlb, vma) do { } while (0) 25#define tlb_start_vma(tlb, vma) do { } while (0)
109#define tlb_end_vma(tlb, vma) do { } while (0) 26#define tlb_end_vma(tlb, vma) do { } while (0)
27#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
28#define tlb_flush(tlb) flush_tlb_pending()
29
30#include <asm-generic/tlb.h>
110 31
111#endif /* _SPARC64_TLB_H */ 32#endif /* _SPARC64_TLB_H */
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
index fbb675dbe0c9..2ef463494153 100644
--- a/arch/sparc/include/asm/tlbflush_64.h
+++ b/arch/sparc/include/asm/tlbflush_64.h
@@ -5,9 +5,17 @@
5#include <asm/mmu_context.h> 5#include <asm/mmu_context.h>
6 6
7/* TSB flush operations. */ 7/* TSB flush operations. */
8struct mmu_gather; 8
9#define TLB_BATCH_NR 192
10
11struct tlb_batch {
12 struct mm_struct *mm;
13 unsigned long tlb_nr;
14 unsigned long vaddrs[TLB_BATCH_NR];
15};
16
9extern void flush_tsb_kernel_range(unsigned long start, unsigned long end); 17extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
10extern void flush_tsb_user(struct mmu_gather *mp); 18extern void flush_tsb_user(struct tlb_batch *tb);
11 19
12/* TLB flush operations. */ 20/* TLB flush operations. */
13 21