aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/e820_64.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2008-01-30 07:33:17 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:17 -0500
commit751752789162fde69474edfa15935d0a77c0bc17 (patch)
tree43eef77784989bc25979da1cc128e31fc46b3cea /arch/x86/kernel/e820_64.c
parentedcd81199dbad5db11ae91b507cec1d46dd94a49 (diff)
x86: replace hard coded reservations in 64-bit early boot code with dynamic table
On x86-64 there are several memory allocations before bootmem. To avoid them stomping on each other they used to be all hard coded in bad_area(). Replace this with an array that is filled as needed. This cleans up the code considerably and allows to expand its use. Cc: peterz@infradead.org Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/e820_64.c')
-rw-r--r--arch/x86/kernel/e820_64.c95
1 files changed, 52 insertions, 43 deletions
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index 07cfaae7ab07..f8b7bebb4344 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -47,56 +47,65 @@ unsigned long end_pfn_map;
47 */ 47 */
48static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT; 48static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
49 49
50/* Check for some hardcoded bad areas that early boot is not allowed to touch */ 50/*
51static inline int bad_addr(unsigned long *addrp, unsigned long size) 51 * Early reserved memory areas.
52{ 52 */
53 unsigned long addr = *addrp, last = addr + size; 53#define MAX_EARLY_RES 20
54
55struct early_res {
56 unsigned long start, end;
57};
58static struct early_res early_res[MAX_EARLY_RES] __initdata = {
59 { 0, PAGE_SIZE }, /* BIOS data page */
60#ifdef CONFIG_SMP
61 { SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE },
62#endif
63 {}
64};
54 65
55 /* various gunk below that needed for SMP startup */ 66void __init reserve_early(unsigned long start, unsigned long end)
56 if (addr < 0x8000) { 67{
57 *addrp = PAGE_ALIGN(0x8000); 68 int i;
58 return 1; 69 struct early_res *r;
70 for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
71 r = &early_res[i];
72 if (end > r->start && start < r->end)
73 panic("Duplicated early reservation %lx-%lx\n",
74 start, end);
59 } 75 }
76 if (i >= MAX_EARLY_RES)
77 panic("Too many early reservations");
78 r = &early_res[i];
79 r->start = start;
80 r->end = end;
81}
60 82
61 /* direct mapping tables of the kernel */ 83void __init early_res_to_bootmem(void)
62 if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 84{
63 *addrp = PAGE_ALIGN(table_end << PAGE_SHIFT); 85 int i;
64 return 1; 86 for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
87 struct early_res *r = &early_res[i];
88 reserve_bootmem_generic(r->start, r->end - r->start);
65 } 89 }
90}
66 91
67 /* initrd */ 92/* Check for already reserved areas */
68#ifdef CONFIG_BLK_DEV_INITRD 93static inline int bad_addr(unsigned long *addrp, unsigned long size)
69 if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) { 94{
70 unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; 95 int i;
71 unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; 96 unsigned long addr = *addrp, last;
72 unsigned long ramdisk_end = ramdisk_image+ramdisk_size; 97 int changed = 0;
73 98again:
74 if (last >= ramdisk_image && addr < ramdisk_end) { 99 last = addr + size;
75 *addrp = PAGE_ALIGN(ramdisk_end); 100 for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
76 return 1; 101 struct early_res *r = &early_res[i];
102 if (last >= r->start && addr < r->end) {
103 *addrp = addr = r->end;
104 changed = 1;
105 goto again;
77 } 106 }
78 } 107 }
79#endif 108 return changed;
80 /* kernel code */
81 if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
82 *addrp = PAGE_ALIGN(__pa_symbol(&_end));
83 return 1;
84 }
85
86 if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
87 *addrp = PAGE_ALIGN(ebda_addr + ebda_size);
88 return 1;
89 }
90
91#ifdef CONFIG_NUMA
92 /* NUMA memory to node map */
93 if (last >= nodemap_addr && addr < nodemap_addr + nodemap_size) {
94 *addrp = nodemap_addr + nodemap_size;
95 return 1;
96 }
97#endif
98 /* XXX ramdisk image here? */
99 return 0;
100} 109}
101 110
102/* 111/*