aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-06 18:39:01 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-08-04 22:56:07 -0400
commite63075a3c9377536d085bc013cd3fe6323162449 (patch)
tree28fde124dde6df867947882fc686d228502846df
parent27f574c223d2c09610058b3ec7a29582d63a3e06 (diff)
memblock: Introduce default allocation limit and use it to replace explicit ones
This introduce memblock.current_limit which is used to limit allocations from memblock_alloc() or memblock_alloc_base(..., MEMBLOCK_ALLOC_ACCESSIBLE). The old MEMBLOCK_ALLOC_ANYWHERE changes value from 0 to ~(u64)0 and can still be used with memblock_alloc_base() to allocate really anywhere. It is -no-longer- cropped to MEMBLOCK_REAL_LIMIT which disappears. Note to archs: I'm leaving the default limit to MEMBLOCK_ALLOC_ANYWHERE. I strongly recommend that you ensure that you set an appropriate limit during boot in order to guarantee that an memblock_alloc() at any time results in something that is accessible with a simple __va(). The reason is that a subsequent patch will introduce the ability for the array to resize itself by reallocating itself. The MEMBLOCK core will honor the current limit when performing those allocations. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/microblaze/include/asm/memblock.h3
-rw-r--r--arch/powerpc/include/asm/memblock.h7
-rw-r--r--arch/powerpc/kernel/prom.c20
-rw-r--r--arch/powerpc/kernel/setup_32.c2
-rw-r--r--arch/powerpc/mm/40x_mmu.c5
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c3
-rw-r--r--arch/powerpc/mm/hash_utils_64.c3
-rw-r--r--arch/powerpc/mm/init_32.c29
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c3
-rw-r--r--arch/powerpc/mm/tlb_nohash.c2
-rw-r--r--arch/sh/include/asm/memblock.h2
-rw-r--r--arch/sparc/include/asm/memblock.h2
-rw-r--r--include/linux/memblock.h16
-rw-r--r--mm/memblock.c19
14 files changed, 63 insertions, 53 deletions
diff --git a/arch/microblaze/include/asm/memblock.h b/arch/microblaze/include/asm/memblock.h
index f9c2fa331d2a..20a8e257c77f 100644
--- a/arch/microblaze/include/asm/memblock.h
+++ b/arch/microblaze/include/asm/memblock.h
@@ -9,9 +9,6 @@
9#ifndef _ASM_MICROBLAZE_MEMBLOCK_H 9#ifndef _ASM_MICROBLAZE_MEMBLOCK_H
10#define _ASM_MICROBLAZE_MEMBLOCK_H 10#define _ASM_MICROBLAZE_MEMBLOCK_H
11 11
12/* MEMBLOCK limit is OFF */
13#define MEMBLOCK_REAL_LIMIT 0xFFFFFFFF
14
15#endif /* _ASM_MICROBLAZE_MEMBLOCK_H */ 12#endif /* _ASM_MICROBLAZE_MEMBLOCK_H */
16 13
17 14
diff --git a/arch/powerpc/include/asm/memblock.h b/arch/powerpc/include/asm/memblock.h
index 3c29728b56b1..43efc345065e 100644
--- a/arch/powerpc/include/asm/memblock.h
+++ b/arch/powerpc/include/asm/memblock.h
@@ -5,11 +5,4 @@
5 5
6#define MEMBLOCK_DBG(fmt...) udbg_printf(fmt) 6#define MEMBLOCK_DBG(fmt...) udbg_printf(fmt)
7 7
8#ifdef CONFIG_PPC32
9extern phys_addr_t lowmem_end_addr;
10#define MEMBLOCK_REAL_LIMIT lowmem_end_addr
11#else
12#define MEMBLOCK_REAL_LIMIT 0
13#endif
14
15#endif /* _ASM_POWERPC_MEMBLOCK_H */ 8#endif /* _ASM_POWERPC_MEMBLOCK_H */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index fed9bf6187d1..3aec0b980f6a 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -98,7 +98,7 @@ static void __init move_device_tree(void)
98 98
99 if ((memory_limit && (start + size) > memory_limit) || 99 if ((memory_limit && (start + size) > memory_limit) ||
100 overlaps_crashkernel(start, size)) { 100 overlaps_crashkernel(start, size)) {
101 p = __va(memblock_alloc_base(size, PAGE_SIZE, memblock.rmo_size)); 101 p = __va(memblock_alloc(size, PAGE_SIZE));
102 memcpy(p, initial_boot_params, size); 102 memcpy(p, initial_boot_params, size);
103 initial_boot_params = (struct boot_param_header *)p; 103 initial_boot_params = (struct boot_param_header *)p;
104 DBG("Moved device tree to 0x%p\n", p); 104 DBG("Moved device tree to 0x%p\n", p);
@@ -655,6 +655,21 @@ static void __init phyp_dump_reserve_mem(void)
655static inline void __init phyp_dump_reserve_mem(void) {} 655static inline void __init phyp_dump_reserve_mem(void) {}
656#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ 656#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
657 657
658static void set_boot_memory_limit(void)
659{
660#ifdef CONFIG_PPC32
661 /* 601 can only access 16MB at the moment */
662 if (PVR_VER(mfspr(SPRN_PVR)) == 1)
663 memblock_set_current_limit(0x01000000);
664 /* 8xx can only access 8MB at the moment */
665 else if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
666 memblock_set_current_limit(0x00800000);
667 else
668 memblock_set_current_limit(0x10000000);
669#else
670 memblock_set_current_limit(memblock.rmo_size);
671#endif
672}
658 673
659void __init early_init_devtree(void *params) 674void __init early_init_devtree(void *params)
660{ 675{
@@ -683,6 +698,7 @@ void __init early_init_devtree(void *params)
683 698
684 /* Scan memory nodes and rebuild MEMBLOCKs */ 699 /* Scan memory nodes and rebuild MEMBLOCKs */
685 memblock_init(); 700 memblock_init();
701
686 of_scan_flat_dt(early_init_dt_scan_root, NULL); 702 of_scan_flat_dt(early_init_dt_scan_root, NULL);
687 of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); 703 of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
688 704
@@ -718,6 +734,8 @@ void __init early_init_devtree(void *params)
718 734
719 DBG("Phys. mem: %llx\n", memblock_phys_mem_size()); 735 DBG("Phys. mem: %llx\n", memblock_phys_mem_size());
720 736
737 set_boot_memory_limit();
738
721 /* We may need to relocate the flat tree, do it now. 739 /* We may need to relocate the flat tree, do it now.
722 * FIXME .. and the initrd too? */ 740 * FIXME .. and the initrd too? */
723 move_device_tree(); 741 move_device_tree();
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index a10ffc85ada7..b7eb1ded3b5f 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -246,7 +246,7 @@ static void __init irqstack_early_init(void)
246 unsigned int i; 246 unsigned int i;
247 247
248 /* interrupt stacks must be in lowmem, we get that for free on ppc32 248 /* interrupt stacks must be in lowmem, we get that for free on ppc32
249 * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */ 249 * as the memblock is limited to lowmem by default */
250 for_each_possible_cpu(i) { 250 for_each_possible_cpu(i) {
251 softirq_ctx[i] = (struct thread_info *) 251 softirq_ctx[i] = (struct thread_info *)
252 __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); 252 __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index 1dc2fa5ce1bd..58969b51f454 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -35,6 +35,7 @@
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/highmem.h> 37#include <linux/highmem.h>
38#include <linux/memblock.h>
38 39
39#include <asm/pgalloc.h> 40#include <asm/pgalloc.h>
40#include <asm/prom.h> 41#include <asm/prom.h>
@@ -47,6 +48,7 @@
47#include <asm/bootx.h> 48#include <asm/bootx.h>
48#include <asm/machdep.h> 49#include <asm/machdep.h>
49#include <asm/setup.h> 50#include <asm/setup.h>
51
50#include "mmu_decl.h" 52#include "mmu_decl.h"
51 53
52extern int __map_without_ltlbs; 54extern int __map_without_ltlbs;
@@ -139,8 +141,7 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
139 * coverage with normal-sized pages (or other reasons) do not 141 * coverage with normal-sized pages (or other reasons) do not
140 * attempt to allocate outside the allowed range. 142 * attempt to allocate outside the allowed range.
141 */ 143 */
142 144 memblock_set_current_limit(memstart_addr + mapped);
143 __initial_memory_limit_addr = memstart_addr + mapped;
144 145
145 return mapped; 146 return mapped;
146} 147}
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index cdc7526e9c93..e525f862d759 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -40,6 +40,7 @@
40#include <linux/init.h> 40#include <linux/init.h>
41#include <linux/delay.h> 41#include <linux/delay.h>
42#include <linux/highmem.h> 42#include <linux/highmem.h>
43#include <linux/memblock.h>
43 44
44#include <asm/pgalloc.h> 45#include <asm/pgalloc.h>
45#include <asm/prom.h> 46#include <asm/prom.h>
@@ -212,5 +213,5 @@ void __init adjust_total_lowmem(void)
212 pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20, 213 pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20,
213 (unsigned int)((total_lowmem - __max_low_memory) >> 20)); 214 (unsigned int)((total_lowmem - __max_low_memory) >> 20));
214 215
215 __initial_memory_limit_addr = memstart_addr + __max_low_memory; 216 memblock_set_current_limit(memstart_addr + __max_low_memory);
216} 217}
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index a542ff5ec8a9..b05890e23813 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -696,7 +696,8 @@ static void __init htab_initialize(void)
696#endif /* CONFIG_U3_DART */ 696#endif /* CONFIG_U3_DART */
697 BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), 697 BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
698 prot, mmu_linear_psize, mmu_kernel_ssize)); 698 prot, mmu_linear_psize, mmu_kernel_ssize));
699 } 699 }
700 memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
700 701
701 /* 702 /*
702 * If we have a memory_limit and we've allocated TCEs then we need to 703 * If we have a memory_limit and we've allocated TCEs then we need to
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 6a6975dc2654..59b208b7ec6f 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -92,12 +92,6 @@ int __allow_ioremap_reserved;
92unsigned long __max_low_memory = MAX_LOW_MEM; 92unsigned long __max_low_memory = MAX_LOW_MEM;
93 93
94/* 94/*
95 * address of the limit of what is accessible with initial MMU setup -
96 * 256MB usually, but only 16MB on 601.
97 */
98phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000;
99
100/*
101 * Check for command-line options that affect what MMU_init will do. 95 * Check for command-line options that affect what MMU_init will do.
102 */ 96 */
103void MMU_setup(void) 97void MMU_setup(void)
@@ -126,13 +120,6 @@ void __init MMU_init(void)
126 if (ppc_md.progress) 120 if (ppc_md.progress)
127 ppc_md.progress("MMU:enter", 0x111); 121 ppc_md.progress("MMU:enter", 0x111);
128 122
129 /* 601 can only access 16MB at the moment */
130 if (PVR_VER(mfspr(SPRN_PVR)) == 1)
131 __initial_memory_limit_addr = 0x01000000;
132 /* 8xx can only access 8MB at the moment */
133 if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
134 __initial_memory_limit_addr = 0x00800000;
135
136 /* parse args from command line */ 123 /* parse args from command line */
137 MMU_setup(); 124 MMU_setup();
138 125
@@ -190,20 +177,18 @@ void __init MMU_init(void)
190#ifdef CONFIG_BOOTX_TEXT 177#ifdef CONFIG_BOOTX_TEXT
191 btext_unmap(); 178 btext_unmap();
192#endif 179#endif
180
181 /* Shortly after that, the entire linear mapping will be available */
182 memblock_set_current_limit(lowmem_end_addr);
193} 183}
194 184
195/* This is only called until mem_init is done. */ 185/* This is only called until mem_init is done. */
196void __init *early_get_page(void) 186void __init *early_get_page(void)
197{ 187{
198 void *p; 188 if (init_bootmem_done)
199 189 return alloc_bootmem_pages(PAGE_SIZE);
200 if (init_bootmem_done) { 190 else
201 p = alloc_bootmem_pages(PAGE_SIZE); 191 return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
202 } else {
203 p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE,
204 __initial_memory_limit_addr));
205 }
206 return p;
207} 192}
208 193
209/* Free up now-unused memory */ 194/* Free up now-unused memory */
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index f8a01829d64f..7d34e170e80f 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -223,8 +223,7 @@ void __init MMU_init_hw(void)
223 * Find some memory for the hash table. 223 * Find some memory for the hash table.
224 */ 224 */
225 if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); 225 if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
226 Hash = __va(memblock_alloc_base(Hash_size, Hash_size, 226 Hash = __va(memblock_alloc(Hash_size, Hash_size));
227 __initial_memory_limit_addr));
228 cacheable_memzero(Hash, Hash_size); 227 cacheable_memzero(Hash, Hash_size);
229 _SDR1 = __pa(Hash) | SDR1_LOW_BITS; 228 _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
230 229
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index d8695b02a968..7ba32e762990 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -432,6 +432,8 @@ static void __early_init_mmu(int boot_cpu)
432 * the MMU configuration 432 * the MMU configuration
433 */ 433 */
434 mb(); 434 mb();
435
436 memblock_set_current_limit(linear_map_top);
435} 437}
436 438
437void __init early_init_mmu(void) 439void __init early_init_mmu(void)
diff --git a/arch/sh/include/asm/memblock.h b/arch/sh/include/asm/memblock.h
index dfe683b88075..e87063fad2ea 100644
--- a/arch/sh/include/asm/memblock.h
+++ b/arch/sh/include/asm/memblock.h
@@ -1,6 +1,4 @@
1#ifndef __ASM_SH_MEMBLOCK_H 1#ifndef __ASM_SH_MEMBLOCK_H
2#define __ASM_SH_MEMBLOCK_H 2#define __ASM_SH_MEMBLOCK_H
3 3
4#define MEMBLOCK_REAL_LIMIT 0
5
6#endif /* __ASM_SH_MEMBLOCK_H */ 4#endif /* __ASM_SH_MEMBLOCK_H */
diff --git a/arch/sparc/include/asm/memblock.h b/arch/sparc/include/asm/memblock.h
index f12af880649b..c67b047ef85e 100644
--- a/arch/sparc/include/asm/memblock.h
+++ b/arch/sparc/include/asm/memblock.h
@@ -5,6 +5,4 @@
5 5
6#define MEMBLOCK_DBG(fmt...) prom_printf(fmt) 6#define MEMBLOCK_DBG(fmt...) prom_printf(fmt)
7 7
8#define MEMBLOCK_REAL_LIMIT 0
9
10#endif /* !(_SPARC64_MEMBLOCK_H) */ 8#endif /* !(_SPARC64_MEMBLOCK_H) */
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 3cf3304e901d..c4f6e53264ed 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -34,6 +34,7 @@ struct memblock_type {
34struct memblock { 34struct memblock {
35 unsigned long debug; 35 unsigned long debug;
36 u64 rmo_size; 36 u64 rmo_size;
37 u64 current_limit;
37 struct memblock_type memory; 38 struct memblock_type memory;
38 struct memblock_type reserved; 39 struct memblock_type reserved;
39}; 40};
@@ -46,11 +47,16 @@ extern long memblock_add(u64 base, u64 size);
46extern long memblock_remove(u64 base, u64 size); 47extern long memblock_remove(u64 base, u64 size);
47extern long __init memblock_free(u64 base, u64 size); 48extern long __init memblock_free(u64 base, u64 size);
48extern long __init memblock_reserve(u64 base, u64 size); 49extern long __init memblock_reserve(u64 base, u64 size);
50
49extern u64 __init memblock_alloc_nid(u64 size, u64 align, int nid); 51extern u64 __init memblock_alloc_nid(u64 size, u64 align, int nid);
50extern u64 __init memblock_alloc(u64 size, u64 align); 52extern u64 __init memblock_alloc(u64 size, u64 align);
53
54/* Flags for memblock_alloc_base() amd __memblock_alloc_base() */
55#define MEMBLOCK_ALLOC_ANYWHERE (~(u64)0)
56#define MEMBLOCK_ALLOC_ACCESSIBLE 0
57
51extern u64 __init memblock_alloc_base(u64 size, 58extern u64 __init memblock_alloc_base(u64 size,
52 u64, u64 max_addr); 59 u64, u64 max_addr);
53#define MEMBLOCK_ALLOC_ANYWHERE 0
54extern u64 __init __memblock_alloc_base(u64 size, 60extern u64 __init __memblock_alloc_base(u64 size,
55 u64 align, u64 max_addr); 61 u64 align, u64 max_addr);
56extern u64 __init memblock_phys_mem_size(void); 62extern u64 __init memblock_phys_mem_size(void);
@@ -66,6 +72,14 @@ extern void memblock_dump_all(void);
66/* Provided by the architecture */ 72/* Provided by the architecture */
67extern u64 memblock_nid_range(u64 start, u64 end, int *nid); 73extern u64 memblock_nid_range(u64 start, u64 end, int *nid);
68 74
75/**
76 * memblock_set_current_limit - Set the current allocation limit to allow
77 * limiting allocations to what is currently
78 * accessible during boot
79 * @limit: New limit value (physical address)
80 */
81extern void memblock_set_current_limit(u64 limit);
82
69 83
70/* 84/*
71 * pfn conversion functions 85 * pfn conversion functions
diff --git a/mm/memblock.c b/mm/memblock.c
index 0131684c42f8..770c5bfac2cd 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -115,6 +115,8 @@ void __init memblock_init(void)
115 memblock.reserved.regions[0].base = 0; 115 memblock.reserved.regions[0].base = 0;
116 memblock.reserved.regions[0].size = 0; 116 memblock.reserved.regions[0].size = 0;
117 memblock.reserved.cnt = 1; 117 memblock.reserved.cnt = 1;
118
119 memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
118} 120}
119 121
120void __init memblock_analyze(void) 122void __init memblock_analyze(void)
@@ -373,7 +375,7 @@ u64 __init memblock_alloc_nid(u64 size, u64 align, int nid)
373 375
374u64 __init memblock_alloc(u64 size, u64 align) 376u64 __init memblock_alloc(u64 size, u64 align)
375{ 377{
376 return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE); 378 return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
377} 379}
378 380
379u64 __init memblock_alloc_base(u64 size, u64 align, u64 max_addr) 381u64 __init memblock_alloc_base(u64 size, u64 align, u64 max_addr)
@@ -399,14 +401,9 @@ u64 __init __memblock_alloc_base(u64 size, u64 align, u64 max_addr)
399 401
400 size = memblock_align_up(size, align); 402 size = memblock_align_up(size, align);
401 403
402 /* On some platforms, make sure we allocate lowmem */
403 /* Note that MEMBLOCK_REAL_LIMIT may be MEMBLOCK_ALLOC_ANYWHERE */
404 if (max_addr == MEMBLOCK_ALLOC_ANYWHERE)
405 max_addr = MEMBLOCK_REAL_LIMIT;
406
407 /* Pump up max_addr */ 404 /* Pump up max_addr */
408 if (max_addr == MEMBLOCK_ALLOC_ANYWHERE) 405 if (max_addr == MEMBLOCK_ALLOC_ACCESSIBLE)
409 max_addr = ~(u64)0; 406 max_addr = memblock.current_limit;
410 407
411 /* We do a top-down search, this tends to limit memory 408 /* We do a top-down search, this tends to limit memory
412 * fragmentation by keeping early boot allocs near the 409 * fragmentation by keeping early boot allocs near the
@@ -527,3 +524,9 @@ int memblock_is_region_reserved(u64 base, u64 size)
527 return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; 524 return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
528} 525}
529 526
527
528void __init memblock_set_current_limit(u64 limit)
529{
530 memblock.current_limit = limit;
531}
532