aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/mmu.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-10-27 14:57:38 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-10-28 08:54:45 -0400
commit8df6516864462cb7a6f87d5a46df68fb0faebbb5 (patch)
tree2db5634fa29b20bf6e64ce9446aef5a5e51b9c54 /arch/arm/mm/mmu.c
parentf25b4b4c89ff118df72421dd2cb080a6380896ac (diff)
ARM: memblock: setup lowmem mappings using memblock
Use memblock information to setup lowmem mappings rather than the membank array. This allows platforms to manipulate the memblock information during initialization to reserve (and remove) memory from the kernel's view of memory - and thus allowing platforms to setup their own private mappings for this memory without causing problems with multiple aliasing mappings: size = min(size, SZ_2M); base = memblock_alloc(size, min(align, SZ_2M)); memblock_free(base, size); memblock_remove(base, size); This is needed because multiple mappings of regions with differing attributes (sharability, type, cache) are not permitted with ARMv6 and above. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r--arch/arm/mm/mmu.c49
1 files changed, 29 insertions, 20 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 5222d3850960..72ad3e1f56cf 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -744,11 +744,14 @@ static int __init early_vmalloc(char *arg)
744} 744}
745early_param("vmalloc", early_vmalloc); 745early_param("vmalloc", early_vmalloc);
746 746
747static phys_addr_t lowmem_limit __initdata = 0;
748
747static void __init sanity_check_meminfo(void) 749static void __init sanity_check_meminfo(void)
748{ 750{
749 int i, j, highmem = 0; 751 int i, j, highmem = 0;
750 752
751 memblock_set_current_limit(__pa(vmalloc_min - 1) + 1); 753 lowmem_limit = __pa(vmalloc_min - 1) + 1;
754 memblock_set_current_limit(lowmem_limit);
752 755
753 for (i = 0, j = 0; i < meminfo.nr_banks; i++) { 756 for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
754 struct membank *bank = &meminfo.bank[j]; 757 struct membank *bank = &meminfo.bank[j];
@@ -849,6 +852,7 @@ static void __init sanity_check_meminfo(void)
849static inline void prepare_page_table(void) 852static inline void prepare_page_table(void)
850{ 853{
851 unsigned long addr; 854 unsigned long addr;
855 phys_addr_t end;
852 856
853 /* 857 /*
854 * Clear out all the mappings below the kernel image. 858 * Clear out all the mappings below the kernel image.
@@ -864,10 +868,17 @@ static inline void prepare_page_table(void)
864 pmd_clear(pmd_off_k(addr)); 868 pmd_clear(pmd_off_k(addr));
865 869
866 /* 870 /*
871 * Find the end of the first block of lowmem.
872 */
873 end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
874 if (end >= lowmem_limit)
875 end = lowmem_limit;
876
877 /*
867 * Clear out all the kernel space mappings, except for the first 878 * Clear out all the kernel space mappings, except for the first
868 * memory bank, up to the end of the vmalloc region. 879 * memory bank, up to the end of the vmalloc region.
869 */ 880 */
870 for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0])); 881 for (addr = __phys_to_virt(end);
871 addr < VMALLOC_END; addr += PGDIR_SIZE) 882 addr < VMALLOC_END; addr += PGDIR_SIZE)
872 pmd_clear(pmd_off_k(addr)); 883 pmd_clear(pmd_off_k(addr));
873} 884}
@@ -984,29 +995,27 @@ static void __init kmap_init(void)
984#endif 995#endif
985} 996}
986 997
987static inline void map_memory_bank(struct membank *bank)
988{
989 struct map_desc map;
990
991 map.pfn = bank_pfn_start(bank);
992 map.virtual = __phys_to_virt(bank_phys_start(bank));
993 map.length = bank_phys_size(bank);
994 map.type = MT_MEMORY;
995
996 create_mapping(&map);
997}
998
999static void __init map_lowmem(void) 998static void __init map_lowmem(void)
1000{ 999{
1001 struct meminfo *mi = &meminfo; 1000 struct memblock_region *reg;
1002 int i;
1003 1001
1004 /* Map all the lowmem memory banks. */ 1002 /* Map all the lowmem memory banks. */
1005 for (i = 0; i < mi->nr_banks; i++) { 1003 for_each_memblock(memory, reg) {
1006 struct membank *bank = &mi->bank[i]; 1004 phys_addr_t start = reg->base;
1005 phys_addr_t end = start + reg->size;
1006 struct map_desc map;
1007
1008 if (end > lowmem_limit)
1009 end = lowmem_limit;
1010 if (start >= end)
1011 break;
1012
1013 map.pfn = __phys_to_pfn(start);
1014 map.virtual = __phys_to_virt(start);
1015 map.length = end - start;
1016 map.type = MT_MEMORY;
1007 1017
1008 if (!bank->highmem) 1018 create_mapping(&map);
1009 map_memory_bank(bank);
1010 } 1019 }
1011} 1020}
1012 1021