aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/mm/init.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index aaf9a3eee997..141d4cc5fc53 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -310,6 +310,7 @@ struct linux_prom_translation {
310 unsigned long size; 310 unsigned long size;
311 unsigned long data; 311 unsigned long data;
312}; 312};
313static struct linux_prom_translation prom_trans[512] __initdata;
313 314
314extern unsigned long prom_boot_page; 315extern unsigned long prom_boot_page;
315extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); 316extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
@@ -363,7 +364,6 @@ unsigned long prom_virt_to_phys(unsigned long promva, int *error)
363 364
364static void inherit_prom_mappings(void) 365static void inherit_prom_mappings(void)
365{ 366{
366 struct linux_prom_translation *trans;
367 unsigned long phys_page, tte_vaddr, tte_data; 367 unsigned long phys_page, tte_vaddr, tte_data;
368 void (*remap_func)(unsigned long, unsigned long, int); 368 void (*remap_func)(unsigned long, unsigned long, int);
369 pmd_t *pmdp; 369 pmd_t *pmdp;
@@ -373,30 +373,27 @@ static void inherit_prom_mappings(void)
373 node = prom_finddevice("/virtual-memory"); 373 node = prom_finddevice("/virtual-memory");
374 n = prom_getproplen(node, "translations"); 374 n = prom_getproplen(node, "translations");
375 if (n == 0 || n == -1) { 375 if (n == 0 || n == -1) {
376 prom_printf("Couldn't get translation property\n"); 376 prom_printf("prom_mappings: Couldn't get size.\n");
377 prom_halt(); 377 prom_halt();
378 } 378 }
379 n += 5 * sizeof(struct linux_prom_translation); 379 n += 24 * sizeof(struct linux_prom_translation);
380 for (tsz = 1; tsz < n; tsz <<= 1) 380 if (n > sizeof(prom_trans)) {
381 /* empty */; 381 prom_printf("prom_mappings: prom_trans too small, "
382 trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base); 382 "need %Zd bytes\n", n);
383 if (trans == NULL) {
384 prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
385 prom_halt(); 383 prom_halt();
386 } 384 }
387 memset(trans, 0, tsz); 385 tsz = n;
388 386 if ((n = prom_getproperty(node, "translations",
389 if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) { 387 (char *)&prom_trans[0], tsz)) == -1) {
390 prom_printf("Couldn't get translation property\n"); 388 prom_printf("prom_mappings: Couldn't get property.\n");
391 prom_halt(); 389 prom_halt();
392 } 390 }
393 n = n / sizeof(*trans); 391 n = n / sizeof(struct linux_prom_translation);
394 392
395 /* 393 /* The obp translations are saved based on 8k pagesize, since obp
396 * The obp translations are saved based on 8k pagesize, since obp can 394 * can use a mixture of pagesizes. Misses to the 0xf0000000 ->
397 * use a mixture of pagesizes. Misses to the 0xf0000000 - 0x100000000, 395 * 0x100000000, ie obp range, are handled in entry.S and do not
398 * ie obp range, are handled in entry.S and do not use the vpte scheme 396 * use the vpte scheme (see rant: inherit_locked_prom_mappings).
399 * (see rant in inherit_locked_prom_mappings()).
400 */ 397 */
401#define OBP_PMD_SIZE 2048 398#define OBP_PMD_SIZE 2048
402 prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base); 399 prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base);
@@ -406,9 +403,9 @@ static void inherit_prom_mappings(void)
406 for (i = 0; i < n; i++) { 403 for (i = 0; i < n; i++) {
407 unsigned long vaddr; 404 unsigned long vaddr;
408 405
409 if (trans[i].virt >= LOW_OBP_ADDRESS && trans[i].virt < HI_OBP_ADDRESS) { 406 if (prom_trans[i].virt >= LOW_OBP_ADDRESS && prom_trans[i].virt < HI_OBP_ADDRESS) {
410 for (vaddr = trans[i].virt; 407 for (vaddr = prom_trans[i].virt;
411 ((vaddr < trans[i].virt + trans[i].size) && 408 ((vaddr < prom_trans[i].virt + prom_trans[i].size) &&
412 (vaddr < HI_OBP_ADDRESS)); 409 (vaddr < HI_OBP_ADDRESS));
413 vaddr += BASE_PAGE_SIZE) { 410 vaddr += BASE_PAGE_SIZE) {
414 unsigned long val; 411 unsigned long val;
@@ -426,7 +423,7 @@ static void inherit_prom_mappings(void)
426 ptep = (pte_t *)__pmd_page(*pmdp) + 423 ptep = (pte_t *)__pmd_page(*pmdp) +
427 ((vaddr >> 13) & 0x3ff); 424 ((vaddr >> 13) & 0x3ff);
428 425
429 val = trans[i].data; 426 val = prom_trans[i].data;
430 427
431 /* Clear diag TTE bits. */ 428 /* Clear diag TTE bits. */
432 if (tlb_type == spitfire) 429 if (tlb_type == spitfire)
@@ -434,7 +431,7 @@ static void inherit_prom_mappings(void)
434 431
435 set_pte_at(&init_mm, vaddr, 432 set_pte_at(&init_mm, vaddr,
436 ptep, __pte(val | _PAGE_MODIFIED)); 433 ptep, __pte(val | _PAGE_MODIFIED));
437 trans[i].data += BASE_PAGE_SIZE; 434 prom_trans[i].data += BASE_PAGE_SIZE;
438 } 435 }
439 } 436 }
440 } 437 }
@@ -571,15 +568,16 @@ static void inherit_prom_mappings(void)
571 } 568 }
572 569
573 /* Re-read translations property. */ 570 /* Re-read translations property. */
574 if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) { 571 if ((n = prom_getproperty(node, "translations",
575 prom_printf("Couldn't get translation property\n"); 572 (char *)&prom_trans[0], tsz)) == -1) {
573 prom_printf("prom_mappings: Can't reread prom_trans.\n");
576 prom_halt(); 574 prom_halt();
577 } 575 }
578 n = n / sizeof(*trans); 576 n = n / sizeof(struct linux_prom_translation);
579 577
580 for (i = 0; i < n; i++) { 578 for (i = 0; i < n; i++) {
581 unsigned long vaddr = trans[i].virt; 579 unsigned long vaddr = prom_trans[i].virt;
582 unsigned long size = trans[i].size; 580 unsigned long size = prom_trans[i].size;
583 581
584 if (vaddr < 0xf0000000UL) { 582 if (vaddr < 0xf0000000UL) {
585 unsigned long avoid_start = (unsigned long) KERNBASE; 583 unsigned long avoid_start = (unsigned long) KERNBASE;