From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com (foss.arm.com [217.140.101.70]) by ml01.01.org (Postfix) with ESMTP id E90B121FC746C for ; Mon, 9 Oct 2017 03:33:42 -0700 (PDT) Subject: Re: [PATCH v8] dma-mapping: introduce dma_get_iommu_domain() References: <150732935473.22363.1853399637339625023.stgit@dwillia2-desk3.amr.corp.intel.com> <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> From: Robin Murphy Message-ID: <8161efa8-a315-3b0b-4159-9bdf3bfb98aa@arm.com> Date: Mon, 9 Oct 2017 11:37:04 +0100 MIME-Version: 1.0 In-Reply-To: <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" To: Dan Williams , linux-nvdimm@lists.01.org Cc: Jan Kara , Ashok Raj , "Darrick J. Wong" , linux-rdma@vger.kernel.org, Greg Kroah-Hartman , Joerg Roedel , Dave Chinner , linux-xfs@vger.kernel.org, linux-mm@kvack.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, David Woodhouse , Christoph Hellwig , Marek Szyprowski List-ID: Hi Dan, On 08/10/17 04:45, Dan Williams wrote: > Add a dma-mapping api helper to retrieve the generic iommu_domain for a device. > The motivation for this interface is making RDMA transfers to DAX mappings > safe. If the DAX file's block map changes we need to be to reliably stop > accesses to blocks that have been freed or re-assigned to a new file. ...which is also going to require some way to force the IOMMU drivers (on x86 at least) to do a fully-synchronous unmap, instead of just throwing the IOVA onto a flush queue to invalidate the TLBs at some point in the future. Assuming of course that there's an IOMMU both present and performing DMA translation in the first place. > With the > iommu_domain and a callback from the DAX filesystem the kernel can safely > revoke access to a DMA device. The process that performed the RDMA memory > registration is also notified of this revocation event, but the kernel can not > otherwise be in the position of waiting for userspace to quiesce the device. OK, but why reinvent iommu_get_domain_for_dev()? > Since PMEM+DAX is currently only enabled for x86, we only update the x86 > iommu drivers. Note in particular that those two drivers happen to be the *only* place this approach could work - everyone else is going to have to fall back to the generic IOMMU API function anyway. Robin. > Cc: Marek Szyprowski > Cc: Robin Murphy > Cc: Greg Kroah-Hartman > Cc: Joerg Roedel > Cc: David Woodhouse > Cc: Ashok Raj > Cc: Jan Kara > Cc: Jeff Moyer > Cc: Christoph Hellwig > Cc: Dave Chinner > Cc: "Darrick J. Wong" > Cc: Ross Zwisler > Signed-off-by: Dan Williams > --- > Changes since v7: > * retrieve the iommu_domain so that we can later pass the results of > dma_map_* to iommu_unmap() in advance of the actual dma_unmap_*. > > drivers/base/dma-mapping.c | 10 ++++++++++ > drivers/iommu/amd_iommu.c | 10 ++++++++++ > drivers/iommu/intel-iommu.c | 15 +++++++++++++++ > include/linux/dma-mapping.h | 3 +++ > 4 files changed, 38 insertions(+) > > diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c > index e584eddef0a7..fdb9764f95a4 100644 > --- a/drivers/base/dma-mapping.c > +++ b/drivers/base/dma-mapping.c > @@ -369,3 +369,13 @@ void dma_deconfigure(struct device *dev) > of_dma_deconfigure(dev); > acpi_dma_deconfigure(dev); > } > + > +struct iommu_domain *dma_get_iommu_domain(struct device *dev) > +{ > + const struct dma_map_ops *ops = get_dma_ops(dev); > + > + if (ops && ops->get_iommu) > + return ops->get_iommu(dev); > + return NULL; > +} > +EXPORT_SYMBOL(dma_get_iommu_domain); > diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c > index 51f8215877f5..c8e1a45af182 100644 > --- a/drivers/iommu/amd_iommu.c > +++ b/drivers/iommu/amd_iommu.c > @@ -2271,6 +2271,15 @@ static struct protection_domain *get_domain(struct device *dev) > return domain; > } > > +static struct iommu_domain *amd_dma_get_iommu(struct device *dev) > +{ > + struct protection_domain *domain = get_domain(dev); > + > + if (IS_ERR(domain)) > + return NULL; > + return &domain->domain; > +} > + > static void update_device_table(struct protection_domain *domain) > { > struct iommu_dev_data *dev_data; > @@ -2689,6 +2698,7 @@ static const struct dma_map_ops amd_iommu_dma_ops = { > .unmap_sg = unmap_sg, > .dma_supported = amd_iommu_dma_supported, > .mapping_error = amd_iommu_mapping_error, > + .get_iommu = amd_dma_get_iommu, > }; > > static int init_reserved_iova_ranges(void) > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index 6784a05dd6b2..f3f4939cebad 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -3578,6 +3578,20 @@ static int iommu_no_mapping(struct device *dev) > return 0; > } > > +static struct iommu_domain *intel_dma_get_iommu(struct device *dev) > +{ > + struct dmar_domain *domain; > + > + if (iommu_no_mapping(dev)) > + return NULL; > + > + domain = get_valid_domain_for_dev(dev); > + if (!domain) > + return NULL; > + > + return &domain->domain; > +} > + > static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, > size_t size, int dir, u64 dma_mask) > { > @@ -3872,6 +3886,7 @@ const struct dma_map_ops intel_dma_ops = { > .map_page = intel_map_page, > .unmap_page = intel_unmap_page, > .mapping_error = intel_mapping_error, > + .get_iommu = intel_dma_get_iommu, > #ifdef CONFIG_X86 > .dma_supported = x86_dma_supported, > #endif > diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h > index 29ce9815da87..aa62df1d0d72 100644 > --- a/include/linux/dma-mapping.h > +++ b/include/linux/dma-mapping.h > @@ -128,6 +128,7 @@ struct dma_map_ops { > enum dma_data_direction dir); > int (*mapping_error)(struct device *dev, dma_addr_t dma_addr); > int (*dma_supported)(struct device *dev, u64 mask); > + struct iommu_domain *(*get_iommu)(struct device *dev); > #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK > u64 (*get_required_mask)(struct device *dev); > #endif > @@ -221,6 +222,8 @@ static inline const struct dma_map_ops *get_dma_ops(struct device *dev) > } > #endif > > +extern struct iommu_domain *dma_get_iommu_domain(struct device *dev); > + > static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, > size_t size, > enum dma_data_direction dir, > _______________________________________________ Linux-nvdimm mailing list Linux-nvdimm@lists.01.org https://lists.01.org/mailman/listinfo/linux-nvdimm From mboxrd@z Thu Jan 1 00:00:00 1970 From: Robin Murphy Subject: Re: [PATCH v8] dma-mapping: introduce dma_get_iommu_domain() Date: Mon, 9 Oct 2017 11:37:04 +0100 Message-ID: <8161efa8-a315-3b0b-4159-9bdf3bfb98aa@arm.com> References: <150732935473.22363.1853399637339625023.stgit@dwillia2-desk3.amr.corp.intel.com> <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <150743420333.12880.6968831423519457797.stgit-p8uTFz9XbKj2zm6wflaqv1nYeNYlB/vhral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Content-Language: en-US Sender: linux-rdma-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Dan Williams , linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org Cc: Jan Kara , Ashok Raj , "Darrick J. Wong" , linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Greg Kroah-Hartman , Joerg Roedel , Dave Chinner , linux-xfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org, Jeff Moyer , linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Ross Zwisler , David Woodhouse , Christoph Hellwig , Marek Szyprowski List-Id: linux-rdma@vger.kernel.org Hi Dan, On 08/10/17 04:45, Dan Williams wrote: > Add a dma-mapping api helper to retrieve the generic iommu_domain for a device. > The motivation for this interface is making RDMA transfers to DAX mappings > safe. If the DAX file's block map changes we need to be to reliably stop > accesses to blocks that have been freed or re-assigned to a new file. ...which is also going to require some way to force the IOMMU drivers (on x86 at least) to do a fully-synchronous unmap, instead of just throwing the IOVA onto a flush queue to invalidate the TLBs at some point in the future. Assuming of course that there's an IOMMU both present and performing DMA translation in the first place. > With the > iommu_domain and a callback from the DAX filesystem the kernel can safely > revoke access to a DMA device. The process that performed the RDMA memory > registration is also notified of this revocation event, but the kernel can not > otherwise be in the position of waiting for userspace to quiesce the device. OK, but why reinvent iommu_get_domain_for_dev()? > Since PMEM+DAX is currently only enabled for x86, we only update the x86 > iommu drivers. Note in particular that those two drivers happen to be the *only* place this approach could work - everyone else is going to have to fall back to the generic IOMMU API function anyway. Robin. > Cc: Marek Szyprowski > Cc: Robin Murphy > Cc: Greg Kroah-Hartman > Cc: Joerg Roedel > Cc: David Woodhouse > Cc: Ashok Raj > Cc: Jan Kara > Cc: Jeff Moyer > Cc: Christoph Hellwig > Cc: Dave Chinner > Cc: "Darrick J. Wong" > Cc: Ross Zwisler > Signed-off-by: Dan Williams > --- > Changes since v7: > * retrieve the iommu_domain so that we can later pass the results of > dma_map_* to iommu_unmap() in advance of the actual dma_unmap_*. > > drivers/base/dma-mapping.c | 10 ++++++++++ > drivers/iommu/amd_iommu.c | 10 ++++++++++ > drivers/iommu/intel-iommu.c | 15 +++++++++++++++ > include/linux/dma-mapping.h | 3 +++ > 4 files changed, 38 insertions(+) > > diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c > index e584eddef0a7..fdb9764f95a4 100644 > --- a/drivers/base/dma-mapping.c > +++ b/drivers/base/dma-mapping.c > @@ -369,3 +369,13 @@ void dma_deconfigure(struct device *dev) > of_dma_deconfigure(dev); > acpi_dma_deconfigure(dev); > } > + > +struct iommu_domain *dma_get_iommu_domain(struct device *dev) > +{ > + const struct dma_map_ops *ops = get_dma_ops(dev); > + > + if (ops && ops->get_iommu) > + return ops->get_iommu(dev); > + return NULL; > +} > +EXPORT_SYMBOL(dma_get_iommu_domain); > diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c > index 51f8215877f5..c8e1a45af182 100644 > --- a/drivers/iommu/amd_iommu.c > +++ b/drivers/iommu/amd_iommu.c > @@ -2271,6 +2271,15 @@ static struct protection_domain *get_domain(struct device *dev) > return domain; > } > > +static struct iommu_domain *amd_dma_get_iommu(struct device *dev) > +{ > + struct protection_domain *domain = get_domain(dev); > + > + if (IS_ERR(domain)) > + return NULL; > + return &domain->domain; > +} > + > static void update_device_table(struct protection_domain *domain) > { > struct iommu_dev_data *dev_data; > @@ -2689,6 +2698,7 @@ static const struct dma_map_ops amd_iommu_dma_ops = { > .unmap_sg = unmap_sg, > .dma_supported = amd_iommu_dma_supported, > .mapping_error = amd_iommu_mapping_error, > + .get_iommu = amd_dma_get_iommu, > }; > > static int init_reserved_iova_ranges(void) > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index 6784a05dd6b2..f3f4939cebad 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -3578,6 +3578,20 @@ static int iommu_no_mapping(struct device *dev) > return 0; > } > > +static struct iommu_domain *intel_dma_get_iommu(struct device *dev) > +{ > + struct dmar_domain *domain; > + > + if (iommu_no_mapping(dev)) > + return NULL; > + > + domain = get_valid_domain_for_dev(dev); > + if (!domain) > + return NULL; > + > + return &domain->domain; > +} > + > static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, > size_t size, int dir, u64 dma_mask) > { > @@ -3872,6 +3886,7 @@ const struct dma_map_ops intel_dma_ops = { > .map_page = intel_map_page, > .unmap_page = intel_unmap_page, > .mapping_error = intel_mapping_error, > + .get_iommu = intel_dma_get_iommu, > #ifdef CONFIG_X86 > .dma_supported = x86_dma_supported, > #endif > diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h > index 29ce9815da87..aa62df1d0d72 100644 > --- a/include/linux/dma-mapping.h > +++ b/include/linux/dma-mapping.h > @@ -128,6 +128,7 @@ struct dma_map_ops { > enum dma_data_direction dir); > int (*mapping_error)(struct device *dev, dma_addr_t dma_addr); > int (*dma_supported)(struct device *dev, u64 mask); > + struct iommu_domain *(*get_iommu)(struct device *dev); > #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK > u64 (*get_required_mask)(struct device *dev); > #endif > @@ -221,6 +222,8 @@ static inline const struct dma_map_ops *get_dma_ops(struct device *dev) > } > #endif > > +extern struct iommu_domain *dma_get_iommu_domain(struct device *dev); > + > static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, > size_t size, > enum dma_data_direction dir, > -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH v8] dma-mapping: introduce dma_get_iommu_domain() To: Dan Williams , linux-nvdimm@lists.01.org Cc: Jan Kara , Ashok Raj , "Darrick J. Wong" , linux-rdma@vger.kernel.org, Greg Kroah-Hartman , Joerg Roedel , Dave Chinner , linux-xfs@vger.kernel.org, linux-mm@kvack.org, Jeff Moyer , linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, Ross Zwisler , David Woodhouse , Christoph Hellwig , Marek Szyprowski References: <150732935473.22363.1853399637339625023.stgit@dwillia2-desk3.amr.corp.intel.com> <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> From: Robin Murphy Message-ID: <8161efa8-a315-3b0b-4159-9bdf3bfb98aa@arm.com> Date: Mon, 9 Oct 2017 11:37:04 +0100 MIME-Version: 1.0 In-Reply-To: <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: owner-linux-mm@kvack.org List-ID: Hi Dan, On 08/10/17 04:45, Dan Williams wrote: > Add a dma-mapping api helper to retrieve the generic iommu_domain for a device. > The motivation for this interface is making RDMA transfers to DAX mappings > safe. If the DAX file's block map changes we need to be to reliably stop > accesses to blocks that have been freed or re-assigned to a new file. ...which is also going to require some way to force the IOMMU drivers (on x86 at least) to do a fully-synchronous unmap, instead of just throwing the IOVA onto a flush queue to invalidate the TLBs at some point in the future. Assuming of course that there's an IOMMU both present and performing DMA translation in the first place. > With the > iommu_domain and a callback from the DAX filesystem the kernel can safely > revoke access to a DMA device. The process that performed the RDMA memory > registration is also notified of this revocation event, but the kernel can not > otherwise be in the position of waiting for userspace to quiesce the device. OK, but why reinvent iommu_get_domain_for_dev()? > Since PMEM+DAX is currently only enabled for x86, we only update the x86 > iommu drivers. Note in particular that those two drivers happen to be the *only* place this approach could work - everyone else is going to have to fall back to the generic IOMMU API function anyway. Robin. > Cc: Marek Szyprowski > Cc: Robin Murphy > Cc: Greg Kroah-Hartman > Cc: Joerg Roedel > Cc: David Woodhouse > Cc: Ashok Raj > Cc: Jan Kara > Cc: Jeff Moyer > Cc: Christoph Hellwig > Cc: Dave Chinner > Cc: "Darrick J. Wong" > Cc: Ross Zwisler > Signed-off-by: Dan Williams > --- > Changes since v7: > * retrieve the iommu_domain so that we can later pass the results of > dma_map_* to iommu_unmap() in advance of the actual dma_unmap_*. > > drivers/base/dma-mapping.c | 10 ++++++++++ > drivers/iommu/amd_iommu.c | 10 ++++++++++ > drivers/iommu/intel-iommu.c | 15 +++++++++++++++ > include/linux/dma-mapping.h | 3 +++ > 4 files changed, 38 insertions(+) > > diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c > index e584eddef0a7..fdb9764f95a4 100644 > --- a/drivers/base/dma-mapping.c > +++ b/drivers/base/dma-mapping.c > @@ -369,3 +369,13 @@ void dma_deconfigure(struct device *dev) > of_dma_deconfigure(dev); > acpi_dma_deconfigure(dev); > } > + > +struct iommu_domain *dma_get_iommu_domain(struct device *dev) > +{ > + const struct dma_map_ops *ops = get_dma_ops(dev); > + > + if (ops && ops->get_iommu) > + return ops->get_iommu(dev); > + return NULL; > +} > +EXPORT_SYMBOL(dma_get_iommu_domain); > diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c > index 51f8215877f5..c8e1a45af182 100644 > --- a/drivers/iommu/amd_iommu.c > +++ b/drivers/iommu/amd_iommu.c > @@ -2271,6 +2271,15 @@ static struct protection_domain *get_domain(struct device *dev) > return domain; > } > > +static struct iommu_domain *amd_dma_get_iommu(struct device *dev) > +{ > + struct protection_domain *domain = get_domain(dev); > + > + if (IS_ERR(domain)) > + return NULL; > + return &domain->domain; > +} > + > static void update_device_table(struct protection_domain *domain) > { > struct iommu_dev_data *dev_data; > @@ -2689,6 +2698,7 @@ static const struct dma_map_ops amd_iommu_dma_ops = { > .unmap_sg = unmap_sg, > .dma_supported = amd_iommu_dma_supported, > .mapping_error = amd_iommu_mapping_error, > + .get_iommu = amd_dma_get_iommu, > }; > > static int init_reserved_iova_ranges(void) > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index 6784a05dd6b2..f3f4939cebad 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -3578,6 +3578,20 @@ static int iommu_no_mapping(struct device *dev) > return 0; > } > > +static struct iommu_domain *intel_dma_get_iommu(struct device *dev) > +{ > + struct dmar_domain *domain; > + > + if (iommu_no_mapping(dev)) > + return NULL; > + > + domain = get_valid_domain_for_dev(dev); > + if (!domain) > + return NULL; > + > + return &domain->domain; > +} > + > static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, > size_t size, int dir, u64 dma_mask) > { > @@ -3872,6 +3886,7 @@ const struct dma_map_ops intel_dma_ops = { > .map_page = intel_map_page, > .unmap_page = intel_unmap_page, > .mapping_error = intel_mapping_error, > + .get_iommu = intel_dma_get_iommu, > #ifdef CONFIG_X86 > .dma_supported = x86_dma_supported, > #endif > diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h > index 29ce9815da87..aa62df1d0d72 100644 > --- a/include/linux/dma-mapping.h > +++ b/include/linux/dma-mapping.h > @@ -128,6 +128,7 @@ struct dma_map_ops { > enum dma_data_direction dir); > int (*mapping_error)(struct device *dev, dma_addr_t dma_addr); > int (*dma_supported)(struct device *dev, u64 mask); > + struct iommu_domain *(*get_iommu)(struct device *dev); > #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK > u64 (*get_required_mask)(struct device *dev); > #endif > @@ -221,6 +222,8 @@ static inline const struct dma_map_ops *get_dma_ops(struct device *dev) > } > #endif > > +extern struct iommu_domain *dma_get_iommu_domain(struct device *dev); > + > static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, > size_t size, > enum dma_data_direction dir, > -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com ([217.140.101.70]:54318 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751401AbdJIKhK (ORCPT ); Mon, 9 Oct 2017 06:37:10 -0400 Subject: Re: [PATCH v8] dma-mapping: introduce dma_get_iommu_domain() References: <150732935473.22363.1853399637339625023.stgit@dwillia2-desk3.amr.corp.intel.com> <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> From: Robin Murphy Message-ID: <8161efa8-a315-3b0b-4159-9bdf3bfb98aa@arm.com> Date: Mon, 9 Oct 2017 11:37:04 +0100 MIME-Version: 1.0 In-Reply-To: <150743420333.12880.6968831423519457797.stgit@dwillia2-desk3.amr.corp.intel.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-xfs-owner@vger.kernel.org List-ID: List-Id: xfs To: Dan Williams , linux-nvdimm@lists.01.org Cc: Jan Kara , Ashok Raj , "Darrick J. Wong" , linux-rdma@vger.kernel.org, Greg Kroah-Hartman , Joerg Roedel , Dave Chinner , linux-xfs@vger.kernel.org, linux-mm@kvack.org, Jeff Moyer , linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, Ross Zwisler , David Woodhouse , Christoph Hellwig , Marek Szyprowski Hi Dan, On 08/10/17 04:45, Dan Williams wrote: > Add a dma-mapping api helper to retrieve the generic iommu_domain for a device. > The motivation for this interface is making RDMA transfers to DAX mappings > safe. If the DAX file's block map changes we need to be to reliably stop > accesses to blocks that have been freed or re-assigned to a new file. ...which is also going to require some way to force the IOMMU drivers (on x86 at least) to do a fully-synchronous unmap, instead of just throwing the IOVA onto a flush queue to invalidate the TLBs at some point in the future. Assuming of course that there's an IOMMU both present and performing DMA translation in the first place. > With the > iommu_domain and a callback from the DAX filesystem the kernel can safely > revoke access to a DMA device. The process that performed the RDMA memory > registration is also notified of this revocation event, but the kernel can not > otherwise be in the position of waiting for userspace to quiesce the device. OK, but why reinvent iommu_get_domain_for_dev()? > Since PMEM+DAX is currently only enabled for x86, we only update the x86 > iommu drivers. Note in particular that those two drivers happen to be the *only* place this approach could work - everyone else is going to have to fall back to the generic IOMMU API function anyway. Robin. > Cc: Marek Szyprowski > Cc: Robin Murphy > Cc: Greg Kroah-Hartman > Cc: Joerg Roedel > Cc: David Woodhouse > Cc: Ashok Raj > Cc: Jan Kara > Cc: Jeff Moyer > Cc: Christoph Hellwig > Cc: Dave Chinner > Cc: "Darrick J. Wong" > Cc: Ross Zwisler > Signed-off-by: Dan Williams > --- > Changes since v7: > * retrieve the iommu_domain so that we can later pass the results of > dma_map_* to iommu_unmap() in advance of the actual dma_unmap_*. > > drivers/base/dma-mapping.c | 10 ++++++++++ > drivers/iommu/amd_iommu.c | 10 ++++++++++ > drivers/iommu/intel-iommu.c | 15 +++++++++++++++ > include/linux/dma-mapping.h | 3 +++ > 4 files changed, 38 insertions(+) > > diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c > index e584eddef0a7..fdb9764f95a4 100644 > --- a/drivers/base/dma-mapping.c > +++ b/drivers/base/dma-mapping.c > @@ -369,3 +369,13 @@ void dma_deconfigure(struct device *dev) > of_dma_deconfigure(dev); > acpi_dma_deconfigure(dev); > } > + > +struct iommu_domain *dma_get_iommu_domain(struct device *dev) > +{ > + const struct dma_map_ops *ops = get_dma_ops(dev); > + > + if (ops && ops->get_iommu) > + return ops->get_iommu(dev); > + return NULL; > +} > +EXPORT_SYMBOL(dma_get_iommu_domain); > diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c > index 51f8215877f5..c8e1a45af182 100644 > --- a/drivers/iommu/amd_iommu.c > +++ b/drivers/iommu/amd_iommu.c > @@ -2271,6 +2271,15 @@ static struct protection_domain *get_domain(struct device *dev) > return domain; > } > > +static struct iommu_domain *amd_dma_get_iommu(struct device *dev) > +{ > + struct protection_domain *domain = get_domain(dev); > + > + if (IS_ERR(domain)) > + return NULL; > + return &domain->domain; > +} > + > static void update_device_table(struct protection_domain *domain) > { > struct iommu_dev_data *dev_data; > @@ -2689,6 +2698,7 @@ static const struct dma_map_ops amd_iommu_dma_ops = { > .unmap_sg = unmap_sg, > .dma_supported = amd_iommu_dma_supported, > .mapping_error = amd_iommu_mapping_error, > + .get_iommu = amd_dma_get_iommu, > }; > > static int init_reserved_iova_ranges(void) > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index 6784a05dd6b2..f3f4939cebad 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -3578,6 +3578,20 @@ static int iommu_no_mapping(struct device *dev) > return 0; > } > > +static struct iommu_domain *intel_dma_get_iommu(struct device *dev) > +{ > + struct dmar_domain *domain; > + > + if (iommu_no_mapping(dev)) > + return NULL; > + > + domain = get_valid_domain_for_dev(dev); > + if (!domain) > + return NULL; > + > + return &domain->domain; > +} > + > static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, > size_t size, int dir, u64 dma_mask) > { > @@ -3872,6 +3886,7 @@ const struct dma_map_ops intel_dma_ops = { > .map_page = intel_map_page, > .unmap_page = intel_unmap_page, > .mapping_error = intel_mapping_error, > + .get_iommu = intel_dma_get_iommu, > #ifdef CONFIG_X86 > .dma_supported = x86_dma_supported, > #endif > diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h > index 29ce9815da87..aa62df1d0d72 100644 > --- a/include/linux/dma-mapping.h > +++ b/include/linux/dma-mapping.h > @@ -128,6 +128,7 @@ struct dma_map_ops { > enum dma_data_direction dir); > int (*mapping_error)(struct device *dev, dma_addr_t dma_addr); > int (*dma_supported)(struct device *dev, u64 mask); > + struct iommu_domain *(*get_iommu)(struct device *dev); > #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK > u64 (*get_required_mask)(struct device *dev); > #endif > @@ -221,6 +222,8 @@ static inline const struct dma_map_ops *get_dma_ops(struct device *dev) > } > #endif > > +extern struct iommu_domain *dma_get_iommu_domain(struct device *dev); > + > static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, > size_t size, > enum dma_data_direction dir, >