From: Russell King Date: Fri, 13 Jan 2012 15:00:51 +0000 (+0000) Subject: ARM: Add arm_memblock_steal() to allocate memory away from the kernel X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=716a3dc2008;p=linux-beck.git ARM: Add arm_memblock_steal() to allocate memory away from the kernel 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 --- diff --git a/arch/arm/include/asm/memblock.h b/arch/arm/include/asm/memblock.h index b8da2e415e4e..00ca5f92648e 100644 --- a/arch/arm/include/asm/memblock.h +++ b/arch/arm/include/asm/memblock.h @@ -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 diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 89c33258639f..4d1aab154400 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -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)") diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index b95981dacb2b..f225262b5c38 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -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") diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index d7e151669ed3..e48854b9d990 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -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") diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 904bd1dfcd2e..a8ba7b96dcd1 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -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 diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c index 69f3c72d959b..d8f8ef40290f 100644 --- a/arch/arm/mach-omap2/omap-secure.c +++ b/arch/arm/mach-omap2/omap-secure.c @@ -16,6 +16,7 @@ #include #include +#include #include @@ -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; } diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index bc16c818c6b7..40a8fbc07e4b 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -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; diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index e34ea8adc1f9..6ec1226fc62d 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -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(); } diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 19719329a47b..60278f47c0bd 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -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; }