From patchwork Thu Aug 11 09:18:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 9274779 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CE7A460231 for ; Thu, 11 Aug 2016 09:21:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BCC7728581 for ; Thu, 11 Aug 2016 09:21:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B1AA3285B0; Thu, 11 Aug 2016 09:21:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EE16F285B3 for ; Thu, 11 Aug 2016 09:21:25 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bXm8J-0002dN-24; Thu, 11 Aug 2016 09:18:35 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bXm8G-0002QO-9n; Thu, 11 Aug 2016 09:18:32 +0000 Received: from [85.158.139.211] by server-7.bemta-5.messagelabs.com id C8/FC-05127-7E24CA75; Thu, 11 Aug 2016 09:18:31 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrNLMWRWlGSWpSXmKPExsVyuP0Ov+4zpzX hBs0NZhZvvy5htvi+ZTKTA5PH4Q9XWAIYo1gz85LyKxJYM26/X8xSsMGmYu/Vd6wNjFf1uhg5 OSQEjCTeTvzH1MXIxSEksJBRYvnmmYwgCTYBVYkN10+xgtgiAm4SX77PYgOxmQUiJOZ8OMUCY gsLOEi8WzcFrJ4FqH7m9llg9bxA8T+XlrJCLJCTuD5zOhOIzQkUXzP9I5gtJGAv8WXOJZYJjN wLGBlWMWoUpxaVpRbpGhnrJRVlpmeU5CZm5ugaGpjq5aYWFyemp+YkJhXrJefnbmIEerqegYF xB+OOdr9DjJIcTEqivMIxq8OF+JLyUyozEosz4otKc1KLDzHKcHAoSfCKAANHSLAoNT21Ii0z BxhyMGkJDh4lEd77jkBp3uKCxNzizHSI1ClGRSlx3uMgCQGQREZpHlwbLMwvMcpKCfMyMjAwC PEUpBblZpagyr9iFOdgVBLmXQUyhSczrwRu+iugxUxAi0+YgS0uSURISTUwsrT8lP5w8K7A6e YpvCatTgr3swJ/zF1aFqx+zvjugrUiRV/2+vgLvXnyqeTeJ51Py/mW6lRta6z8+aTpfYM8R/w qE6mviq3hWypPZ7zbbd13ed7DpZeTDB5N0dHZlFOmEnjnjf+9v4oPhGSu1abKmr8Ju2VeVazP 2qBefkFEqTzijKRyzb2PSizFGYmGWsxFxYkAAnnyrm4CAAA= X-Env-Sender: jgross@suse.com X-Msg-Ref: server-13.tower-206.messagelabs.com!1470907110!38364378!1 X-Originating-IP: [195.135.220.15] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.84; banners=-,-,- X-VirusChecked: Checked Received: (qmail 20090 invoked from network); 11 Aug 2016 09:18:30 -0000 Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by server-13.tower-206.messagelabs.com with DHE-RSA-CAMELLIA256-SHA encrypted SMTP; 11 Aug 2016 09:18:30 -0000 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 856ABAC21; Thu, 11 Aug 2016 09:18:30 +0000 (UTC) From: Juergen Gross To: minios-devel@lists.xenproject.org, xen-devel@lists.xenproject.org Date: Thu, 11 Aug 2016 11:18:20 +0200 Message-Id: <1470907102-14656-18-git-send-email-jgross@suse.com> X-Mailer: git-send-email 2.6.6 In-Reply-To: <1470907102-14656-1-git-send-email-jgross@suse.com> References: <1470907102-14656-1-git-send-email-jgross@suse.com> Cc: Juergen Gross , samuel.thibault@ens-lyon.org, wei.liu2@citrix.com Subject: [Xen-devel] [PATCH v3 17/19] mini-os: add support for ballooning up X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add support for ballooning the domain up by a specified amount of pages. Following steps are performed: - extending the p2m map - extending the page allocator's bitmap - getting new memory pages from the hypervisor - adding the memory at the current end of guest memory Signed-off-by: Juergen Gross Reviewed-by: Samuel Thibault --- V3: change "if" to "while" in balloon_up() as requested by Samuel Thibault --- arch/arm/balloon.c | 9 ++++++ arch/x86/balloon.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ balloon.c | 64 +++++++++++++++++++++++++++++++++++++ include/balloon.h | 5 +++ mm.c | 4 +++ 5 files changed, 176 insertions(+) diff --git a/arch/arm/balloon.c b/arch/arm/balloon.c index 549e51b..7f35328 100644 --- a/arch/arm/balloon.c +++ b/arch/arm/balloon.c @@ -27,4 +27,13 @@ unsigned long virt_kernel_area_end; /* TODO: find a virtual area */ +int arch_expand_p2m(unsigned long max_pfn) +{ + return 0; +} + +void arch_pfn_add(unsigned long pfn, unsigned long mfn) +{ +} + #endif diff --git a/arch/x86/balloon.c b/arch/x86/balloon.c index a7f20e4..42389e4 100644 --- a/arch/x86/balloon.c +++ b/arch/x86/balloon.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -30,9 +31,36 @@ unsigned long virt_kernel_area_end = VIRT_KERNEL_AREA; +static void p2m_invalidate(unsigned long *list, unsigned long start_idx) +{ + unsigned long idx; + + for ( idx = start_idx; idx < P2M_ENTRIES; idx++ ) + list[idx] = INVALID_P2M_ENTRY; +} + +static inline unsigned long *p2m_l3list(void) +{ + return mfn_to_virt(HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list); +} + +static inline unsigned long *p2m_to_virt(unsigned long p2m) +{ + return ( p2m == INVALID_P2M_ENTRY ) ? NULL : mfn_to_virt(p2m); +} + void arch_remap_p2m(unsigned long max_pfn) { unsigned long pfn; + unsigned long *l3_list, *l2_list, *l1_list; + + l3_list = p2m_l3list(); + l2_list = p2m_to_virt(l3_list[L3_P2M_IDX(max_pfn - 1)]); + l1_list = p2m_to_virt(l2_list[L2_P2M_IDX(max_pfn - 1)]); + + p2m_invalidate(l3_list, L3_P2M_IDX(max_pfn - 1) + 1); + p2m_invalidate(l2_list, L2_P2M_IDX(max_pfn - 1) + 1); + p2m_invalidate(l1_list, L1_P2M_IDX(max_pfn - 1) + 1); if ( p2m_pages(nr_max_pages) <= p2m_pages(max_pfn) ) return; @@ -50,4 +78,70 @@ void arch_remap_p2m(unsigned long max_pfn) ASSERT(virt_kernel_area_end <= VIRT_DEMAND_AREA); } +int arch_expand_p2m(unsigned long max_pfn) +{ + unsigned long pfn; + unsigned long *l1_list, *l2_list, *l3_list; + + p2m_chk_pfn(max_pfn - 1); + l3_list = p2m_l3list(); + + for ( pfn = (HYPERVISOR_shared_info->arch.max_pfn + P2M_MASK) & ~P2M_MASK; + pfn < max_pfn; pfn += P2M_ENTRIES ) + { + l2_list = p2m_to_virt(l3_list[L3_P2M_IDX(pfn)]); + if ( !l2_list ) + { + l2_list = (unsigned long*)alloc_page(); + if ( !l2_list ) + return -ENOMEM; + p2m_invalidate(l2_list, 0); + l3_list[L3_P2M_IDX(pfn)] = virt_to_mfn(l2_list); + } + l1_list = p2m_to_virt(l2_list[L2_P2M_IDX(pfn)]); + if ( !l1_list ) + { + l1_list = (unsigned long*)alloc_page(); + if ( !l1_list ) + return -ENOMEM; + p2m_invalidate(l1_list, 0); + l2_list[L2_P2M_IDX(pfn)] = virt_to_mfn(l1_list); + + if ( map_frame_rw((unsigned long)(phys_to_machine_mapping + pfn), + l2_list[L2_P2M_IDX(pfn)]) ) + return -ENOMEM; + } + } + + HYPERVISOR_shared_info->arch.max_pfn = max_pfn; + + /* Make sure the new last page can be mapped. */ + if ( !need_pgt((unsigned long)pfn_to_virt(max_pfn - 1)) ) + return -ENOMEM; + + return 0; +} + +void arch_pfn_add(unsigned long pfn, unsigned long mfn) +{ + mmu_update_t mmu_updates[1]; + pgentry_t *pgt; + int rc; + + phys_to_machine_mapping[pfn] = mfn; + + pgt = need_pgt((unsigned long)pfn_to_virt(pfn)); + ASSERT(pgt); + mmu_updates[0].ptr = virt_to_mach(pgt) | MMU_NORMAL_PT_UPDATE; + mmu_updates[0].val = (pgentry_t)(mfn << PAGE_SHIFT) | + _PAGE_PRESENT | _PAGE_RW; + rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF); + if ( rc < 0 ) + { + printk("ERROR: build_pagetable(): PTE could not be updated\n"); + printk(" mmu_update failed with rc=%d\n", rc); + do_exit(); + } +} + #endif diff --git a/balloon.c b/balloon.c index 78b30af..07ef532 100644 --- a/balloon.c +++ b/balloon.c @@ -23,11 +23,13 @@ #include #include +#include #include #include #include unsigned long nr_max_pages; +unsigned long nr_mem_pages; void get_max_pages(void) { @@ -62,3 +64,65 @@ void mm_alloc_bitmap_remap(void) virt_kernel_area_end += round_pgup((nr_max_pages + 1) >> (PAGE_SHIFT + 3)); ASSERT(virt_kernel_area_end <= VIRT_DEMAND_AREA); } + +#define N_BALLOON_FRAMES 64 +static unsigned long balloon_frames[N_BALLOON_FRAMES]; + +int balloon_up(unsigned long n_pages) +{ + unsigned long page, pfn; + int rc; + struct xen_memory_reservation reservation = { + .address_bits = 0, + .extent_order = 0, + .domid = DOMID_SELF + }; + + if ( n_pages > nr_max_pages - nr_mem_pages ) + n_pages = nr_max_pages - nr_mem_pages; + if ( n_pages > N_BALLOON_FRAMES ) + n_pages = N_BALLOON_FRAMES; + + /* Resize alloc_bitmap if necessary. */ + while ( mm_bitmap_size * 8 < nr_mem_pages + n_pages ) + { + page = alloc_page(); + if ( !page ) + return -ENOMEM; + + memset((void *)page, ~0, PAGE_SIZE); + if ( map_frame_rw((unsigned long)mm_bitmap + mm_bitmap_size, + virt_to_mfn(page)) ) + { + free_page((void *)page); + return -ENOMEM; + } + + mm_bitmap_size += PAGE_SIZE; + } + + rc = arch_expand_p2m(nr_mem_pages + n_pages); + if ( rc ) + return rc; + + /* Get new memory from hypervisor. */ + for ( pfn = 0; pfn < n_pages; pfn++ ) + { + balloon_frames[pfn] = nr_mem_pages + pfn; + } + set_xen_guest_handle(reservation.extent_start, balloon_frames); + reservation.nr_extents = n_pages; + rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); + if ( rc <= 0 ) + return rc; + + for ( pfn = 0; pfn < rc; pfn++ ) + { + arch_pfn_add(nr_mem_pages + pfn, balloon_frames[pfn]); + free_page(pfn_to_virt(nr_mem_pages + pfn)); + } + + nr_mem_pages += rc; + + return rc; +} diff --git a/include/balloon.h b/include/balloon.h index 9154f44..5ec1bbb 100644 --- a/include/balloon.h +++ b/include/balloon.h @@ -28,10 +28,15 @@ extern unsigned long nr_max_pages; extern unsigned long virt_kernel_area_end; +extern unsigned long nr_mem_pages; void get_max_pages(void); +int balloon_up(unsigned long n_pages); + void arch_remap_p2m(unsigned long max_pfn); void mm_alloc_bitmap_remap(void); +int arch_expand_p2m(unsigned long max_pfn); +void arch_pfn_add(unsigned long pfn, unsigned long mfn); #else /* CONFIG_BALLOON */ diff --git a/mm.c b/mm.c index e2f55af..5364079 100644 --- a/mm.c +++ b/mm.c @@ -382,6 +382,10 @@ void init_mm(void) arch_init_p2m(max_pfn); arch_init_demand_mapping_area(); + +#ifdef CONFIG_BALLOON + nr_mem_pages = max_pfn; +#endif } void fini_mm(void)