]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/arm64/mm/mmu.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
[karo-tx-linux.git] / arch / arm64 / mm / mmu.c
index a8d1059b91b2d916f1baf60f137ac81279c9a038..f557ebbe7013edb71599570f0e4904a318b9dafc 100644 (file)
@@ -296,6 +296,7 @@ void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt)
 static void __init map_mem(void)
 {
        struct memblock_region *reg;
+       phys_addr_t limit;
 
        /*
         * Temporarily limit the memblock range. We need to do this as
@@ -303,9 +304,11 @@ static void __init map_mem(void)
         * memory addressable from the initial direct kernel mapping.
         *
         * The initial direct kernel mapping, located at swapper_pg_dir,
-        * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (aligned).
+        * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (which must be
+        * aligned to 2MB as per Documentation/arm64/booting.txt).
         */
-       memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
+       limit = PHYS_OFFSET + PGDIR_SIZE;
+       memblock_set_current_limit(limit);
 
        /* map all the memory banks */
        for_each_memblock(memory, reg) {
@@ -315,6 +318,22 @@ static void __init map_mem(void)
                if (start >= end)
                        break;
 
+#ifndef CONFIG_ARM64_64K_PAGES
+               /*
+                * For the first memory bank align the start address and
+                * current memblock limit to prevent create_mapping() from
+                * allocating pte page tables from unmapped memory.
+                * When 64K pages are enabled, the pte page table for the
+                * first PGDIR_SIZE is already present in swapper_pg_dir.
+                */
+               if (start < limit)
+                       start = ALIGN(start, PMD_SIZE);
+               if (end < limit) {
+                       limit = end & PMD_MASK;
+                       memblock_set_current_limit(limit);
+               }
+#endif
+
                create_mapping(start, __phys_to_virt(start), end - start);
        }