diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-11-28 10:39:02 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-11-28 10:39:02 -0500 |
commit | 7ef4de17cc55a3c3b8d093743b1e3b845d8eba47 (patch) | |
tree | adf87c996affbb6c42850d55cb34c0e5a2f6d340 /arch/arm/mm/mmu.c | |
parent | f412b09f4ed7c57f5b8935ed7d6fc786f402a629 (diff) | |
parent | b5ee9002583fc14e6d45a04c18f208987a8fbced (diff) |
Merge branch 'highmem' into devel
Conflicts:
arch/arm/mach-clps7500/include/mach/memory.h
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r-- | arch/arm/mm/mmu.c | 114 |
1 files changed, 66 insertions, 48 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index f24803c1fb0b..c0b9a78d7b87 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -646,61 +646,79 @@ static void __init early_vmalloc(char **arg) | |||
646 | "vmalloc area too small, limiting to %luMB\n", | 646 | "vmalloc area too small, limiting to %luMB\n", |
647 | vmalloc_reserve >> 20); | 647 | vmalloc_reserve >> 20); |
648 | } | 648 | } |
649 | |||
650 | if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { | ||
651 | vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); | ||
652 | printk(KERN_WARNING | ||
653 | "vmalloc area is too big, limiting to %luMB\n", | ||
654 | vmalloc_reserve >> 20); | ||
655 | } | ||
649 | } | 656 | } |
650 | __early_param("vmalloc=", early_vmalloc); | 657 | __early_param("vmalloc=", early_vmalloc); |
651 | 658 | ||
652 | #define VMALLOC_MIN (void *)(VMALLOC_END - vmalloc_reserve) | 659 | #define VMALLOC_MIN (void *)(VMALLOC_END - vmalloc_reserve) |
653 | 660 | ||
654 | static int __init check_membank_valid(struct membank *mb) | 661 | static void __init sanity_check_meminfo(void) |
655 | { | 662 | { |
656 | /* | 663 | int i, j; |
657 | * Check whether this memory region has non-zero size or | ||
658 | * invalid node number. | ||
659 | */ | ||
660 | if (mb->size == 0 || mb->node >= MAX_NUMNODES) | ||
661 | return 0; | ||
662 | |||
663 | /* | ||
664 | * Check whether this memory region would entirely overlap | ||
665 | * the vmalloc area. | ||
666 | */ | ||
667 | if (phys_to_virt(mb->start) >= VMALLOC_MIN) { | ||
668 | printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " | ||
669 | "(vmalloc region overlap).\n", | ||
670 | mb->start, mb->start + mb->size - 1); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * Check whether this memory region would partially overlap | ||
676 | * the vmalloc area. | ||
677 | */ | ||
678 | if (phys_to_virt(mb->start + mb->size) < phys_to_virt(mb->start) || | ||
679 | phys_to_virt(mb->start + mb->size) > VMALLOC_MIN) { | ||
680 | unsigned long newsize = VMALLOC_MIN - phys_to_virt(mb->start); | ||
681 | |||
682 | printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx " | ||
683 | "to -%.8lx (vmalloc region overlap).\n", | ||
684 | mb->start, mb->start + mb->size - 1, | ||
685 | mb->start + newsize - 1); | ||
686 | mb->size = newsize; | ||
687 | } | ||
688 | 664 | ||
689 | return 1; | 665 | for (i = 0, j = 0; i < meminfo.nr_banks; i++) { |
690 | } | 666 | struct membank *bank = &meminfo.bank[j]; |
667 | *bank = meminfo.bank[i]; | ||
691 | 668 | ||
692 | static void __init sanity_check_meminfo(struct meminfo *mi) | 669 | #ifdef CONFIG_HIGHMEM |
693 | { | 670 | /* |
694 | int i, j; | 671 | * Split those memory banks which are partially overlapping |
672 | * the vmalloc area greatly simplifying things later. | ||
673 | */ | ||
674 | if (__va(bank->start) < VMALLOC_MIN && | ||
675 | bank->size > VMALLOC_MIN - __va(bank->start)) { | ||
676 | if (meminfo.nr_banks >= NR_BANKS) { | ||
677 | printk(KERN_CRIT "NR_BANKS too low, " | ||
678 | "ignoring high memory\n"); | ||
679 | } else { | ||
680 | memmove(bank + 1, bank, | ||
681 | (meminfo.nr_banks - i) * sizeof(*bank)); | ||
682 | meminfo.nr_banks++; | ||
683 | i++; | ||
684 | bank[1].size -= VMALLOC_MIN - __va(bank->start); | ||
685 | bank[1].start = __pa(VMALLOC_MIN - 1) + 1; | ||
686 | j++; | ||
687 | } | ||
688 | bank->size = VMALLOC_MIN - __va(bank->start); | ||
689 | } | ||
690 | #else | ||
691 | /* | ||
692 | * Check whether this memory bank would entirely overlap | ||
693 | * the vmalloc area. | ||
694 | */ | ||
695 | if (__va(bank->start) >= VMALLOC_MIN) { | ||
696 | printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx " | ||
697 | "(vmalloc region overlap).\n", | ||
698 | bank->start, bank->start + bank->size - 1); | ||
699 | continue; | ||
700 | } | ||
695 | 701 | ||
696 | for (i = 0, j = 0; i < mi->nr_banks; i++) { | 702 | /* |
697 | if (check_membank_valid(&mi->bank[i])) | 703 | * Check whether this memory bank would partially overlap |
698 | mi->bank[j++] = mi->bank[i]; | 704 | * the vmalloc area. |
705 | */ | ||
706 | if (__va(bank->start + bank->size) > VMALLOC_MIN || | ||
707 | __va(bank->start + bank->size) < __va(bank->start)) { | ||
708 | unsigned long newsize = VMALLOC_MIN - __va(bank->start); | ||
709 | printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx " | ||
710 | "to -%.8lx (vmalloc region overlap).\n", | ||
711 | bank->start, bank->start + bank->size - 1, | ||
712 | bank->start + newsize - 1); | ||
713 | bank->size = newsize; | ||
714 | } | ||
715 | #endif | ||
716 | j++; | ||
699 | } | 717 | } |
700 | mi->nr_banks = j; | 718 | meminfo.nr_banks = j; |
701 | } | 719 | } |
702 | 720 | ||
703 | static inline void prepare_page_table(struct meminfo *mi) | 721 | static inline void prepare_page_table(void) |
704 | { | 722 | { |
705 | unsigned long addr; | 723 | unsigned long addr; |
706 | 724 | ||
@@ -721,7 +739,7 @@ static inline void prepare_page_table(struct meminfo *mi) | |||
721 | * Clear out all the kernel space mappings, except for the first | 739 | * Clear out all the kernel space mappings, except for the first |
722 | * memory bank, up to the end of the vmalloc region. | 740 | * memory bank, up to the end of the vmalloc region. |
723 | */ | 741 | */ |
724 | for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size); | 742 | for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0])); |
725 | addr < VMALLOC_END; addr += PGDIR_SIZE) | 743 | addr < VMALLOC_END; addr += PGDIR_SIZE) |
726 | pmd_clear(pmd_off_k(addr)); | 744 | pmd_clear(pmd_off_k(addr)); |
727 | } | 745 | } |
@@ -880,14 +898,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
880 | * paging_init() sets up the page tables, initialises the zone memory | 898 | * paging_init() sets up the page tables, initialises the zone memory |
881 | * maps, and sets up the zero page, bad page and bad page tables. | 899 | * maps, and sets up the zero page, bad page and bad page tables. |
882 | */ | 900 | */ |
883 | void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) | 901 | void __init paging_init(struct machine_desc *mdesc) |
884 | { | 902 | { |
885 | void *zero_page; | 903 | void *zero_page; |
886 | 904 | ||
887 | build_mem_type_table(); | 905 | build_mem_type_table(); |
888 | sanity_check_meminfo(mi); | 906 | sanity_check_meminfo(); |
889 | prepare_page_table(mi); | 907 | prepare_page_table(); |
890 | bootmem_init(mi); | 908 | bootmem_init(); |
891 | devicemaps_init(mdesc); | 909 | devicemaps_init(mdesc); |
892 | 910 | ||
893 | top_pmd = pmd_off_k(0xffff0000); | 911 | top_pmd = pmd_off_k(0xffff0000); |