diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/mm/init.c | 54 |
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 | }; |
313 | static struct linux_prom_translation prom_trans[512] __initdata; | ||
313 | 314 | ||
314 | extern unsigned long prom_boot_page; | 315 | extern unsigned long prom_boot_page; |
315 | extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); | 316 | extern 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 | ||
364 | static void inherit_prom_mappings(void) | 365 | static 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; |