diff options
Diffstat (limited to 'arch/x86/kernel/e820_64.c')
-rw-r--r-- | arch/x86/kernel/e820_64.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 4a0953857cb2..4509757844eb 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c | |||
@@ -114,6 +114,40 @@ again: | |||
114 | return changed; | 114 | return changed; |
115 | } | 115 | } |
116 | 116 | ||
117 | /* Check for already reserved areas */ | ||
118 | static inline int | ||
119 | bad_addr_size(unsigned long *addrp, unsigned long *sizep, unsigned long align) | ||
120 | { | ||
121 | int i; | ||
122 | unsigned long addr = *addrp, last; | ||
123 | unsigned long size = *sizep; | ||
124 | int changed = 0; | ||
125 | again: | ||
126 | last = addr + size; | ||
127 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) { | ||
128 | struct early_res *r = &early_res[i]; | ||
129 | if (last > r->start && addr < r->start) { | ||
130 | size = r->start - addr; | ||
131 | changed = 1; | ||
132 | goto again; | ||
133 | } | ||
134 | if (last > r->end && addr < r->end) { | ||
135 | addr = round_up(r->end, align); | ||
136 | size = last - addr; | ||
137 | changed = 1; | ||
138 | goto again; | ||
139 | } | ||
140 | if (last <= r->end && addr >= r->start) { | ||
141 | (*sizep)++; | ||
142 | return 0; | ||
143 | } | ||
144 | } | ||
145 | if (changed) { | ||
146 | *addrp = addr; | ||
147 | *sizep = size; | ||
148 | } | ||
149 | return changed; | ||
150 | } | ||
117 | /* | 151 | /* |
118 | * This function checks if any part of the range <start,end> is mapped | 152 | * This function checks if any part of the range <start,end> is mapped |
119 | * with type. | 153 | * with type. |
@@ -190,7 +224,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, | |||
190 | ei_last = ei->addr + ei->size; | 224 | ei_last = ei->addr + ei->size; |
191 | if (addr < start) | 225 | if (addr < start) |
192 | addr = round_up(start, align); | 226 | addr = round_up(start, align); |
193 | if (addr > ei_last) | 227 | if (addr >= ei_last) |
194 | continue; | 228 | continue; |
195 | while (bad_addr(&addr, size, align) && addr+size <= ei_last) | 229 | while (bad_addr(&addr, size, align) && addr+size <= ei_last) |
196 | ; | 230 | ; |
@@ -205,6 +239,40 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, | |||
205 | } | 239 | } |
206 | 240 | ||
207 | /* | 241 | /* |
242 | * Find next free range after *start | ||
243 | */ | ||
244 | unsigned long __init find_e820_area_size(unsigned long start, unsigned long *sizep, unsigned long align) | ||
245 | { | ||
246 | int i; | ||
247 | |||
248 | for (i = 0; i < e820.nr_map; i++) { | ||
249 | struct e820entry *ei = &e820.map[i]; | ||
250 | unsigned long addr, last; | ||
251 | unsigned long ei_last; | ||
252 | |||
253 | if (ei->type != E820_RAM) | ||
254 | continue; | ||
255 | addr = round_up(ei->addr, align); | ||
256 | ei_last = ei->addr + ei->size; | ||
257 | // printk(KERN_DEBUG "find_e820_area_size : e820 %d [%llx, %lx]\n", i, ei->addr, ei_last); | ||
258 | if (addr < start) | ||
259 | addr = round_up(start, align); | ||
260 | // printk(KERN_DEBUG "find_e820_area_size : 0 [%lx, %lx]\n", addr, ei_last); | ||
261 | if (addr >= ei_last) | ||
262 | continue; | ||
263 | *sizep = ei_last - addr; | ||
264 | while (bad_addr_size(&addr, sizep, align) && addr+ *sizep <= ei_last) | ||
265 | ; | ||
266 | last = addr + *sizep; | ||
267 | // printk(KERN_DEBUG "find_e820_area_size : 1 [%lx, %lx]\n", addr, last); | ||
268 | if (last > ei_last) | ||
269 | continue; | ||
270 | return addr; | ||
271 | } | ||
272 | return -1UL; | ||
273 | |||
274 | } | ||
275 | /* | ||
208 | * Find the highest page frame number we have available | 276 | * Find the highest page frame number we have available |
209 | */ | 277 | */ |
210 | unsigned long __init e820_end_of_ram(void) | 278 | unsigned long __init e820_end_of_ram(void) |