diff options
Diffstat (limited to 'drivers/xen/balloon.c')
-rw-r--r-- | drivers/xen/balloon.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 5dfd8f8ff07f..5876e1ae6c2d 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -501,20 +501,24 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target); | |||
501 | * alloc_xenballooned_pages - get pages that have been ballooned out | 501 | * alloc_xenballooned_pages - get pages that have been ballooned out |
502 | * @nr_pages: Number of pages to get | 502 | * @nr_pages: Number of pages to get |
503 | * @pages: pages returned | 503 | * @pages: pages returned |
504 | * @highmem: highmem or lowmem pages | ||
504 | * @return 0 on success, error otherwise | 505 | * @return 0 on success, error otherwise |
505 | */ | 506 | */ |
506 | int alloc_xenballooned_pages(int nr_pages, struct page** pages) | 507 | int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem) |
507 | { | 508 | { |
508 | int pgno = 0; | 509 | int pgno = 0; |
509 | struct page* page; | 510 | struct page* page; |
510 | mutex_lock(&balloon_mutex); | 511 | mutex_lock(&balloon_mutex); |
511 | while (pgno < nr_pages) { | 512 | while (pgno < nr_pages) { |
512 | page = balloon_retrieve(true); | 513 | page = balloon_retrieve(highmem); |
513 | if (page) { | 514 | if (page && PageHighMem(page) == highmem) { |
514 | pages[pgno++] = page; | 515 | pages[pgno++] = page; |
515 | } else { | 516 | } else { |
516 | enum bp_state st; | 517 | enum bp_state st; |
517 | st = decrease_reservation(nr_pages - pgno, GFP_HIGHUSER); | 518 | if (page) |
519 | balloon_append(page); | ||
520 | st = decrease_reservation(nr_pages - pgno, | ||
521 | highmem ? GFP_HIGHUSER : GFP_USER); | ||
518 | if (st != BP_DONE) | 522 | if (st != BP_DONE) |
519 | goto out_undo; | 523 | goto out_undo; |
520 | } | 524 | } |
@@ -555,17 +559,40 @@ void free_xenballooned_pages(int nr_pages, struct page** pages) | |||
555 | } | 559 | } |
556 | EXPORT_SYMBOL(free_xenballooned_pages); | 560 | EXPORT_SYMBOL(free_xenballooned_pages); |
557 | 561 | ||
558 | static int __init balloon_init(void) | 562 | static void __init balloon_add_region(unsigned long start_pfn, |
563 | unsigned long pages) | ||
559 | { | 564 | { |
560 | unsigned long pfn, extra_pfn_end; | 565 | unsigned long pfn, extra_pfn_end; |
561 | struct page *page; | 566 | struct page *page; |
562 | 567 | ||
568 | /* | ||
569 | * If the amount of usable memory has been limited (e.g., with | ||
570 | * the 'mem' command line parameter), don't add pages beyond | ||
571 | * this limit. | ||
572 | */ | ||
573 | extra_pfn_end = min(max_pfn, start_pfn + pages); | ||
574 | |||
575 | for (pfn = start_pfn; pfn < extra_pfn_end; pfn++) { | ||
576 | page = pfn_to_page(pfn); | ||
577 | /* totalram_pages and totalhigh_pages do not | ||
578 | include the boot-time balloon extension, so | ||
579 | don't subtract from it. */ | ||
580 | __balloon_append(page); | ||
581 | } | ||
582 | } | ||
583 | |||
584 | static int __init balloon_init(void) | ||
585 | { | ||
586 | int i; | ||
587 | |||
563 | if (!xen_domain()) | 588 | if (!xen_domain()) |
564 | return -ENODEV; | 589 | return -ENODEV; |
565 | 590 | ||
566 | pr_info("xen/balloon: Initialising balloon driver.\n"); | 591 | pr_info("xen/balloon: Initialising balloon driver.\n"); |
567 | 592 | ||
568 | balloon_stats.current_pages = xen_pv_domain() ? min(xen_start_info->nr_pages, max_pfn) : max_pfn; | 593 | balloon_stats.current_pages = xen_pv_domain() |
594 | ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn) | ||
595 | : max_pfn; | ||
569 | balloon_stats.target_pages = balloon_stats.current_pages; | 596 | balloon_stats.target_pages = balloon_stats.current_pages; |
570 | balloon_stats.balloon_low = 0; | 597 | balloon_stats.balloon_low = 0; |
571 | balloon_stats.balloon_high = 0; | 598 | balloon_stats.balloon_high = 0; |
@@ -584,24 +611,13 @@ static int __init balloon_init(void) | |||
584 | #endif | 611 | #endif |
585 | 612 | ||
586 | /* | 613 | /* |
587 | * Initialise the balloon with excess memory space. We need | 614 | * Initialize the balloon with pages from the extra memory |
588 | * to make sure we don't add memory which doesn't exist or | 615 | * regions (see arch/x86/xen/setup.c). |
589 | * logically exist. The E820 map can be trimmed to be smaller | ||
590 | * than the amount of physical memory due to the mem= command | ||
591 | * line parameter. And if this is a 32-bit non-HIGHMEM kernel | ||
592 | * on a system with memory which requires highmem to access, | ||
593 | * don't try to use it. | ||
594 | */ | 616 | */ |
595 | extra_pfn_end = min(min(max_pfn, e820_end_of_ram_pfn()), | 617 | for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) |
596 | (unsigned long)PFN_DOWN(xen_extra_mem_start + xen_extra_mem_size)); | 618 | if (xen_extra_mem[i].size) |
597 | for (pfn = PFN_UP(xen_extra_mem_start); | 619 | balloon_add_region(PFN_UP(xen_extra_mem[i].start), |
598 | pfn < extra_pfn_end; | 620 | PFN_DOWN(xen_extra_mem[i].size)); |
599 | pfn++) { | ||
600 | page = pfn_to_page(pfn); | ||
601 | /* totalram_pages and totalhigh_pages do not include the boot-time | ||
602 | balloon extension, so don't subtract from it. */ | ||
603 | __balloon_append(page); | ||
604 | } | ||
605 | 621 | ||
606 | return 0; | 622 | return 0; |
607 | } | 623 | } |