aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/e820.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-09-27 18:16:47 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-27 18:16:47 -0400
commit3b9f6cb8a1ec791be79c6c7595fea922f12d1e64 (patch)
tree2393a448add846e6c2ed12f68106c3018b72c6a9 /arch/x86_64/kernel/e820.c
parentc38778c3a9aeadcd1ee319cfc8ea5a9cbf8cdafa (diff)
parenta77c64c1a641950626181b4857abb701d8f38ccc (diff)
Merge branch 'master' into upstream
Diffstat (limited to 'arch/x86_64/kernel/e820.c')
-rw-r--r--arch/x86_64/kernel/e820.c243
1 files changed, 101 insertions, 142 deletions
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 708a3cd9a27e..b3f0908668ec 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -25,6 +25,8 @@
25#include <asm/bootsetup.h> 25#include <asm/bootsetup.h>
26#include <asm/sections.h> 26#include <asm/sections.h>
27 27
28struct e820map e820 __initdata;
29
28/* 30/*
29 * PFN of last memory page. 31 * PFN of last memory page.
30 */ 32 */
@@ -41,7 +43,7 @@ unsigned long end_pfn_map;
41/* 43/*
42 * Last pfn which the user wants to use. 44 * Last pfn which the user wants to use.
43 */ 45 */
44unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT; 46static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
45 47
46extern struct resource code_resource, data_resource; 48extern struct resource code_resource, data_resource;
47 49
@@ -70,12 +72,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
70 return 1; 72 return 1;
71 } 73 }
72#endif 74#endif
73 /* kernel code + 640k memory hole (later should not be needed, but 75 /* kernel code */
74 be paranoid for now) */
75 if (last >= 640*1024 && addr < 1024*1024) {
76 *addrp = 1024*1024;
77 return 1;
78 }
79 if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { 76 if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
80 *addrp = __pa_symbol(&_end); 77 *addrp = __pa_symbol(&_end);
81 return 1; 78 return 1;
@@ -165,59 +162,14 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
165 return -1UL; 162 return -1UL;
166} 163}
167 164
168/*
169 * Free bootmem based on the e820 table for a node.
170 */
171void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end)
172{
173 int i;
174 for (i = 0; i < e820.nr_map; i++) {
175 struct e820entry *ei = &e820.map[i];
176 unsigned long last, addr;
177
178 if (ei->type != E820_RAM ||
179 ei->addr+ei->size <= start ||
180 ei->addr >= end)
181 continue;
182
183 addr = round_up(ei->addr, PAGE_SIZE);
184 if (addr < start)
185 addr = start;
186
187 last = round_down(ei->addr + ei->size, PAGE_SIZE);
188 if (last >= end)
189 last = end;
190
191 if (last > addr && last-addr >= PAGE_SIZE)
192 free_bootmem_node(pgdat, addr, last-addr);
193 }
194}
195
196/* 165/*
197 * Find the highest page frame number we have available 166 * Find the highest page frame number we have available
198 */ 167 */
199unsigned long __init e820_end_of_ram(void) 168unsigned long __init e820_end_of_ram(void)
200{ 169{
201 int i;
202 unsigned long end_pfn = 0; 170 unsigned long end_pfn = 0;
171 end_pfn = find_max_pfn_with_active_regions();
203 172
204 for (i = 0; i < e820.nr_map; i++) {
205 struct e820entry *ei = &e820.map[i];
206 unsigned long start, end;
207
208 start = round_up(ei->addr, PAGE_SIZE);
209 end = round_down(ei->addr + ei->size, PAGE_SIZE);
210 if (start >= end)
211 continue;
212 if (ei->type == E820_RAM) {
213 if (end > end_pfn<<PAGE_SHIFT)
214 end_pfn = end>>PAGE_SHIFT;
215 } else {
216 if (end > end_pfn_map<<PAGE_SHIFT)
217 end_pfn_map = end>>PAGE_SHIFT;
218 }
219 }
220
221 if (end_pfn > end_pfn_map) 173 if (end_pfn > end_pfn_map)
222 end_pfn_map = end_pfn; 174 end_pfn_map = end_pfn;
223 if (end_pfn_map > MAXMEM>>PAGE_SHIFT) 175 if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
@@ -227,43 +179,10 @@ unsigned long __init e820_end_of_ram(void)
227 if (end_pfn > end_pfn_map) 179 if (end_pfn > end_pfn_map)
228 end_pfn = end_pfn_map; 180 end_pfn = end_pfn_map;
229 181
182 printk("end_pfn_map = %lu\n", end_pfn_map);
230 return end_pfn; 183 return end_pfn;
231} 184}
232 185
233/*
234 * Compute how much memory is missing in a range.
235 * Unlike the other functions in this file the arguments are in page numbers.
236 */
237unsigned long __init
238e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
239{
240 unsigned long ram = 0;
241 unsigned long start = start_pfn << PAGE_SHIFT;
242 unsigned long end = end_pfn << PAGE_SHIFT;
243 int i;
244 for (i = 0; i < e820.nr_map; i++) {
245 struct e820entry *ei = &e820.map[i];
246 unsigned long last, addr;
247
248 if (ei->type != E820_RAM ||
249 ei->addr+ei->size <= start ||
250 ei->addr >= end)
251 continue;
252
253 addr = round_up(ei->addr, PAGE_SIZE);
254 if (addr < start)
255 addr = start;
256
257 last = round_down(ei->addr + ei->size, PAGE_SIZE);
258 if (last >= end)
259 last = end;
260
261 if (last > addr)
262 ram += last - addr;
263 }
264 return ((end - start) - ram) >> PAGE_SHIFT;
265}
266
267/* 186/*
268 * Mark e820 reserved areas as busy for the resource manager. 187 * Mark e820 reserved areas as busy for the resource manager.
269 */ 188 */
@@ -345,6 +264,49 @@ void __init e820_mark_nosave_regions(void)
345 } 264 }
346} 265}
347 266
267/* Walk the e820 map and register active regions within a node */
268void __init
269e820_register_active_regions(int nid, unsigned long start_pfn,
270 unsigned long end_pfn)
271{
272 int i;
273 unsigned long ei_startpfn, ei_endpfn;
274 for (i = 0; i < e820.nr_map; i++) {
275 struct e820entry *ei = &e820.map[i];
276 ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
277 ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE)
278 >> PAGE_SHIFT;
279
280 /* Skip map entries smaller than a page */
281 if (ei_startpfn > ei_endpfn)
282 continue;
283
284 /* Check if end_pfn_map should be updated */
285 if (ei->type != E820_RAM && ei_endpfn > end_pfn_map)
286 end_pfn_map = ei_endpfn;
287
288 /* Skip if map is outside the node */
289 if (ei->type != E820_RAM ||
290 ei_endpfn <= start_pfn ||
291 ei_startpfn >= end_pfn)
292 continue;
293
294 /* Check for overlaps */
295 if (ei_startpfn < start_pfn)
296 ei_startpfn = start_pfn;
297 if (ei_endpfn > end_pfn)
298 ei_endpfn = end_pfn;
299
300 /* Obey end_user_pfn to save on memmap */
301 if (ei_startpfn >= end_user_pfn)
302 continue;
303 if (ei_endpfn > end_user_pfn)
304 ei_endpfn = end_user_pfn;
305
306 add_active_range(nid, ei_startpfn, ei_endpfn);
307 }
308}
309
348/* 310/*
349 * Add a memory region to the kernel e820 map. 311 * Add a memory region to the kernel e820 map.
350 */ 312 */
@@ -565,13 +527,6 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
565 * If we're lucky and live on a modern system, the setup code 527 * If we're lucky and live on a modern system, the setup code
566 * will have given us a memory map that we can use to properly 528 * will have given us a memory map that we can use to properly
567 * set up memory. If we aren't, we'll fake a memory map. 529 * set up memory. If we aren't, we'll fake a memory map.
568 *
569 * We check to see that the memory map contains at least 2 elements
570 * before we'll use it, because the detection code in setup.S may
571 * not be perfect and most every PC known to man has two memory
572 * regions: one from 0 to 640k, and one from 1mb up. (The IBM
573 * thinkpad 560x, for example, does not cooperate with the memory
574 * detection code.)
575 */ 530 */
576static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) 531static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
577{ 532{
@@ -589,34 +544,19 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
589 if (start > end) 544 if (start > end)
590 return -1; 545 return -1;
591 546
592 /*
593 * Some BIOSes claim RAM in the 640k - 1M region.
594 * Not right. Fix it up.
595 *
596 * This should be removed on Hammer which is supposed to not
597 * have non e820 covered ISA mappings there, but I had some strange
598 * problems so it stays for now. -AK
599 */
600 if (type == E820_RAM) {
601 if (start < 0x100000ULL && end > 0xA0000ULL) {
602 if (start < 0xA0000ULL)
603 add_memory_region(start, 0xA0000ULL-start, type);
604 if (end <= 0x100000ULL)
605 continue;
606 start = 0x100000ULL;
607 size = end - start;
608 }
609 }
610
611 add_memory_region(start, size, type); 547 add_memory_region(start, size, type);
612 } while (biosmap++,--nr_map); 548 } while (biosmap++,--nr_map);
613 return 0; 549 return 0;
614} 550}
615 551
616void __init setup_memory_region(void) 552void early_panic(char *msg)
617{ 553{
618 char *who = "BIOS-e820"; 554 early_printk(msg);
555 panic(msg);
556}
619 557
558void __init setup_memory_region(void)
559{
620 /* 560 /*
621 * Try to copy the BIOS-supplied E820-map. 561 * Try to copy the BIOS-supplied E820-map.
622 * 562 *
@@ -624,51 +564,70 @@ void __init setup_memory_region(void)
624 * the next section from 1mb->appropriate_mem_k 564 * the next section from 1mb->appropriate_mem_k
625 */ 565 */
626 sanitize_e820_map(E820_MAP, &E820_MAP_NR); 566 sanitize_e820_map(E820_MAP, &E820_MAP_NR);
627 if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) { 567 if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0)
628 unsigned long mem_size; 568 early_panic("Cannot find a valid memory map");
629
630 /* compare results from other methods and take the greater */
631 if (ALT_MEM_K < EXT_MEM_K) {
632 mem_size = EXT_MEM_K;
633 who = "BIOS-88";
634 } else {
635 mem_size = ALT_MEM_K;
636 who = "BIOS-e801";
637 }
638
639 e820.nr_map = 0;
640 add_memory_region(0, LOWMEMSIZE(), E820_RAM);
641 add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
642 }
643 printk(KERN_INFO "BIOS-provided physical RAM map:\n"); 569 printk(KERN_INFO "BIOS-provided physical RAM map:\n");
644 e820_print_map(who); 570 e820_print_map("BIOS-e820");
645} 571}
646 572
647void __init parse_memopt(char *p, char **from) 573static int __init parse_memopt(char *p)
648{ 574{
649 end_user_pfn = memparse(p, from); 575 if (!p)
576 return -EINVAL;
577 end_user_pfn = memparse(p, &p);
650 end_user_pfn >>= PAGE_SHIFT; 578 end_user_pfn >>= PAGE_SHIFT;
579 return 0;
651} 580}
581early_param("mem", parse_memopt);
652 582
653void __init parse_memmapopt(char *p, char **from) 583static int userdef __initdata;
584
585static int __init parse_memmap_opt(char *p)
654{ 586{
587 char *oldp;
655 unsigned long long start_at, mem_size; 588 unsigned long long start_at, mem_size;
656 589
657 mem_size = memparse(p, from); 590 if (!strcmp(p, "exactmap")) {
658 p = *from; 591#ifdef CONFIG_CRASH_DUMP
592 /* If we are doing a crash dump, we
593 * still need to know the real mem
594 * size before original memory map is
595 * reset.
596 */
597 saved_max_pfn = e820_end_of_ram();
598#endif
599 end_pfn_map = 0;
600 e820.nr_map = 0;
601 userdef = 1;
602 return 0;
603 }
604
605 oldp = p;
606 mem_size = memparse(p, &p);
607 if (p == oldp)
608 return -EINVAL;
659 if (*p == '@') { 609 if (*p == '@') {
660 start_at = memparse(p+1, from); 610 start_at = memparse(p+1, &p);
661 add_memory_region(start_at, mem_size, E820_RAM); 611 add_memory_region(start_at, mem_size, E820_RAM);
662 } else if (*p == '#') { 612 } else if (*p == '#') {
663 start_at = memparse(p+1, from); 613 start_at = memparse(p+1, &p);
664 add_memory_region(start_at, mem_size, E820_ACPI); 614 add_memory_region(start_at, mem_size, E820_ACPI);
665 } else if (*p == '$') { 615 } else if (*p == '$') {
666 start_at = memparse(p+1, from); 616 start_at = memparse(p+1, &p);
667 add_memory_region(start_at, mem_size, E820_RESERVED); 617 add_memory_region(start_at, mem_size, E820_RESERVED);
668 } else { 618 } else {
669 end_user_pfn = (mem_size >> PAGE_SHIFT); 619 end_user_pfn = (mem_size >> PAGE_SHIFT);
670 } 620 }
671 p = *from; 621 return *p == '\0' ? 0 : -EINVAL;
622}
623early_param("memmap", parse_memmap_opt);
624
625void finish_e820_parsing(void)
626{
627 if (userdef) {
628 printk(KERN_INFO "user-defined physical RAM map:\n");
629 e820_print_map("user");
630 }
672} 631}
673 632
674unsigned long pci_mem_start = 0xaeedbabe; 633unsigned long pci_mem_start = 0xaeedbabe;