aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/hash_utils_64.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-11-06 22:42:09 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-06 22:42:09 -0500
commitc6135234550ed89a6fd0e8cb229633967e41d649 (patch)
tree22cef33e314839c4fb30d6fc888c0caa2a0f6602 /arch/powerpc/mm/hash_utils_64.c
parent76032de898f34db55b5048349db56557828a1390 (diff)
parent0b154bb7d0cce80e9c0bcf11d4f9e71b59409d26 (diff)
Merge ../linux-2.6
Diffstat (limited to 'arch/powerpc/mm/hash_utils_64.c')
-rw-r--r--arch/powerpc/mm/hash_utils_64.c532
1 files changed, 415 insertions, 117 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index b6970c96d96f..37273f518a35 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -19,6 +19,7 @@
19 */ 19 */
20 20
21#undef DEBUG 21#undef DEBUG
22#undef DEBUG_LOW
22 23
23#include <linux/config.h> 24#include <linux/config.h>
24#include <linux/spinlock.h> 25#include <linux/spinlock.h>
@@ -58,6 +59,15 @@
58#define DBG(fmt...) 59#define DBG(fmt...)
59#endif 60#endif
60 61
62#ifdef DEBUG_LOW
63#define DBG_LOW(fmt...) udbg_printf(fmt)
64#else
65#define DBG_LOW(fmt...)
66#endif
67
68#define KB (1024)
69#define MB (1024*KB)
70
61/* 71/*
62 * Note: pte --> Linux PTE 72 * Note: pte --> Linux PTE
63 * HPTE --> PowerPC Hashed Page Table Entry 73 * HPTE --> PowerPC Hashed Page Table Entry
@@ -76,91 +86,290 @@ extern unsigned long dart_tablebase;
76 86
77hpte_t *htab_address; 87hpte_t *htab_address;
78unsigned long htab_hash_mask; 88unsigned long htab_hash_mask;
79
80unsigned long _SDR1; 89unsigned long _SDR1;
90struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
91int mmu_linear_psize = MMU_PAGE_4K;
92int mmu_virtual_psize = MMU_PAGE_4K;
93#ifdef CONFIG_HUGETLB_PAGE
94int mmu_huge_psize = MMU_PAGE_16M;
95unsigned int HPAGE_SHIFT;
96#endif
81 97
82#define KB (1024) 98/* There are definitions of page sizes arrays to be used when none
83#define MB (1024*KB) 99 * is provided by the firmware.
84 100 */
85static inline void loop_forever(void)
86{
87 volatile unsigned long x = 1;
88 for(;x;x|=1)
89 ;
90}
91 101
92static inline void create_pte_mapping(unsigned long start, unsigned long end, 102/* Pre-POWER4 CPUs (4k pages only)
93 unsigned long mode, int large) 103 */
104struct mmu_psize_def mmu_psize_defaults_old[] = {
105 [MMU_PAGE_4K] = {
106 .shift = 12,
107 .sllp = 0,
108 .penc = 0,
109 .avpnm = 0,
110 .tlbiel = 0,
111 },
112};
113
114/* POWER4, GPUL, POWER5
115 *
116 * Support for 16Mb large pages
117 */
118struct mmu_psize_def mmu_psize_defaults_gp[] = {
119 [MMU_PAGE_4K] = {
120 .shift = 12,
121 .sllp = 0,
122 .penc = 0,
123 .avpnm = 0,
124 .tlbiel = 1,
125 },
126 [MMU_PAGE_16M] = {
127 .shift = 24,
128 .sllp = SLB_VSID_L,
129 .penc = 0,
130 .avpnm = 0x1UL,
131 .tlbiel = 0,
132 },
133};
134
135
136int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
137 unsigned long pstart, unsigned long mode, int psize)
94{ 138{
95 unsigned long addr; 139 unsigned long vaddr, paddr;
96 unsigned int step; 140 unsigned int step, shift;
97 unsigned long tmp_mode; 141 unsigned long tmp_mode;
98 unsigned long vflags; 142 int ret = 0;
99 143
100 if (large) { 144 shift = mmu_psize_defs[psize].shift;
101 step = 16*MB; 145 step = 1 << shift;
102 vflags = HPTE_V_BOLTED | HPTE_V_LARGE;
103 } else {
104 step = 4*KB;
105 vflags = HPTE_V_BOLTED;
106 }
107 146
108 for (addr = start; addr < end; addr += step) { 147 for (vaddr = vstart, paddr = pstart; vaddr < vend;
148 vaddr += step, paddr += step) {
109 unsigned long vpn, hash, hpteg; 149 unsigned long vpn, hash, hpteg;
110 unsigned long vsid = get_kernel_vsid(addr); 150 unsigned long vsid = get_kernel_vsid(vaddr);
111 unsigned long va = (vsid << 28) | (addr & 0xfffffff); 151 unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);
112 int ret = -1;
113
114 if (large)
115 vpn = va >> HPAGE_SHIFT;
116 else
117 vpn = va >> PAGE_SHIFT;
118
119 152
153 vpn = va >> shift;
120 tmp_mode = mode; 154 tmp_mode = mode;
121 155
122 /* Make non-kernel text non-executable */ 156 /* Make non-kernel text non-executable */
123 if (!in_kernel_text(addr)) 157 if (!in_kernel_text(vaddr))
124 tmp_mode = mode | HW_NO_EXEC; 158 tmp_mode = mode | HPTE_R_N;
125
126 hash = hpt_hash(vpn, large);
127 159
160 hash = hpt_hash(va, shift);
128 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); 161 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
129 162
163 /* The crap below can be cleaned once ppd_md.probe() can
164 * set up the hash callbacks, thus we can just used the
165 * normal insert callback here.
166 */
130#ifdef CONFIG_PPC_ISERIES 167#ifdef CONFIG_PPC_ISERIES
131 if (systemcfg->platform & PLATFORM_ISERIES_LPAR) 168 if (systemcfg->platform == PLATFORM_ISERIES_LPAR)
132 ret = iSeries_hpte_bolt_or_insert(hpteg, va, 169 ret = iSeries_hpte_insert(hpteg, va,
133 virt_to_abs(addr) >> PAGE_SHIFT, 170 virt_to_abs(paddr),
134 vflags, tmp_mode); 171 tmp_mode,
172 HPTE_V_BOLTED,
173 psize);
135 else 174 else
136#endif 175#endif
137#ifdef CONFIG_PPC_PSERIES 176#ifdef CONFIG_PPC_PSERIES
138 if (systemcfg->platform & PLATFORM_LPAR) 177 if (systemcfg->platform & PLATFORM_LPAR)
139 ret = pSeries_lpar_hpte_insert(hpteg, va, 178 ret = pSeries_lpar_hpte_insert(hpteg, va,
140 virt_to_abs(addr) >> PAGE_SHIFT, 179 virt_to_abs(paddr),
141 vflags, tmp_mode); 180 tmp_mode,
181 HPTE_V_BOLTED,
182 psize);
142 else 183 else
143#endif 184#endif
144#ifdef CONFIG_PPC_MULTIPLATFORM 185#ifdef CONFIG_PPC_MULTIPLATFORM
145 ret = native_hpte_insert(hpteg, va, 186 ret = native_hpte_insert(hpteg, va,
146 virt_to_abs(addr) >> PAGE_SHIFT, 187 virt_to_abs(paddr),
147 vflags, tmp_mode); 188 tmp_mode, HPTE_V_BOLTED,
189 psize);
148#endif 190#endif
191 if (ret < 0)
192 break;
193 }
194 return ret < 0 ? ret : 0;
195}
149 196
150 if (ret == -1) { 197static int __init htab_dt_scan_page_sizes(unsigned long node,
151 ppc64_terminate_msg(0x20, "create_pte_mapping"); 198 const char *uname, int depth,
152 loop_forever(); 199 void *data)
200{
201 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
202 u32 *prop;
203 unsigned long size = 0;
204
205 /* We are scanning "cpu" nodes only */
206 if (type == NULL || strcmp(type, "cpu") != 0)
207 return 0;
208
209 prop = (u32 *)of_get_flat_dt_prop(node,
210 "ibm,segment-page-sizes", &size);
211 if (prop != NULL) {
212 DBG("Page sizes from device-tree:\n");
213 size /= 4;
214 cur_cpu_spec->cpu_features &= ~(CPU_FTR_16M_PAGE);
215 while(size > 0) {
216 unsigned int shift = prop[0];
217 unsigned int slbenc = prop[1];
218 unsigned int lpnum = prop[2];
219 unsigned int lpenc = 0;
220 struct mmu_psize_def *def;
221 int idx = -1;
222
223 size -= 3; prop += 3;
224 while(size > 0 && lpnum) {
225 if (prop[0] == shift)
226 lpenc = prop[1];
227 prop += 2; size -= 2;
228 lpnum--;
229 }
230 switch(shift) {
231 case 0xc:
232 idx = MMU_PAGE_4K;
233 break;
234 case 0x10:
235 idx = MMU_PAGE_64K;
236 break;
237 case 0x14:
238 idx = MMU_PAGE_1M;
239 break;
240 case 0x18:
241 idx = MMU_PAGE_16M;
242 cur_cpu_spec->cpu_features |= CPU_FTR_16M_PAGE;
243 break;
244 case 0x22:
245 idx = MMU_PAGE_16G;
246 break;
247 }
248 if (idx < 0)
249 continue;
250 def = &mmu_psize_defs[idx];
251 def->shift = shift;
252 if (shift <= 23)
253 def->avpnm = 0;
254 else
255 def->avpnm = (1 << (shift - 23)) - 1;
256 def->sllp = slbenc;
257 def->penc = lpenc;
258 /* We don't know for sure what's up with tlbiel, so
259 * for now we only set it for 4K and 64K pages
260 */
261 if (idx == MMU_PAGE_4K || idx == MMU_PAGE_64K)
262 def->tlbiel = 1;
263 else
264 def->tlbiel = 0;
265
266 DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, "
267 "tlbiel=%d, penc=%d\n",
268 idx, shift, def->sllp, def->avpnm, def->tlbiel,
269 def->penc);
153 } 270 }
271 return 1;
272 }
273 return 0;
274}
275
276
277static void __init htab_init_page_sizes(void)
278{
279 int rc;
280
281 /* Default to 4K pages only */
282 memcpy(mmu_psize_defs, mmu_psize_defaults_old,
283 sizeof(mmu_psize_defaults_old));
284
285 /*
286 * Try to find the available page sizes in the device-tree
287 */
288 rc = of_scan_flat_dt(htab_dt_scan_page_sizes, NULL);
289 if (rc != 0) /* Found */
290 goto found;
291
292 /*
293 * Not in the device-tree, let's fallback on known size
294 * list for 16M capable GP & GR
295 */
296 if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) &&
297 cpu_has_feature(CPU_FTR_16M_PAGE))
298 memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
299 sizeof(mmu_psize_defaults_gp));
300 found:
301 /*
302 * Pick a size for the linear mapping. Currently, we only support
303 * 16M, 1M and 4K which is the default
304 */
305 if (mmu_psize_defs[MMU_PAGE_16M].shift)
306 mmu_linear_psize = MMU_PAGE_16M;
307 else if (mmu_psize_defs[MMU_PAGE_1M].shift)
308 mmu_linear_psize = MMU_PAGE_1M;
309
310 /*
311 * Pick a size for the ordinary pages. Default is 4K, we support
312 * 64K if cache inhibited large pages are supported by the
313 * processor
314 */
315#ifdef CONFIG_PPC_64K_PAGES
316 if (mmu_psize_defs[MMU_PAGE_64K].shift &&
317 cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
318 mmu_virtual_psize = MMU_PAGE_64K;
319#endif
320
321 printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n",
322 mmu_psize_defs[mmu_linear_psize].shift,
323 mmu_psize_defs[mmu_virtual_psize].shift);
324
325#ifdef CONFIG_HUGETLB_PAGE
326 /* Init large page size. Currently, we pick 16M or 1M depending
327 * on what is available
328 */
329 if (mmu_psize_defs[MMU_PAGE_16M].shift)
330 mmu_huge_psize = MMU_PAGE_16M;
331 else if (mmu_psize_defs[MMU_PAGE_1M].shift)
332 mmu_huge_psize = MMU_PAGE_1M;
333
334 /* Calculate HPAGE_SHIFT and sanity check it */
335 if (mmu_psize_defs[mmu_huge_psize].shift > 16 &&
336 mmu_psize_defs[mmu_huge_psize].shift < 28)
337 HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift;
338 else
339 HPAGE_SHIFT = 0; /* No huge pages dude ! */
340#endif /* CONFIG_HUGETLB_PAGE */
341}
342
343static int __init htab_dt_scan_pftsize(unsigned long node,
344 const char *uname, int depth,
345 void *data)
346{
347 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
348 u32 *prop;
349
350 /* We are scanning "cpu" nodes only */
351 if (type == NULL || strcmp(type, "cpu") != 0)
352 return 0;
353
354 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL);
355 if (prop != NULL) {
356 /* pft_size[0] is the NUMA CEC cookie */
357 ppc64_pft_size = prop[1];
358 return 1;
154 } 359 }
360 return 0;
155} 361}
156 362
157static unsigned long get_hashtable_size(void) 363static unsigned long __init htab_get_table_size(void)
158{ 364{
159 unsigned long rnd_mem_size, pteg_count; 365 unsigned long rnd_mem_size, pteg_count;
160 366
161 /* If hash size wasn't obtained in prom.c, we calculate it now based on 367 /* If hash size isn't already provided by the platform, we try to
162 * the total RAM size 368 * retreive it from the device-tree. If it's not there neither, we
369 * calculate it now based on the total RAM size
163 */ 370 */
371 if (ppc64_pft_size == 0)
372 of_scan_flat_dt(htab_dt_scan_pftsize, NULL);
164 if (ppc64_pft_size) 373 if (ppc64_pft_size)
165 return 1UL << ppc64_pft_size; 374 return 1UL << ppc64_pft_size;
166 375
@@ -180,17 +389,21 @@ void __init htab_initialize(void)
180 unsigned long table, htab_size_bytes; 389 unsigned long table, htab_size_bytes;
181 unsigned long pteg_count; 390 unsigned long pteg_count;
182 unsigned long mode_rw; 391 unsigned long mode_rw;
183 int i, use_largepages = 0;
184 unsigned long base = 0, size = 0; 392 unsigned long base = 0, size = 0;
393 int i;
394
185 extern unsigned long tce_alloc_start, tce_alloc_end; 395 extern unsigned long tce_alloc_start, tce_alloc_end;
186 396
187 DBG(" -> htab_initialize()\n"); 397 DBG(" -> htab_initialize()\n");
188 398
399 /* Initialize page sizes */
400 htab_init_page_sizes();
401
189 /* 402 /*
190 * Calculate the required size of the htab. We want the number of 403 * Calculate the required size of the htab. We want the number of
191 * PTEGs to equal one half the number of real pages. 404 * PTEGs to equal one half the number of real pages.
192 */ 405 */
193 htab_size_bytes = get_hashtable_size(); 406 htab_size_bytes = htab_get_table_size();
194 pteg_count = htab_size_bytes >> 7; 407 pteg_count = htab_size_bytes >> 7;
195 408
196 htab_hash_mask = pteg_count - 1; 409 htab_hash_mask = pteg_count - 1;
@@ -204,14 +417,11 @@ void __init htab_initialize(void)
204 * the absolute address space. 417 * the absolute address space.
205 */ 418 */
206 table = lmb_alloc(htab_size_bytes, htab_size_bytes); 419 table = lmb_alloc(htab_size_bytes, htab_size_bytes);
420 BUG_ON(table == 0);
207 421
208 DBG("Hash table allocated at %lx, size: %lx\n", table, 422 DBG("Hash table allocated at %lx, size: %lx\n", table,
209 htab_size_bytes); 423 htab_size_bytes);
210 424
211 if ( !table ) {
212 ppc64_terminate_msg(0x20, "hpt space");
213 loop_forever();
214 }
215 htab_address = abs_to_virt(table); 425 htab_address = abs_to_virt(table);
216 426
217 /* htab absolute addr + encoded htabsize */ 427 /* htab absolute addr + encoded htabsize */
@@ -227,8 +437,6 @@ void __init htab_initialize(void)
227 * _NOT_ map it to avoid cache paradoxes as it's remapped non 437 * _NOT_ map it to avoid cache paradoxes as it's remapped non
228 * cacheable later on 438 * cacheable later on
229 */ 439 */
230 if (cpu_has_feature(CPU_FTR_16M_PAGE))
231 use_largepages = 1;
232 440
233 /* create bolted the linear mapping in the hash table */ 441 /* create bolted the linear mapping in the hash table */
234 for (i=0; i < lmb.memory.cnt; i++) { 442 for (i=0; i < lmb.memory.cnt; i++) {
@@ -239,27 +447,32 @@ void __init htab_initialize(void)
239 447
240#ifdef CONFIG_U3_DART 448#ifdef CONFIG_U3_DART
241 /* Do not map the DART space. Fortunately, it will be aligned 449 /* Do not map the DART space. Fortunately, it will be aligned
242 * in such a way that it will not cross two lmb regions and will 450 * in such a way that it will not cross two lmb regions and
243 * fit within a single 16Mb page. 451 * will fit within a single 16Mb page.
244 * The DART space is assumed to be a full 16Mb region even if we 452 * The DART space is assumed to be a full 16Mb region even if
245 * only use 2Mb of that space. We will use more of it later for 453 * we only use 2Mb of that space. We will use more of it later
246 * AGP GART. We have to use a full 16Mb large page. 454 * for AGP GART. We have to use a full 16Mb large page.
247 */ 455 */
248 DBG("DART base: %lx\n", dart_tablebase); 456 DBG("DART base: %lx\n", dart_tablebase);
249 457
250 if (dart_tablebase != 0 && dart_tablebase >= base 458 if (dart_tablebase != 0 && dart_tablebase >= base
251 && dart_tablebase < (base + size)) { 459 && dart_tablebase < (base + size)) {
252 if (base != dart_tablebase) 460 if (base != dart_tablebase)
253 create_pte_mapping(base, dart_tablebase, mode_rw, 461 BUG_ON(htab_bolt_mapping(base, dart_tablebase,
254 use_largepages); 462 base, mode_rw,
463 mmu_linear_psize));
255 if ((base + size) > (dart_tablebase + 16*MB)) 464 if ((base + size) > (dart_tablebase + 16*MB))
256 create_pte_mapping(dart_tablebase + 16*MB, base + size, 465 BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB,
257 mode_rw, use_largepages); 466 base + size,
467 dart_tablebase+16*MB,
468 mode_rw,
469 mmu_linear_psize));
258 continue; 470 continue;
259 } 471 }
260#endif /* CONFIG_U3_DART */ 472#endif /* CONFIG_U3_DART */
261 create_pte_mapping(base, base + size, mode_rw, use_largepages); 473 BUG_ON(htab_bolt_mapping(base, base + size, base,
262 } 474 mode_rw, mmu_linear_psize));
475 }
263 476
264 /* 477 /*
265 * If we have a memory_limit and we've allocated TCEs then we need to 478 * If we have a memory_limit and we've allocated TCEs then we need to
@@ -275,8 +488,9 @@ void __init htab_initialize(void)
275 if (base + size >= tce_alloc_start) 488 if (base + size >= tce_alloc_start)
276 tce_alloc_start = base + size + 1; 489 tce_alloc_start = base + size + 1;
277 490
278 create_pte_mapping(tce_alloc_start, tce_alloc_end, 491 BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end,
279 mode_rw, use_largepages); 492 tce_alloc_start, mode_rw,
493 mmu_linear_psize));
280 } 494 }
281 495
282 DBG(" <- htab_initialize()\n"); 496 DBG(" <- htab_initialize()\n");
@@ -291,9 +505,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
291{ 505{
292 struct page *page; 506 struct page *page;
293 507
294 if (!pfn_valid(pte_pfn(pte)))
295 return pp;
296
297 page = pte_page(pte); 508 page = pte_page(pte);
298 509
299 /* page is dirty */ 510 /* page is dirty */
@@ -302,7 +513,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
302 __flush_dcache_icache(page_address(page)); 513 __flush_dcache_icache(page_address(page));
303 set_bit(PG_arch_1, &page->flags); 514 set_bit(PG_arch_1, &page->flags);
304 } else 515 } else
305 pp |= HW_NO_EXEC; 516 pp |= HPTE_R_N;
306 } 517 }
307 return pp; 518 return pp;
308} 519}
@@ -318,94 +529,169 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
318 unsigned long vsid; 529 unsigned long vsid;
319 struct mm_struct *mm; 530 struct mm_struct *mm;
320 pte_t *ptep; 531 pte_t *ptep;
321 int ret;
322 int user_region = 0;
323 int local = 0;
324 cpumask_t tmp; 532 cpumask_t tmp;
533 int rc, user_region = 0, local = 0;
325 534
326 if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) 535 DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
327 return 1; 536 ea, access, trap);
328 537
538 if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) {
539 DBG_LOW(" out of pgtable range !\n");
540 return 1;
541 }
542
543 /* Get region & vsid */
329 switch (REGION_ID(ea)) { 544 switch (REGION_ID(ea)) {
330 case USER_REGION_ID: 545 case USER_REGION_ID:
331 user_region = 1; 546 user_region = 1;
332 mm = current->mm; 547 mm = current->mm;
333 if (! mm) 548 if (! mm) {
549 DBG_LOW(" user region with no mm !\n");
334 return 1; 550 return 1;
335 551 }
336 vsid = get_vsid(mm->context.id, ea); 552 vsid = get_vsid(mm->context.id, ea);
337 break; 553 break;
338 case VMALLOC_REGION_ID: 554 case VMALLOC_REGION_ID:
339 mm = &init_mm; 555 mm = &init_mm;
340 vsid = get_kernel_vsid(ea); 556 vsid = get_kernel_vsid(ea);
341 break; 557 break;
342#if 0
343 case KERNEL_REGION_ID:
344 /*
345 * Should never get here - entire 0xC0... region is bolted.
346 * Send the problem up to do_page_fault
347 */
348#endif
349 default: 558 default:
350 /* Not a valid range 559 /* Not a valid range
351 * Send the problem up to do_page_fault 560 * Send the problem up to do_page_fault
352 */ 561 */
353 return 1; 562 return 1;
354 break;
355 } 563 }
564 DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
356 565
566 /* Get pgdir */
357 pgdir = mm->pgd; 567 pgdir = mm->pgd;
358
359 if (pgdir == NULL) 568 if (pgdir == NULL)
360 return 1; 569 return 1;
361 570
571 /* Check CPU locality */
362 tmp = cpumask_of_cpu(smp_processor_id()); 572 tmp = cpumask_of_cpu(smp_processor_id());
363 if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) 573 if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
364 local = 1; 574 local = 1;
365 575
366 /* Is this a huge page ? */ 576 /* Handle hugepage regions */
367 if (unlikely(in_hugepage_area(mm->context, ea))) 577 if (unlikely(in_hugepage_area(mm->context, ea))) {
368 ret = hash_huge_page(mm, access, ea, vsid, local); 578 DBG_LOW(" -> huge page !\n");
369 else { 579 return hash_huge_page(mm, access, ea, vsid, local);
370 ptep = find_linux_pte(pgdir, ea); 580 }
371 if (ptep == NULL) 581
372 return 1; 582 /* Get PTE and page size from page tables */
373 ret = __hash_page(ea, access, vsid, ptep, trap, local); 583 ptep = find_linux_pte(pgdir, ea);
584 if (ptep == NULL || !pte_present(*ptep)) {
585 DBG_LOW(" no PTE !\n");
586 return 1;
587 }
588
589#ifndef CONFIG_PPC_64K_PAGES
590 DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep));
591#else
592 DBG_LOW(" i-pte: %016lx %016lx\n", pte_val(*ptep),
593 pte_val(*(ptep + PTRS_PER_PTE)));
594#endif
595 /* Pre-check access permissions (will be re-checked atomically
596 * in __hash_page_XX but this pre-check is a fast path
597 */
598 if (access & ~pte_val(*ptep)) {
599 DBG_LOW(" no access !\n");
600 return 1;
374 } 601 }
375 602
376 return ret; 603 /* Do actual hashing */
604#ifndef CONFIG_PPC_64K_PAGES
605 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
606#else
607 if (mmu_virtual_psize == MMU_PAGE_64K)
608 rc = __hash_page_64K(ea, access, vsid, ptep, trap, local);
609 else
610 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
611#endif /* CONFIG_PPC_64K_PAGES */
612
613#ifndef CONFIG_PPC_64K_PAGES
614 DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep));
615#else
616 DBG_LOW(" o-pte: %016lx %016lx\n", pte_val(*ptep),
617 pte_val(*(ptep + PTRS_PER_PTE)));
618#endif
619 DBG_LOW(" -> rc=%d\n", rc);
620 return rc;
377} 621}
378 622
379void flush_hash_page(unsigned long va, pte_t pte, int local) 623void hash_preload(struct mm_struct *mm, unsigned long ea,
624 unsigned long access, unsigned long trap)
380{ 625{
381 unsigned long vpn, hash, secondary, slot; 626 unsigned long vsid;
382 unsigned long huge = pte_huge(pte); 627 void *pgdir;
628 pte_t *ptep;
629 cpumask_t mask;
630 unsigned long flags;
631 int local = 0;
632
633 /* We don't want huge pages prefaulted for now
634 */
635 if (unlikely(in_hugepage_area(mm->context, ea)))
636 return;
637
638 DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx,"
639 " trap=%lx\n", mm, mm->pgd, ea, access, trap);
383 640
384 if (huge) 641 /* Get PTE, VSID, access mask */
385 vpn = va >> HPAGE_SHIFT; 642 pgdir = mm->pgd;
643 if (pgdir == NULL)
644 return;
645 ptep = find_linux_pte(pgdir, ea);
646 if (!ptep)
647 return;
648 vsid = get_vsid(mm->context.id, ea);
649
650 /* Hash it in */
651 local_irq_save(flags);
652 mask = cpumask_of_cpu(smp_processor_id());
653 if (cpus_equal(mm->cpu_vm_mask, mask))
654 local = 1;
655#ifndef CONFIG_PPC_64K_PAGES
656 __hash_page_4K(ea, access, vsid, ptep, trap, local);
657#else
658 if (mmu_virtual_psize == MMU_PAGE_64K)
659 __hash_page_64K(ea, access, vsid, ptep, trap, local);
386 else 660 else
387 vpn = va >> PAGE_SHIFT; 661 __hash_page_4K(ea, access, vsid, ptep, trap, local);
388 hash = hpt_hash(vpn, huge); 662#endif /* CONFIG_PPC_64K_PAGES */
389 secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15; 663 local_irq_restore(flags);
390 if (secondary) 664}
391 hash = ~hash; 665
392 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 666void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local)
393 slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12; 667{
394 668 unsigned long hash, index, shift, hidx, slot;
395 ppc_md.hpte_invalidate(slot, va, huge, local); 669
670 DBG_LOW("flush_hash_page(va=%016x)\n", va);
671 pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
672 hash = hpt_hash(va, shift);
673 hidx = __rpte_to_hidx(pte, index);
674 if (hidx & _PTEIDX_SECONDARY)
675 hash = ~hash;
676 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
677 slot += hidx & _PTEIDX_GROUP_IX;
678 DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx);
679 ppc_md.hpte_invalidate(slot, va, psize, local);
680 } pte_iterate_hashed_end();
396} 681}
397 682
398void flush_hash_range(unsigned long number, int local) 683void flush_hash_range(unsigned long number, int local)
399{ 684{
400 if (ppc_md.flush_hash_range) { 685 if (ppc_md.flush_hash_range)
401 ppc_md.flush_hash_range(number, local); 686 ppc_md.flush_hash_range(number, local);
402 } else { 687 else {
403 int i; 688 int i;
404 struct ppc64_tlb_batch *batch = 689 struct ppc64_tlb_batch *batch =
405 &__get_cpu_var(ppc64_tlb_batch); 690 &__get_cpu_var(ppc64_tlb_batch);
406 691
407 for (i = 0; i < number; i++) 692 for (i = 0; i < number; i++)
408 flush_hash_page(batch->vaddr[i], batch->pte[i], local); 693 flush_hash_page(batch->vaddr[i], batch->pte[i],
694 batch->psize, local);
409 } 695 }
410} 696}
411 697
@@ -445,6 +731,18 @@ void __init htab_finish_init(void)
445 extern unsigned int *htab_call_hpte_remove; 731 extern unsigned int *htab_call_hpte_remove;
446 extern unsigned int *htab_call_hpte_updatepp; 732 extern unsigned int *htab_call_hpte_updatepp;
447 733
734#ifdef CONFIG_PPC_64K_PAGES
735 extern unsigned int *ht64_call_hpte_insert1;
736 extern unsigned int *ht64_call_hpte_insert2;
737 extern unsigned int *ht64_call_hpte_remove;
738 extern unsigned int *ht64_call_hpte_updatepp;
739
740 make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert);
741 make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert);
742 make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove);
743 make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp);
744#endif /* CONFIG_PPC_64K_PAGES */
745
448 make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert); 746 make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
449 make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert); 747 make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
450 make_bl(htab_call_hpte_remove, ppc_md.hpte_remove); 748 make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);