vserver 1.9.3
[linux-2.6.git] / include / asm-sparc64 / tlb.h
1 #ifndef _SPARC64_TLB_H
2 #define _SPARC64_TLB_H
3
4 #include <linux/config.h>
5 #include <linux/swap.h>
6 #include <linux/vs_memory.h>
7
8 #include <asm/pgalloc.h>
9 #include <asm/tlbflush.h>
10 #include <asm/mmu_context.h>
11
12 #define TLB_BATCH_NR    192
13
14 /*
15  * For UP we don't need to worry about TLB flush
16  * and page free order so much..
17  */
18 #ifdef CONFIG_SMP
19   #define FREE_PTE_NR   506
20   #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U)
21 #else
22   #define FREE_PTE_NR   1
23   #define tlb_fast_mode(bp) 1
24 #endif
25
26 struct mmu_gather {
27         struct mm_struct *mm;
28         unsigned int pages_nr;
29         unsigned int need_flush;
30         unsigned int tlb_frozen;
31         unsigned int tlb_nr;
32         unsigned long freed;
33         unsigned long vaddrs[TLB_BATCH_NR];
34         struct page *pages[FREE_PTE_NR];
35 };
36
37 DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
38
39 #ifdef CONFIG_SMP
40 extern void smp_flush_tlb_pending(struct mm_struct *,
41                                   unsigned long, unsigned long *);
42 #endif
43
44 extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
45 extern void flush_tlb_pending(void);
46
47 static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
48 {
49         struct mmu_gather *mp = &per_cpu(mmu_gathers, smp_processor_id());
50
51         BUG_ON(mp->tlb_nr);
52
53         mp->mm = mm;
54         mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U;
55         mp->tlb_frozen = full_mm_flush;
56         mp->freed = 0;
57
58         return mp;
59 }
60
61
62 static inline void tlb_flush_mmu(struct mmu_gather *mp)
63 {
64         if (mp->need_flush) {
65                 mp->need_flush = 0;
66                 if (!tlb_fast_mode(mp)) {
67                         free_pages_and_swap_cache(mp->pages, mp->pages_nr);
68                         mp->pages_nr = 0;
69                 }
70         }
71
72 }
73
74 #ifdef CONFIG_SMP
75 extern void smp_flush_tlb_mm(struct mm_struct *mm);
76 #define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
77 #else
78 #define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT)
79 #endif
80
81 static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end)
82 {
83         unsigned long freed = mp->freed;
84         struct mm_struct *mm = mp->mm;
85         unsigned long rss = mm->rss;
86
87         if (rss < freed)
88                 freed = rss;
89         mm->rss = rss - freed;
90
91         tlb_flush_mmu(mp);
92
93         if (mp->tlb_frozen) {
94                 unsigned long context = mm->context;
95
96                 if (CTX_VALID(context))
97                         do_flush_tlb_mm(mm);
98                 mp->tlb_frozen = 0;
99         } else
100                 flush_tlb_pending();
101
102         /* keep the page table cache within bounds */
103         check_pgt_cache();
104 }
105
106 static inline unsigned int tlb_is_full_mm(struct mmu_gather *mp)
107 {
108         return mp->tlb_frozen;
109 }
110
111 static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
112 {
113         mp->need_flush = 1;
114         if (tlb_fast_mode(mp)) {
115                 free_page_and_swap_cache(page);
116                 return;
117         }
118         mp->pages[mp->pages_nr++] = page;
119         if (mp->pages_nr >= FREE_PTE_NR)
120                 tlb_flush_mmu(mp);
121 }
122
123 #define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
124 #define pte_free_tlb(mp,ptepage) pte_free(ptepage)
125 #define pmd_free_tlb(mp,pmdp) pmd_free(pmdp)
126
127 #define tlb_migrate_finish(mm)  do { } while (0)
128 #define tlb_start_vma(tlb, vma) do { } while (0)
129 #define tlb_end_vma(tlb, vma)   do { } while (0)
130
131 #endif /* _SPARC64_TLB_H */