aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/e820_64.c8
-rw-r--r--arch/x86/kernel/setup_64.c3
-rw-r--r--arch/x86/mm/init_64.c13
-rw-r--r--arch/x86/mm/numa_64.c35
-rw-r--r--include/asm-x86/e820_64.h2
5 files changed, 32 insertions, 29 deletions
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index b74e83b214cc..9f65b4cc323c 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -171,12 +171,13 @@ int __init e820_all_mapped(unsigned long start, unsigned long end,
171} 171}
172 172
173/* 173/*
174 * Find a free area in a specific range. 174 * Find a free area with specified alignment in a specific range.
175 */ 175 */
176unsigned long __init find_e820_area(unsigned long start, unsigned long end, 176unsigned long __init find_e820_area(unsigned long start, unsigned long end,
177 unsigned size) 177 unsigned size, unsigned long align)
178{ 178{
179 int i; 179 int i;
180 unsigned long mask = ~(align - 1);
180 181
181 for (i = 0; i < e820.nr_map; i++) { 182 for (i = 0; i < e820.nr_map; i++) {
182 struct e820entry *ei = &e820.map[i]; 183 struct e820entry *ei = &e820.map[i];
@@ -190,7 +191,8 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
190 continue; 191 continue;
191 while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size) 192 while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
192 ; 193 ;
193 last = PAGE_ALIGN(addr) + size; 194 addr = (addr + align - 1) & mask;
195 last = addr + size;
194 if (last > ei->addr + ei->size) 196 if (last > ei->addr + ei->size)
195 continue; 197 continue;
196 if (last > end) 198 if (last > end)
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 77fb87bf6e5a..18df70c534b9 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -182,7 +182,8 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
182 unsigned long bootmap_size, bootmap; 182 unsigned long bootmap_size, bootmap;
183 183
184 bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; 184 bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
185 bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); 185 bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
186 PAGE_SIZE);
186 if (bootmap == -1L) 187 if (bootmap == -1L)
187 panic("Cannot find bootmem map of size %ld\n", bootmap_size); 188 panic("Cannot find bootmem map of size %ld\n", bootmap_size);
188 bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn); 189 bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 9a471be4f5f1..eabcaed76c28 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -354,17 +354,10 @@ static void __init find_early_table_space(unsigned long end)
354 * need roughly 0.5KB per GB. 354 * need roughly 0.5KB per GB.
355 */ 355 */
356 start = 0x8000; 356 start = 0x8000;
357 table_start = find_e820_area(start, end, tables); 357 table_start = find_e820_area(start, end, tables, PAGE_SIZE);
358 if (table_start == -1UL) 358 if (table_start == -1UL)
359 panic("Cannot find space for the kernel page tables"); 359 panic("Cannot find space for the kernel page tables");
360 360
361 /*
362 * When you have a lot of RAM like 256GB, early_table will not fit
363 * into 0x8000 range, find_e820_area() will find area after kernel
364 * bss but the table_start is not page aligned, so need to round it
365 * up to avoid overlap with bss:
366 */
367 table_start = round_up(table_start, PAGE_SIZE);
368 table_start >>= PAGE_SHIFT; 361 table_start >>= PAGE_SHIFT;
369 table_end = table_start; 362 table_end = table_start;
370 363
@@ -420,7 +413,9 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
420 mmu_cr4_features = read_cr4(); 413 mmu_cr4_features = read_cr4();
421 __flush_tlb_all(); 414 __flush_tlb_all();
422 415
423 reserve_early(table_start << PAGE_SHIFT, table_end << PAGE_SHIFT, "PGTABLE"); 416 if (!after_bootmem)
417 reserve_early(table_start << PAGE_SHIFT,
418 table_end << PAGE_SHIFT, "PGTABLE");
424} 419}
425 420
426#ifndef CONFIG_NUMA 421#ifndef CONFIG_NUMA
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index d33954866085..9f533deb9dad 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -84,25 +84,23 @@ static int __init populate_memnodemap(const struct bootnode *nodes,
84 84
85static int __init allocate_cachealigned_memnodemap(void) 85static int __init allocate_cachealigned_memnodemap(void)
86{ 86{
87 unsigned long pad, pad_addr; 87 unsigned long addr;
88 88
89 memnodemap = memnode.embedded_map; 89 memnodemap = memnode.embedded_map;
90 if (memnodemapsize <= ARRAY_SIZE(memnode.embedded_map)) 90 if (memnodemapsize <= ARRAY_SIZE(memnode.embedded_map))
91 return 0; 91 return 0;
92 92
93 pad = L1_CACHE_BYTES - 1; 93 addr = 0x8000;
94 pad_addr = 0x8000; 94 nodemap_size = round_up(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
95 nodemap_size = pad + sizeof(s16) * memnodemapsize; 95 nodemap_addr = find_e820_area(addr, end_pfn<<PAGE_SHIFT,
96 nodemap_addr = find_e820_area(pad_addr, end_pfn<<PAGE_SHIFT, 96 nodemap_size, L1_CACHE_BYTES);
97 nodemap_size);
98 if (nodemap_addr == -1UL) { 97 if (nodemap_addr == -1UL) {
99 printk(KERN_ERR 98 printk(KERN_ERR
100 "NUMA: Unable to allocate Memory to Node hash map\n"); 99 "NUMA: Unable to allocate Memory to Node hash map\n");
101 nodemap_addr = nodemap_size = 0; 100 nodemap_addr = nodemap_size = 0;
102 return -1; 101 return -1;
103 } 102 }
104 pad_addr = (nodemap_addr + pad) & ~pad; 103 memnodemap = phys_to_virt(nodemap_addr);
105 memnodemap = phys_to_virt(pad_addr);
106 reserve_early(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP"); 104 reserve_early(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
107 105
108 printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n", 106 printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
@@ -164,15 +162,17 @@ int early_pfn_to_nid(unsigned long pfn)
164} 162}
165 163
166static void * __init early_node_mem(int nodeid, unsigned long start, 164static void * __init early_node_mem(int nodeid, unsigned long start,
167 unsigned long end, unsigned long size) 165 unsigned long end, unsigned long size,
166 unsigned long align)
168{ 167{
169 unsigned long mem = find_e820_area(start, end, size); 168 unsigned long mem = find_e820_area(start, end, size, align);
170 void *ptr; 169 void *ptr;
171 170
172 if (mem != -1L) 171 if (mem != -1L) {
172 mem = round_up(mem, align);
173 return __va(mem); 173 return __va(mem);
174 ptr = __alloc_bootmem_nopanic(size, 174 }
175 SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)); 175 ptr = __alloc_bootmem_nopanic(size, align, __pa(MAX_DMA_ADDRESS));
176 if (ptr == NULL) { 176 if (ptr == NULL) {
177 printk(KERN_ERR "Cannot find %lu bytes in node %d\n", 177 printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
178 size, nodeid); 178 size, nodeid);
@@ -198,7 +198,8 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
198 start_pfn = start >> PAGE_SHIFT; 198 start_pfn = start >> PAGE_SHIFT;
199 end_pfn = end >> PAGE_SHIFT; 199 end_pfn = end >> PAGE_SHIFT;
200 200
201 node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size); 201 node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size,
202 SMP_CACHE_BYTES);
202 if (node_data[nodeid] == NULL) 203 if (node_data[nodeid] == NULL)
203 return; 204 return;
204 nodedata_phys = __pa(node_data[nodeid]); 205 nodedata_phys = __pa(node_data[nodeid]);
@@ -211,8 +212,12 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
211 /* Find a place for the bootmem map */ 212 /* Find a place for the bootmem map */
212 bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 213 bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
213 bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); 214 bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
215 /*
216 * SMP_CAHCE_BYTES could be enough, but init_bootmem_node like
217 * to use that to align to PAGE_SIZE
218 */
214 bootmap = early_node_mem(nodeid, bootmap_start, end, 219 bootmap = early_node_mem(nodeid, bootmap_start, end,
215 bootmap_pages<<PAGE_SHIFT); 220 bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
216 if (bootmap == NULL) { 221 if (bootmap == NULL) {
217 if (nodedata_phys < start || nodedata_phys >= end) 222 if (nodedata_phys < start || nodedata_phys >= end)
218 free_bootmem((unsigned long)node_data[nodeid], 223 free_bootmem((unsigned long)node_data[nodeid],
diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h
index cc0946996055..a560c4f5d500 100644
--- a/include/asm-x86/e820_64.h
+++ b/include/asm-x86/e820_64.h
@@ -15,7 +15,7 @@
15 15
16#ifndef __ASSEMBLY__ 16#ifndef __ASSEMBLY__
17extern unsigned long find_e820_area(unsigned long start, unsigned long end, 17extern unsigned long find_e820_area(unsigned long start, unsigned long end,
18 unsigned size); 18 unsigned size, unsigned long align);
19extern void add_memory_region(unsigned long start, unsigned long size, 19extern void add_memory_region(unsigned long start, unsigned long size,
20 int type); 20 int type);
21extern void setup_memory_region(void); 21extern void setup_memory_region(void);