ARM: Add arm_memblock_steal() to allocate memory away from the kernel
authorRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 13 Jan 2012 15:00:51 +0000 (15:00 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 13 Jan 2012 15:02:35 +0000 (15:02 +0000)
Several platforms are now using the memblock_alloc+memblock_free+
memblock_remove trick to obtain memory which won't be mapped in the
kernel's page tables.  Most platforms do this (correctly) in the
->reserve callback.  However, OMAP has started to call these functions
outside of this callback, and this is extremely unsafe - memory will
not be unmapped, and could well be given out after memblock is no
longer responsible for its management.

So, provide arm_memblock_steal() to perform this function, and ensure
that it panic()s if it is used inappropriately.  Convert everyone
over, including OMAP.

As a result, OMAP with OMAP4_ERRATA_I688 enabled will panic on boot
with this change.  Mark this option as BROKEN and make it depend on
BROKEN.  OMAP needs to be fixed, or 137d105d50 (ARM: OMAP4: Fix
errata i688 with MPU interconnect barriers.) reverted until such
time it can be fixed correctly.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/include/asm/memblock.h
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-pcm037.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/omap-secure.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mm/init.c
arch/arm/plat-omap/devices.c

index b8da2e415e4eb21a870cbb52333b5400a50ad163..00ca5f92648ea56616afe8bfbd4a25ff8f0b0e27 100644 (file)
@@ -6,4 +6,6 @@ struct machine_desc;
 
 extern void arm_memblock_init(struct meminfo *, struct machine_desc *);
 
+phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align);
+
 #endif
index 89c33258639f89a9b075a2f9bf6ca0bf41b7a0e8..4d1aab154400fb43e4e0de2ea38e49c932d278e0 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
 #include <mach/3ds_debugboard.h>
@@ -754,10 +755,8 @@ static struct sys_timer mx31_3ds_timer = {
 static void __init mx31_3ds_reserve(void)
 {
        /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
-       mx3_camera_base = memblock_alloc(MX31_3DS_CAMERA_BUF_SIZE,
+       mx3_camera_base = arm_memblock_steal(MX31_3DS_CAMERA_BUF_SIZE,
                                         MX31_3DS_CAMERA_BUF_SIZE);
-       memblock_free(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
-       memblock_remove(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
 }
 
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
index b95981dacb2bcef2ff8138b59d32f58d85d3a394..f225262b5c38551cb6ec424e01cb71139f9a551f 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 #include <mach/board-mx31moboard.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -584,10 +585,8 @@ struct sys_timer mx31moboard_timer = {
 static void __init mx31moboard_reserve(void)
 {
        /* reserve 4 MiB for mx3-camera */
-       mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE,
+       mx3_camera_base = arm_memblock_steal(MX3_CAMERA_BUF_SIZE,
                        MX3_CAMERA_BUF_SIZE);
-       memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
-       memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
 }
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
index d7e151669ed347591e1687de4c628156aa56820d..e48854b9d9907a7c76095b5531c3a9f63eb0db23 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
@@ -680,10 +681,8 @@ struct sys_timer pcm037_timer = {
 static void __init pcm037_reserve(void)
 {
        /* reserve 4 MiB for mx3-camera */
-       mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE,
+       mx3_camera_base = arm_memblock_steal(MX3_CAMERA_BUF_SIZE,
                        MX3_CAMERA_BUF_SIZE);
-       memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
-       memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
 }
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
index 904bd1dfcd2e26b194f24ebe62eee9a377a05016..a8ba7b96dcd1c3177b11e634e5e8e4608dc7a4d4 100644 (file)
@@ -366,8 +366,8 @@ config OMAP3_SDRC_AC_TIMING
          going on could result in system crashes;
 
 config OMAP4_ERRATA_I688
-       bool "OMAP4 errata: Async Bridge Corruption"
-       depends on ARCH_OMAP4
+       bool "OMAP4 errata: Async Bridge Corruption (BROKEN)"
+       depends on ARCH_OMAP4 && BROKEN
        select ARCH_HAS_BARRIERS
        help
          If a data is stalled inside asynchronous bridge because of back
index 69f3c72d959b61e6cefe7c62462fc30f05a0b15f..d8f8ef40290f4dc4c803e69ce87fe5111baed499 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/memblock.h>
 
 #include <asm/cacheflush.h>
+#include <asm/memblock.h>
 
 #include <mach/omap-secure.h>
 
@@ -57,20 +58,10 @@ u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
 /* Allocate the memory to save secure ram */
 int __init omap_secure_ram_reserve_memblock(void)
 {
-       phys_addr_t paddr;
        u32 size = OMAP_SECURE_RAM_STORAGE;
 
        size = ALIGN(size, SZ_1M);
-       paddr = memblock_alloc(size, SZ_1M);
-       if (!paddr) {
-               pr_err("%s: failed to reserve %x bytes\n",
-                               __func__, size);
-               return -ENOMEM;
-       }
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
-
-       omap_secure_memblock_base = paddr;
+       omap_secure_memblock_base = arm_memblock_steal(size, SZ_1M);
 
        return 0;
 }
index bc16c818c6b72e77ae276976c887b7a85647a9df..40a8fbc07e4b766717b35e8b69f88794c1335df7 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 
 #include <plat/irqs.h>
 #include <plat/sram.h>
@@ -61,13 +62,8 @@ static int __init omap_barriers_init(void)
                return -ENODEV;
 
        size = ALIGN(PAGE_SIZE, SZ_1M);
-       paddr = memblock_alloc(size, SZ_1M);
-       if (!paddr) {
-               pr_err("%s: failed to reserve 4 Kbytes\n", __func__);
-               return -ENOMEM;
-       }
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
+       paddr = arm_memblock_steal(size, SZ_1M);
+
        dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
        dram_io_desc[0].pfn = __phys_to_pfn(paddr);
        dram_io_desc[0].length = size;
index e34ea8adc1f928fe8ebeadc677aba06fbd8b4f47..6ec1226fc62d2fc58caa6c795614455c0f7e8ed7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/memblock.h>
 
 #include <asm/mach-types.h>
+#include <asm/memblock.h>
 #include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -307,6 +308,21 @@ static void arm_memory_present(void)
 }
 #endif
 
+static bool arm_memblock_steal_permitted = true;
+
+phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
+{
+       phys_addr_t phys;
+
+       BUG_ON(!arm_memblock_steal_permitted);
+
+       phys = memblock_alloc(size, align);
+       memblock_free(phys, size);
+       memblock_remove(phys, size);
+
+       return phys;
+}
+
 void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 {
        int i;
@@ -349,6 +365,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
        if (mdesc->reserve)
                mdesc->reserve();
 
+       arm_memblock_steal_permitted = false;
        memblock_allow_resize();
        memblock_dump_all();
 }
index 19719329a47b0fb96a4b75e42f8103f505c00c84..60278f47c0bdd71953cc5c1483a68a7a02a0b50f 100644 (file)
@@ -20,6 +20,7 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
+#include <asm/memblock.h>
 
 #include <plat/tc.h>
 #include <plat/board.h>
@@ -164,14 +165,12 @@ void __init omap_dsp_reserve_sdram_memblock(void)
        if (!size)
                return;
 
-       paddr = memblock_alloc(size, SZ_1M);
+       paddr = arm_memblock_steal(size, SZ_1M);
        if (!paddr) {
                pr_err("%s: failed to reserve %x bytes\n",
                                __func__, size);
                return;
        }
-       memblock_free(paddr, size);
-       memblock_remove(paddr, size);
 
        omap_dsp_phys_mempool_base = paddr;
 }