|
@@ -476,6 +476,29 @@ out:
|
|
|
return -1ULL;
|
|
|
}
|
|
|
|
|
|
+u64 __init find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
|
|
|
+ u64 *sizep, u64 align)
|
|
|
+{
|
|
|
+ u64 addr, last;
|
|
|
+
|
|
|
+ addr = round_up(ei_start, align);
|
|
|
+ if (addr < start)
|
|
|
+ addr = round_up(start, align);
|
|
|
+ if (addr >= ei_last)
|
|
|
+ goto out;
|
|
|
+ *sizep = ei_last - addr;
|
|
|
+ while (bad_addr_size(&addr, sizep, align) && addr + *sizep <= ei_last)
|
|
|
+ ;
|
|
|
+ last = addr + *sizep;
|
|
|
+ if (last > ei_last)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ return addr;
|
|
|
+
|
|
|
+out:
|
|
|
+ return -1ULL;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Find a free area with specified alignment in a specific range.
|
|
|
*/
|
|
@@ -513,24 +536,20 @@ u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
|
|
|
|
|
|
for (i = 0; i < e820.nr_map; i++) {
|
|
|
struct e820entry *ei = &e820.map[i];
|
|
|
- u64 addr, last;
|
|
|
- u64 ei_last;
|
|
|
+ u64 addr;
|
|
|
+ u64 ei_start, ei_last;
|
|
|
|
|
|
if (ei->type != E820_RAM)
|
|
|
continue;
|
|
|
- addr = round_up(ei->addr, align);
|
|
|
+
|
|
|
ei_last = ei->addr + ei->size;
|
|
|
- if (addr < start)
|
|
|
- addr = round_up(start, align);
|
|
|
- if (addr >= ei_last)
|
|
|
- continue;
|
|
|
- *sizep = ei_last - addr;
|
|
|
- while (bad_addr_size(&addr, sizep, align) &&
|
|
|
- addr + *sizep <= ei_last)
|
|
|
- ;
|
|
|
- last = addr + *sizep;
|
|
|
- if (last > ei_last)
|
|
|
+ ei_start = ei->addr;
|
|
|
+ addr = find_early_area_size(ei_start, ei_last, start,
|
|
|
+ sizep, align);
|
|
|
+
|
|
|
+ if (addr == -1ULL)
|
|
|
continue;
|
|
|
+
|
|
|
return addr;
|
|
|
}
|
|
|
|