IOMMU/DMA map_resource support for peer-to-peer
Subsystems (6)
cover IOMMU/DMA map_resource support for peer-to-peer
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of map_page and map_sg convert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
Thanks,
Will
Will Davis (6):
dma-debug: add checking for map/unmap_resource
DMA-API: Introduce dma_(un)map_resource
dma-mapping: pci: add pci_(un)map_resource iommu/amd: Implement (un)map_resource iommu/vt-d: implement (un)map_resource
x86: add pci-nommu implementation of map_resource
arch/x86/kernel/pci-nommu.c | 17 +++++++ drivers/iommu/amd_iommu.c | 76 ++++++++++++++++++++++++++------ drivers/iommu/intel-iommu.c | 18 ++++++++ include/asm-generic/dma-mapping-broken.h | 9 ++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++ include/asm-generic/pci-dma-compat.h | 14 ++++++ include/linux/dma-debug.h | 20 +++++++++ include/linux/dma-mapping.h | 7 +++ lib/dma-debug.c | 48 ++++++++++++++++++++ 9 files changed, 230 insertions(+), 13 deletions(-)
Signature · 1 line
2.3.7
PATCH 1/6 dma-debug: add checking for map/unmap_resource
From: Will Davis <[email protected]>
Add debug callbacks for the new dma_map_resource and dma_unmap_resource functions.
--- include/linux/dma-debug.h | 20 ++++++++++++++++++++ lib/dma-debug.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+)
include/linux/dma-debug.h +20 -0
@@ -44,6 +44,13 @@ extern void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);extern void debug_dma_unmap_page (struct device *dev,dma_addr_t addr,size_t size,int direction,bool map_single); +extern void debug_dma_map_resource (struct device *dev,struct resource *res, +size_t offset,size_t size,int direction, +dma_addr_t dma_addr); + +extern void debug_dma_unmap_resource (struct device *dev,dma_addr_t addr, +size_t size,int direction); +extern void debug_dma_map_sg (struct device *dev,struct scatterlist *sg,int nents,int mapped_ents,int direction);
@@ -120,6 +127,19 @@ static inline void debug_dma_unmap_page(struct device *dev, dma_addr_t addr, { } +static inline void debug_dma_map_resource (struct device *dev, +struct resource *res,size_t offset, +size_t size,int direction, +dma_addr_t dma_addr) +{ +} + +static inline void debug_dma_unmap_resource (struct device *dev, +dma_addr_t addr,size_t size, +int direction) +{ +} +static inline void debug_dma_map_sg (struct device *dev,struct scatterlist *sg,int nents,int mapped_ents,int direction) {
lib/dma-debug.c +48 -0
60 lines not on this page · raw message
Signature · 1 line
2.3.7
PATCH 2/6 DMA-API: Introduce dma_(un)map_resource
In reply to [email protected]From: Will Davis <[email protected]>
Add functions to DMA-map and -unmap a resource for a given device. This will allow devices to DMA-map a peer device's resource (for example, another device's BAR region on PCI) to enable peer-to-peer transactions.
--- include/asm-generic/dma-mapping-broken.h | 9 +++++++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++++++++++++++++++++ include/linux/dma-mapping.h | 7 +++++++ 3 files changed, 50 insertions(+)
include/asm-generic/dma-mapping-broken.h +9 -0
@@ -59,6 +59,15 @@ extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction); +extern dma_addr_t +dma_map_resource (struct device *dev,struct resource *res, +unsigned long offset,size_t size, +enum dma_data_direction direction); + +extern void +dma_unmap_resource (struct device *dev,dma_addr_t dma_address,size_t size, +enum dma_data_direction direction); +extern void dma_sync_single_for_cpu (struct device *dev,dma_addr_t dma_handle,size_t size,enum dma_data_direction direction);
include/asm-generic/dma-mapping-common.h +34 -0
@@ -73,6 +73,36 @@ static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg ops->unmap_sg (dev, sg, nents, dir, attrs); } +static inline dma_addr_t dma_map_resource_attrs (struct device *dev, +struct resource *res, +size_t offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +const struct dma_map_ops *ops =get_dma_ops (dev); +dma_addr_t addr =0 ; + +BUG_ON (!valid_dma_direction (dir)); +if (ops->map_resource) + addr = ops->map_resource (dev, res, offset, size, dir, attrs); +debug_dma_map_resource (dev, res, offset, size, dir, addr); + +return addr; +} + +static inline void dma_unmap_resource_attrs (struct device *dev,dma_addr_t addr, +size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +const struct dma_map_ops *ops =get_dma_ops (dev); + +BUG_ON (!valid_dma_direction (dir)); +if (ops->unmap_resource) + ops->unmap_resource (dev, addr, size, dir, attrs); +debug_dma_unmap_resource (dev, addr, size, dir); +} +static inline dma_addr_t dma_map_page (struct device *dev,struct page *page,size_t offset,size_t size,enum dma_data_direction dir)
@@ -180,6 +210,10 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,#define dma_unmap_single (d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)#define dma_map_sg (d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)#define dma_unmap_sg (d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL) +#define dma_map_resource (d, e, o, s, r) \ + dma_map_resource_attrs(d, e, o, s, r, NULL) +#define dma_unmap_resource (d, a, s, r) \ + dma_unmap_resource_attrs(d, a, s, r, NULL)extern int dma_common_mmap (struct device *dev,struct vm_area_struct *vma,void *cpu_addr,dma_addr_t dma_addr,size_t size);
include/linux/dma-mapping.h +7 -0
@@ -34,6 +34,13 @@ struct dma_map_ops {void (*unmap_page)(struct device *dev,dma_addr_t dma_handle,size_t size,enum dma_data_direction dir,struct dma_attrs *attrs); +dma_addr_t (*map_resource)(struct device *dev,struct resource *res, +unsigned long offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs); +void (*unmap_resource)(struct device *dev,dma_addr_t dma_handle, +size_t size,enum dma_data_direction dir, +struct dma_attrs *attrs);/* * map_sg returns 0 on error and a value > 0 on success. * It should never return a value < 0.
Signature · 1 line
2.3.7
Bjorn Helgaas
maintainerRe: [PATCH 2/6] DMA-API: Introduce dma_(un)map_resource
Quoted 6 lines · On Fri, May 01, 2015 at 01:32:14PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Add functions to DMA-map and -unmap a resource for a given device. This will allow devices to DMA-map a peer device's resource (for example, another device's BAR region on PCI) to enable peer-to-peer transactions.
Quoted 7 lines
Signed-off-by Will Davis <[email protected]>Reviewed-by Terence Ripperda <[email protected]>Reviewed-by John Hubbard <[email protected]>--- include/asm-generic/dma-mapping-broken.h | 9 +++++++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++++++++++++++++++++ include/linux/dma-mapping.h | 7 +++++++
You should document these new interfaces in Documentation/DMA-API-*
Bjorn
RE: [PATCH 2/6] DMA-API: Introduce dma_(un)map_resource
Quoted 24 lines
-----Original Message-----
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Thursday, May 7, 2015 10:10 AM
To: William Davis
Cc: [email protected]; [email protected]; linux- [email protected]; Terence Ripperda; John Hubbard; [email protected]
Subject: Re: [PATCH 2/6] DMA-API: Introduce dma_(un)map_resourceQuoted 5 lines · On Fri, May 01, 2015 at 01:32:14PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Add functions to DMA-map and -unmap a resource for a given device. This will allow devices to DMA-map a peer device's resource (for example, another device's BAR region on PCI) to enable peer-to-peer
transactions.
Quoted 7 lines
Signed-off-by Will Davis <[email protected]>Reviewed-by Terence Ripperda <[email protected]>Reviewed-by John Hubbard <[email protected]>--- include/asm-generic/dma-mapping-broken.h | 9 +++++++++
include/asm-generic/dma-mapping-common.h| 34
Quoted 5 lines
++++++++++++++++++++++++++++++++
Quoted 1 line
include/linux/dma-mapping.h | 7 +++++++You should document these new interfaces in
Documentation/DMA-API-*
Will do.
Thanks,
Will
--
nvpublic
PATCH 3/6 dma-mapping: pci: add pci_(un)map_resource
In reply to [email protected]From: Will Davis <[email protected]>
Simply route these through to the new dma_(un)map_resource APIs.
--- include/asm-generic/pci-dma-compat.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
include/asm-generic/pci-dma-compat.h +14 -0
@@ -61,6 +61,20 @@ pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,dma_unmap_page (hwdev ==NULL ?NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction )direction); } +static inline dma_addr_t +pci_map_resource (struct pci_dev *hwdev,struct resource *resource, +unsigned long offset,size_t size,int direction) +{ +return dma_map_resource (hwdev ==NULL ?NULL : &hwdev->dev, resource, offset, size, (enum dma_data_direction )direction); +} + +static inline void +pci_unmap_resource (struct pci_dev *hwdev,dma_addr_t dma_address,size_t size, +int direction) +{ +dma_unmap_resource (hwdev ==NULL ?NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction )direction); +} +static inline int pci_map_sg (struct pci_dev *hwdev,struct scatterlist *sg,int nents,int direction)
Signature · 1 line
2.3.7
A message that is not in the archive (sent off-list or not yet received): 1430505138-2877-4-git-send-email-wdavis-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org
Re: [PATCH 3/6] dma-mapping: pci: add pci_(un)map_resource
[+cc Dave for sparc64, Yinghai]
Quoted 16 lines · On Fri, May 01, 2015 at 01:32:15PM -0500…
From: Will Davis <[email protected]>
Simply route these through to the new dma_(un)map_resource APIs.
Signed-off-by Will Davis <[email protected]>Reviewed-by Terence Ripperda <[email protected]>Reviewed-by John Hubbard <[email protected]>--- include/asm-generic/pci-dma-compat.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)include/asm-generic/pci-dma-compat.h +0
-0
include/asm-generic/pci-dma-compat.h pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, · line 69
Quoted 9 lines
include/asm-generic/pci-dma-compat.h +6
-0@@ -61,6 +61,20 @@ pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,dma_unmap_page (hwdev ==NULL ?NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction )direction); } +static inline dma_addr_t +pci_map_resource (struct pci_dev *hwdev,struct resource *resource, +unsigned long offset,size_t size,int direction) +{ +return dma_map_resource (hwdev ==NULL ?NULL : &hwdev->dev, resource, offset, size, (enum dma_data_direction )direction); +}
On sparc64, PCI bus addresses, e.g., raw BAR values, can be 64 bits wide, but dma_addr_t is only 32 bits [1]. So dma_addr_t is a bit of a problem here. It's likely that we will add a pci_bus_addr_t, but that hasn't happened yet [2].
We do have existing problems already, e.g,. pci_bus_address() returns a dma_addr_t, so it has the same problem. So I guess this is just a heads-up that this needs to be fixed eventually.
Bjorn
[1] http://lkml.kernel.org/r/20150327.145016.86183910134380870.davem-fT/PcQaiUtIeIZ0/[email protected]
[2] http://lkml.kernel.org/r/1427857069-6789-2-git-send-email-yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 3/6] dma-mapping: pci: add pci_(un)map_resource
Quoted 22 lines · Bjorn Helgaas
[+cc Dave for sparc64, Yinghai]
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:15PM -0500…
From: Will Davis <[email protected]>
Simply route these through to the new dma_(un)map_resource APIs.
Signed-off-by Will Davis <[email protected]>Reviewed-by Terence Ripperda <[email protected]>Reviewed-by John Hubbard <[email protected]>--- include/asm-generic/pci-dma-compat.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)include/asm-generic/pci-dma-compat.h +0
-0@@ -61,6 +61,20 @@ pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,dma_unmap_page (hwdev ==NULL ?NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction )direction); }
Quoted 11 lines
include/asm-generic/pci-dma-compat.h pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, · line 69
Quoted 6 lines
include/asm-generic/pci-dma-compat.h +6
-0+static inline dma_addr_t +pci_map_resource (struct pci_dev *hwdev,struct resource *resource, +unsigned long offset,size_t size,int direction) +{ +return dma_map_resource (hwdev ==NULL ?NULL : &hwdev->dev, resource, offset, size, (enum dma_data_direction )direction); +}On sparc64, PCI bus addresses, e.g., raw BAR values, can be 64 bits wide, but
dma_addr_tis only 32 bits [1]. Sodma_addr_tis a bit of a problem here. It's likely that we will add apci_bus_addr_t, but that hasn't happened yet [2].
Why not just expand the 'dma_addr_t' to be unsigned long (if to support the T5-8 box)?
Quoted 13 lines
We do have existing problems already, e.g,.
pci_bus_address()returns adma_addr_t, so it has the same problem. So I guess this is just a heads-up that this needs to be fixed eventually.Bjorn
[1] http://lkml.kernel.org/r/20150327.145016.86183910134380870.davem-fT/PcQaiUtIeIZ0/[email protected]
[2] http://lkml.kernel.org/r/1427857069-6789-2-git-send-email-yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
_______________________________________________
iommu mailing list
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Bjorn Helgaas
maintainerRe: [PATCH 3/6] dma-mapping: pci: add pci_(un)map_resource
Quoted 35 lines · Konrad Rzeszutek Wilk
Quoted 22 lines · Bjorn Helgaas
[+cc Dave for sparc64, Yinghai]
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:15PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Simply route these through to the new dma_(un)map_resource APIs.
Signed-off-by Will Davis <[email protected]>Reviewed-by Terence Ripperda <[email protected]>Reviewed-by John Hubbard <[email protected]>--- include/asm-generic/pci-dma-compat.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)include/asm-generic/pci-dma-compat.h +0
-0@@ -61,6 +61,20 @@ pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,dma_unmap_page (hwdev ==NULL ?NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction )direction); }Quoted 11 lines
include/asm-generic/pci-dma-compat.h pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, · line 69
Quoted 6 lines
include/asm-generic/pci-dma-compat.h +6
-0+static inline dma_addr_t +pci_map_resource (struct pci_dev *hwdev,struct resource *resource, +unsigned long offset,size_t size,int direction) +{ +return dma_map_resource (hwdev ==NULL ?NULL : &hwdev->dev, resource, offset, size, (enum dma_data_direction )direction); +}On sparc64, PCI bus addresses, e.g., raw BAR values, can be 64 bits wide, but
dma_addr_tis only 32 bits [1]. Sodma_addr_tis a bit of a problem here. It's likely that we will add apci_bus_addr_t, but that hasn't happened yet [2].
Quoted 2 lines
Why not just expand the '
dma_addr_t' to be unsigned long (if to support the T5-8 box)?
That would work, but would increase the kernel memory footprint [3]. I don't have numbers (maybe Dave does), but if it is really significant, other platforms with IOMMUs might want to explore using a dma_addr_t smaller than 64 bits, too.
Quoted 2 lines
Quoted 2 lines
[1] http://lkml.kernel.org/r/[email protected]
[2] http://lkml.kernel.org/r/[email protected]
PATCH 4/6 iommu/amd: Implement (un)map_resource
In reply to [email protected]From: Will Davis <[email protected]>
Implement 'map_resource' for the AMD IOMMU driver. Generalize the existing map_page implementation to operate on a physical address, and make both map_page and map_resource wrappers around that helper (and similiarly, for unmap_page and unmap_resource).
This allows a device to map another's resource, to enable peer-to-peer transactions.
--- drivers/iommu/amd_iommu.c | 76 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 13 deletions(-)
drivers/iommu/amd_iommu.c +63 -13
@@ -503,6 +503,8 @@ DECLARE_STATS_COUNTER(cnt_map_single);DECLARE_STATS_COUNTER (cnt_unmap_single);DECLARE_STATS_COUNTER (cnt_map_sg);DECLARE_STATS_COUNTER (cnt_unmap_sg); +DECLARE_STATS_COUNTER (cnt_map_resource); +DECLARE_STATS_COUNTER (cnt_unmap_resource);DECLARE_STATS_COUNTER (cnt_alloc_coherent);DECLARE_STATS_COUNTER (cnt_free_coherent);DECLARE_STATS_COUNTER (cross_page);
@@ -541,6 +543,8 @@ static void amd_iommu_stats_init(void)amd_iommu_stats_add (&cnt_unmap_single);amd_iommu_stats_add (&cnt_map_sg);amd_iommu_stats_add (&cnt_unmap_sg); +amd_iommu_stats_add (&cnt_map_resource); +amd_iommu_stats_add (&cnt_unmap_resource);amd_iommu_stats_add (&cnt_alloc_coherent);amd_iommu_stats_add (&cnt_free_coherent);amd_iommu_stats_add (&cross_page);
@@ -2752,20 +2756,16 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, }/* -* The exported map_single function for dma_ops. +* Wrapper function that contains code common to mapping a physical address +* range from a page or a resource. */ -static dma_addr_t map_page (struct device *dev,struct page *page, -unsigned long offset,size_t size, -enum dma_data_direction dir, -struct dma_attrs *attrs) +static dma_addr_t __map_phys (struct device *dev,phys_addr_t paddr, +size_t size,enum dma_data_direction dir) {unsigned long flags;struct protection_domain *domain;dma_addr_t addr;u64 dma_mask; -phys_addr_t paddr =page_to_phys (page) + offset; - -INC_STATS_COUNTER (cnt_map_single); domain =get_domain (dev);if (PTR_ERR (domain) == -EINVAL )
@@ -2791,16 +2791,15 @@ out: }/* -* The exported unmap_single function for dma_ops. +* Wrapper function that contains code common to unmapping a physical address +* range from a page or a resource. */ -static void unmap_page (struct device *dev,dma_addr_t dma_addr,size_t size, -enum dma_data_direction dir,struct dma_attrs *attrs) +static void __unmap_phys (struct device *dev,dma_addr_t dma_addr,size_t size, +enum dma_data_direction dir) {unsigned long flags;struct protection_domain *domain; -INC_STATS_COUNTER (cnt_unmap_single); - domain =get_domain (dev);if (IS_ERR (domain))return ;
@@ -2815,6 +2814,55 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, }/* +* The exported map_single function for dma_ops. +*/ +static dma_addr_t map_page (struct device *dev,struct page *page, +unsigned long offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +INC_STATS_COUNTER (cnt_map_single); + +return __map_phys (dev,page_to_phys (page) + offset, size, dir); +} + +/* +* The exported unmap_single function for dma_ops. +*/ +static void unmap_page (struct device *dev,dma_addr_t dma_addr,size_t size, +enum dma_data_direction dir,struct dma_attrs *attrs) +{ +INC_STATS_COUNTER (cnt_unmap_single); + +__unmap_phys (dev, dma_addr, size, dir); +} + +/* +* The exported map_resource function for dma_ops. +*/ +static dma_addr_t map_resource (struct device *dev,struct resource *res, +unsigned long offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +INC_STATS_COUNTER (cnt_map_resource); + +return __map_phys (dev, res->start + offset, size, dir); +} + +/* +* The exported unmap_resource function for dma_ops. +*/ +static void unmap_resource (struct device *dev,dma_addr_t dma_addr, +size_t size,enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +INC_STATS_COUNTER (cnt_unmap_resource); + +__unmap_phys (dev, dma_addr, size, dir); +} + +/* * The exported map_sg function for dma_ops (handles scatter-gather * lists). */
@@ -3066,6 +3114,8 @@ static struct dma_map_ops amd_iommu_dma_ops = { .unmap_page = unmap_page, .map_sg = map_sg, .unmap_sg = unmap_sg, + .map_resource = map_resource, + .unmap_resource = unmap_resource, .dma_supported = amd_iommu_dma_supported, };
Signature · 1 line
2.3.7
PATCH 5/6 iommu/vt-d: implement (un)map_resource
In reply to [email protected]From: Will Davis <[email protected]>
Implement 'map_resource' for the Intel IOMMU driver. Simply translate the resource to a physical address and route it to the same handlers used by the 'map_page' API.
This allows a device to map another's resource, to enable peer-to-peer transactions.
--- drivers/iommu/intel-iommu.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/iommu/intel-iommu.c +18 -0
@@ -3095,6 +3095,15 @@ static dma_addr_t intel_map_page(struct device *dev, struct page *page, dir, *dev->dma_mask); } +static dma_addr_t intel_map_resource (struct device *dev,struct resource *res, +unsigned long offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +return __intel_map_single (dev, res->start + offset, size, + dir, *dev->dma_mask); +} +static void flush_unmaps (void ) {int i, j;
@@ -3226,6 +3235,13 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,intel_unmap (dev, dev_addr); } +static void intel_unmap_resource (struct device *dev,dma_addr_t dev_addr, +size_t size,enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +intel_unmap (dev, dev_addr); +} +static void *intel_alloc_coherent (struct device *dev,size_t size,dma_addr_t *dma_handle,gfp_t flags,struct dma_attrs *attrs)
@@ -3382,6 +3398,8 @@ struct dma_map_ops intel_dma_ops = { .unmap_sg = intel_unmap_sg, .map_page = intel_map_page, .unmap_page = intel_unmap_page, + .map_resource = intel_map_resource, + .unmap_resource = intel_unmap_resource, .mapping_error = intel_mapping_error, };
Signature · 1 line
2.3.7
PATCH 6/6 x86: add pci-nommu implementation of map_resource
In reply to [email protected]From: Will Davis <[email protected]>
Simply pass through the physical address as the DMA address.
--- arch/x86/kernel/pci-nommu.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
arch/x86/kernel/pci-nommu.c +17 -0
@@ -38,6 +38,22 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,return bus; } +static dma_addr_t nommu_map_resource (struct device *dev,struct resource *res, +unsigned long offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +dma_addr_t bus = res->start + offset; + +WARN_ON (size ==0 ); + +if (!check_addr ("map_resource" , dev, bus, size)) +return DMA_ERROR_CODE ; +flush_write_buffers (); +return bus; +} + +/* Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scatter-gather version of the * above pci_map_single interface. Here the scatter gather list
@@ -93,6 +109,7 @@ struct dma_map_ops nommu_dma_ops = { .free = dma_generic_free_coherent, .map_sg = nommu_map_sg, .map_page = nommu_map_page, + .map_resource = nommu_map_resource, .sync_single_for_device = nommu_sync_single_for_device, .sync_sg_for_device = nommu_sync_sg_for_device, .is_phys = 1,
Signature · 1 line
2.3.7
Bjorn Helgaas
maintainerRe: [PATCH 6/6] x86: add pci-nommu implementation of map_resource
Quoted 16 lines · On Fri, May 01, 2015 at 01:32:18PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Simply pass through the physical address as the DMA address.
Signed-off-by Will Davis <[email protected]>Reviewed-by Terence Ripperda <[email protected]>Reviewed-by John Hubbard <[email protected]>--- arch/x86/kernel/pci-nommu.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)arch/x86/kernel/pci-nommu.c +0
-0
arch/x86/kernel/pci-nommu.c static dma_addr_t nommu_map_page(struct device *dev, struct page *page, · line 46
Quoted 9 lines
arch/x86/kernel/pci-nommu.c +6
-0@@ -38,6 +38,22 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,return bus; } +static dma_addr_t nommu_map_resource (struct device *dev,struct resource *res, +unsigned long offset,size_t size, +enum dma_data_direction dir, +struct dma_attrs *attrs) +{ +dma_addr_t bus = res->start + offset;
"res->start" is the CPU physical address, not the bus address. There is a pci_bus_address() interface to get the bus address.
On many, but not all, x86 platforms the CPU physical address is identical to the PCI bus address.
Quoted 28 lines
arch/x86/kernel/pci-nommu.c +11
-0+ +WARN_ON (size ==0 ); + +if (!check_addr ("map_resource" , dev, bus, size)) +return DMA_ERROR_CODE ; +flush_write_buffers (); +return bus; +} + +/* Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scatter-gather version of the * above pci_map_single interface. Here the scatter gather list @@ -93,6 +109,7 @@ struct dma_map_ops nommu_dma_ops = { .free = dma_generic_free_coherent, .map_sg = nommu_map_sg, .map_page = nommu_map_page, + .map_resource = nommu_map_resource, .sync_single_for_device = nommu_sync_single_for_device, .sync_sg_for_device = nommu_sync_sg_for_device, .is_phys = 1,Signature · 6 lines
2.3.7 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 6/6] x86: add pci-nommu implementation of map_resource
Quoted 33 lines
-----Original Message-----
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Thursday, May 7, 2015 10:08 AM
To: William Davis
Cc: [email protected]; [email protected]; linux- [email protected]; Terence Ripperda; John Hubbard; [email protected]
Subject: Re: [PATCH 6/6] x86: add pci-nommu implementation ofmap_resourcearch/x86/kernel/pci-nommu.c static dma_addr_t nommu_map_page(struct device *dev,
Quoted 7 lines · On Fri, May 01, 2015 at 01:32:18PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
arch/x86/kernel/pci-nommu.c +0
-0@@ -38,6 +38,22 @@ static dma_addr_t nommu_map_page(struct device *dev,struct page *page,
arch/x86/kernel/pci-nommu.c static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
Quoted 4 lines
arch/x86/kernel/pci-nommu.c +1
-0return bus; } +static dma_addr_t nommu_map_resource(struct device *dev, struct resource*res,
arch/x86/kernel/pci-nommu.c static dma_addr_t nommu_map_page(struct device *dev, struct page *page, · line 46
Quoted 5 lines
arch/x86/kernel/pci-nommu.c +5
-0+ unsigned long offset, size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + dma_addr_t bus = res->start + offset;"
res->start" is the CPU physical address, not the bus address. There is apci_bus_address()interface to get the bus address.
Quoted 3 lines
On many, but not all, x86 platforms the CPU physical address is identical to the PCI bus address.
Thanks for pointing that out. Since we already have the resource here (and not the BAR index), I'll use pcibios_resource_to_bus(), as pci_bus_address() does.
Thanks,
Will
--
nvpublic
Bjorn Helgaas
maintainer[+cc Yijing, Dave J, Dave M, Alex]
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of
map_pageandmap_sgconvert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.
Quoted 3 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
I think we currently assume there's no peer-to-peer traffic.
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see pcie_bus_configure_settings()).
- PCIe ACS, e.g., pci_acs_enabled(). My guess is that this one is OK, but Alex would know better.
- dma_addr_t. Currently dma_addr_t is big enough to hold any address returned from the DMA API. That's not necessarily big enough to hold a PCI bus address, e.g., a raw BAR value.
Quoted 26 lines
Will Davis (6):
dma-debug: add checking for map/unmap_resource
DMA-API: Introduce dma_(un)map_resource
dma-mapping: pci: add pci_(un)map_resource iommu/amd: Implement (un)map_resource iommu/vt-d: implement (un)map_resource
x86: add pci-nommu implementation ofmap_resourcearch/x86/kernel/pci-nommu.c | 17 +++++++ drivers/iommu/amd_iommu.c | 76 ++++++++++++++++++++++++++------ drivers/iommu/intel-iommu.c | 18 ++++++++ include/asm-generic/dma-mapping-broken.h | 9 ++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++ include/asm-generic/pci-dma-compat.h | 14 ++++++ include/linux/dma-debug.h | 20 +++++++++ include/linux/dma-mapping.h | 7 +++ lib/dma-debug.c | 48 ++++++++++++++++++++ 9 files changed, 230 insertions(+), 13 deletions(-)Signature · 6 lines
2.3.7 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 28 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of
map_pageandmap_sgconvert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.Quoted 3 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
I think we currently assume there's no peer-to-peer traffic.
Quoted 7 lines
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).- PCIe ACS, e.g.,
pci_acs_enabled(). My guess is that this one is OK, but Alex would know better.
I think it should be OK too. ACS will force the transaction upstream for IOMMU translation rather than possible allowing redirection lower in the topology, but that's sort of the price we pay for isolation. The p2p context entries need to be present in the IOMMU, so without actually reading the patches, this does seem like something a driver might want to do via the DMA API. The IOMMU API already allows us to avoid the struct page issue and create mappings for p2p in the IOMMU.
Quoted 34 lines
-
dma_addr_t. Currentlydma_addr_tis big enough to hold any address returned from the DMA API. That's not necessarily big enough to hold a PCI bus address, e.g., a raw BAR value.Quoted 8 lines
Will Davis (6):
dma-debug: add checking for map/unmap_resource
DMA-API: Introduce dma_(un)map_resource
dma-mapping: pci: add pci_(un)map_resource iommu/amd: Implement (un)map_resource iommu/vt-d: implement (un)map_resource
x86: add pci-nommu implementation ofmap_resourceQuoted 18 lines
arch/x86/kernel/pci-nommu.c | 17 +++++++ drivers/iommu/amd_iommu.c | 76 ++++++++++++++++++++++++++------ drivers/iommu/intel-iommu.c | 18 ++++++++ include/asm-generic/dma-mapping-broken.h | 9 ++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++ include/asm-generic/pci-dma-compat.h | 14 ++++++ include/linux/dma-debug.h | 20 +++++++++ include/linux/dma-mapping.h | 7 +++ lib/dma-debug.c | 48 ++++++++++++++++++++ 9 files changed, 230 insertions(+), 13 deletions(-)Signature · 6 lines
2.3.7 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 26 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of
map_pageandmap_sgconvert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.Quoted 3 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
Quoted 6 lines
I think we currently assume there's no peer-to-peer traffic.
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).
I think it should be ok for PCIe MPS configuration, PCIE_BUS_PEER2PEER force every device's MPS to 128B, what its concern is the TLP payload size. In this series, it seems to only map a iova for device bar region.
Quoted 37 lines
- PCIe ACS, e.g.,
pci_acs_enabled(). My guess is that this one is OK, but Alex would know better.-
dma_addr_t. Currentlydma_addr_tis big enough to hold any address returned from the DMA API. That's not necessarily big enough to hold a PCI bus address, e.g., a raw BAR value.Quoted 8 lines
Will Davis (6):
dma-debug: add checking for map/unmap_resource
DMA-API: Introduce dma_(un)map_resource
dma-mapping: pci: add pci_(un)map_resource iommu/amd: Implement (un)map_resource iommu/vt-d: implement (un)map_resource
x86: add pci-nommu implementation ofmap_resourceQuoted 18 lines
arch/x86/kernel/pci-nommu.c | 17 +++++++ drivers/iommu/amd_iommu.c | 76 ++++++++++++++++++++++++++------ drivers/iommu/intel-iommu.c | 18 ++++++++ include/asm-generic/dma-mapping-broken.h | 9 ++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++ include/asm-generic/pci-dma-compat.h | 14 ++++++ include/linux/dma-debug.h | 20 +++++++++ include/linux/dma-mapping.h | 7 +++ lib/dma-debug.c | 48 ++++++++++++++++++++ 9 files changed, 230 insertions(+), 13 deletions(-)Signature · 6 lines
2.3.7 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html.
Signature · 2 lines
Thanks! Yijing
Bjorn Helgaas
maintainerQuoted 20 lines · Yijing Wang
Quoted 19 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 8 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
Quoted 5 lines
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
...I think we currently assume there's no peer-to-peer traffic.
Quoted 8 lines
Quoted 4 lines
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).I think it should be ok for PCIe MPS configuration,
PCIE_BUS_PEER2PEERforce every device's MPS to 128B, what its concern is the TLP payload size. In this series, it seems to only map a iova for device bar region.
MPS configuration makes assumptions about whether there will be any peer-to-peer traffic. If there will be none, MPS can be configured more aggressively.
I don't think Linux has any way to detect whether a driver is doing peer-to-peer, and there's no way to prevent a driver from doing it. We're stuck with requiring the user to specify boot options ("pci=pcie_bus_safe", "pci=pcie_bus_perf", "pci=pcie_bus_peer2peer", etc.) that tell the PCI core what the user expects to happen.
This is a terrible user experience. The user has no way to tell what drivers are going to do. If he specifies the wrong thing, e.g., "assume no peer-to-peer traffic," and then loads a driver that does peer-to-peer, the kernel will configure MPS aggressively and when the device does a peer-to-peer transfer, it may cause a Malformed TLP error.
Bjorn
Quoted 51 lines
-----Original Message-----
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Thursday, May 7, 2015 8:13 AM
To: Yijing Wang
Cc: William Davis; Joerg Roedel; open list:INTEL IOMMU (VT-d); linux- [email protected]; Terence Ripperda; John Hubbard; Jerome Glisse; Dave Jiang; David S. Miller; Alex Williamson
Subject: Re: [PATCH 0/6] IOMMU/DMAmap_resourcesupport for peer-to-peerQuoted 20 lines · Yijing Wang
Quoted 19 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 8 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
Quoted 5 lines
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
...I think we currently assume there's no peer-to-peer traffic.
Quoted 8 lines
Quoted 4 lines
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).I think it should be ok for PCIe MPS configuration,
PCIE_BUS_PEER2PEERforce every device's MPS to 128B, what its concern is the TLP payload size. In this series, it seems to only map a iova for device bar region.MPS configuration makes assumptions about whether there will be any peer- to-peer traffic. If there will be none, MPS can be configured more aggressively.
I don't think Linux has any way to detect whether a driver is doing peer- to-peer, and there's no way to prevent a driver from doing it. We're stuck with requiring the user to specify boot options ("pci=pcie_bus_safe", "pci=pcie_bus_perf", "pci=pcie_bus_peer2peer", etc.) that tell the PCI core what the user expects to happen.
Quoted 6 lines
This is a terrible user experience. The user has no way to tell what drivers are going to do. If he specifies the wrong thing, e.g., "assume no peer-to-peer traffic," and then loads a driver that does peer-to-peer, the kernel will configure MPS aggressively and when the device does a peer-to- peer transfer, it may cause a Malformed TLP error.
I agree that this isn't a great user experience, but just want to clarify that this problem is orthogonal to this patch series, correct?
Prior to this series, the MPS mismatch is still possible with p2p traffic, but when an IOMMU is enabled p2p traffic will result in DMAR faults. The aim of the series is to allow drivers to fix the latter, not the former.
Thanks,
Will
--
nvpublic
Bjorn Helgaas
maintainerQuoted 58 lines · William Davis
Quoted 51 lines
-----Original Message-----
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Thursday, May 7, 2015 8:13 AM
To: Yijing Wang
Cc: William Davis; Joerg Roedel; open list:INTEL IOMMU (VT-d); linux- [email protected]; Terence Ripperda; John Hubbard; Jerome Glisse; Dave Jiang; David S. Miller; Alex Williamson
Subject: Re: [PATCH 0/6] IOMMU/DMAmap_resourcesupport for peer-to-peerQuoted 20 lines · Yijing Wang
Quoted 19 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 8 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
Quoted 5 lines
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
...I think we currently assume there's no peer-to-peer traffic.
Quoted 8 lines
Quoted 4 lines
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).I think it should be ok for PCIe MPS configuration,
PCIE_BUS_PEER2PEERforce every device's MPS to 128B, what its concern is the TLP payload size. In this series, it seems to only map a iova for device bar region.MPS configuration makes assumptions about whether there will be any peer- to-peer traffic. If there will be none, MPS can be configured more aggressively.
I don't think Linux has any way to detect whether a driver is doing peer- to-peer, and there's no way to prevent a driver from doing it. We're stuck with requiring the user to specify boot options ("pci=pcie_bus_safe", "pci=pcie_bus_perf", "pci=pcie_bus_peer2peer", etc.) that tell the PCI core what the user expects to happen.
Quoted 6 lines
This is a terrible user experience. The user has no way to tell what drivers are going to do. If he specifies the wrong thing, e.g., "assume no peer-to-peer traffic," and then loads a driver that does peer-to-peer, the kernel will configure MPS aggressively and when the device does a peer-to- peer transfer, it may cause a Malformed TLP error.
Quoted 3 lines
I agree that this isn't a great user experience, but just want to clarify that this problem is orthogonal to this patch series, correct?
Prior to this series, the MPS mismatch is still possible with p2p traffic, but when an IOMMU is enabled p2p traffic will result in DMAR faults. The aim of the series is to allow drivers to fix the latter, not the former.
Prior to this series, there wasn't any infrastructure for drivers to do p2p, so it was mostly reasonable to assume that there *was* no p2p traffic.
I think we currently default to doing nothing to MPS. Prior to this series, it might have been reasonable to optimize based on a "no-p2p" assumption, e.g., default to pcie_bus_safe or pcie_bus_perf. After this series, I'm not sure what we could do, because p2p will be much more likely.
It's just an issue; I don't know what the resolution is.
Bjorn
Quoted 67 lines · Bjorn Helgaas
Quoted 55 lines · William Davis
Quoted 48 lines
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Thursday, May 7, 2015 8:13 AM
To: Yijing Wang
Cc: William Davis; Joerg Roedel; open list:INTEL IOMMU (VT-d); linux- [email protected]; Terence Ripperda; John Hubbard; Jerome Glisse; Dave Jiang; David S. Miller; Alex Williamson
Subject: Re: [PATCH 0/6] IOMMU/DMAmap_resourcesupport for peer-to-peerQuoted 20 lines · Yijing Wang
Quoted 19 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 8 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
Quoted 5 lines
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
...I think we currently assume there's no peer-to-peer traffic.
Quoted 8 lines
Quoted 4 lines
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).I think it should be ok for PCIe MPS configuration,
PCIE_BUS_PEER2PEERforce every device's MPS to 128B, what its concern is the TLP payload size. In this series, it seems to only map a iova for device bar region.MPS configuration makes assumptions about whether there will be any peer- to-peer traffic. If there will be none, MPS can be configured more aggressively.
I don't think Linux has any way to detect whether a driver is doing peer- to-peer, and there's no way to prevent a driver from doing it. We're stuck with requiring the user to specify boot options ("pci=pcie_bus_safe", "pci=pcie_bus_perf", "pci=pcie_bus_peer2peer", etc.) that tell the PCI core what the user expects to happen.
Quoted 6 lines
This is a terrible user experience. The user has no way to tell what drivers are going to do. If he specifies the wrong thing, e.g., "assume no peer-to-peer traffic," and then loads a driver that does peer-to-peer, the kernel will configure MPS aggressively and when the device does a peer-to- peer transfer, it may cause a Malformed TLP error.
Quoted 6 lines
I agree that this isn't a great user experience, but just want to clarify that this problem is orthogonal to this patch series, correct?
Prior to this series, the MPS mismatch is still possible with p2p traffic, but when an IOMMU is enabled p2p traffic will result in DMAR faults. The aim of the series is to allow drivers to fix the latter, not the former.
Prior to this series, there wasn't any infrastructure for drivers to do p2p, so it was mostly reasonable to assume that there *was* no p2p traffic.
Quoted 7 lines
I think we currently default to doing nothing to MPS. Prior to this series, it might have been reasonable to optimize based on a "no-p2p" assumption, e.g., default to
pcie_bus_safeorpcie_bus_perf. After this series, I'm not sure what we could do, because p2p will be much more likely.It's just an issue; I don't know what the resolution is.
Can't we just have each device update its MPS at runtime. So if device A decide to map something from device B then device A update MPS for A and B to lowest common supported value.
Of course you need to keep track of that per device so that if a device C comes around and want to exchange with device B and both C and B support higher payload than A then if C reprogram B it will trigger issue for A.
I know we update other PCIE configuration parameter at runtime for GPU, dunno if it is widely tested for other devices.
Cheers,
Jérôme
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 80 lines · Jerome Glisse
Quoted 67 lines · Bjorn Helgaas
Quoted 55 lines · William Davis
Quoted 48 lines
From: Bjorn Helgaas [mailto:[email protected]]
Sent: Thursday, May 7, 2015 8:13 AM
To: Yijing Wang
Cc: William Davis; Joerg Roedel; open list:INTEL IOMMU (VT-d); linux- [email protected]; Terence Ripperda; John Hubbard; Jerome Glisse; Dave Jiang; David S. Miller; Alex Williamson
Subject: Re: [PATCH 0/6] IOMMU/DMAmap_resourcesupport for peer-to-peerQuoted 20 lines · Yijing Wang
Quoted 19 lines · Bjorn Helgaas
[+cc Yijing, Dave J, Dave M, Alex]
Quoted 8 lines · On Fri, May 01, 2015 at 01:32:12PM -0500…
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
Quoted 5 lines
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
...I think we currently assume there's no peer-to-peer traffic.
Quoted 8 lines
Quoted 4 lines
I don't know whether changing that will break anything, but I'm concerned about these:
- PCIe MPS configuration (see
pcie_bus_configure_settings()).I think it should be ok for PCIe MPS configuration,
PCIE_BUS_PEER2PEERforce every device's MPS to 128B, what its concern is the TLP payload size. In this series, it seems to only map a iova for device bar region.MPS configuration makes assumptions about whether there will be any peer- to-peer traffic. If there will be none, MPS can be configured more aggressively.
I don't think Linux has any way to detect whether a driver is doing peer- to-peer, and there's no way to prevent a driver from doing it. We're stuck with requiring the user to specify boot options ("pci=pcie_bus_safe", "pci=pcie_bus_perf", "pci=pcie_bus_peer2peer", etc.) that tell the PCI core what the user expects to happen.
Quoted 6 lines
This is a terrible user experience. The user has no way to tell what drivers are going to do. If he specifies the wrong thing, e.g., "assume no peer-to-peer traffic," and then loads a driver that does peer-to-peer, the kernel will configure MPS aggressively and when the device does a peer-to- peer transfer, it may cause a Malformed TLP error.
Quoted 6 lines
I agree that this isn't a great user experience, but just want to clarify that this problem is orthogonal to this patch series, correct?
Prior to this series, the MPS mismatch is still possible with p2p traffic, but when an IOMMU is enabled p2p traffic will result in DMAR faults. The aim of the series is to allow drivers to fix the latter, not the former.
Prior to this series, there wasn't any infrastructure for drivers to do p2p, so it was mostly reasonable to assume that there *was* no p2p traffic.
Quoted 7 lines
I think we currently default to doing nothing to MPS. Prior to this series, it might have been reasonable to optimize based on a "no-p2p" assumption, e.g., default to
pcie_bus_safeorpcie_bus_perf. After this series, I'm not sure what we could do, because p2p will be much more likely.It's just an issue; I don't know what the resolution is.
Can't we just have each device update its MPS at runtime. So if device A decide to map something from device B then device A update MPS for A and B to lowest common supported value.
Quoted 7 lines
Of course you need to keep track of that per device so that if a device C comes around and want to exchange with device B and both C and B support higher payload than A then if C reprogram B it will trigger issue for A.
I know we update other PCIE configuration parameter at runtime for GPU, dunno if it is widely tested for other devices.
I believe all these cases are btwn endpts and the upstream ports of a PCIe port/host-bringe/PCIe switch they are connected to, i.e., true, wire peers -- not across a PCIe domain, which is the context of this p2p that the MPS has to span.
Quoted 7 lines
Cheers,
Jérôme
_______________________________________________
iommu mailing list iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of
map_pageandmap_sgconvert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.
Quoted 3 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
Does it work if you boot with 'iommu=soft swiotlb=force' which will mandate an strict usage of the DMA API?
Quoted 30 lines
Thanks,
WillWill Davis (6):
dma-debug: add checking for map/unmap_resource
DMA-API: Introduce dma_(un)map_resource
dma-mapping: pci: add pci_(un)map_resource iommu/amd: Implement (un)map_resource iommu/vt-d: implement (un)map_resource
x86: add pci-nommu implementation ofmap_resourcearch/x86/kernel/pci-nommu.c | 17 +++++++ drivers/iommu/amd_iommu.c | 76 ++++++++++++++++++++++++++------ drivers/iommu/intel-iommu.c | 18 ++++++++ include/asm-generic/dma-mapping-broken.h | 9 ++++ include/asm-generic/dma-mapping-common.h | 34 ++++++++++++++ include/asm-generic/pci-dma-compat.h | 14 ++++++ include/linux/dma-debug.h | 20 +++++++++ include/linux/dma-mapping.h | 7 +++ lib/dma-debug.c | 48 ++++++++++++++++++++ 9 files changed, 230 insertions(+), 13 deletions(-)Signature · 6 lines
2.3.7 _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Quoted 20 lines · Konrad Rzeszutek Wilk
Quoted 19 lines · On Fri, May 01, 2015 at 01:32:12PM -0500…
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of
map_pageandmap_sgconvert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.
Quoted 7 lines
Quoted 3 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
Does it work if you boot with 'iommu=soft swiotlb=force' which will mandate an strict usage of the DMA API?
PCIe peer2peer is borked on all motherboards I've tried. Only writes are possible. Reads are not supported. I suppose if you have a platform with only PCI and an IOMMU this would be very useful. Without both read and write PCIe peer2peer support, this seems unnecessary.
Mark
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 25 lines · Mark Hounschell
Quoted 24 lines · Konrad Rzeszutek Wilk
Quoted 22 lines · On Fri, May 01, 2015 at 01:32:12PM -0500…
From: Will Davis <[email protected]>
Hi,
This patch series adds DMA APIs to map and unmap a struct resource to and from a PCI device's IOVA domain, and implements the AMD, Intel, and nommu versions of these interfaces.
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
The underlying implementations of
map_pageandmap_sgconvert the struct page into its physical address anyway, so we just need a way to route the physical address of the BAR region to these implementations. The new interfaces do this by taking the struct resource describing a device's BAR region, from which the physical address is derived.The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
Quoted 5 lines
Quoted 3 lines
Does it work if you boot with 'iommu=soft swiotlb=force' which will mandate an strict usage of the DMA API?
PCIe peer2peer is borked on all motherboards I've tried. Only writes are
:-(
Quoted 4 lines
possible. Reads are not supported. I suppose if you have a platform with only PCI and an IOMMU this would be very useful. Without both read and write PCIe peer2peer support, this seems unnecessary.
It is a perfect way to test the code to make sure the API works (or it fails in the failure modes) _and_ that the drivers as well (use the pci_map_sync, and so on).
Quoted 3 lines
Mark
Quoted 25 lines
-----Original Message-----
From: Mark Hounschell [mailto:[email protected]]
Sent: Friday, May 08, 2015 3:46 PM
To: Konrad Rzeszutek Wilk; William Davis
Cc: [email protected]; [email protected]; [email protected]; John Hubbard; Terence Ripperda
Subject: Re: [PATCH 0/6] IOMMU/DMAmap_resourcesupport for peer-to-peerQuoted 5 lines · Konrad Rzeszutek Wilk
Quoted 4 lines · On Fri, May 01, 2015 at 01:32:12PM -0500, [email protected] wrote:
From: Will Davis <[email protected]>
Hi,
...
Quoted 6 lines
Quoted 6 lines
This solves a long-standing problem with the existing DMA-remapping interfaces, which require that a struct page be given for the region to be mapped into a device's IOVA domain. This requirement cannot support peer device BAR ranges, for which no struct pages exist.
...
Quoted 1 line
Quoted 1 line
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation.
PCIe peer2peer is borked on all motherboards I've tried. Only writes are possible. Reads are not supported. I suppose if you have a platform with only PCI and an IOMMU this would be very useful. Without both read and write PCIe peer2peer support, this seems unnecessary.
PCIe peer-to-peer isn't inherently broken or useless itself, even if a lot of its implementations are; I've successfully tested these patches with existing hardware (dual NVIDIA GPUs + an old-ish workstation), and it solves a longstanding problem for us [1], so I disagree with the assessment that this would be unnecessary.
I guess I don't see why the existence of some, or even a lot of, poor implementations suffices as a reason to reject a generic mechanism to support the "good", standardized implementations.
Thanks,
Will
--
nvpublic
Quoted 10 lines
-----Original Message-----
From: Konrad Rzeszutek Wilk [mailto:[email protected]]
Sent: Friday, May 08, 2015 3:22 PM
To: William Davis
Cc: [email protected]; [email protected]; [email protected]; [email protected]; John Hubbard; Terence Ripperda
Subject: Re: [PATCH 0/6] IOMMU/DMAmap_resourcesupport for peer-to-peer
Quoted 9 lines
...
Quoted 4 lines
The Intel and nommu versions have been verified on a dual Intel Xeon E5405 workstation. I'm in the process of obtaining hardware to test the AMD version as well. Please review.
Does it work if you boot with 'iommu=soft swiotlb=force' which will mandate an strict usage of the DMA API?
This patch series doesn't yet add a SWIOTLB implementation, and so the dma_map_resource() call would return 0 to indicate the path is not implemented (see patch 2/6). So no, the new interfaces would not work with that configuration, but they're also not expected to at this point.
Thanks,
Will
--
nvpublic