From patchwork Thu Aug 11 11:06:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?SsO8cmdlbiBHcm/Dnw==?= X-Patchwork-Id: 9275087 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 2FDA4600CB for ; Thu, 11 Aug 2016 11:09:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F6252858B for ; Thu, 11 Aug 2016 11:09:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1437828605; Thu, 11 Aug 2016 11:09:06 +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 574AF2858B for ; Thu, 11 Aug 2016 11:09:05 +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 1bXnoy-0007gp-6m; Thu, 11 Aug 2016 11:06:44 +0000 Received: from mail6.bemta6.messagelabs.com ([85.158.143.247]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bXnow-0007gL-Ou; Thu, 11 Aug 2016 11:06:42 +0000 Received: from [193.109.254.147] by server-8.bemta-6.messagelabs.com id AF/FC-05361-14C5CA75; Thu, 11 Aug 2016 11:06:41 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrFLMWRWlGSWpSXmKPExsVyuP0Ov65jzJp wgylbpC3efl3CbPF9y2QmByaPwx+usAQwRrFm5iXlVySwZvzYN4W94IRNReeu/+wNjG/1uhg5 OSQEjCTeTvzH1MXIxSEksJBR4viuzWwgCTYBVYkN10+xgtgiAm4SX77PAoszC0RIzPlwigXEF hZwkHjwcB9YnAWofu+JxWD1vAL2EjNnrWCBWCAncX3mdCYQmxOofkXbN2YQWwioZuLjFSwTGL kXMDKsYlQvTi0qSy3SNdVLKspMzyjJTczM0TU0MNPLTS0uTkxPzUlMKtZLzs/dxAj0MwMQ7GC cftn/EKMkB5OSKK9wzOpwIb6k/JTKjMTijPii0pzU4kOMMhwcShK8DVFrwoUEi1LTUyvSMnOA AQeTluDgURLhPQ2S5i0uSMwtzkyHSJ1iVJQSh0gIgCQySvPg2mBBfolRVkqYlxHoECGegtSi3 MwSVPlXjOIcjErCvFNApvBk5pXATX8FtJgJaPEJM7DFJYkIKakGRv2oKX9+9T/n0Vqm6fu9kW UJL9cvtpCcEsNjj+P91DhuKBie6r7Xb33j5T2+QxeOLSz/Z/vUvCmS45/lCoFf4Ysu5TNfEGs O2uYYuG75yxl/nZ56cSv/EOvTuOKr+eliucB69XOpZwKDXdcyNenkr4n2uDvZckOR7JHN8sv2 /bUy027803hkgRJLcUaioRZzUXEiADoeDiJtAgAA X-Env-Sender: jgross@suse.com X-Msg-Ref: server-4.tower-27.messagelabs.com!1470913601!52645200!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 33207 invoked from network); 11 Aug 2016 11:06:41 -0000 Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by server-4.tower-27.messagelabs.com with DHE-RSA-CAMELLIA256-SHA encrypted SMTP; 11 Aug 2016 11:06:41 -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 C9F65AC21; Thu, 11 Aug 2016 11:06:40 +0000 (UTC) From: Juergen Gross To: minios-devel@lists.xenproject.org, xen-devel@lists.xenproject.org Date: Thu, 11 Aug 2016 13:06:37 +0200 Message-Id: <1470913597-30133-2-git-send-email-jgross@suse.com> X-Mailer: git-send-email 2.6.6 In-Reply-To: <1470913597-30133-1-git-send-email-jgross@suse.com> References: <1470913597-30133-1-git-send-email-jgross@suse.com> Cc: Juergen Gross , samuel.thibault@ens-lyon.org, wei.liu2@citrix.com Subject: [Xen-devel] [PATCH v4 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 0a3342c..e1af778 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_alloc_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_alloc_bitmap + mm_alloc_bitmap_size, + virt_to_mfn(page)) ) + { + free_page((void *)page); + return -ENOMEM; + } + + mm_alloc_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 9e3a479..9a048c3 100644 --- a/mm.c +++ b/mm.c @@ -383,6 +383,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)