From patchwork Tue Mar 10 17:49:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 11430019 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 438D792A for ; Tue, 10 Mar 2020 17:52:02 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 27DA321927 for ; Tue, 10 Mar 2020 17:52:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 27DA321927 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=xen.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jBj0o-0008Uy-Jq; Tue, 10 Mar 2020 17:49:50 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jBj0m-0008UR-JS for xen-devel@lists.xenproject.org; Tue, 10 Mar 2020 17:49:48 +0000 X-Inumbo-ID: 890665e2-62f7-11ea-92cf-bc764e2007e4 Received: from smtp-fw-2101.amazon.com (unknown [72.21.196.25]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 890665e2-62f7-11ea-92cf-bc764e2007e4; Tue, 10 Mar 2020 17:49:48 +0000 (UTC) IronPort-SDR: oX/UlJu7eG6FxjcRLT2HKn6kKW40hEZs37AgDxuizfy5WTSEAZfT9hQhOsfZguxJRMAOTh1dIt lmRPTrfJHvlg== X-IronPort-AV: E=Sophos;i="5.70,537,1574121600"; d="scan'208";a="20895789" Received: from iad12-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-2a-53356bf6.us-west-2.amazon.com) ([10.43.8.2]) by smtp-border-fw-out-2101.iad2.amazon.com with ESMTP; 10 Mar 2020 17:49:45 +0000 Received: from EX13MTAUEA002.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan2.pdx.amazon.com [10.170.41.162]) by email-inbound-relay-2a-53356bf6.us-west-2.amazon.com (Postfix) with ESMTPS id 22425A27A7; Tue, 10 Mar 2020 17:49:44 +0000 (UTC) Received: from EX13D32EUB003.ant.amazon.com (10.43.166.165) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Tue, 10 Mar 2020 17:49:33 +0000 Received: from EX13MTAUEB002.ant.amazon.com (10.43.60.12) by EX13D32EUB003.ant.amazon.com (10.43.166.165) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Tue, 10 Mar 2020 17:49:32 +0000 Received: from u2f063a87eabd5f.cbg10.amazon.com (10.125.106.135) by mail-relay.amazon.com (10.43.60.234) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Tue, 10 Mar 2020 17:49:30 +0000 From: To: Date: Tue, 10 Mar 2020 17:49:17 +0000 Message-ID: <20200310174917.1514-6-paul@xen.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200310174917.1514-1-paul@xen.org> References: <20200310174917.1514-1-paul@xen.org> MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH v6 5/5] domain: use PGC_extra domheap page for shared_info X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Julien Grall , Wei Liu , Paul Durrant , Andrew Cooper , Paul Durrant , Konrad Rzeszutek Wilk , Ian Jackson , George Dunlap , Jan Beulich , Volodymyr Babchuk Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Paul Durrant Currently shared_info is a shared xenheap page but shared xenheap pages complicate future plans for live-update of Xen so it is desirable to, where possible, not use them [1]. This patch therefore converts shared_info into a PGC_extra domheap page. This does entail freeing shared_info during domain_relinquish_resources() rather than domain_destroy() so care is needed to avoid de-referencing a NULL shared_info pointer hence some extra checks of 'is_dying' are needed. NOTE: For Arm, the call to free_shared_info() in arch_domain_destroy() is left in place since it is idempotent and called in the error path for arch_domain_create(). [1] See https://lists.xenproject.org/archives/html/xen-devel/2020-02/msg02018.html Signed-off-by: Paul Durrant --- Cc: Stefano Stabellini Cc: Julien Grall Cc: Volodymyr Babchuk Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Jan Beulich Cc: Konrad Rzeszutek Wilk Cc: Wei Liu v6: - Drop dump_shared_info() but tag the shared info in the 'ExtraPage' dump v5: - Incorporate new dump_shared_info() function v2: - Addressed comments from Julien - Expanded the commit comment to explain why this patch is wanted --- xen/arch/arm/domain.c | 2 ++ xen/arch/x86/domain.c | 10 +++++++--- xen/common/domain.c | 28 ++++++++++++++++++++++++---- xen/common/event_channel.c | 3 +++ xen/common/time.c | 15 +++++++++++++++ 5 files changed, 51 insertions(+), 7 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 5298d80bd2..741f6dd444 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -1005,6 +1005,8 @@ int domain_relinquish_resources(struct domain *d) BUG(); } + free_shared_info(d); + return 0; } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 2dda2dbca1..539b5d9fe0 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -260,9 +260,12 @@ void dump_pageframe_info(struct domain *d) page_list_for_each ( page, &d->extra_page_list ) { - printk(" ExtraPage %p: caf=%08lx, taf=%" PRtype_info "\n", + const char *tag = mfn_eq(page_to_mfn(page), d->shared_info.mfn) ? + "[SHARED INFO]" : ""; + + printk(" ExtraPage %p: caf=%08lx, taf=%" PRtype_info " %s\n", _p(mfn_x(page_to_mfn(page))), - page->count_info, page->u.inuse.type_info); + page->count_info, page->u.inuse.type_info, tag); } spin_unlock(&d->page_alloc_lock); } @@ -697,7 +700,6 @@ void arch_domain_destroy(struct domain *d) pv_domain_destroy(d); free_perdomain_mappings(d); - free_shared_info(d); cleanup_domain_irq_mapping(d); psr_domain_free(d); @@ -2252,6 +2254,8 @@ int domain_relinquish_resources(struct domain *d) if ( is_hvm_domain(d) ) hvm_domain_relinquish_resources(d); + free_shared_info(d); + return 0; } diff --git a/xen/common/domain.c b/xen/common/domain.c index 4ef0d3b21e..4f3266454f 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -1651,24 +1651,44 @@ int continue_hypercall_on_cpu( int alloc_shared_info(struct domain *d, unsigned int memflags) { - if ( (d->shared_info.virt = alloc_xenheap_pages(0, memflags)) == NULL ) + struct page_info *pg; + + pg = alloc_domheap_page(d, MEMF_no_refcount | memflags); + if ( !pg ) return -ENOMEM; - d->shared_info.mfn = virt_to_mfn(d->shared_info.virt); + if ( !get_page_and_type(pg, d, PGT_writable_page) ) + { + /* + * The domain should not be running at this point so there is + * no way we should reach this error path. + */ + ASSERT_UNREACHABLE(); + return -ENODATA; + } + + d->shared_info.mfn = page_to_mfn(pg); + d->shared_info.virt = __map_domain_page_global(pg); clear_page(d->shared_info.virt); - share_xen_page_with_guest(mfn_to_page(d->shared_info.mfn), d, SHARE_rw); return 0; } void free_shared_info(struct domain *d) { + struct page_info *pg; + if ( !d->shared_info.virt ) return; - free_xenheap_page(d->shared_info.virt); + unmap_domain_page_global(d->shared_info.virt); d->shared_info.virt = NULL; + + pg = mfn_to_page(d->shared_info.mfn); + + put_page_alloc_ref(pg); + put_page_and_type(pg); } /* diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index e86e2bfab0..a17422284d 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -1325,6 +1325,9 @@ void evtchn_destroy(struct domain *d) { unsigned int i; + /* This must be done before shared_info is freed */ + BUG_ON(!d->shared_info.virt); + /* After this barrier no new event-channel allocations can occur. */ BUG_ON(!d->is_dying); spin_barrier(&d->event_lock); diff --git a/xen/common/time.c b/xen/common/time.c index 58fa9abc40..ada02faf07 100644 --- a/xen/common/time.c +++ b/xen/common/time.c @@ -99,6 +99,18 @@ void update_domain_wallclock_time(struct domain *d) uint32_t *wc_version; uint64_t sec; + if ( d != current->domain ) + { + /* + * We need to check is_dying here as, if it is set, the + * shared_info may have been freed. To do this safely we need + * hold the domain lock. + */ + domain_lock(d); + if ( d->is_dying ) + goto unlock; + } + spin_lock(&wc_lock); wc_version = &shared_info(d, wc_version); @@ -121,6 +133,9 @@ void update_domain_wallclock_time(struct domain *d) *wc_version = version_update_end(*wc_version); spin_unlock(&wc_lock); + unlock: + if ( d != current->domain ) + domain_unlock(d); } /* Set clock to after 00:00:00 UTC, 1 January, 1970. */