From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dave McCracken Subject: [PATCH] Add 2M page support to Xen balloon driver Date: Tue, 16 Jun 2009 10:53:29 -0500 Message-ID: <200906161053.30707.dcm@mccr.org> Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_6/7NKDbNAK7enDx" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Jeremy Fitzhardinge Cc: Xen Developers List List-Id: xen-devel@lists.xenproject.org --Boundary-00=_6/7NKDbNAK7enDx Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline This patch adds a kernel command line option "balloon_hugepages" that, when enabled, will make the balloon driver work in 2M pages (ie hugepages). This will work in conjunction with the "superpages" domain creation option so once a domain is created with 2M contiguous pages it will continue to free and re- allocate at the 2M page size. Note that the current hypervisor code does not allow 2M page allocations for all guest domains. Keir has agreed to change the hypervisor to allow them, but for now "balloon_hugepages" should only be specified on hypervisors that have this change. Dave McCracken Oracle Corp. --Boundary-00=_6/7NKDbNAK7enDx Content-Type: text/plain; charset="us-ascii"; name="xen-balloon-2.6.30-1.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="xen-balloon-2.6.30-1.patch" --- 2.6.30/./drivers/xen/balloon.c 2009-06-09 22:05:27.000000000 -0500 +++ 2.6.30-domu/./drivers/xen/balloon.c 2009-06-16 10:23:25.000000000 -0500 @@ -58,7 +58,7 @@ #include #include -#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) +#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT+balloon_order-10)) #define BALLOON_CLASS_NAME "xen_memory" @@ -93,6 +93,13 @@ static DEFINE_SPINLOCK(balloon_lock); static struct balloon_stats balloon_stats; +/* + * Work in pages of this order. Can be either 0 for normal pages + * or 9 for hugepages. + */ +static int balloon_order; +static unsigned long balloon_npages; + /* We increase/decrease in batches which fit in a page */ static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; @@ -197,12 +204,11 @@ static unsigned long current_target(void static int increase_reservation(unsigned long nr_pages) { - unsigned long pfn, i, flags; + unsigned long pfn, mfn, i, j, flags; struct page *page; long rc; struct xen_memory_reservation reservation = { .address_bits = 0, - .extent_order = 0, .domid = DOMID_SELF }; @@ -214,12 +220,14 @@ static int increase_reservation(unsigned page = balloon_first_page(); for (i = 0; i < nr_pages; i++) { BUG_ON(page == NULL); - frame_list[i] = page_to_pfn(page);; + frame_list[i] = page_to_pfn(page); page = balloon_next_page(page); } set_xen_guest_handle(reservation.extent_start, frame_list); reservation.nr_extents = nr_pages; + reservation.extent_order = balloon_order; + rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); if (rc < nr_pages) { if (rc > 0) { @@ -242,19 +250,22 @@ static int increase_reservation(unsigned BUG_ON(page == NULL); pfn = page_to_pfn(page); + mfn = frame_list[i]; BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) && phys_to_machine_mapping_valid(pfn)); - set_phys_to_machine(pfn, frame_list[i]); + for (j = 0; j < balloon_npages; j++, pfn++, mfn++) { + set_phys_to_machine(pfn, mfn); - /* Link back into the page tables if not highmem. */ - if (pfn < max_low_pfn) { - int ret; - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - mfn_pte(frame_list[i], PAGE_KERNEL), - 0); - BUG_ON(ret); + /* Link back into the page tables if not highmem. */ + if (pfn < max_low_pfn) { + int ret; + ret = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + mfn_pte(mfn, PAGE_KERNEL), + 0); + BUG_ON(ret); + } } /* Relinquish the page back to the allocator. */ @@ -264,7 +275,7 @@ static int increase_reservation(unsigned } balloon_stats.current_pages += nr_pages; - totalram_pages = balloon_stats.current_pages; + totalram_pages = balloon_stats.current_pages << balloon_order; out: spin_unlock_irqrestore(&balloon_lock, flags); @@ -274,13 +285,12 @@ static int increase_reservation(unsigned static int decrease_reservation(unsigned long nr_pages) { - unsigned long pfn, i, flags; + unsigned long pfn, i, j, flags; struct page *page; int need_sleep = 0; int ret; struct xen_memory_reservation reservation = { .address_bits = 0, - .extent_order = 0, .domid = DOMID_SELF }; @@ -288,7 +298,7 @@ static int decrease_reservation(unsigned nr_pages = ARRAY_SIZE(frame_list); for (i = 0; i < nr_pages; i++) { - if ((page = alloc_page(GFP_BALLOON)) == NULL) { + if ((page = alloc_pages(GFP_BALLOON, balloon_order)) == NULL) { nr_pages = i; need_sleep = 1; break; @@ -298,14 +308,6 @@ static int decrease_reservation(unsigned frame_list[i] = pfn_to_mfn(pfn); scrub_page(page); - - if (!PageHighMem(page)) { - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - __pte_ma(0), 0); - BUG_ON(ret); - } - } /* Ensure that ballooned highmem pages don't have kmaps. */ @@ -317,17 +319,26 @@ static int decrease_reservation(unsigned /* No more mappings: invalidate P2M and add to balloon. */ for (i = 0; i < nr_pages; i++) { pfn = mfn_to_pfn(frame_list[i]); - set_phys_to_machine(pfn, INVALID_P2M_ENTRY); balloon_append(pfn_to_page(pfn)); + for (j = 0; j < balloon_npages; j++, pfn++) { + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + if (!PageHighMem(page)) { + ret = HYPERVISOR_update_va_mapping( + (unsigned long)__va(pfn << PAGE_SHIFT), + __pte_ma(0), 0); + BUG_ON(ret); + } + } } set_xen_guest_handle(reservation.extent_start, frame_list); reservation.nr_extents = nr_pages; + reservation.extent_order = balloon_order; ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); BUG_ON(ret != nr_pages); balloon_stats.current_pages -= nr_pages; - totalram_pages = balloon_stats.current_pages; + totalram_pages = balloon_stats.current_pages << balloon_order; spin_unlock_irqrestore(&balloon_lock, flags); @@ -397,7 +408,7 @@ static void watch_target(struct xenbus_w /* The given memory/target value is in KiB, so it needs converting to * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. */ - balloon_set_new_target(new_target >> (PAGE_SHIFT - 10)); + balloon_set_new_target(new_target >> (PAGE_SHIFT - 10 + balloon_order)); } static int balloon_init_watcher(struct notifier_block *notifier, @@ -423,10 +434,13 @@ static int __init balloon_init(void) if (!xen_pv_domain()) return -ENODEV; - pr_info("xen_balloon: Initialising balloon driver.\n"); + pr_info("xen_balloon: Initialising balloon driver with page order %d.\n", + balloon_order); + + balloon_npages = 1 << balloon_order; - balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); - totalram_pages = balloon_stats.current_pages; + balloon_stats.current_pages = (min(xen_start_info->nr_pages, max_pfn)) >> balloon_order; + totalram_pages = balloon_stats.current_pages << balloon_order; balloon_stats.target_pages = balloon_stats.current_pages; balloon_stats.balloon_low = 0; balloon_stats.balloon_high = 0; @@ -440,10 +454,12 @@ static int __init balloon_init(void) register_balloon(&balloon_sysdev); /* Initialise the balloon with excess memory space. */ - for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) { - page = pfn_to_page(pfn); - if (!PageReserved(page)) - balloon_append(page); + if (!balloon_order) { + for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) { + page = pfn_to_page(pfn); + if (!PageReserved(page)) + balloon_append(page); + } } target_watch.callback = watch_target; @@ -464,6 +480,14 @@ static void balloon_exit(void) module_exit(balloon_exit); +static int __init balloon_parse_huge(char *s) +{ + balloon_order = 9; + return 1; +} + +__setup("balloon_hugepages", balloon_parse_huge); + #define BALLOON_SHOW(name, format, args...) \ static ssize_t show_##name(struct sys_device *dev, \ struct sysdev_attribute *attr, \ @@ -500,7 +524,7 @@ static ssize_t store_target_kb(struct sy target_bytes = simple_strtoull(buf, &endchar, 0) * 1024; - balloon_set_new_target(target_bytes >> PAGE_SHIFT); + balloon_set_new_target(target_bytes >> (PAGE_SHIFT + balloon_order)); return count; } @@ -514,7 +538,7 @@ static ssize_t show_target(struct sys_de { return sprintf(buf, "%llu\n", (unsigned long long)balloon_stats.target_pages - << PAGE_SHIFT); + << (PAGE_SHIFT + balloon_order)); } static ssize_t store_target(struct sys_device *dev, @@ -530,7 +554,7 @@ static ssize_t store_target(struct sys_d target_bytes = memparse(buf, &endchar); - balloon_set_new_target(target_bytes >> PAGE_SHIFT); + balloon_set_new_target(target_bytes >> (PAGE_SHIFT + balloon_order)); return count; } --Boundary-00=_6/7NKDbNAK7enDx Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --Boundary-00=_6/7NKDbNAK7enDx--