Commit 716a3dc20084da9b3ab17bd125005a5345e23e3b

Authored by Russell King
1 parent 4de3a8e101

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>

Showing 9 changed files with 34 additions and 32 deletions Side-by-side Diff

arch/arm/include/asm/memblock.h
... ... @@ -6,5 +6,7 @@
6 6  
7 7 extern void arm_memblock_init(struct meminfo *, struct machine_desc *);
8 8  
  9 +phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align);
  10 +
9 11 #endif
arch/arm/mach-imx/mach-mx31_3ds.c
... ... @@ -36,6 +36,7 @@
36 36 #include <asm/mach/time.h>
37 37 #include <asm/memory.h>
38 38 #include <asm/mach/map.h>
  39 +#include <asm/memblock.h>
39 40 #include <mach/common.h>
40 41 #include <mach/iomux-mx3.h>
41 42 #include <mach/3ds_debugboard.h>
42 43  
... ... @@ -754,10 +755,8 @@
754 755 static void __init mx31_3ds_reserve(void)
755 756 {
756 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 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  
763 762 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
arch/arm/mach-imx/mach-mx31moboard.c
... ... @@ -41,6 +41,7 @@
41 41 #include <asm/mach/arch.h>
42 42 #include <asm/mach/time.h>
43 43 #include <asm/mach/map.h>
  44 +#include <asm/memblock.h>
44 45 #include <mach/board-mx31moboard.h>
45 46 #include <mach/common.h>
46 47 #include <mach/hardware.h>
47 48  
... ... @@ -584,10 +585,8 @@
584 585 static void __init mx31moboard_reserve(void)
585 586 {
586 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 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  
593 592 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
arch/arm/mach-imx/mach-pcm037.c
... ... @@ -39,6 +39,7 @@
39 39 #include <asm/mach/arch.h>
40 40 #include <asm/mach/time.h>
41 41 #include <asm/mach/map.h>
  42 +#include <asm/memblock.h>
42 43 #include <mach/common.h>
43 44 #include <mach/hardware.h>
44 45 #include <mach/iomux-mx3.h>
45 46  
... ... @@ -680,10 +681,8 @@
680 681 static void __init pcm037_reserve(void)
681 682 {
682 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 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  
689 688 MACHINE_START(PCM037, "Phytec Phycore pcm037")
arch/arm/mach-omap2/Kconfig
... ... @@ -366,8 +366,8 @@
366 366 going on could result in system crashes;
367 367  
368 368 config OMAP4_ERRATA_I688
369   - bool "OMAP4 errata: Async Bridge Corruption"
370   - depends on ARCH_OMAP4
  369 + bool "OMAP4 errata: Async Bridge Corruption (BROKEN)"
  370 + depends on ARCH_OMAP4 && BROKEN
371 371 select ARCH_HAS_BARRIERS
372 372 help
373 373 If a data is stalled inside asynchronous bridge because of back
arch/arm/mach-omap2/omap-secure.c
... ... @@ -16,6 +16,7 @@
16 16 #include <linux/memblock.h>
17 17  
18 18 #include <asm/cacheflush.h>
  19 +#include <asm/memblock.h>
19 20  
20 21 #include <mach/omap-secure.h>
21 22  
22 23  
... ... @@ -57,20 +58,10 @@
57 58 /* Allocate the memory to save secure ram */
58 59 int __init omap_secure_ram_reserve_memblock(void)
59 60 {
60   - phys_addr_t paddr;
61 61 u32 size = OMAP_SECURE_RAM_STORAGE;
62 62  
63 63 size = ALIGN(size, SZ_1M);
64   - paddr = memblock_alloc(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;
  64 + omap_secure_memblock_base = arm_memblock_steal(size, SZ_1M);
74 65  
75 66 return 0;
76 67 }
arch/arm/mach-omap2/omap4-common.c
... ... @@ -20,6 +20,7 @@
20 20 #include <asm/hardware/gic.h>
21 21 #include <asm/hardware/cache-l2x0.h>
22 22 #include <asm/mach/map.h>
  23 +#include <asm/memblock.h>
23 24  
24 25 #include <plat/irqs.h>
25 26 #include <plat/sram.h>
... ... @@ -61,13 +62,8 @@
61 62 return -ENODEV;
62 63  
63 64 size = ALIGN(PAGE_SIZE, SZ_1M);
64   - paddr = memblock_alloc(size, SZ_1M);
65   - if (!paddr) {
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);
  65 + paddr = arm_memblock_steal(size, SZ_1M);
  66 +
71 67 dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
72 68 dram_io_desc[0].pfn = __phys_to_pfn(paddr);
73 69 dram_io_desc[0].length = size;
... ... @@ -22,6 +22,7 @@
22 22 #include <linux/memblock.h>
23 23  
24 24 #include <asm/mach-types.h>
  25 +#include <asm/memblock.h>
25 26 #include <asm/prom.h>
26 27 #include <asm/sections.h>
27 28 #include <asm/setup.h>
... ... @@ -307,6 +308,21 @@
307 308 }
308 309 #endif
309 310  
  311 +static bool arm_memblock_steal_permitted = true;
  312 +
  313 +phys_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 +
310 326 void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
311 327 {
312 328 int i;
... ... @@ -349,6 +365,7 @@
349 365 if (mdesc->reserve)
350 366 mdesc->reserve();
351 367  
  368 + arm_memblock_steal_permitted = false;
352 369 memblock_allow_resize();
353 370 memblock_dump_all();
354 371 }
arch/arm/plat-omap/devices.c
... ... @@ -20,6 +20,7 @@
20 20 #include <mach/hardware.h>
21 21 #include <asm/mach-types.h>
22 22 #include <asm/mach/map.h>
  23 +#include <asm/memblock.h>
23 24  
24 25 #include <plat/tc.h>
25 26 #include <plat/board.h>
26 27  
... ... @@ -164,14 +165,12 @@
164 165 if (!size)
165 166 return;
166 167  
167   - paddr = memblock_alloc(size, SZ_1M);
  168 + paddr = arm_memblock_steal(size, SZ_1M);
168 169 if (!paddr) {
169 170 pr_err("%s: failed to reserve %x bytes\n",
170 171 __func__, size);
171 172 return;
172 173 }
173   - memblock_free(paddr, size);
174   - memblock_remove(paddr, size);
175 174  
176 175 omap_dsp_phys_mempool_base = paddr;
177 176 }