>From 0d37840d4c3b6e838320ac9fb96855bbdf6513fb Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Fri, 25 Oct 2013 09:58:23 +0100 Subject: [PATCH] xen-ballon: fix and clean balloon driver Remove unused cruft from the Xen balloon driver, fix calling a sleepable malloc while holding the balloon mutex and do proper accounting of the memory used by the domain. --- sys/dev/xen/balloon/balloon.c | 193 +++++++++++------------------------------ 1 files changed, 50 insertions(+), 143 deletions(-) diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c index 9021abb..894aa9a 100644 --- a/sys/dev/xen/balloon/balloon.c +++ b/sys/dev/xen/balloon/balloon.c @@ -52,18 +52,13 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_BALLOON, "Balloon", "Xen Balloon Driver"); -struct mtx balloon_mutex; +/* Convert from KB (as fetched from xenstore) to number of PAGES */ +#define KB_TO_PAGE_SHIFT (PAGE_SHIFT - 10) -/* - * Protects atomic reservation decrease/increase against concurrent increases. - * Also protects non-atomic updates of current_pages and driver_pages, and - * balloon lists. - */ -struct mtx balloon_lock; +struct mtx balloon_mutex; /* We increase/decrease in batches which fit in a page */ static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; -#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0])) struct balloon_stats { /* We aim for 'current allocation' == 'target allocation'. */ @@ -116,15 +111,21 @@ static void balloon_process(void *unused); printk(KERN_WARNING "xen_mem: " fmt, ##args) /* balloon_append: add the given page to the balloon. */ -static void +static int balloon_append(vm_page_t page) { struct balloon_entry *entry; - entry = malloc(sizeof(struct balloon_entry), M_BALLOON, M_WAITOK); + mtx_assert(&balloon_mutex, MA_OWNED); + + entry = malloc(sizeof(struct balloon_entry), M_BALLOON, M_NOWAIT); + if (!entry) + return (ENOMEM); entry->page = page; STAILQ_INSERT_HEAD(&ballooned_pages, entry, list); bs.balloon_low++; + + return 0; } /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ @@ -134,6 +135,8 @@ balloon_retrieve(void) vm_page_t page; struct balloon_entry *entry; + mtx_assert(&balloon_mutex, MA_OWNED); + if (STAILQ_EMPTY(&ballooned_pages)) return NULL; @@ -210,10 +213,10 @@ increase_reservation(unsigned long nr_pages) .domid = DOMID_SELF }; - if (nr_pages > ARRAY_SIZE(frame_list)) - nr_pages = ARRAY_SIZE(frame_list); + mtx_assert(&balloon_mutex, MA_OWNED); - mtx_lock(&balloon_lock); + if (nr_pages > nitems(frame_list)) + nr_pages = nitems(frame_list); for (entry = STAILQ_FIRST(&ballooned_pages), i = 0; i < nr_pages; i++, entry = STAILQ_NEXT(entry, list)) { @@ -253,32 +256,13 @@ increase_reservation(unsigned long nr_pages) set_phys_to_machine(pfn, frame_list[i]); -#if 0 -#ifndef XENHVM - /* 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), - pfn_pte_ma(frame_list[i], PAGE_KERNEL), - 0); - PASSING(ret == 0, - ("HYPERVISOR_update_va_mapping failed")); - } -#endif -#endif - - /* Relinquish the page back to the allocator. */ vm_page_unwire(page, 0); vm_page_free(page); } bs.current_pages += nr_pages; - //totalram_pages = bs.current_pages; out: - mtx_unlock(&balloon_lock); - return 0; } @@ -295,8 +279,10 @@ decrease_reservation(unsigned long nr_pages) .domid = DOMID_SELF }; - if (nr_pages > ARRAY_SIZE(frame_list)) - nr_pages = ARRAY_SIZE(frame_list); + mtx_assert(&balloon_mutex, MA_OWNED); + + if (nr_pages > nitems(frame_list)) + nr_pages = nitems(frame_list); for (i = 0; i < nr_pages; i++) { if ((page = vm_page_alloc(NULL, 0, @@ -310,39 +296,15 @@ decrease_reservation(unsigned long nr_pages) pfn = (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT); frame_list[i] = PFNTOMFN(pfn); -#if 0 - if (!PageHighMem(page)) { - v = phys_to_virt(pfn << PAGE_SHIFT); - scrub_pages(v, 1); -#ifdef CONFIG_XEN - ret = HYPERVISOR_update_va_mapping( - (unsigned long)v, __pte_ma(0), 0); - BUG_ON(ret); -#endif - } -#endif -#ifdef CONFIG_XEN_SCRUB_PAGES - else { - v = kmap(page); - scrub_pages(v, 1); - kunmap(page); - } -#endif - } - -#ifdef CONFIG_XEN - /* Ensure that ballooned highmem pages don't have kmaps. */ - kmap_flush_unused(); - flush_tlb_all(); -#endif - - mtx_lock(&balloon_lock); - - /* No more mappings: invalidate P2M and add to balloon. */ - for (i = 0; i < nr_pages; i++) { - pfn = MFNTOPFN(frame_list[i]); set_phys_to_machine(pfn, INVALID_P2M_ENTRY); - balloon_append(PHYS_TO_VM_PAGE(pfn << PAGE_SHIFT)); + if (balloon_append(page)) { + vm_page_unwire(page, 0); + vm_page_free(page); + + nr_pages = i; + need_sleep = 1; + break; + } } set_xen_guest_handle(reservation.extent_start, frame_list); @@ -351,9 +313,6 @@ decrease_reservation(unsigned long nr_pages) KASSERT(ret == nr_pages, ("HYPERVISOR_memory_op failed")); bs.current_pages -= nr_pages; - //totalram_pages = bs.current_pages; - - mtx_unlock(&balloon_lock); return (need_sleep); } @@ -428,7 +387,7 @@ watch_target(struct xs_watch *watch, /* The given memory/target value is in KiB, so it needs converting to pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. */ - set_new_target(new_target >> (PAGE_SHIFT - 10)); + set_new_target(new_target >> KB_TO_PAGE_SHIFT); } @@ -456,18 +415,35 @@ balloon_init(void *arg) unsigned long pfn; #define max_pfn HYPERVISOR_shared_info->arch.max_pfn +#else + unsigned long long static_max, video_ram = 0; + int err; #endif if (!is_running_on_xen()) return; - mtx_init(&balloon_lock, "balloon_lock", NULL, MTX_DEF); mtx_init(&balloon_mutex, "balloon_mutex", NULL, MTX_DEF); #ifndef XENHVM bs.current_pages = min(xen_start_info->nr_pages, max_pfn); #else - bs.current_pages = physmem; + err = xs_scanf(XST_NIL, "memory", "static-max", NULL, "%llu", + &static_max); + xs_scanf(XST_NIL, "memory", "videoram", NULL, "%llu", + &video_ram); + if (err) { + /* + * Using physmem is not accurate, prefer xenstore + * values as given by Xen when possible. + */ + static_max = physmem; + } else { + static_max -= video_ram; + static_max >>= KB_TO_PAGE_SHIFT; + } + + bs.current_pages = static_max; #endif bs.target_pages = bs.current_pages; bs.balloon_low = 0; @@ -497,76 +473,7 @@ void balloon_update_driver_allowance(long delta); void balloon_update_driver_allowance(long delta) { - mtx_lock(&balloon_lock); + mtx_lock(&balloon_mutex); bs.driver_pages += delta; - mtx_unlock(&balloon_lock); -} - -#if 0 -static int dealloc_pte_fn( - pte_t *pte, struct page *pte_page, unsigned long addr, void *data) -{ - unsigned long mfn = pte_mfn(*pte); - int ret; - struct xen_memory_reservation reservation = { - .extent_start = &mfn, - .nr_extents = 1, - .extent_order = 0, - .domid = DOMID_SELF - }; - set_pte_at(&init_mm, addr, pte, __pte_ma(0)); - set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY); - ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); - KASSERT(ret == 1, ("HYPERVISOR_memory_op failed")); - return 0; -} - -#endif - -#if 0 -vm_page_t -balloon_alloc_empty_page_range(unsigned long nr_pages) -{ - vm_page_t pages; - int i, rc; - unsigned long *mfn_list; - struct xen_memory_reservation reservation = { - .address_bits = 0, - .extent_order = 0, - .domid = DOMID_SELF - }; - - pages = vm_page_alloc_contig(nr_pages, 0, -1, 4, 4) - if (pages == NULL) - return NULL; - - mfn_list = malloc(nr_pages*sizeof(unsigned long), M_DEVBUF, M_WAITOK); - - for (i = 0; i < nr_pages; i++) { - mfn_list[i] = PFNTOMFN(VM_PAGE_TO_PHYS(pages[i]) >> PAGE_SHIFT); - PFNTOMFN(i) = INVALID_P2M_ENTRY; - reservation.extent_start = mfn_list; - reservation.nr_extents = nr_pages; - rc = HYPERVISOR_memory_op(XENMEM_decrease_reservation, - &reservation); - KASSERT(rc == nr_pages, ("HYPERVISOR_memory_op failed")); - } - - current_pages -= nr_pages; - - wakeup(balloon_process); - - return pages; -} - -void -balloon_dealloc_empty_page_range(vm_page_t page, unsigned long nr_pages) -{ - unsigned long i; - - for (i = 0; i < nr_pages; i++) - balloon_append(page + i); - - wakeup(balloon_process); + mtx_unlock(&balloon_mutex); } -#endif -- 1.7.7.5 (Apple Git-26)