From nobody Tue Feb 10 14:32:53 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 166245002276965.6251769475233; Tue, 6 Sep 2022 00:40:22 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.399549.640799 (Exim 4.92) (envelope-from ) id 1oVTBh-00018c-TJ; Tue, 06 Sep 2022 07:40:01 +0000 Received: by outflank-mailman (output) from mailman id 399549.640799; Tue, 06 Sep 2022 07:40:01 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1oVTBh-00017v-O3; Tue, 06 Sep 2022 07:40:01 +0000 Received: by outflank-mailman (input) for mailman id 399549; Tue, 06 Sep 2022 07:40:00 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1oVTBg-0008BB-3R for xen-devel@lists.xenproject.org; Tue, 06 Sep 2022 07:40:00 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 1a7238db-2db7-11ed-af93-0125da4c0113; Tue, 06 Sep 2022 09:39:56 +0200 (CEST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7C042139F; Tue, 6 Sep 2022 00:40:04 -0700 (PDT) Received: from a011292.shanghai.arm.com (a011292.shanghai.arm.com [10.169.190.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 77E0C3F73D; Tue, 6 Sep 2022 00:40:23 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 1a7238db-2db7-11ed-af93-0125da4c0113 From: Penny Zheng To: xen-devel@lists.xenproject.org Cc: wei.chen@arm.com, Penny Zheng , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu , Penny Zheng Subject: [PATCH v12 6/6] xen: retrieve reserved pages on populate_physmap Date: Tue, 6 Sep 2022 15:39:19 +0800 Message-Id: <20220906073919.941934-7-Penny.Zheng@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220906073919.941934-1-Penny.Zheng@arm.com> References: <20220906073919.941934-1-Penny.Zheng@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1662450023571100001 When a static domain populates memory through populate_physmap at runtime, it shall retrieve reserved pages from resv_page_list to make sure that guest RAM is still restricted in statically configured memory regions. This commit also introduces a new helper acquire_reserved_page to make it w= ork. Signed-off-by: Penny Zheng Reviewed-by: Julien Grall --- v12 changes: - it should be acquire_domstatic_pages() calling unprepare_staticmem_pages() on failing - add in-code comment --- v11 change: - with assignment having failed and the page not exposed to the guest at any point, there is no need for scrubbing --- v10 changes: - add lock on the fail path --- v9 changes: - Use ASSERT_ALLOC_CONTEXT() in acquire_reserved_page - Add free_staticmem_pages to undo prepare_staticmem_pages when assign_domstatic_pages - Remove redundant static in error message --- v8 changes: - As concurrent free/allocate could modify the resv_page_list, we still need the lock --- v7 changes: - remove the lock, since we add the page to rsv_page_list after it has been totally freed. --- v6 changes: - drop the lock before returning --- v5 changes: - extract common codes for assigning pages into a helper assign_domstatic_p= ages - refine commit message - remove stub function acquire_reserved_page - Alloc/free of memory can happen concurrently. So access to rsv_page_list needs to be protected with a spinlock --- v4 changes=EF=BC=9A - miss dropping __init in acquire_domstatic_pages - add the page back to the reserved list in case of error - remove redundant printk - refine log message and make it warn level --- v3 changes: - move is_domain_using_staticmem to the common header file - remove #ifdef CONFIG_STATIC_MEMORY-ary - remove meaningless page_to_mfn(page) in error log --- v2 changes: - introduce acquire_reserved_page to retrieve reserved pages from resv_page_list - forbid non-zero-order requests in populate_physmap - let is_domain_static return ((void)(d), false) on x86 --- xen/common/memory.c | 23 +++++++++++++ xen/common/page_alloc.c | 74 +++++++++++++++++++++++++++++++++-------- xen/include/xen/mm.h | 1 + 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index bc89442ba5..ae8163a738 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -245,6 +245,29 @@ static void populate_physmap(struct memop_args *a) =20 mfn =3D _mfn(gpfn); } + else if ( is_domain_using_staticmem(d) ) + { + /* + * No easy way to guarantee the retrieved pages are contig= uous, + * so forbid non-zero-order requests here. + */ + if ( a->extent_order !=3D 0 ) + { + gdprintk(XENLOG_WARNING, + "Cannot allocate static order-%u pages for %p= d\n", + a->extent_order, d); + goto out; + } + + mfn =3D acquire_reserved_page(d, a->memflags); + if ( mfn_eq(mfn, INVALID_MFN) ) + { + gdprintk(XENLOG_WARNING, + "%pd: failed to retrieve a reserved page\n", + d); + goto out; + } + } else { page =3D alloc_domheap_pages(d, a->extent_order, a->memfla= gs); diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 18d34d1b69..215f4c234b 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -2755,9 +2755,8 @@ void free_domstatic_page(struct page_info *page) put_domain(d); } =20 -static bool __init prepare_staticmem_pages(struct page_info *pg, - unsigned long nr_mfns, - unsigned int memflags) +static bool prepare_staticmem_pages(struct page_info *pg, unsigned long nr= _mfns, + unsigned int memflags) { bool need_tlbflush =3D false; uint32_t tlbflush_timestamp =3D 0; @@ -2838,6 +2837,25 @@ static struct page_info * __init acquire_staticmem_p= ages(mfn_t smfn, return pg; } =20 +static int assign_domstatic_pages(struct domain *d, struct page_info *pg, + unsigned int nr_mfns, unsigned int memfl= ags) +{ + if ( !d || (memflags & (MEMF_no_owner | MEMF_no_refcount)) ) + { + /* + * Respective handling omitted here because right now + * acquired static memory is only for guest RAM. + */ + ASSERT_UNREACHABLE(); + return -EINVAL; + } + + if ( assign_pages(pg, nr_mfns, d, memflags) ) + return -EINVAL; + + return 0; +} + /* * Acquire nr_mfns contiguous pages, starting at #smfn, of static memory, * then assign them to one specific domain #d. @@ -2853,17 +2871,7 @@ int __init acquire_domstatic_pages(struct domain *d,= mfn_t smfn, if ( !pg ) return -ENOENT; =20 - if ( !d || (memflags & (MEMF_no_owner | MEMF_no_refcount)) ) - { - /* - * Respective handling omitted here because right now - * acquired static memory is only for guest RAM. - */ - ASSERT_UNREACHABLE(); - return -EINVAL; - } - - if ( assign_pages(pg, nr_mfns, d, memflags) ) + if ( assign_domstatic_pages(d, pg, nr_mfns, memflags) ) { unprepare_staticmem_pages(pg, nr_mfns, memflags & MEMF_no_scrub); return -EINVAL; @@ -2871,6 +2879,44 @@ int __init acquire_domstatic_pages(struct domain *d,= mfn_t smfn, =20 return 0; } + +/* + * Acquire a page from reserved page list(resv_page_list), when populating + * memory for static domain on runtime. + */ +mfn_t acquire_reserved_page(struct domain *d, unsigned int memflags) +{ + struct page_info *page; + + ASSERT_ALLOC_CONTEXT(); + + /* Acquire a page from reserved page list(resv_page_list). */ + spin_lock(&d->page_alloc_lock); + page =3D page_list_remove_head(&d->resv_page_list); + spin_unlock(&d->page_alloc_lock); + if ( unlikely(!page) ) + return INVALID_MFN; + + if ( !prepare_staticmem_pages(page, 1, memflags) ) + goto fail; + + if ( assign_domstatic_pages(d, page, 1, memflags) ) + goto fail_assign; + + return page_to_mfn(page); + + fail_assign: + /* + * The page was never accessible by the domain. So scrubbing can be + * skipped + */ + unprepare_staticmem_pages(page, 1, false); + fail: + spin_lock(&d->page_alloc_lock); + page_list_add_tail(page, &d->resv_page_list); + spin_unlock(&d->page_alloc_lock); + return INVALID_MFN; +} #endif =20 /* diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index 93db3c4418..a925028ab3 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -198,6 +198,7 @@ struct npfec { #else #define MAX_ORDER 20 /* 2^20 contiguous pages */ #endif +mfn_t acquire_reserved_page(struct domain *d, unsigned int memflags); =20 /* Private domain structs for DOMID_XEN, DOMID_IO, etc. */ extern struct domain *dom_xen, *dom_io; --=20 2.25.1