diff options
author | Andi Kleen <ak@suse.de> | 2008-01-30 07:33:17 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:33:17 -0500 |
commit | 751752789162fde69474edfa15935d0a77c0bc17 (patch) | |
tree | 43eef77784989bc25979da1cc128e31fc46b3cea /arch/x86/kernel/e820_64.c | |
parent | edcd81199dbad5db11ae91b507cec1d46dd94a49 (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.c | 95 |
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 | */ |
48 | static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT; | 48 | static 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 | /* |
51 | static 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 | |||
55 | struct early_res { | ||
56 | unsigned long start, end; | ||
57 | }; | ||
58 | static 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 */ | 66 | void __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 */ | 83 | void __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 | 93 | static 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 | 98 | again: | |
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 | /* |