aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-01-13 10:00:51 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-01-13 10:02:35 -0500
commit716a3dc20084da9b3ab17bd125005a5345e23e3b (patch)
treef7ba487050d33fc2913fdee81b384f5578ccb105
parent4de3a8e101150feaefa1139611a50ff37467f33e (diff)
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 <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/memblock.h2
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c5
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c5
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c5
-rw-r--r--arch/arm/mach-omap2/Kconfig4
-rw-r--r--arch/arm/mach-omap2/omap-secure.c13
-rw-r--r--arch/arm/mach-omap2/omap4-common.c10
-rw-r--r--arch/arm/mm/init.c17
-rw-r--r--arch/arm/plat-omap/devices.c5
9 files changed, 34 insertions, 32 deletions
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;
6 6
7extern void arm_memblock_init(struct meminfo *, struct machine_desc *); 7extern void arm_memblock_init(struct meminfo *, struct machine_desc *);
8 8
9phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align);
10
9#endif 11#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 @@
36#include <asm/mach/time.h> 36#include <asm/mach/time.h>
37#include <asm/memory.h> 37#include <asm/memory.h>
38#include <asm/mach/map.h> 38#include <asm/mach/map.h>
39#include <asm/memblock.h>
39#include <mach/common.h> 40#include <mach/common.h>
40#include <mach/iomux-mx3.h> 41#include <mach/iomux-mx3.h>
41#include <mach/3ds_debugboard.h> 42#include <mach/3ds_debugboard.h>
@@ -754,10 +755,8 @@ static struct sys_timer mx31_3ds_timer = {
754static void __init mx31_3ds_reserve(void) 755static void __init mx31_3ds_reserve(void)
755{ 756{
756 /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */ 757 /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
757 mx3_camera_base = memblock_alloc(MX31_3DS_CAMERA_BUF_SIZE, 758 mx3_camera_base = arm_memblock_steal(MX31_3DS_CAMERA_BUF_SIZE,
758 MX31_3DS_CAMERA_BUF_SIZE); 759 MX31_3DS_CAMERA_BUF_SIZE);
759 memblock_free(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
760 memblock_remove(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
761} 760}
762 761
763MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") 762MACHINE_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 @@
41#include <asm/mach/arch.h> 41#include <asm/mach/arch.h>
42#include <asm/mach/time.h> 42#include <asm/mach/time.h>
43#include <asm/mach/map.h> 43#include <asm/mach/map.h>
44#include <asm/memblock.h>
44#include <mach/board-mx31moboard.h> 45#include <mach/board-mx31moboard.h>
45#include <mach/common.h> 46#include <mach/common.h>
46#include <mach/hardware.h> 47#include <mach/hardware.h>
@@ -584,10 +585,8 @@ struct sys_timer mx31moboard_timer = {
584static void __init mx31moboard_reserve(void) 585static void __init mx31moboard_reserve(void)
585{ 586{
586 /* reserve 4 MiB for mx3-camera */ 587 /* reserve 4 MiB for mx3-camera */
587 mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE, 588 mx3_camera_base = arm_memblock_steal(MX3_CAMERA_BUF_SIZE,
588 MX3_CAMERA_BUF_SIZE); 589 MX3_CAMERA_BUF_SIZE);
589 memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
590 memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
591} 590}
592 591
593MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard") 592MACHINE_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 @@
39#include <asm/mach/arch.h> 39#include <asm/mach/arch.h>
40#include <asm/mach/time.h> 40#include <asm/mach/time.h>
41#include <asm/mach/map.h> 41#include <asm/mach/map.h>
42#include <asm/memblock.h>
42#include <mach/common.h> 43#include <mach/common.h>
43#include <mach/hardware.h> 44#include <mach/hardware.h>
44#include <mach/iomux-mx3.h> 45#include <mach/iomux-mx3.h>
@@ -680,10 +681,8 @@ struct sys_timer pcm037_timer = {
680static void __init pcm037_reserve(void) 681static void __init pcm037_reserve(void)
681{ 682{
682 /* reserve 4 MiB for mx3-camera */ 683 /* reserve 4 MiB for mx3-camera */
683 mx3_camera_base = memblock_alloc(MX3_CAMERA_BUF_SIZE, 684 mx3_camera_base = arm_memblock_steal(MX3_CAMERA_BUF_SIZE,
684 MX3_CAMERA_BUF_SIZE); 685 MX3_CAMERA_BUF_SIZE);
685 memblock_free(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
686 memblock_remove(mx3_camera_base, MX3_CAMERA_BUF_SIZE);
687} 686}
688 687
689MACHINE_START(PCM037, "Phytec Phycore pcm037") 688MACHINE_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
366 going on could result in system crashes; 366 going on could result in system crashes;
367 367
368config OMAP4_ERRATA_I688 368config OMAP4_ERRATA_I688
369 bool "OMAP4 errata: Async Bridge Corruption" 369 bool "OMAP4 errata: Async Bridge Corruption (BROKEN)"
370 depends on ARCH_OMAP4 370 depends on ARCH_OMAP4 && BROKEN
371 select ARCH_HAS_BARRIERS 371 select ARCH_HAS_BARRIERS
372 help 372 help
373 If a data is stalled inside asynchronous bridge because of back 373 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 @@
16#include <linux/memblock.h> 16#include <linux/memblock.h>
17 17
18#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
19#include <asm/memblock.h>
19 20
20#include <mach/omap-secure.h> 21#include <mach/omap-secure.h>
21 22
@@ -57,20 +58,10 @@ u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2,
57/* Allocate the memory to save secure ram */ 58/* Allocate the memory to save secure ram */
58int __init omap_secure_ram_reserve_memblock(void) 59int __init omap_secure_ram_reserve_memblock(void)
59{ 60{
60 phys_addr_t paddr;
61 u32 size = OMAP_SECURE_RAM_STORAGE; 61 u32 size = OMAP_SECURE_RAM_STORAGE;
62 62
63 size = ALIGN(size, SZ_1M); 63 size = ALIGN(size, SZ_1M);
64 paddr = memblock_alloc(size, SZ_1M); 64 omap_secure_memblock_base = arm_memblock_steal(size, SZ_1M);
65 if (!paddr) {
66 pr_err("%s: failed to reserve %x bytes\n",
67 __func__, size);
68 return -ENOMEM;
69 }
70 memblock_free(paddr, size);
71 memblock_remove(paddr, size);
72
73 omap_secure_memblock_base = paddr;
74 65
75 return 0; 66 return 0;
76} 67}
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 @@
20#include <asm/hardware/gic.h> 20#include <asm/hardware/gic.h>
21#include <asm/hardware/cache-l2x0.h> 21#include <asm/hardware/cache-l2x0.h>
22#include <asm/mach/map.h> 22#include <asm/mach/map.h>
23#include <asm/memblock.h>
23 24
24#include <plat/irqs.h> 25#include <plat/irqs.h>
25#include <plat/sram.h> 26#include <plat/sram.h>
@@ -61,13 +62,8 @@ static int __init omap_barriers_init(void)
61 return -ENODEV; 62 return -ENODEV;
62 63
63 size = ALIGN(PAGE_SIZE, SZ_1M); 64 size = ALIGN(PAGE_SIZE, SZ_1M);
64 paddr = memblock_alloc(size, SZ_1M); 65 paddr = arm_memblock_steal(size, SZ_1M);
65 if (!paddr) { 66
66 pr_err("%s: failed to reserve 4 Kbytes\n", __func__);
67 return -ENOMEM;
68 }
69 memblock_free(paddr, size);
70 memblock_remove(paddr, size);
71 dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA; 67 dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
72 dram_io_desc[0].pfn = __phys_to_pfn(paddr); 68 dram_io_desc[0].pfn = __phys_to_pfn(paddr);
73 dram_io_desc[0].length = size; 69 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 @@
22#include <linux/memblock.h> 22#include <linux/memblock.h>
23 23
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25#include <asm/memblock.h>
25#include <asm/prom.h> 26#include <asm/prom.h>
26#include <asm/sections.h> 27#include <asm/sections.h>
27#include <asm/setup.h> 28#include <asm/setup.h>
@@ -307,6 +308,21 @@ static void arm_memory_present(void)
307} 308}
308#endif 309#endif
309 310
311static bool arm_memblock_steal_permitted = true;
312
313phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
314{
315 phys_addr_t phys;
316
317 BUG_ON(!arm_memblock_steal_permitted);
318
319 phys = memblock_alloc(size, align);
320 memblock_free(phys, size);
321 memblock_remove(phys, size);
322
323 return phys;
324}
325
310void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) 326void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
311{ 327{
312 int i; 328 int i;
@@ -349,6 +365,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
349 if (mdesc->reserve) 365 if (mdesc->reserve)
350 mdesc->reserve(); 366 mdesc->reserve();
351 367
368 arm_memblock_steal_permitted = false;
352 memblock_allow_resize(); 369 memblock_allow_resize();
353 memblock_dump_all(); 370 memblock_dump_all();
354} 371}
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 @@
20#include <mach/hardware.h> 20#include <mach/hardware.h>
21#include <asm/mach-types.h> 21#include <asm/mach-types.h>
22#include <asm/mach/map.h> 22#include <asm/mach/map.h>
23#include <asm/memblock.h>
23 24
24#include <plat/tc.h> 25#include <plat/tc.h>
25#include <plat/board.h> 26#include <plat/board.h>
@@ -164,14 +165,12 @@ void __init omap_dsp_reserve_sdram_memblock(void)
164 if (!size) 165 if (!size)
165 return; 166 return;
166 167
167 paddr = memblock_alloc(size, SZ_1M); 168 paddr = arm_memblock_steal(size, SZ_1M);
168 if (!paddr) { 169 if (!paddr) {
169 pr_err("%s: failed to reserve %x bytes\n", 170 pr_err("%s: failed to reserve %x bytes\n",
170 __func__, size); 171 __func__, size);
171 return; 172 return;
172 } 173 }
173 memblock_free(paddr, size);
174 memblock_remove(paddr, size);
175 174
176 omap_dsp_phys_mempool_base = paddr; 175 omap_dsp_phys_mempool_base = paddr;
177} 176}