diff options
| -rw-r--r-- | arch/x86/include/asm/memblock.h | 1 | ||||
| -rw-r--r-- | arch/x86/mm/memblock.c | 48 |
2 files changed, 49 insertions, 0 deletions
diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h index 3a86b10380f3..fc3c230812e6 100644 --- a/arch/x86/include/asm/memblock.h +++ b/arch/x86/include/asm/memblock.h | |||
| @@ -15,5 +15,6 @@ void memblock_x86_register_active_regions(int nid, unsigned long start_pfn, | |||
| 15 | unsigned long last_pfn); | 15 | unsigned long last_pfn); |
| 16 | u64 memblock_x86_hole_size(u64 start, u64 end); | 16 | u64 memblock_x86_hole_size(u64 start, u64 end); |
| 17 | u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align); | 17 | u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align); |
| 18 | u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit); | ||
| 18 | 19 | ||
| 19 | #endif | 20 | #endif |
diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c index 22ff0a39b227..30d60cf29ce3 100644 --- a/arch/x86/mm/memblock.c +++ b/arch/x86/mm/memblock.c | |||
| @@ -211,6 +211,54 @@ void __init memblock_x86_to_bootmem(u64 start, u64 end) | |||
| 211 | } | 211 | } |
| 212 | #endif | 212 | #endif |
| 213 | 213 | ||
| 214 | u64 __init memblock_x86_free_memory_in_range(u64 addr, u64 limit) | ||
| 215 | { | ||
| 216 | int i, count; | ||
| 217 | struct range *range; | ||
| 218 | int nr_range; | ||
| 219 | u64 final_start, final_end; | ||
| 220 | u64 free_size; | ||
| 221 | struct memblock_region *r; | ||
| 222 | |||
| 223 | count = (memblock.reserved.cnt + memblock.memory.cnt) * 2; | ||
| 224 | |||
| 225 | range = find_range_array(count); | ||
| 226 | nr_range = 0; | ||
| 227 | |||
| 228 | addr = PFN_UP(addr); | ||
| 229 | limit = PFN_DOWN(limit); | ||
| 230 | |||
| 231 | for_each_memblock(memory, r) { | ||
| 232 | final_start = PFN_UP(r->base); | ||
| 233 | final_end = PFN_DOWN(r->base + r->size); | ||
| 234 | if (final_start >= final_end) | ||
| 235 | continue; | ||
| 236 | if (final_start >= limit || final_end <= addr) | ||
| 237 | continue; | ||
| 238 | |||
| 239 | nr_range = add_range(range, count, nr_range, final_start, final_end); | ||
| 240 | } | ||
| 241 | subtract_range(range, count, 0, addr); | ||
| 242 | subtract_range(range, count, limit, -1ULL); | ||
| 243 | for_each_memblock(reserved, r) { | ||
| 244 | final_start = PFN_DOWN(r->base); | ||
| 245 | final_end = PFN_UP(r->base + r->size); | ||
| 246 | if (final_start >= final_end) | ||
| 247 | continue; | ||
| 248 | if (final_start >= limit || final_end <= addr) | ||
| 249 | continue; | ||
| 250 | |||
| 251 | subtract_range(range, count, final_start, final_end); | ||
| 252 | } | ||
| 253 | nr_range = clean_sort_range(range, count); | ||
| 254 | |||
| 255 | free_size = 0; | ||
| 256 | for (i = 0; i < nr_range; i++) | ||
| 257 | free_size += range[i].end - range[i].start; | ||
| 258 | |||
| 259 | return free_size << PAGE_SHIFT; | ||
| 260 | } | ||
| 261 | |||
| 214 | void __init memblock_x86_reserve_range(u64 start, u64 end, char *name) | 262 | void __init memblock_x86_reserve_range(u64 start, u64 end, char *name) |
| 215 | { | 263 | { |
| 216 | if (start == end) | 264 | if (start == end) |
