From patchwork Wed May 18 08:08:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quan Xu X-Patchwork-Id: 9116781 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4A516BF29F for ; Wed, 18 May 2016 08:14:37 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0F7D920303 for ; Wed, 18 May 2016 08:14:36 +0000 (UTC) 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.kernel.org (Postfix) with ESMTPS id C729920138 for ; Wed, 18 May 2016 08:14:34 +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 1b2wah-0004gJ-EH; Wed, 18 May 2016 08:12:27 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1b2waf-0004g1-UV for xen-devel@lists.xen.org; Wed, 18 May 2016 08:12:26 +0000 Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id D0/F8-03814-9E32C375; Wed, 18 May 2016 08:12:25 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrDLMWRWlGSWpSXmKPExsVywNykQveFsk2 4wdvD/BZLPi5mcWD0OLr7N1MAYxRrZl5SfkUCa8bD1Y4FOx0rHpw9x9rAOF2vi5GDQ0igQmLe 1cguRk4OCQFeiSPLZrBC2P4S1548YAaxhQRqJE6tncsCYrMJKEpsuLicCcQWEZCWuPb5MmMXI xcHs8ALRom2lh5GkISwgKVE093JYINYBFQlrl5YyAZi8wo4SjR9+c0IsUBBYtmXtWALOAWcJF YsnMAOscxRYv7yacwTGHkXMDKsYtQoTi0qSy3SNTTVSyrKTM8oyU3MzNE1NDDWy00tLk5MT81 JTCrWS87P3cQIDAUGINjBuGa75yFGSQ4mJVHerfI24UJ8SfkplRmJxRnxRaU5qcWHGGU4OJQk eG8qAeUEi1LTUyvSMnOAQQmTluDgURLhNQEGphBvcUFibnFmOkTqFKOilDjvbZA+AZBERmkeX BssEi4xykoJ8zICHSLEU5BalJtZgir/ilGcg1FJmPcfyBSezLwSuOmvgBYzAS2+JQa2uCQRIS XVwLgqZvWCV7eeynMrfXv4MyP2Ipek6JTGuKOvf+k5nBKZ16W8+XfuKu6NhzZvvG2rdeL1Ar7 YrIRD1b3N0+9u2DHh6CN+5yJ1td1WDLKSxprZW/b9vLPmo/TiW6se/f3Pwn/4G9eBpYdsTvp9 iLu3LomhcWLA/Onbf2bHve8rKnzmIRyztuzKSbtoJZbijERDLeai4kQAfjm8jX8CAAA= X-Env-Sender: quan.xu@intel.com X-Msg-Ref: server-13.tower-31.messagelabs.com!1463559142!40094725!2 X-Originating-IP: [192.55.52.120] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.34; banners=-,-,- X-VirusChecked: Checked Received: (qmail 26453 invoked from network); 18 May 2016 08:12:23 -0000 Received: from mga04.intel.com (HELO mga04.intel.com) (192.55.52.120) by server-13.tower-31.messagelabs.com with SMTP; 18 May 2016 08:12:23 -0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP; 18 May 2016 01:12:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,328,1459839600"; d="scan'208";a="979407823" Received: from xen-commits.sh.intel.com ([10.239.82.178]) by orsmga002.jf.intel.com with ESMTP; 18 May 2016 01:12:21 -0700 From: Quan Xu To: xen-devel@lists.xen.org Date: Wed, 18 May 2016 16:08:22 +0800 Message-Id: <1463558911-98187-2-git-send-email-quan.xu@intel.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1463558911-98187-1-git-send-email-quan.xu@intel.com> References: <1463558911-98187-1-git-send-email-quan.xu@intel.com> Cc: Kevin Tian , Keir Fraser , Quan Xu , Andrew Cooper , dario.faggioli@citrix.com, Jan Beulich , Feng Wu Subject: [Xen-devel] [PATCH v5 01/10] vt-d: fix the IOMMU flush issue 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-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The propagation value from IOMMU flush interfaces may be positive, which indicates callers need to flush cache, not one of faliures. when the propagation value is positive, this patch fixes this flush issue as follows: - call iommu_flush_write_buffer() to flush cache. - return zero. Signed-off-by: Quan Xu CC: Kevin Tian CC: Feng Wu CC: Keir Fraser CC: Jan Beulich CC: Andrew Cooper --- xen/drivers/passthrough/vtd/iommu.c | 101 ++++++++++++++++++++++++++---------- xen/include/asm-x86/iommu.h | 2 +- 2 files changed, 75 insertions(+), 28 deletions(-) diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index db83949..3ece815 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -557,14 +557,16 @@ static void iommu_flush_all(void) } } -static void __intel_iommu_iotlb_flush(struct domain *d, unsigned long gfn, - int dma_old_pte_present, unsigned int page_count) +static int __intel_iommu_iotlb_flush(struct domain *d, unsigned long gfn, + bool_t dma_old_pte_present, + unsigned int page_count) { struct domain_iommu *hd = dom_iommu(d); struct acpi_drhd_unit *drhd; struct iommu *iommu; int flush_dev_iotlb; int iommu_domid; + int rc = 0; /* * No need pcideves_lock here because we have flush @@ -579,23 +581,28 @@ static void __intel_iommu_iotlb_flush(struct domain *d, unsigned long gfn, flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0; iommu_domid= domain_iommu_domid(d, iommu); + if ( iommu_domid == -1 ) continue; if ( page_count != 1 || gfn == INVALID_GFN ) - { - if ( iommu_flush_iotlb_dsi(iommu, iommu_domid, - 0, flush_dev_iotlb) ) - iommu_flush_write_buffer(iommu); - } + rc = iommu_flush_iotlb_dsi(iommu, iommu_domid, + 0, flush_dev_iotlb); else + rc = iommu_flush_iotlb_psi(iommu, iommu_domid, + (paddr_t)gfn << PAGE_SHIFT_4K, + PAGE_ORDER_4K, + !dma_old_pte_present, + flush_dev_iotlb); + + if ( rc > 0 ) { - if ( iommu_flush_iotlb_psi(iommu, iommu_domid, - (paddr_t)gfn << PAGE_SHIFT_4K, PAGE_ORDER_4K, - !dma_old_pte_present, flush_dev_iotlb) ) - iommu_flush_write_buffer(iommu); + iommu_flush_write_buffer(iommu); + rc = 0; } } + + return rc; } static void intel_iommu_iotlb_flush(struct domain *d, unsigned long gfn, unsigned int page_count) @@ -1278,6 +1285,7 @@ int domain_context_mapping_one( u64 maddr, pgd_maddr; u16 seg = iommu->intel->drhd->segment; int agaw; + int rc; ASSERT(pcidevs_locked()); spin_lock(&iommu->lock); @@ -1391,13 +1399,26 @@ int domain_context_mapping_one( spin_unlock(&iommu->lock); /* Context entry was previously non-present (with domid 0). */ - if ( iommu_flush_context_device(iommu, 0, (((u16)bus) << 8) | devfn, - DMA_CCMD_MASK_NOBIT, 1) ) - iommu_flush_write_buffer(iommu); - else + rc = iommu_flush_context_device(iommu, 0, (((u16)bus) << 8) | devfn, + DMA_CCMD_MASK_NOBIT, 1); + + /* + * The current logic for rc returns: + * - positive invoke iommu_flush_write_buffer to flush cache. + * - zero success. + * - negative failure. Continue to flush IOMMU IOTLB on a best + * effort basis. + */ + if ( rc <= 0 ) { int flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0; - iommu_flush_iotlb_dsi(iommu, 0, 1, flush_dev_iotlb); + + rc = iommu_flush_iotlb_dsi(iommu, 0, 1, flush_dev_iotlb); + } + else + { + iommu_flush_write_buffer(iommu); + rc = 0; } set_bit(iommu->index, &hd->arch.iommu_bitmap); @@ -1407,7 +1428,7 @@ int domain_context_mapping_one( if ( !seg ) me_wifi_quirk(domain, bus, devfn, MAP_ME_PHANTOM_FUNC); - return 0; + return rc; } static int domain_context_mapping( @@ -1502,6 +1523,7 @@ int domain_context_unmap_one( struct context_entry *context, *context_entries; u64 maddr; int iommu_domid; + int rc; ASSERT(pcidevs_locked()); spin_lock(&iommu->lock); @@ -1522,6 +1544,7 @@ int domain_context_unmap_one( iommu_flush_cache_entry(context, sizeof(struct context_entry)); iommu_domid= domain_iommu_domid(domain, iommu); + if ( iommu_domid == -1 ) { spin_unlock(&iommu->lock); @@ -1529,14 +1552,27 @@ int domain_context_unmap_one( return -EINVAL; } - if ( iommu_flush_context_device(iommu, iommu_domid, + rc = iommu_flush_context_device(iommu, iommu_domid, (((u16)bus) << 8) | devfn, - DMA_CCMD_MASK_NOBIT, 0) ) - iommu_flush_write_buffer(iommu); - else + DMA_CCMD_MASK_NOBIT, 0); + + /* + * The current logic for rc returns: + * - positive invoke iommu_flush_write_buffer to flush cache. + * - zero success. + * - negative failure. Continue to flush IOMMU IOTLB on a best + * effort basis. + */ + if ( rc <= 0 ) { int flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0; - iommu_flush_iotlb_dsi(iommu, iommu_domid, 0, flush_dev_iotlb); + + rc = iommu_flush_iotlb_dsi(iommu, iommu_domid, 0, flush_dev_iotlb); + } + else + { + iommu_flush_write_buffer(iommu); + rc = 0; } spin_unlock(&iommu->lock); @@ -1545,7 +1581,7 @@ int domain_context_unmap_one( if ( !iommu->intel->drhd->segment ) me_wifi_quirk(domain, bus, devfn, UNMAP_ME_PHANTOM_FUNC); - return 0; + return rc; } static int domain_context_unmap( @@ -1750,32 +1786,43 @@ static int intel_iommu_unmap_page(struct domain *d, unsigned long gfn) return 0; } -void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, - int order, int present) +int iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, + int order, bool_t present) { struct acpi_drhd_unit *drhd; struct iommu *iommu = NULL; struct domain_iommu *hd = dom_iommu(d); int flush_dev_iotlb; int iommu_domid; + int rc = 0; iommu_flush_cache_entry(pte, sizeof(struct dma_pte)); for_each_drhd_unit ( drhd ) { iommu = drhd->iommu; + if ( !test_bit(iommu->index, &hd->arch.iommu_bitmap) ) continue; flush_dev_iotlb = find_ats_dev_drhd(iommu) ? 1 : 0; iommu_domid= domain_iommu_domid(d, iommu); + if ( iommu_domid == -1 ) continue; - if ( iommu_flush_iotlb_psi(iommu, iommu_domid, + + rc = iommu_flush_iotlb_psi(iommu, iommu_domid, (paddr_t)gfn << PAGE_SHIFT_4K, - order, !present, flush_dev_iotlb) ) + order, !present, flush_dev_iotlb); + + if ( rc > 0 ) + { iommu_flush_write_buffer(iommu); + rc = 0; + } } + + return rc; } static int __init vtd_ept_page_compatible(struct iommu *iommu) diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index e82a2f0..43f1620 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -27,7 +27,7 @@ int iommu_setup_hpet_msi(struct msi_desc *); /* While VT-d specific, this must get declared in a generic header. */ int adjust_vtd_irq_affinities(void); -void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, int order, int present); +int iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, int order, bool_t present); bool_t iommu_supports_eim(void); int iommu_enable_x2apic_IR(void); void iommu_disable_x2apic_IR(void);