diff options
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index d669e9d89001..c9081c6671f0 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1,8 +1,12 @@ | |||
1 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
2 | #include <linux/bootmem.h> | ||
3 | #endif | ||
1 | #include <linux/cpu.h> | 4 | #include <linux/cpu.h> |
2 | #include <linux/kexec.h> | 5 | #include <linux/kexec.h> |
3 | 6 | ||
4 | #include <xen/features.h> | 7 | #include <xen/features.h> |
5 | #include <xen/page.h> | 8 | #include <xen/page.h> |
9 | #include <xen/interface/memory.h> | ||
6 | 10 | ||
7 | #include <asm/xen/hypercall.h> | 11 | #include <asm/xen/hypercall.h> |
8 | #include <asm/xen/hypervisor.h> | 12 | #include <asm/xen/hypervisor.h> |
@@ -331,3 +335,80 @@ void xen_arch_unregister_cpu(int num) | |||
331 | } | 335 | } |
332 | EXPORT_SYMBOL(xen_arch_unregister_cpu); | 336 | EXPORT_SYMBOL(xen_arch_unregister_cpu); |
333 | #endif | 337 | #endif |
338 | |||
339 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
340 | void __init arch_xen_balloon_init(struct resource *hostmem_resource) | ||
341 | { | ||
342 | struct xen_memory_map memmap; | ||
343 | int rc; | ||
344 | unsigned int i, last_guest_ram; | ||
345 | phys_addr_t max_addr = PFN_PHYS(max_pfn); | ||
346 | struct e820_table *xen_e820_table; | ||
347 | const struct e820_entry *entry; | ||
348 | struct resource *res; | ||
349 | |||
350 | if (!xen_initial_domain()) | ||
351 | return; | ||
352 | |||
353 | xen_e820_table = kmalloc(sizeof(*xen_e820_table), GFP_KERNEL); | ||
354 | if (!xen_e820_table) | ||
355 | return; | ||
356 | |||
357 | memmap.nr_entries = ARRAY_SIZE(xen_e820_table->entries); | ||
358 | set_xen_guest_handle(memmap.buffer, xen_e820_table->entries); | ||
359 | rc = HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap); | ||
360 | if (rc) { | ||
361 | pr_warn("%s: Can't read host e820 (%d)\n", __func__, rc); | ||
362 | goto out; | ||
363 | } | ||
364 | |||
365 | last_guest_ram = 0; | ||
366 | for (i = 0; i < memmap.nr_entries; i++) { | ||
367 | if (xen_e820_table->entries[i].addr >= max_addr) | ||
368 | break; | ||
369 | if (xen_e820_table->entries[i].type == E820_TYPE_RAM) | ||
370 | last_guest_ram = i; | ||
371 | } | ||
372 | |||
373 | entry = &xen_e820_table->entries[last_guest_ram]; | ||
374 | if (max_addr >= entry->addr + entry->size) | ||
375 | goto out; /* No unallocated host RAM. */ | ||
376 | |||
377 | hostmem_resource->start = max_addr; | ||
378 | hostmem_resource->end = entry->addr + entry->size; | ||
379 | |||
380 | /* | ||
381 | * Mark non-RAM regions between the end of dom0 RAM and end of host RAM | ||
382 | * as unavailable. The rest of that region can be used for hotplug-based | ||
383 | * ballooning. | ||
384 | */ | ||
385 | for (; i < memmap.nr_entries; i++) { | ||
386 | entry = &xen_e820_table->entries[i]; | ||
387 | |||
388 | if (entry->type == E820_TYPE_RAM) | ||
389 | continue; | ||
390 | |||
391 | if (entry->addr >= hostmem_resource->end) | ||
392 | break; | ||
393 | |||
394 | res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
395 | if (!res) | ||
396 | goto out; | ||
397 | |||
398 | res->name = "Unavailable host RAM"; | ||
399 | res->start = entry->addr; | ||
400 | res->end = (entry->addr + entry->size < hostmem_resource->end) ? | ||
401 | entry->addr + entry->size : hostmem_resource->end; | ||
402 | rc = insert_resource(hostmem_resource, res); | ||
403 | if (rc) { | ||
404 | pr_warn("%s: Can't insert [%llx - %llx) (%d)\n", | ||
405 | __func__, res->start, res->end, rc); | ||
406 | kfree(res); | ||
407 | goto out; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | out: | ||
412 | kfree(xen_e820_table); | ||
413 | } | ||
414 | #endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */ | ||