import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm64 / mm / mmu.c
index ba7477efad5ca60912476d0bd93ca2e776b49d20..a8fbe5387b386f68ee9e38f8116a5c2b4287a0d2 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/sizes.h>
 #include <asm/tlb.h>
 #include <asm/mmu_context.h>
+#include <mach/mtk_memcfg.h>
 
 #include "mm.h"
 
@@ -304,17 +305,59 @@ 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
+        * create_mapping requires puds, pmds and ptes to be allocated from
+        * memory addressable from the initial direct kernel mapping.
+        *
+        * The initial direct kernel mapping, located at swapper_pg_dir, gives
+        * us PUD_SIZE (4K pages) or PMD_SIZE (64K pages) memory starting from
+        * PHYS_OFFSET (which must be aligned to 2MB as per
+        * Documentation/arm64/booting.txt).
+        */
+       if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+               limit = PHYS_OFFSET + PMD_SIZE;
+       else
+               limit = PHYS_OFFSET + PUD_SIZE;
+       memblock_set_current_limit(limit);
 
        /* map all the memory banks */
        for_each_memblock(memory, reg) {
                phys_addr_t start = reg->base;
                phys_addr_t end = start + reg->size;
+               MTK_MEMCFG_LOG_AND_PRINTK(KERN_ALERT
+                       "[PHY layout]kernel   :   "
+                       "0x%08llx - 0x%08llx (0x%llx)\n",
+                       (unsigned long long)start, 
+                       (unsigned long long)start + reg->size - 1,
+                       (unsigned long long)reg->size);
 
                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);
        }
+
+       /* Limit no longer required. */
+       memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
 }
 
 /*
@@ -325,12 +368,6 @@ void __init paging_init(void)
 {
        void *zero_page;
 
-       /*
-        * Maximum PGDIR_SIZE addressable via the initial direct kernel
-        * mapping in swapper_pg_dir.
-        */
-       memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
-
        init_mem_pgprot();
        map_mem();