From patchwork Tue Jan 7 09:00:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 307561 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 848A42C00CF for ; Tue, 7 Jan 2014 20:01:43 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756460AbaAGJA5 (ORCPT ); Tue, 7 Jan 2014 04:00:57 -0500 Received: from mga11.intel.com ([192.55.52.93]:3277 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751262AbaAGJAz (ORCPT ); Tue, 7 Jan 2014 04:00:55 -0500 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 07 Jan 2014 01:00:54 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,617,1384329600"; d="scan'208";a="454740181" Received: from gerry-dev.bj.intel.com ([10.238.158.74]) by fmsmga001.fm.intel.com with ESMTP; 07 Jan 2014 01:00:50 -0800 From: Jiang Liu To: Joerg Roedel , David Woodhouse , Yinghai Lu , Bjorn Helgaas , Dan Williams , Vinod Koul Cc: Jiang Liu , Ashok Raj , Yijing Wang , Tony Luck , iommu@lists.linux-foundation.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org Subject: [RFC Patch Part2 V1 14/14] iommu/vt-d: update IOMMU state when memory hotplug happens Date: Tue, 7 Jan 2014 17:00:34 +0800 Message-Id: <1389085234-22296-15-git-send-email-jiang.liu@linux.intel.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1389085234-22296-1-git-send-email-jiang.liu@linux.intel.com> References: <1389085234-22296-1-git-send-email-jiang.liu@linux.intel.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org If static identity domain is created, IOMMU driver needs to update si_domain page table when memory hotplug event happens. Otherwise PCI device DMA operations can't access the hot-added memory regions. Signed-off-by: Jiang Liu --- drivers/iommu/intel-iommu.c | 52 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 83e3ed4..35a987d 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -3689,6 +3690,54 @@ static struct notifier_block device_nb = { .notifier_call = device_notifier, }; +static int intel_iommu_memory_notifier(struct notifier_block *nb, + unsigned long val, void *v) +{ + struct memory_notify *mhp = v; + unsigned long long start, end; + struct iova *iova; + + switch (val) { + case MEM_GOING_ONLINE: + start = mhp->start_pfn << PAGE_SHIFT; + end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1; + if (iommu_domain_identity_map(si_domain, start, end)) { + pr_warn("dmar: failed to build identity map for [%llx-%llx]\n", + start, end); + return NOTIFY_BAD; + } + break; + case MEM_OFFLINE: + case MEM_CANCEL_ONLINE: + /* TODO: enhance RB-tree and IOVA code to support of splitting iova */ + iova = find_iova(&si_domain->iovad, mhp->start_pfn); + if (iova) { + unsigned long start_pfn, last_pfn; + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; + + start_pfn = mm_to_dma_pfn(iova->pfn_lo); + last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; + dma_pte_clear_range(si_domain, start_pfn, last_pfn); + dma_pte_free_pagetable(si_domain, start_pfn, last_pfn); + rcu_read_lock(); + for_each_active_iommu(iommu, drhd) + iommu_flush_iotlb_psi(iommu, si_domain->id, + start_pfn, last_pfn - start_pfn + 1, 0); + rcu_read_unlock(); + __free_iova(&si_domain->iovad, iova); + } + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block intel_iommu_memory_nb = { + .notifier_call = intel_iommu_memory_notifier, + .priority = 0 +}; + int __init intel_iommu_init(void) { int ret = -ENODEV; @@ -3761,8 +3810,9 @@ int __init intel_iommu_init(void) init_iommu_pm_ops(); bus_set_iommu(&pci_bus_type, &intel_iommu_ops); - bus_register_notifier(&pci_bus_type, &device_nb); + if (si_domain) + register_memory_notifier(&intel_iommu_memory_nb); intel_iommu_enabled = 1;