diff options
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r-- | arch/arm/mm/mmu.c | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index ff7b43b5885a..6cf76b3b68d1 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -533,7 +533,7 @@ static void __init *early_alloc(unsigned long sz) | |||
533 | static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) | 533 | static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) |
534 | { | 534 | { |
535 | if (pmd_none(*pmd)) { | 535 | if (pmd_none(*pmd)) { |
536 | pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); | 536 | pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE); |
537 | __pmd_populate(pmd, __pa(pte), prot); | 537 | __pmd_populate(pmd, __pa(pte), prot); |
538 | } | 538 | } |
539 | BUG_ON(pmd_bad(*pmd)); | 539 | BUG_ON(pmd_bad(*pmd)); |
@@ -551,11 +551,11 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
551 | } while (pte++, addr += PAGE_SIZE, addr != end); | 551 | } while (pte++, addr += PAGE_SIZE, addr != end); |
552 | } | 552 | } |
553 | 553 | ||
554 | static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | 554 | static void __init alloc_init_section(pud_t *pud, unsigned long addr, |
555 | unsigned long end, phys_addr_t phys, | 555 | unsigned long end, phys_addr_t phys, |
556 | const struct mem_type *type) | 556 | const struct mem_type *type) |
557 | { | 557 | { |
558 | pmd_t *pmd = pmd_offset(pgd, addr); | 558 | pmd_t *pmd = pmd_offset(pud, addr); |
559 | 559 | ||
560 | /* | 560 | /* |
561 | * Try a section mapping - end, addr and phys must all be aligned | 561 | * Try a section mapping - end, addr and phys must all be aligned |
@@ -584,6 +584,19 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | |||
584 | } | 584 | } |
585 | } | 585 | } |
586 | 586 | ||
587 | static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
588 | unsigned long phys, const struct mem_type *type) | ||
589 | { | ||
590 | pud_t *pud = pud_offset(pgd, addr); | ||
591 | unsigned long next; | ||
592 | |||
593 | do { | ||
594 | next = pud_addr_end(addr, end); | ||
595 | alloc_init_section(pud, addr, next, phys, type); | ||
596 | phys += next - addr; | ||
597 | } while (pud++, addr = next, addr != end); | ||
598 | } | ||
599 | |||
587 | static void __init create_36bit_mapping(struct map_desc *md, | 600 | static void __init create_36bit_mapping(struct map_desc *md, |
588 | const struct mem_type *type) | 601 | const struct mem_type *type) |
589 | { | 602 | { |
@@ -592,13 +605,13 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
592 | pgd_t *pgd; | 605 | pgd_t *pgd; |
593 | 606 | ||
594 | addr = md->virtual; | 607 | addr = md->virtual; |
595 | phys = (unsigned long)__pfn_to_phys(md->pfn); | 608 | phys = __pfn_to_phys(md->pfn); |
596 | length = PAGE_ALIGN(md->length); | 609 | length = PAGE_ALIGN(md->length); |
597 | 610 | ||
598 | if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { | 611 | if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { |
599 | printk(KERN_ERR "MM: CPU does not support supersection " | 612 | printk(KERN_ERR "MM: CPU does not support supersection " |
600 | "mapping for 0x%08llx at 0x%08lx\n", | 613 | "mapping for 0x%08llx at 0x%08lx\n", |
601 | __pfn_to_phys((u64)md->pfn), addr); | 614 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
602 | return; | 615 | return; |
603 | } | 616 | } |
604 | 617 | ||
@@ -611,14 +624,14 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
611 | if (type->domain) { | 624 | if (type->domain) { |
612 | printk(KERN_ERR "MM: invalid domain in supersection " | 625 | printk(KERN_ERR "MM: invalid domain in supersection " |
613 | "mapping for 0x%08llx at 0x%08lx\n", | 626 | "mapping for 0x%08llx at 0x%08lx\n", |
614 | __pfn_to_phys((u64)md->pfn), addr); | 627 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
615 | return; | 628 | return; |
616 | } | 629 | } |
617 | 630 | ||
618 | if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { | 631 | if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { |
619 | printk(KERN_ERR "MM: cannot create mapping for " | 632 | printk(KERN_ERR "MM: cannot create mapping for 0x%08llx" |
620 | "0x%08llx at 0x%08lx invalid alignment\n", | 633 | " at 0x%08lx invalid alignment\n", |
621 | __pfn_to_phys((u64)md->pfn), addr); | 634 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
622 | return; | 635 | return; |
623 | } | 636 | } |
624 | 637 | ||
@@ -631,7 +644,8 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
631 | pgd = pgd_offset_k(addr); | 644 | pgd = pgd_offset_k(addr); |
632 | end = addr + length; | 645 | end = addr + length; |
633 | do { | 646 | do { |
634 | pmd_t *pmd = pmd_offset(pgd, addr); | 647 | pud_t *pud = pud_offset(pgd, addr); |
648 | pmd_t *pmd = pmd_offset(pud, addr); | ||
635 | int i; | 649 | int i; |
636 | 650 | ||
637 | for (i = 0; i < 16; i++) | 651 | for (i = 0; i < 16; i++) |
@@ -652,22 +666,23 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
652 | */ | 666 | */ |
653 | static void __init create_mapping(struct map_desc *md) | 667 | static void __init create_mapping(struct map_desc *md) |
654 | { | 668 | { |
655 | unsigned long phys, addr, length, end; | 669 | unsigned long addr, length, end; |
670 | phys_addr_t phys; | ||
656 | const struct mem_type *type; | 671 | const struct mem_type *type; |
657 | pgd_t *pgd; | 672 | pgd_t *pgd; |
658 | 673 | ||
659 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { | 674 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { |
660 | printk(KERN_WARNING "BUG: not creating mapping for " | 675 | printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx" |
661 | "0x%08llx at 0x%08lx in user region\n", | 676 | " at 0x%08lx in user region\n", |
662 | __pfn_to_phys((u64)md->pfn), md->virtual); | 677 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); |
663 | return; | 678 | return; |
664 | } | 679 | } |
665 | 680 | ||
666 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && | 681 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && |
667 | md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { | 682 | md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { |
668 | printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx " | 683 | printk(KERN_WARNING "BUG: mapping for 0x%08llx" |
669 | "overlaps vmalloc space\n", | 684 | " at 0x%08lx overlaps vmalloc space\n", |
670 | __pfn_to_phys((u64)md->pfn), md->virtual); | 685 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); |
671 | } | 686 | } |
672 | 687 | ||
673 | type = &mem_types[md->type]; | 688 | type = &mem_types[md->type]; |
@@ -681,13 +696,13 @@ static void __init create_mapping(struct map_desc *md) | |||
681 | } | 696 | } |
682 | 697 | ||
683 | addr = md->virtual & PAGE_MASK; | 698 | addr = md->virtual & PAGE_MASK; |
684 | phys = (unsigned long)__pfn_to_phys(md->pfn); | 699 | phys = __pfn_to_phys(md->pfn); |
685 | length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); | 700 | length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); |
686 | 701 | ||
687 | if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { | 702 | if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { |
688 | printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not " | 703 | printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not " |
689 | "be mapped using pages, ignoring.\n", | 704 | "be mapped using pages, ignoring.\n", |
690 | __pfn_to_phys(md->pfn), addr); | 705 | (long long)__pfn_to_phys(md->pfn), addr); |
691 | return; | 706 | return; |
692 | } | 707 | } |
693 | 708 | ||
@@ -696,7 +711,7 @@ static void __init create_mapping(struct map_desc *md) | |||
696 | do { | 711 | do { |
697 | unsigned long next = pgd_addr_end(addr, end); | 712 | unsigned long next = pgd_addr_end(addr, end); |
698 | 713 | ||
699 | alloc_init_section(pgd, addr, next, phys, type); | 714 | alloc_init_pud(pgd, addr, next, phys, type); |
700 | 715 | ||
701 | phys += next - addr; | 716 | phys += next - addr; |
702 | addr = next; | 717 | addr = next; |
@@ -794,9 +809,10 @@ static void __init sanity_check_meminfo(void) | |||
794 | */ | 809 | */ |
795 | if (__va(bank->start) >= vmalloc_min || | 810 | if (__va(bank->start) >= vmalloc_min || |
796 | __va(bank->start) < (void *)PAGE_OFFSET) { | 811 | __va(bank->start) < (void *)PAGE_OFFSET) { |
797 | printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " | 812 | printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx " |
798 | "(vmalloc region overlap).\n", | 813 | "(vmalloc region overlap).\n", |
799 | bank->start, bank->start + bank->size - 1); | 814 | (unsigned long long)bank->start, |
815 | (unsigned long long)bank->start + bank->size - 1); | ||
800 | continue; | 816 | continue; |
801 | } | 817 | } |
802 | 818 | ||
@@ -807,10 +823,11 @@ static void __init sanity_check_meminfo(void) | |||
807 | if (__va(bank->start + bank->size) > vmalloc_min || | 823 | if (__va(bank->start + bank->size) > vmalloc_min || |
808 | __va(bank->start + bank->size) < __va(bank->start)) { | 824 | __va(bank->start + bank->size) < __va(bank->start)) { |
809 | unsigned long newsize = vmalloc_min - __va(bank->start); | 825 | unsigned long newsize = vmalloc_min - __va(bank->start); |
810 | printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx " | 826 | printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " |
811 | "to -%.8lx (vmalloc region overlap).\n", | 827 | "to -%.8llx (vmalloc region overlap).\n", |
812 | bank->start, bank->start + bank->size - 1, | 828 | (unsigned long long)bank->start, |
813 | bank->start + newsize - 1); | 829 | (unsigned long long)bank->start + bank->size - 1, |
830 | (unsigned long long)bank->start + newsize - 1); | ||
814 | bank->size = newsize; | 831 | bank->size = newsize; |
815 | } | 832 | } |
816 | #endif | 833 | #endif |