blob: 1c4e5c2dfc5377675789f1728c9197f17fb61ec0 [file] [log] [blame]
David S. Miller74bf4312006-01-31 18:29:18 -08001/* arch/sparc64/mm/tsb.c
2 *
3 * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kernel.h>
7#include <asm/system.h>
8#include <asm/page.h>
9#include <asm/tlbflush.h>
10#include <asm/tlb.h>
David S. Miller09f94282006-01-31 18:31:06 -080011#include <asm/mmu_context.h>
David S. Miller98c55842006-01-31 18:31:20 -080012#include <asm/pgtable.h>
David S. Millerbd407912006-01-31 18:31:38 -080013#include <asm/tsb.h>
David S. Miller74bf4312006-01-31 18:29:18 -080014
David S. Miller74bf4312006-01-31 18:29:18 -080015extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
16
David S. Miller98c55842006-01-31 18:31:20 -080017static inline unsigned long tsb_hash(unsigned long vaddr, unsigned long nentries)
David S. Miller74bf4312006-01-31 18:29:18 -080018{
19 vaddr >>= PAGE_SHIFT;
David S. Miller98c55842006-01-31 18:31:20 -080020 return vaddr & (nentries - 1);
David S. Miller74bf4312006-01-31 18:29:18 -080021}
22
23static inline int tag_compare(struct tsb *entry, unsigned long vaddr, unsigned long context)
24{
25 if (context == ~0UL)
26 return 1;
27
28 return (entry->tag == ((vaddr >> 22) | (context << 48)));
29}
30
31/* TSB flushes need only occur on the processor initiating the address
32 * space modification, not on each cpu the address space has run on.
33 * Only the TLB flush needs that treatment.
34 */
35
36void flush_tsb_kernel_range(unsigned long start, unsigned long end)
37{
38 unsigned long v;
39
40 for (v = start; v < end; v += PAGE_SIZE) {
David S. Miller98c55842006-01-31 18:31:20 -080041 unsigned long hash = tsb_hash(v, KERNEL_TSB_NENTRIES);
42 struct tsb *ent = &swapper_tsb[hash];
David S. Miller74bf4312006-01-31 18:29:18 -080043
44 if (tag_compare(ent, v, 0)) {
45 ent->tag = 0UL;
46 membar_storeload_storestore();
47 }
48 }
49}
50
51void flush_tsb_user(struct mmu_gather *mp)
52{
53 struct mm_struct *mm = mp->mm;
David S. Miller98c55842006-01-31 18:31:20 -080054 struct tsb *tsb = mm->context.tsb;
David S. Miller74bf4312006-01-31 18:29:18 -080055 unsigned long ctx = ~0UL;
David S. Miller98c55842006-01-31 18:31:20 -080056 unsigned long nentries = mm->context.tsb_nentries;
David S. Miller74bf4312006-01-31 18:29:18 -080057 int i;
58
59 if (CTX_VALID(mm->context))
60 ctx = CTX_HWBITS(mm->context);
61
62 for (i = 0; i < mp->tlb_nr; i++) {
63 unsigned long v = mp->vaddrs[i];
64 struct tsb *ent;
65
66 v &= ~0x1UL;
67
David S. Miller98c55842006-01-31 18:31:20 -080068 ent = &tsb[tsb_hash(v, nentries)];
David S. Miller74bf4312006-01-31 18:29:18 -080069 if (tag_compare(ent, v, ctx)) {
70 ent->tag = 0UL;
71 membar_storeload_storestore();
72 }
73 }
74}
David S. Miller09f94282006-01-31 18:31:06 -080075
David S. Miller98c55842006-01-31 18:31:20 -080076static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes)
77{
78 unsigned long tsb_reg, base, tsb_paddr;
79 unsigned long page_sz, tte;
80
81 mm->context.tsb_nentries = tsb_bytes / sizeof(struct tsb);
82
83 base = TSBMAP_BASE;
84 tte = (_PAGE_VALID | _PAGE_L | _PAGE_CP |
85 _PAGE_CV | _PAGE_P | _PAGE_W);
86 tsb_paddr = __pa(mm->context.tsb);
87
88 /* Use the smallest page size that can map the whole TSB
89 * in one TLB entry.
90 */
91 switch (tsb_bytes) {
92 case 8192 << 0:
93 tsb_reg = 0x0UL;
94#ifdef DCACHE_ALIASING_POSSIBLE
95 base += (tsb_paddr & 8192);
96#endif
97 tte |= _PAGE_SZ8K;
98 page_sz = 8192;
99 break;
100
101 case 8192 << 1:
102 tsb_reg = 0x1UL;
103 tte |= _PAGE_SZ64K;
104 page_sz = 64 * 1024;
105 break;
106
107 case 8192 << 2:
108 tsb_reg = 0x2UL;
109 tte |= _PAGE_SZ64K;
110 page_sz = 64 * 1024;
111 break;
112
113 case 8192 << 3:
114 tsb_reg = 0x3UL;
115 tte |= _PAGE_SZ64K;
116 page_sz = 64 * 1024;
117 break;
118
119 case 8192 << 4:
120 tsb_reg = 0x4UL;
121 tte |= _PAGE_SZ512K;
122 page_sz = 512 * 1024;
123 break;
124
125 case 8192 << 5:
126 tsb_reg = 0x5UL;
127 tte |= _PAGE_SZ512K;
128 page_sz = 512 * 1024;
129 break;
130
131 case 8192 << 6:
132 tsb_reg = 0x6UL;
133 tte |= _PAGE_SZ512K;
134 page_sz = 512 * 1024;
135 break;
136
137 case 8192 << 7:
138 tsb_reg = 0x7UL;
139 tte |= _PAGE_SZ4MB;
140 page_sz = 4 * 1024 * 1024;
141 break;
David S. Millerbd407912006-01-31 18:31:38 -0800142
143 default:
144 BUG();
David S. Miller98c55842006-01-31 18:31:20 -0800145 };
146
147 tsb_reg |= base;
148 tsb_reg |= (tsb_paddr & (page_sz - 1UL));
149 tte |= (tsb_paddr & ~(page_sz - 1UL));
150
151 mm->context.tsb_reg_val = tsb_reg;
152 mm->context.tsb_map_vaddr = base;
153 mm->context.tsb_map_pte = tte;
154}
155
David S. Millerbd407912006-01-31 18:31:38 -0800156/* The page tables are locked against modifications while this
157 * runs.
158 *
159 * XXX do some prefetching...
160 */
161static void copy_tsb(struct tsb *old_tsb, unsigned long old_size,
162 struct tsb *new_tsb, unsigned long new_size)
163{
164 unsigned long old_nentries = old_size / sizeof(struct tsb);
165 unsigned long new_nentries = new_size / sizeof(struct tsb);
166 unsigned long i;
167
168 for (i = 0; i < old_nentries; i++) {
169 register unsigned long tag asm("o4");
170 register unsigned long pte asm("o5");
171 unsigned long v;
172 unsigned int hash;
173
174 __asm__ __volatile__(
175 "ldda [%2] %3, %0"
176 : "=r" (tag), "=r" (pte)
177 : "r" (&old_tsb[i]), "i" (ASI_NUCLEUS_QUAD_LDD));
178
David S. Miller4753eb22006-01-31 18:32:44 -0800179 if (!tag || (tag & (1UL << TSB_TAG_LOCK_BIT)))
David S. Millerbd407912006-01-31 18:31:38 -0800180 continue;
181
182 /* We only put base page size PTEs into the TSB,
183 * but that might change in the future. This code
184 * would need to be changed if we start putting larger
185 * page size PTEs into there.
186 */
187 WARN_ON((pte & _PAGE_ALL_SZ_BITS) != _PAGE_SZBITS);
188
189 /* The tag holds bits 22 to 63 of the virtual address
190 * and the context. Clear out the context, and shift
191 * up to make a virtual address.
192 */
193 v = (tag & ((1UL << 42UL) - 1UL)) << 22UL;
194
195 /* The implied bits of the tag (bits 13 to 21) are
196 * determined by the TSB entry index, so fill that in.
197 */
198 v |= (i & (512UL - 1UL)) << 13UL;
199
200 hash = tsb_hash(v, new_nentries);
201 new_tsb[hash].tag = tag;
202 new_tsb[hash].pte = pte;
203 }
204}
205
206/* When the RSS of an address space exceeds mm->context.tsb_rss_limit,
207 * update_mmu_cache() invokes this routine to try and grow the TSB.
208 * When we reach the maximum TSB size supported, we stick ~0UL into
209 * mm->context.tsb_rss_limit so the grow checks in update_mmu_cache()
210 * will not trigger any longer.
211 *
212 * The TSB can be anywhere from 8K to 1MB in size, in increasing powers
213 * of two. The TSB must be aligned to it's size, so f.e. a 512K TSB
214 * must be 512K aligned.
215 *
216 * The idea here is to grow the TSB when the RSS of the process approaches
217 * the number of entries that the current TSB can hold at once. Currently,
218 * we trigger when the RSS hits 3/4 of the TSB capacity.
219 */
220void tsb_grow(struct mm_struct *mm, unsigned long rss, gfp_t gfp_flags)
221{
222 unsigned long max_tsb_size = 1 * 1024 * 1024;
223 unsigned long size, old_size;
224 struct page *page;
225 struct tsb *old_tsb;
226
227 if (max_tsb_size > (PAGE_SIZE << MAX_ORDER))
228 max_tsb_size = (PAGE_SIZE << MAX_ORDER);
229
230 for (size = PAGE_SIZE; size < max_tsb_size; size <<= 1UL) {
231 unsigned long n_entries = size / sizeof(struct tsb);
232
233 n_entries = (n_entries * 3) / 4;
234 if (n_entries > rss)
235 break;
236 }
237
238 page = alloc_pages(gfp_flags | __GFP_ZERO, get_order(size));
239 if (unlikely(!page))
240 return;
241
242 if (size == max_tsb_size)
243 mm->context.tsb_rss_limit = ~0UL;
244 else
245 mm->context.tsb_rss_limit =
246 ((size / sizeof(struct tsb)) * 3) / 4;
247
248 old_tsb = mm->context.tsb;
249 old_size = mm->context.tsb_nentries * sizeof(struct tsb);
250
251 if (old_tsb)
252 copy_tsb(old_tsb, old_size, page_address(page), size);
253
254 mm->context.tsb = page_address(page);
255 setup_tsb_params(mm, size);
256
257 /* If old_tsb is NULL, we're being invoked for the first time
258 * from init_new_context().
259 */
260 if (old_tsb) {
261 /* Now force all other processors to reload the new
262 * TSB state.
263 */
264 smp_tsb_sync(mm);
265
266 /* Finally reload it on the local cpu. No further
267 * references will remain to the old TSB and we can
268 * thus free it up.
269 */
270 tsb_context_switch(mm);
271
272 free_pages((unsigned long) old_tsb, get_order(old_size));
273 }
274}
275
David S. Miller09f94282006-01-31 18:31:06 -0800276int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
277{
David S. Millerbd407912006-01-31 18:31:38 -0800278 unsigned long initial_rss;
David S. Miller09f94282006-01-31 18:31:06 -0800279
280 mm->context.sparc64_ctx_val = 0UL;
David S. Miller09f94282006-01-31 18:31:06 -0800281
David S. Millerbd407912006-01-31 18:31:38 -0800282 /* copy_mm() copies over the parent's mm_struct before calling
283 * us, so we need to zero out the TSB pointer or else tsb_grow()
284 * will be confused and think there is an older TSB to free up.
285 */
286 mm->context.tsb = NULL;
287
288 /* If this is fork, inherit the parent's TSB size. We would
289 * grow it to that size on the first page fault anyways.
290 */
291 initial_rss = mm->context.tsb_nentries;
292 if (initial_rss)
293 initial_rss -= 1;
294
295 tsb_grow(mm, initial_rss, GFP_KERNEL);
296
297 if (unlikely(!mm->context.tsb))
298 return -ENOMEM;
David S. Miller09f94282006-01-31 18:31:06 -0800299
300 return 0;
301}
302
303void destroy_context(struct mm_struct *mm)
304{
David S. Millerbd407912006-01-31 18:31:38 -0800305 unsigned long size = mm->context.tsb_nentries * sizeof(struct tsb);
306
307 free_pages((unsigned long) mm->context.tsb, get_order(size));
David S. Miller98c55842006-01-31 18:31:20 -0800308
309 /* We can remove these later, but for now it's useful
310 * to catch any bogus post-destroy_context() references
311 * to the TSB.
312 */
313 mm->context.tsb = NULL;
314 mm->context.tsb_reg_val = 0UL;
David S. Miller09f94282006-01-31 18:31:06 -0800315
316 spin_lock(&ctx_alloc_lock);
317
318 if (CTX_VALID(mm->context)) {
319 unsigned long nr = CTX_NRBITS(mm->context);
320 mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63));
321 }
322
323 spin_unlock(&ctx_alloc_lock);
324}