From patchwork Tue May 14 12:11:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 10942789 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F173713AD for ; Tue, 14 May 2019 12:12:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFE36286E3 for ; Tue, 14 May 2019 12:12:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DC52628710; Tue, 14 May 2019 12:12:55 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 62656286E3 for ; Tue, 14 May 2019 12:12:55 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hQWHM-0006CQ-4W; Tue, 14 May 2019 12:11:32 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hQWHL-0006CL-DD for xen-devel@lists.xenproject.org; Tue, 14 May 2019 12:11:31 +0000 X-Inumbo-ID: 65eab8c2-7641-11e9-a999-475e14e1efe4 Received: from prv1-mh.provo.novell.com (unknown [137.65.248.33]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 65eab8c2-7641-11e9-a999-475e14e1efe4; Tue, 14 May 2019 12:11:27 +0000 (UTC) Received: from INET-PRV1-MTA by prv1-mh.provo.novell.com with Novell_GroupWise; Tue, 14 May 2019 06:11:25 -0600 Message-Id: <5CDAB06B020000780022E990@prv1-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 18.1.0 Date: Tue, 14 May 2019 06:11:23 -0600 From: "Jan Beulich" To: "xen-devel" Mime-Version: 1.0 Content-Disposition: inline Subject: [Xen-devel] [PATCH v2] IOMMU/x86: make page type checks consistent when mapping pages X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: George Dunlap , Andrew Cooper Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP There are currently three more or less different checks: - _get_page_type() adjusts the IOMMU mappings according to the new type alone, - arch_iommu_populate_page_table() wants just the type to be PGT_writable_page, - iommu_hwdom_init() additionally permits all other types with a type refcount of zero. The canonical one is in _get_page_type(), and as of XSA-288 arch_iommu_populate_page_table() also has no need anymore to deal with PGT_none pages. In the PV Dom0 case, however, PGT_none pages are still necessary to consider, since in that case pages don't get handed to guest_physmap_add_entry(). Furthermore, the function so far also established r/o mappings, which is not in line with the rules set forth by the XSA-288 change. For arch_iommu_populate_page_table() to not encounter PGT_none pages anymore even in cases where the IOMMU gets enabled for a domain only when it is already running, replace the IOMMU dependency in guest_physmap_add_entry()'s handling of PV guests to check just the system wide state instead of the domain property. Unfortunately (partially) replacing the iommu_map() call in iommu_hwdom_init() implies resurrecting the flush suppression that got previously eliminated. Note that the call to iommu_map() can't be removed at this point in time - Dom0's initial allocation gets its page types set before iommu_hwdom_init() runs. Signed-off-by: Jan Beulich --- v2: Fix IOTLB flushing. Exclude PVH. Use type safe local variables. --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -873,11 +873,11 @@ guest_physmap_add_entry(struct domain *d * * Retain this property by grabbing a writable type ref and then * dropping it immediately. The result will be pages that have a - * writable type (and an IOMMU entry), but a count of 0 (such that - * any guest-requested type changes succeed and remove the IOMMU - * entry). + * writable type (and an IOMMU entry if necessary), but a count of 0 + * (such that any guest-requested type changes succeed and remove the + * IOMMU entry). */ - if ( !need_iommu_pt_sync(d) || t != p2m_ram_rw ) + if ( !iommu_enabled || t != p2m_ram_rw ) return 0; for ( i = 0; i < (1UL << page_order); ++i, ++page ) --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -192,28 +192,46 @@ void __hwdom_init iommu_hwdom_init(struc unsigned int i = 0, flush_flags = 0; int rc = 0; + this_cpu(iommu_dont_flush_iotlb) = true; + page_list_for_each ( page, &d->page_list ) { - unsigned long mfn = mfn_x(page_to_mfn(page)); - unsigned long dfn = mfn_to_gmfn(d, mfn); - unsigned int mapping = IOMMUF_readable; - int ret; - - if ( ((page->u.inuse.type_info & PGT_count_mask) == 0) || - ((page->u.inuse.type_info & PGT_type_mask) - == PGT_writable_page) ) - mapping |= IOMMUF_writable; - - ret = iommu_map(d, _dfn(dfn), _mfn(mfn), 0, mapping, - &flush_flags); - - if ( !rc ) - rc = ret; + switch ( page->u.inuse.type_info & PGT_type_mask ) + { + case PGT_none: + if ( is_pv_domain(d) ) + { + ASSERT(!(page->u.inuse.type_info & PGT_count_mask)); + if ( get_page_and_type(page, d, PGT_writable_page) ) + { + put_page_and_type(page); + flush_flags |= IOMMUF_readable | IOMMUF_writable; + } + else if ( !rc ) + rc = -EBUSY; + break; + } + /* fall through */ + case PGT_writable_page: + { + mfn_t mfn = page_to_mfn(page); + dfn_t dfn = _dfn(mfn_to_gmfn(d, mfn_x(mfn))); + int ret = iommu_map(d, dfn, mfn, 0, + IOMMUF_readable | IOMMUF_writable, + &flush_flags); + + if ( !rc ) + rc = ret; + break; + } + } if ( !(i++ & 0xfffff) ) process_pending_softirqs(); } + this_cpu(iommu_dont_flush_iotlb) = false; + /* Use while-break to avoid compiler warning */ while ( iommu_iotlb_flush_all(d, flush_flags) ) break;