Merge tag 'v3.10.86' into linux-linaro-lsk-v3.10
[firefly-linux-kernel-4.4.55.git] / arch / arm64 / mm / init.c
index 52806427e15d2cd7ee8cf145cfb132a34b6030ef..67ad3c079ae6497ffbbc2593511da64c5e207765 100644 (file)
@@ -68,6 +68,17 @@ static int __init early_initrd(char *p)
 }
 early_param("initrd", early_initrd);
 
+/*
+ * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
+ * currently assumes that for memory starting above 4G, 32-bit devices will
+ * use a DMA offset.
+ */
+static phys_addr_t max_zone_dma_phys(void)
+{
+       phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
+       return min(offset + (1ULL << 32), memblock_end_of_DRAM());
+}
+
 static void __init zone_sizes_init(unsigned long min, unsigned long max)
 {
        struct memblock_region *reg;
@@ -78,9 +89,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 
        /* 4GB maximum for 32-bit only capable devices */
        if (IS_ENABLED(CONFIG_ZONE_DMA)) {
-               unsigned long max_dma_phys =
-                       (unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1);
-               max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT));
+               max_dma = PFN_DOWN(max_zone_dma_phys());
                zone_size[ZONE_DMA] = max_dma - min;
        }
        zone_size[ZONE_NORMAL] = max - max_dma;
@@ -132,9 +141,29 @@ static void arm64_memory_present(void)
 }
 #endif
 
+static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
+
+/*
+ * Limit the memory size that was specified via FDT.
+ */
+static int __init early_mem(char *p)
+{
+       if (!p)
+               return 1;
+
+       memory_limit = memparse(p, &p) & PAGE_MASK;
+       pr_notice("Memory limited to %lldMB\n", memory_limit >> 20);
+
+       return 0;
+}
+early_param("mem", early_mem);
+
 void __init arm64_memblock_init(void)
 {
        u64 *reserve_map, base, size;
+       phys_addr_t dma_phys_limit = 0;
+
+       memblock_enforce_memory_limit(memory_limit);
 
        /*
         * Register the kernel text, kernel data, initrd, and initial
@@ -170,7 +199,12 @@ void __init arm64_memblock_init(void)
                memblock_reserve(base, size);
        }
 
-       dma_contiguous_reserve(0);
+       early_init_fdt_scan_reserved_mem();
+
+       /* 4GB maximum for 32-bit only capable devices */
+       if (IS_ENABLED(CONFIG_ZONE_DMA))
+               dma_phys_limit = max_zone_dma_phys();
+       dma_contiguous_reserve(dma_phys_limit);
 
        memblock_allow_resize();
        memblock_dump_all();
@@ -261,7 +295,7 @@ static void __init free_unused_memmap(void)
                 * memmap entries are valid from the bank end aligned to
                 * MAX_ORDER_NR_PAGES.
                 */
-               prev_end = ALIGN(start + __phys_to_pfn(reg->size),
+               prev_end = ALIGN(__phys_to_pfn(reg->base + reg->size),
                                 MAX_ORDER_NR_PAGES);
        }