Copy Offload in NVMe Fabrics with P2P PCI Memory
Subsystems (9)
Logan Gunthorpe
maintainerv4 cover Copy Offload in NVMe Fabrics with P2P PCI Memory
Hi Everyone,
Here's v4 of our series to introduce P2P based copy offload to NVMe fabrics. This version has been rebased onto v4.17-rc2. A git repo is here:
https://github.com/sbates130272/linux-p2pmem pci-p2p-v4
Thanks,
Logan
Changes in v4:
* Change the original upstream_bridges_match() function to upstream_bridge_distance() which calculates the distance between two devices as long as they are behind the same root port. This should address Bjorn's concerns that the code was to focused on being behind a single switch.
* The disable ACS function now disables ACS for all bridge ports instead of switch ports (ie. those that had two upstream_bridge ports).
* Change the pci_p2pmem_alloc_sgl() and pci_p2pmem_free_sgl() API to be more like sgl_alloc() in that the alloc function returns the allocated scatterlist and nents is not required bythe free function.
* Moved the new documentation into the driver-api tree as requested by Jonathan
* Add SGL alloc and free helpers in the nvmet code so that the individual drivers can share the code that allocates P2P memory. As requested by Christoph.
* Cleanup the nvmet_p2pmem_store() function as Christoph thought my first attempt was ugly.
* Numerous commit message and comment fix-ups
Changes in v3:
* Many more fixes and minor cleanups that were spotted by Bjorn
* Additional explanation of the ACS change in both the commit message and Kconfig doc. Also, the code that disables the ACS bits is surrounded explicitly by an #ifdef
* Removed the flag we added to rdma_rw_ctx() in favour of using is_pci_p2pdma_page(), as suggested by Sagi.
* Adjust pci_p2pmem_find() so that it prefers P2P providers that are closest to (or the same as) the clients using them. In cases of ties, the provider is randomly chosen.
* Modify the NVMe Target code so that the PCI device name of the provider may be explicitly specified, bypassing the logic in pci_p2pmem_find(). (Note: it's still enforced that the provider must be behind the same switch as the clients).
* As requested by Bjorn, added documentation for driver writers.
Changes in v2:
* Renamed everything to 'p2pdma' per the suggestion from Bjorn as well as a bunch of cleanup and spelling fixes he pointed out in the last series.
* To address Alex's ACS concerns, we change to a simpler method of just disabling ACS behind switches for any kernel that has CONFIG_PCI_P2PDMA.
* We also reject using devices that employ 'dma_virt_ops' which should fairly simply handle Jason's concerns that this work might break with the HFI, QIB and rxe drivers that use the virtual ops to implement their own special DMA operations.
--
This is a continuation of our work to enable using Peer-to-Peer PCI memory in the kernel with initial support for the NVMe fabrics target subsystem. Many thanks go to Christoph Hellwig who provided valuable feedback to get these patches to where they are today.
The concept here is to use memory that's exposed on a PCI BAR as data buffers in the NVMe target code such that data can be transferred from an RDMA NIC to the special memory and then directly to an NVMe device avoiding system memory entirely. The upside of this is better QoS for applications running on the CPU utilizing memory and lower PCI bandwidth required to the CPU (such that systems could be designed with fewer lanes connected to the CPU).
Due to these trade-offs we've designed the system to only enable using the PCI memory in cases where the NIC, NVMe devices and memory are all behind the same PCI switch hierarchy. This will mean many setups that could likely work well will not be supported so that we can be more confident it will work and not place any responsibility on the user to understand their topology. (We chose to go this route based on feedback we received at the last LSF). Future work may enable these transfers using a white list of known good root complexes. However, at this time, there is no reliable way to ensure that Peer-to-Peer transactions are permitted between PCI Root Ports.
In order to enable this functionality, we introduce a few new PCI functions such that a driver can register P2P memory with the system. Struct pages are created for this memory using devm_memremap_pages() and the PCI bus offset is stored in the corresponding pagemap structure.
When the PCI P2PDMA config option is selected the ACS bits in every bridge port in the system are turned off to allow traffic to pass freely behind the root port. At this time, the bit must be disabled at boot so the IOMMU subsystem can correctly create the groups, though this could be addressed in the future. There is no way to dynamically disable the bit and alter the groups.
Another set of functions allow a client driver to create a list of client devices that will be used in a given P2P transactions and then use that list to find any P2P memory that is supported by all the client devices.
In the block layer, we also introduce a P2P request flag to indicate a given request targets P2P memory as well as a flag for a request queue to indicate a given queue supports targeting P2P memory. P2P requests will only be accepted by queues that support it. Also, P2P requests are marked to not be merged seeing a non-homogenous request would complicate the DMA mapping requirements.
In the PCI NVMe driver, we modify the existing CMB support to utilize the new PCI P2P memory infrastructure and also add support for P2P memory in its request queue. When a P2P request is received it uses the pci_p2pmem_map_sg() function which applies the necessary transformation to get the corrent pci_bus_addr_t for the DMA transactions.
In the RDMA core, we also adjust rdma_rw_ctx_init() and rdma_rw_ctx_destroy() to take a flags argument which indicates whether to use the PCI P2P mapping functions or not. To avoid odd RDMA devices that don't use the proper DMA infrastructure this code rejects using any device that employs the virt_dma_ops implementation.
Finally, in the NVMe fabrics target port we introduce a new configuration boolean: 'allow_p2pmem'. When set, the port will attempt to find P2P memory supported by the RDMA NIC and all namespaces. If supported memory is found, it will be used in all IO transfers. And if a port is using P2P memory, adding new namespaces that are not supported by that memory will fail.
These patches have been tested on a number of Intel based systems and for a variety of RDMA NICs (Mellanox, Broadcomm, Chelsio) and NVMe SSDs (Intel, Seagate, Samsung) and p2pdma devices (Eideticom, Microsemi, Chelsio and Everspin) using switches from both Microsemi and Broadcomm.
Logan Gunthorpe (14):
PCI/P2PDMA: Support peer-to-peer memory
PCI/P2PDMA: Add sysfs group to display p2pmem stats PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
docs-rst: Add a new directory for PCI documentation PCI/P2PDMA: Add P2P DMA driver writer's documentation
block: Introduce PCI P2P flags for request and request queue IB/core: Ensure we map P2P memory correctly in
rdma_rw_ctx_[init|destroy]()
nvme-pci: Use PCI p2pmem subsystem to manage the CMB
nvme-pci: Add support for P2P memory in requests
nvme-pci: Add a quirk for a pseudo CMB
nvmet: Introduce helper functions to allocate and free request SGLs
nvmet-rdma: Use new SGL alloc/free helper for requests
nvmet: Optionally use PCI P2P memory
Documentation/ABI/testing/sysfs-bus-pci | 25 +
Documentation/PCI/index.rst | 14 +
Documentation/driver-api/index.rst | 2 +-
Documentation/driver-api/pci/index.rst | 20 +
Documentation/driver-api/pci/p2pdma.rst | 166 ++++++
Documentation/driver-api/{ => pci}/pci.rst | 0
Documentation/index.rst | 3 +-
block/blk-core.c | 3 +
drivers/infiniband/core/rw.c | 13 +-
drivers/nvme/host/core.c | 4 +
drivers/nvme/host/nvme.h | 8 +
drivers/nvme/host/pci.c | 118 +++--
drivers/nvme/target/configfs.c | 67 +++
drivers/nvme/target/core.c | 143 ++++-
drivers/nvme/target/io-cmd.c | 3 +
drivers/nvme/target/nvmet.h | 15 +
drivers/nvme/target/rdma.c | 22 +-
drivers/pci/Kconfig | 26 +
drivers/pci/Makefile | 1 +
drivers/pci/p2pdma.c | 814 +++++++++++++++++++++++++++++
drivers/pci/pci.c | 6 +
include/linux/blk_types.h | 18 +-
include/linux/blkdev.h | 3 +
include/linux/memremap.h | 19 +
include/linux/pci-p2pdma.h | 118 +++++
include/linux/pci.h | 4 +
26 files changed, 1579 insertions(+), 56 deletions(-)
create mode 100644 Documentation/PCI/index.rst
create mode 100644 Documentation/driver-api/pci/index.rst
create mode 100644 Documentation/driver-api/pci/p2pdma.rst
rename Documentation/driver-api/{ => pci}/pci.rst (100%)
create mode 100644 drivers/pci/p2pdma.c
create mode 100644 include/linux/pci-p2pdma.h--
2.11.0
Logan Gunthorpe
maintainerPATCH v4 1/14 PCI/P2PDMA: Support peer-to-peer memory
Some PCI devices may have memory mapped in a BAR space that's intended for use in peer-to-peer transactions. In order to enable such transactions the memory must be registered with ZONE_DEVICE pages so it can be used by DMA interfaces in existing drivers.
Add an interface for other subsystems to find and allocate chunks of P2P memory as necessary to facilitate transfers between two PCI peers:
int pci_p2pdma_add_client();
struct pci_dev *pci_p2pmem_find();
void *pci_alloc_p2pmem();
The new interface requires a driver to collect a list of client devices involved in the transaction with the pci_p2pmem_add_client*() functions then call pci_p2pmem_find() to obtain any suitable P2P memory. Once this is done the list is bound to the memory and the calling driver is free to add and remove clients as necessary (adding incompatible clients will fail). With a suitable p2pmem device, memory can then be allocated with pci_alloc_p2pmem() for use in DMA transactions.
Depending on hardware, using peer-to-peer memory may reduce the bandwidth of the transfer but can significantly reduce pressure on system memory. This may be desirable in many cases: for example a system could be designed with a small CPU connected to a PCI switch by a small number of lanes which would maximize the number of lanes available to connect to NVMe devices.
The code is designed to only utilize the p2pmem device if all the devices involved in a transfer are behind the same root port (typically through a network of PCIe switches). This is because we have no way of knowing whether peer-to-peer routing between PCIe Root Ports is supported (PCIe r4.0, sec 1.3.1). Additionally, the benefits of P2P transfers that go through the RC is limited to only reducing DRAM usage and, in some cases, coding convenience. The PCI-SIG may be exploring adding a new capability bit to advertise whether this is possible for future hardware.
This commit includes significant rework and feedback from Christoph Hellwig.
--- drivers/pci/Kconfig | 17 ++ drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 694 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/memremap.h | 18 ++ include/linux/pci-p2pdma.h | 100 +++++++ include/linux/pci.h | 4 + 6 files changed, 834 insertions(+) create mode 100644 drivers/pci/p2pdma.c create mode 100644 include/linux/pci-p2pdma.h
drivers/pci/Kconfig +17 -0
@@ -124,6 +124,23 @@ config PCI_PASID If unsure, say N. +config PCI_P2PDMA + bool "PCI peer-to-peer transfer support" + depends on PCI && ZONE_DEVICE && EXPERT + select GENERIC_ALLOCATOR + help + Enableѕ drivers to do PCI peer-to-peer transactions to and from + BARs that are exposed in other devices that are the part of + the hierarchy where peer-to-peer DMA is guaranteed by the PCI + specification to work (ie. anything below a single PCI bridge). + + Many PCIe root complexes do not support P2P transactions and + it's hard to tell which support it at all, so at this time, DMA + transations must be between devices behind the same root port. + (Typically behind a network of PCIe switches). + + If unsure, say N. + config PCI_LABEL def_bool y if (DMI || ACPI) depends on PCI
drivers/pci/Makefile +1 -0
@@ -25,6 +25,7 @@ obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o obj-$(CONFIG_PCI_SYSCALL) += syscall.o obj-$(CONFIG_PCI_STUB) += pci-stub.o obj-$(CONFIG_PCI_ECAM) += ecam.o +obj-$(CONFIG_PCI_P2PDMA) += p2pdma.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-y += host/
drivers/pci/p2pdma.c new file +694 -0
694 lines not on this page · raw message
include/linux/memremap.h +18 -0
@@ -53,11 +53,16 @@ struct vmem_altmap {* driver can hotplug the device memory using ZONE_DEVICE and with that memory * type. Any page of a process can be migrated to such memory. However no one * should be allow to pin such memory so that it can always be evicted. +* +* MEMORY_DEVICE_PCI_P2PDMA: +* Device memory residing in a PCI BAR intended for use with Peer-to-Peer +* transactions. */ enum memory_type {MEMORY_DEVICE_HOST =0 ,MEMORY_DEVICE_PRIVATE ,MEMORY_DEVICE_PUBLIC , +MEMORY_DEVICE_PCI_P2PDMA , };/*
@@ -161,6 +166,19 @@ static inline void vmem_altmap_free(struct vmem_altmap *altmap, }#endif /* CONFIG_ZONE_DEVICE */ +#ifdef CONFIG_PCI_P2PDMA +static inline bool is_pci_p2pdma_page (const struct page *page) +{ +return is_zone_device_page (page) && + page->pgmap->type ==MEMORY_DEVICE_PCI_P2PDMA ; +} +#else /* CONFIG_PCI_P2PDMA */ +static inline bool is_pci_p2pdma_page (const struct page *page) +{ +return false; +} +#endif /* CONFIG_PCI_P2PDMA */ +#if defined(CONFIG_DEVICE_PRIVATE ) || defined(CONFIG_DEVICE_PUBLIC )static inline bool is_device_private_page (const struct page *page) {
include/linux/pci-p2pdma.h new file +100 -0
100 lines not on this page · raw message
include/linux/pci.h +4 -0
@@ -277,6 +277,7 @@ struct pcie_link_state;struct pci_vpd ;struct pci_sriov ;struct pci_ats ; +struct pci_p2pdma ;/* The pci_dev structure describes PCI devices */ struct pci_dev {
@@ -430,6 +431,9 @@ struct pci_dev {#ifdef CONFIG_PCI_PASID u16 pasid_features;#endif +#ifdef CONFIG_PCI_P2PDMA +struct pci_p2pdma *p2pdma; +#endif phys_addr_t rom;/* Physical address if not from BAR */ size_t romlen;/* Length if not from BAR */ char *driver_override;/* Driver name to force a match */
Signature · 1 line
2.11.0
Re: [PATCH v4 01/14] PCI/P2PDMA: Support peer-to-peer memory
Quoted 20 lines · Logan Gunthorpe
Some PCI devices may have memory mapped in a BAR space that's intended for use in peer-to-peer transactions. In order to enable such transactions the memory must be registered with
ZONE_DEVICEpages so it can be used by DMA interfaces in existing drivers.Add an interface for other subsystems to find and allocate chunks of P2P memory as necessary to facilitate transfers between two PCI peers:
int
pci_p2pdma_add_client();
structpci_dev*pci_p2pmem_find();
void*pci_alloc_p2pmem();The new interface requires a driver to collect a list of client devices involved in the transaction with the pci_p2pmem_add_client*() functions then call
pci_p2pmem_find()to obtain any suitable P2P memory. Once this is done the list is bound to the memory and the calling driver is free to add and remove clients as necessary (adding incompatible clients will fail). With a suitable p2pmem device, memory can then be allocated withpci_alloc_p2pmem()for use in DMA transactions.
Quoted 4 lines
Depending on hardware, using peer-to-peer memory may reduce the bandwidth of the transfer but can significantly reduce pressure on system memory. This may be desirable in many cases: for example a system could be designed with a small CPU connected to a PCI switch by a small number of lanes
s/PCI/PCIe/
Quoted 5 lines
which would maximize the number of lanes available to connect to NVMe devices.
The code is designed to only utilize the p2pmem device if all the devices involved in a transfer are behind the same root port (typically through
s/root port/PCI bridge/
Quoted 35 lines
a network of PCIe switches). This is because we have no way of knowing whether peer-to-peer routing between PCIe Root Ports is supported (PCIe r4.0, sec 1.3.1). Additionally, the benefits of P2P transfers that go through the RC is limited to only reducing DRAM usage and, in some cases, coding convenience. The PCI-SIG may be exploring adding a new capability bit to advertise whether this is possible for future hardware.
This commit includes significant rework and feedback from Christoph Hellwig.
Signed-off-by Christoph Hellwig <[email protected]>Signed-off-by Logan Gunthorpe <[email protected]>--- drivers/pci/Kconfig | 17 ++ drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 694 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/memremap.h | 18 ++ include/linux/pci-p2pdma.h | 100 +++++++ include/linux/pci.h | 4 + 6 files changed, 834 insertions(+) create mode 100644 drivers/pci/p2pdma.c create mode 100644 include/linux/pci-p2pdma.hdrivers/pci/Kconfig +3
-0@@ -124,6 +124,23 @@ config PCI_PASID If unsure, say N. +config PCI_P2PDMA + bool "PCI peer-to-peer transfer support" + depends on PCI && ZONE_DEVICE && EXPERT
drivers/pci/Kconfig config PCI_PASID · line 139
Quoted 10 lines
drivers/pci/Kconfig +10
-0+ select GENERIC_ALLOCATOR + help + Enableѕ drivers to do PCI peer-to-peer transactions to and from + BARs that are exposed in other devices that are the part of + the hierarchy where peer-to-peer DMA is guaranteed by the PCI + specification to work (ie. anything below a single PCI bridge). + + Many PCIe root complexes do not support P2P transactions and + it's hard to tell which support it at all, so at this time, DMA + transations must be between devices behind the same root port.
s/DMA transactions/PCIe DMA transactions/
(Theoretically P2P should work on conventional PCI, and this sentence only applies to PCIe.)
drivers/pci/Kconfig config PCI_PASID · line 140
Quoted 1 line
drivers/pci/Kconfig +1
-0+ (Typically behind a network of PCIe switches).
Not sure this last sentence adds useful information.
drivers/pci/Kconfig line 9
Quoted 11 lines
drivers/pci/Kconfig +10
-0+++ b/drivers/pci/p2pdma.c@@ -0,0 +1,694 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCI Peer 2 Peer DMA support. + * + * Copyright (c) 2016-2018, Logan Gunthorpe + * Copyright (c) 2016-2017, Microsemi Corporation + * Copyright (c) 2017, Christoph Hellwig + * Copyright (c) 2018, Eideticom Inc. + *
Nit: unnecessary blank line.
drivers/pci/Kconfig line 17
Quoted 8 lines
drivers/pci/Kconfig +8
-0+/* + * If a device is behind a switch, we try to find the upstream bridge + * port of the switch. This requires two calls to pci_upstream_bridge(): + * one for the upstream port on the switch, one on the upstream port + * for the next level in the hierarchy. Because of this, devices connected + * to the root port will be rejected. + */ +static struct pci_dev *get_upstream_bridge_port(struct pci_dev *pdev)
This function doesn't seem to be used anymore. Thanks for all your hard work to get rid of it!
Quoted 14 lines
drivers/pci/Kconfig +14
-0+{ + struct pci_dev *up1, *up2; + + if (!pdev) + return NULL; + + up1 = pci_dev_get(pci_upstream_bridge(pdev)); + if (!up1) + return NULL; + + up2 = pci_dev_get(pci_upstream_bridge(up1)); + pci_dev_put(up1); + + return up2;
drivers/pci/Kconfig line 41
Quoted 10 lines
drivers/pci/Kconfig +10
-0+} + +/* + * Find the distance through the nearest common upstream bridge between + * two PCI devices. + * + * If the two devices are the same device then 0 will be returned. + * + * If there are two virtual functions of the same device behind the same + * bridge port then 2 will be returned (one step down to the bridge then
s/bridge/PCIe switch/
Quoted 8 lines
drivers/pci/Kconfig +8
-0+ * one step back to the same device). + * + * In the case where two devices are connected to the same PCIe switch, the + * value 4 will be returned. This corresponds to the following PCI tree: + * + * -+ Root Port + * \+ Switch Upstream Port + * +-+ Switch Downstream Port
drivers/pci/Kconfig line 59
Quoted 10 lines
drivers/pci/Kconfig +10
-0+ * + \- Device A + * \-+ Switch Downstream Port + * \- Device B + * + * The distance is 4 because we traverse from Device A through the downstream + * port of the switch, to the common upstream port, back up to the second + * downstream port and then to Device B. + * + * Any two devices that don't have a common upstream bridge will return -1. + * In this way devices on seperate root ports will be rejected, which
s/seperate/separate/
s/root port/PCIe root ports/
(Again, since P2P should work on conventional PCI)
drivers/pci/Kconfig line 61
Quoted 2 lines
drivers/pci/Kconfig +2
-0+ * is what we want for peer-to-peer seeing there's no way to determine + * if the root complex supports forwarding between root ports.
s/seeing there's no way.../
seeing each PCIe root port defines a separate hierarchy domain and there's no way to determine whether the root complex supports forwarding between them./
drivers/pci/Kconfig line 69
Quoted 8 lines
drivers/pci/Kconfig +8
-0+ * + * In the case where two devices are connected to different PCIe switches + * this function will still return a positive distance as long as both + * switches evenutally have a common upstream bridge. Note this covers + * the case of using multiple PCIe switches to achieve a desired level of + * fan-out from a root port. The exact distance will be a function of the + * number of switches between Device A and Device B. + *
Nit: unnecessary blank line.
Quoted 2 lines
drivers/pci/Kconfig +2
-0+ */ +static int upstream_bridge_distance(struct pci_dev *a, > + struct pci_dev *b)
Logan Gunthorpe
maintainerRe: [PATCH v4 01/14] PCI/P2PDMA: Support peer-to-peer memory
Thanks for the review. I'll apply all of these for the changes for next version of the set.
Quoted 11 lines
drivers/pci/p2pdma.c line 193
Quoted 8 lines
drivers/pci/p2pdma.c new file +8
-0+/* +* If a device is behind a switch, we try to find the upstream bridge +* port of the switch. This requires two calls to pci_upstream_bridge(): +* one for the upstream port on the switch, one on the upstream port +* for the next level in the hierarchy. Because of this, devices connected +* to the root port will be rejected. +*/ +static struct pci_dev *get_upstream_bridge_port (struct pci_dev *pdev)This function doesn't seem to be used anymore. Thanks for all your hard work to get rid of it!
Oops, I thought I had gotten rid of it entirely, but I guess I messed it up a bit and it gets removed in patch 4. I'll fix it for v5.
Logan
Logan Gunthorpe
maintainerPATCH v4 2/14 PCI/P2PDMA: Add sysfs group to display p2pmem stats
In reply to Logan GunthorpeAdd a sysfs group to display statistics about P2P memory that is registered in each PCI device.
Attributes in the group display the total amount of P2P memory, the amount available and whether it is published or not.
--- Documentation/ABI/testing/sysfs-bus-pci | 25 +++++++++++++++ drivers/pci/p2pdma.c | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+)
Documentation/ABI/testing/sysfs-bus-pci +25 -0
@@ -323,3 +323,28 @@ Description: This is similar to /sys/bus/pci/drivers_autoprobe, but affects only the VFs associated with a specific PF. + +What: /sys/bus/pci/devices/.../p2pmem/available +Date: November 2017 +Contact: Logan Gunthorpe <[email protected]> +Description: + If the device has any Peer-to-Peer memory registered, this + file contains the amount of memory that has not been + allocated (in decimal). + +What: /sys/bus/pci/devices/.../p2pmem/size +Date: November 2017 +Contact: Logan Gunthorpe <[email protected]> +Description: + If the device has any Peer-to-Peer memory registered, this + file contains the total amount of memory that the device + provides (in decimal). + +What: /sys/bus/pci/devices/.../p2pmem/published +Date: November 2017 +Contact: Logan Gunthorpe <[email protected]> +Description: + If the device has any Peer-to-Peer memory registered, this + file contains a '1' if the memory has been published for + use inside the kernel or a '0' if it is only intended + for use within the driver that published it.
drivers/pci/p2pdma.c +54 -0
75 lines not on this page · raw message
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 3/14 PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset
In reply to Logan GunthorpeThe DMA address used when mapping PCI P2P memory must be the PCI bus address. Thus, introduce pci_p2pmem_[un]map_sg() to map the correct addresses when using P2P memory.
For this, we assume that an SGL passed to these functions contain all P2P memory or no P2P memory.
--- drivers/pci/p2pdma.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/memremap.h | 1 + include/linux/pci-p2pdma.h | 13 ++++++++++++ 3 files changed, 65 insertions(+)
drivers/pci/p2pdma.c +51 -0
@@ -190,6 +190,8 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, pgmap->res.flags =pci_resource_flags (pdev, bar); pgmap->ref = &pdev->p2pdma->devmap_ref; pgmap->type =MEMORY_DEVICE_PCI_P2PDMA ; + pgmap->pci_p2pdma_bus_offset =pci_bus_address (pdev, bar) - +pci_resource_start (pdev, bar); addr =devm_memremap_pages (&pdev->dev, pgmap);if (IS_ERR (addr)) {
@@ -746,3 +748,52 @@ void pci_p2pmem_publish(struct pci_dev *pdev, bool publish) pdev->p2pdma->p2pmem_published = publish; }EXPORT_SYMBOL_GPL (pci_p2pmem_publish); + +/** +* pci_p2pdma_map_sg - map a PCI peer-to-peer sg for DMA +* @dev: device doing the DMA request +* @sg: scatter list to map +* @nents: elements in the scatterlist +* @dir: DMA direction +* +* Returns the number of SG entries mapped +*/ +int pci_p2pdma_map_sg (struct device *dev,struct scatterlist *sg,int nents, +enum dma_data_direction dir) +{ +struct dev_pagemap *pgmap; +struct scatterlist *s; +phys_addr_t paddr; +int i; + +/* +* p2pdma mappings are not compatible with devices that use +* dma_virt_ops. +*/ +if (IS_ENABLED (CONFIG_DMA_VIRT_OPS ) && dev->dma_ops == &dma_virt_ops) +return 0 ; + +for_each_sg (sg, s, nents, i) { + pgmap =sg_page (s)->pgmap; + paddr =sg_phys (s); + + s->dma_address = paddr - pgmap->pci_p2pdma_bus_offset; +sg_dma_len (s) = s->length; + } + +return nents; +} +EXPORT_SYMBOL_GPL (pci_p2pdma_map_sg); + +/** +* pci_p2pdma_unmap_sg - unmap a PCI peer-to-peer sg for DMA +* @dev: device doing the DMA request +* @sg: scatter list to map +* @nents: elements in the scatterlist +* @dir: DMA direction +*/ +void pci_p2pdma_unmap_sg (struct device *dev,struct scatterlist *sg,int nents, +enum dma_data_direction dir) +{ +} +EXPORT_SYMBOL_GPL (pci_p2pdma_unmap_sg);
include/linux/memremap.h +1 -0
@@ -125,6 +125,7 @@ struct dev_pagemap {struct device *dev;void *data;enum memory_type type; +u64 pci_p2pdma_bus_offset; };#ifdef CONFIG_ZONE_DEVICE
include/linux/pci-p2pdma.h +13 -0
@@ -35,6 +35,10 @@ struct scatterlist *pci_p2pmem_alloc_sgl(struct pci_dev *pdev, unsigned int *nents, u32 length);void pci_p2pmem_free_sgl (struct pci_dev *pdev,struct scatterlist *sgl);void pci_p2pmem_publish (struct pci_dev *pdev,bool publish); +int pci_p2pdma_map_sg (struct device *dev,struct scatterlist *sg,int nents, +enum dma_data_direction dir); +void pci_p2pdma_unmap_sg (struct device *dev,struct scatterlist *sg,int nents, +enum dma_data_direction dir);#else /* CONFIG_PCI_P2PDMA */ static inline int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset)
@@ -96,5 +100,14 @@ static inline void pci_p2pmem_free_sgl(struct pci_dev *pdev,static inline void pci_p2pmem_publish (struct pci_dev *pdev,bool publish) { } +static inline int pci_p2pdma_map_sg (struct device *dev, +struct scatterlist *sg,int nents,enum dma_data_direction dir) +{ +return 0 ; +} +static inline void pci_p2pdma_unmap_sg (struct device *dev, +struct scatterlist *sg,int nents,enum dma_data_direction dir) +{ +}#endif /* CONFIG_PCI_P2PDMA */ #endif /* _LINUX_PCI_P2P_H */
Signature · 1 line
2.11.0
Re: [PATCH v4 03/14] PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset
s/dma/DMA/ (in subject)
Quoted 8 lines · Logan Gunthorpe
The DMA address used when mapping PCI P2P memory must be the PCI bus address. Thus, introduce pci_p2pmem_[un]map_sg() to map the correct addresses when using P2P memory.
For this, we assume that an SGL passed to these functions contain all P2P memory or no P2P memory.
Signed-off-by Logan Gunthorpe <[email protected]>
Logan Gunthorpe
maintainerPATCH v4 4/14 PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Logan GunthorpeFor peer-to-peer transactions to work the downstream ports in each switch must not have the ACS flags set. At this time there is no way to dynamically change the flags and update the corresponding IOMMU groups so this is done at enumeration time before the groups are assigned.
This effectively means that if CONFIG_PCI_P2PDMA is selected then all devices behind any PCIe switch heirarchy will be in the same IOMMU group. Which implies that individual devices behind any switch heirarchy will not be able to be assigned to separate VMs because there is no isolation between them. Additionally, any malicious PCIe devices will be able to DMA to memory exposed by other EPs in the same domain as TLPs will not be checked by the IOMMU.
Given that the intended use case of P2P Memory is for users with custom hardware designed for purpose, we do not expect distributors to ever need to enable this option. Users that want to use P2P must have compiled a custom kernel with this configuration option and understand the implications regarding ACS. They will either not require ACS or will have design the system in such a way that devices that require isolation will be separate from those using P2P transactions.
--- drivers/pci/Kconfig | 9 +++++++++ drivers/pci/p2pdma.c | 45 ++++++++++++++++++++++++++++++--------------- drivers/pci/pci.c | 6 ++++++ include/linux/pci-p2pdma.h | 5 +++++ 4 files changed, 50 insertions(+), 15 deletions(-)
drivers/pci/Kconfig +9 -0
@@ -139,6 +139,15 @@ config PCI_P2PDMA transations must be between devices behind the same root port. (Typically behind a network of PCIe switches). + Enabling this option will also disable ACS on all ports behind + any PCIe switch. This effectively puts all devices behind any + switch heirarchy into the same IOMMU group. Which implies that + individual devices behind any switch will not be able to be + assigned to separate VMs because there is no isolation between + them. Additionally, any malicious PCIe devices will be able to + DMA to memory exposed by other EPs in the same domain as TLPs + will not be checked by the IOMMU. + If unsure, say N. config PCI_LABEL
drivers/pci/p2pdma.c +30 -15
57 lines not on this page · raw message
drivers/pci/pci.c +6 -0
@@ -16,6 +16,7 @@#include <linux/of.h> #include <linux/of_pci.h> #include <linux/pci.h> +#include <linux/pci-p2pdma.h> #include <linux/pm.h> #include <linux/slab.h> #include <linux/module.h>
@@ -2835,6 +2836,11 @@ static void pci_std_enable_acs(struct pci_dev *dev)*/ void pci_enable_acs (struct pci_dev *dev) { +#ifdef CONFIG_PCI_P2PDMA +if (pci_p2pdma_disable_acs (dev)) +return ; +#endif +if (!pci_acs_enable)return ;
include/linux/pci-p2pdma.h +5 -0
@@ -18,6 +18,7 @@ struct block_device;struct scatterlist ;#ifdef CONFIG_PCI_P2PDMA +int pci_p2pdma_disable_acs (struct pci_dev *pdev);int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset);int pci_p2pdma_add_client (struct list_head *head,struct device *dev);
@@ -40,6 +41,10 @@ int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,void pci_p2pdma_unmap_sg (struct device *dev,struct scatterlist *sg,int nents,enum dma_data_direction dir);#else /* CONFIG_PCI_P2PDMA */ +static inline int pci_p2pdma_disable_acs (struct pci_dev *pdev) +{ +return 0 ; +}static inline int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset) {
Signature · 1 line
2.11.0
Randy Dunlap
reviewerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
On 04/23/2018 04:30 PM, Logan Gunthorpe wrote:> > Signed-off-by: Logan Gunthorpe <[email protected]>> ---
drivers/pci/Kconfig config PCI_P2PDMA · line 144
Quoted 13 lines
drivers/pci/Kconfig| 9 +++++++++>drivers/pci/p2pdma.c| 45 ++++++++++++++++++++++++++++++--------------->drivers/pci/pci.c| 6 ++++++>include/linux/pci-p2pdma.h| 5 +++++> 4 files changed, 50 insertions(+), 15 deletions(-)drivers/pci/Kconfig +3
-0@@ -139,6 +139,15 @@ config PCI_P2PDMA transations must be between devices behind the same root port. (Typically behind a network of PCIe switches). + Enabling this option will also disable ACS on all ports behind + any PCIe switch. This effectively puts all devices behind any + switch heirarchy into the same IOMMU group. Which implies that
hierarchy group, which
and sames fixes in the commit description...
Quoted 9 lines
drivers/pci/Kconfig +6
-0+ individual devices behind any switch will not be able to be + assigned to separate VMs because there is no isolation between + them. Additionally, any malicious PCIe devices will be able to + DMA to memory exposed by other EPs in the same domain as TLPs + will not be checked by the IOMMU. + If unsure, say N. config PCI_LABEL
Signature · 1 line
~Randy
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Logan Gunthorpe[+to Alex]
Alex,
Are you happy with this strategy of turning off ACS based on CONFIG_PCI_P2PDMA? We only check this at enumeration-time and I don't know if there are other places we would care?
Quoted 36 lines · Logan Gunthorpe
For peer-to-peer transactions to work the downstream ports in each switch must not have the ACS flags set. At this time there is no way to dynamically change the flags and update the corresponding IOMMU groups so this is done at enumeration time before the groups are assigned.
This effectively means that if
CONFIG_PCI_P2PDMAis selected then all devices behind any PCIe switch heirarchy will be in the same IOMMU group. Which implies that individual devices behind any switch heirarchy will not be able to be assigned to separate VMs because there is no isolation between them. Additionally, any malicious PCIe devices will be able to DMA to memory exposed by other EPs in the same domain as TLPs will not be checked by the IOMMU.Given that the intended use case of P2P Memory is for users with custom hardware designed for purpose, we do not expect distributors to ever need to enable this option. Users that want to use P2P must have compiled a custom kernel with this configuration option and understand the implications regarding ACS. They will either not require ACS or will have design the system in such a way that devices that require isolation will be separate from those using P2P transactions.
Signed-off-by Logan Gunthorpe <[email protected]>--- drivers/pci/Kconfig | 9 +++++++++ drivers/pci/p2pdma.c | 45 ++++++++++++++++++++++++++++++--------------- drivers/pci/pci.c | 6 ++++++ include/linux/pci-p2pdma.h | 5 +++++ 4 files changed, 50 insertions(+), 15 deletions(-)drivers/pci/Kconfig +0
-0
drivers/pci/Kconfig config PCI_P2PDMA · line 144
Quoted 6 lines
drivers/pci/Kconfig +3
-0@@ -139,6 +139,15 @@ config PCI_P2PDMA transations must be between devices behind the same root port. (Typically behind a network of PCIe switches). + Enabling this option will also disable ACS on all ports behind + any PCIe switch. This effectively puts all devices behind any + switch heirarchy into the same IOMMU group. Which implies that
s/heirarchy/hierarchy/ (also above in changelog)
Quoted 18 lines
drivers/pci/Kconfig +6
-0+ individual devices behind any switch will not be able to be + assigned to separate VMs because there is no isolation between + them. Additionally, any malicious PCIe devices will be able to + DMA to memory exposed by other EPs in the same domain as TLPs + will not be checked by the IOMMU. + If unsure, say N. config PCI_LABELdrivers/pci/p2pdma.c +0
-1@@ -240,27 +240,42 @@ static struct pci_dev *find_parent_pci_dev(struct device *dev) }/* -* If a device is behind a switch, we try to find the upstream bridge
drivers/pci/p2pdma.c static struct pci_dev *find_parent_pci_dev(struct device *dev) · line 248
Quoted 10 lines
drivers/pci/p2pdma.c +6
-4-* port of the switch. This requires two calls to pci_upstream_bridge(): -* one for the upstream port on the switch, one on the upstream port -* for the next level in the hierarchy. Because of this, devices connected -* to the root port will be rejected. +* pci_p2pdma_disable_acs - disable ACS flags for all PCI bridges +* @pdev: device to disable ACS flags for +* +* The ACS flags for P2P Request Redirect and P2P Completion Redirect need +* to be disabled on any PCI bridge in order for the TLPS to not be forwarded +* up to the RC which is not what we want for P2P.
s/PCI bridge/PCIe switch/ (ACS doesn't apply to conventional PCI)
Quoted 93 lines
drivers/pci/p2pdma.c +24
-10+* +* This function is called when the devices are first enumerated and +* will result in all devices behind any bridge to be in the same IOMMU +* group. At this time, there is no way to "hotplug" IOMMU groups so we rely +* on this largish hammer. If you need the devices to be in separate groups +* don't enable CONFIG_PCI_P2PDMA. +* +* Returns 1 if the ACS bits for this device was cleared, otherwise 0. */ -static struct pci_dev *get_upstream_bridge_port (struct pci_dev *pdev) +int pci_p2pdma_disable_acs (struct pci_dev *pdev) { -struct pci_dev *up1, *up2; +int pos; +u16 ctrl; -if (!pdev) -return NULL ; +if (!pci_is_bridge (pdev)) +return 0 ; - up1 =pci_dev_get (pci_upstream_bridge (pdev)); -if (!up1) -return NULL ; + pos =pci_find_ext_capability (pdev,PCI_EXT_CAP_ID_ACS ); +if (!pos) +return 0 ; + +pci_info (pdev,"disabling ACS flags for peer-to-peer DMA\n" ); + +pci_read_config_word (pdev, pos +PCI_ACS_CTRL , &ctrl); + + ctrl &= ~(PCI_ACS_RR |PCI_ACS_CR ); - up2 =pci_dev_get (pci_upstream_bridge (up1)); -pci_dev_put (up1); +pci_write_config_word (pdev, pos +PCI_ACS_CTRL , ctrl); -return up2; +return 1 ; }/* drivers/pci/pci.c +6
-0@@ -16,6 +16,7 @@#include <linux/of.h> #include <linux/of_pci.h> #include <linux/pci.h> +#include <linux/pci-p2pdma.h> #include <linux/pm.h> #include <linux/slab.h> #include <linux/module.h> @@ -2835,6 +2836,11 @@ static void pci_std_enable_acs(struct pci_dev *dev)*/ void pci_enable_acs (struct pci_dev *dev) { +#ifdef CONFIG_PCI_P2PDMA +if (pci_p2pdma_disable_acs (dev)) +return ; +#endif +if (!pci_acs_enable)return ;include/linux/pci-p2pdma.h +5
-0@@ -18,6 +18,7 @@ struct block_device;struct scatterlist ;#ifdef CONFIG_PCI_P2PDMA +int pci_p2pdma_disable_acs (struct pci_dev *pdev);int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset);int pci_p2pdma_add_client (struct list_head *head,struct device *dev);@@ -40,6 +41,10 @@ int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,void pci_p2pdma_unmap_sg (struct device *dev,struct scatterlist *sg,int nents,enum dma_data_direction dir);#else /* CONFIG_PCI_P2PDMA */ +static inline int pci_p2pdma_disable_acs (struct pci_dev *pdev) +{ +return 0 ; +}static inline int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset) {Signature · 1 line
2.11.0
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Hi Bjorn,
Am 08.05.2018 um 01:13 schrieb Bjorn Helgaas:
Quoted 7 lines
[+to Alex]
Alex,
Are you happy with this strategy of turning off ACS based on
CONFIG_PCI_P2PDMA? We only check this at enumeration-time and I don't know if there are other places we would care?
thanks for pointing this out, I totally missed this hack.
AMD APUs mandatory need the ACS flag set for the GPU integrated in the CPU when IOMMU is enabled or otherwise you will break SVM.
Similar problems arise when you do this for dedicated GPU, but we haven't upstreamed the support for this yet.
So that is a clear NAK from my side for the approach.
And what exactly is the problem here? I'm currently testing P2P with GPUs in different IOMMU domains and at least with AMD IOMMUs that works perfectly fine.
Regards,
Christian.
Quoted 169 lines · Logan Gunthorpe
Quoted 36 lines
For peer-to-peer transactions to work the downstream ports in each switch must not have the ACS flags set. At this time there is no way to dynamically change the flags and update the corresponding IOMMU groups so this is done at enumeration time before the groups are assigned.
This effectively means that if
CONFIG_PCI_P2PDMAis selected then all devices behind any PCIe switch heirarchy will be in the same IOMMU group. Which implies that individual devices behind any switch heirarchy will not be able to be assigned to separate VMs because there is no isolation between them. Additionally, any malicious PCIe devices will be able to DMA to memory exposed by other EPs in the same domain as TLPs will not be checked by the IOMMU.Given that the intended use case of P2P Memory is for users with custom hardware designed for purpose, we do not expect distributors to ever need to enable this option. Users that want to use P2P must have compiled a custom kernel with this configuration option and understand the implications regarding ACS. They will either not require ACS or will have design the system in such a way that devices that require isolation will be separate from those using P2P transactions.
Signed-off-by Logan Gunthorpe <[email protected]>--- drivers/pci/Kconfig | 9 +++++++++ drivers/pci/p2pdma.c | 45 ++++++++++++++++++++++++++++++--------------- drivers/pci/pci.c | 6 ++++++ include/linux/pci-p2pdma.h | 5 +++++ 4 files changed, 50 insertions(+), 15 deletions(-)drivers/pci/Kconfig +0
-0drivers/pci/Kconfig config PCI_P2PDMA · line 144
Quoted 6 lines
drivers/pci/Kconfig +3
-0@@ -139,6 +139,15 @@ config PCI_P2PDMA transations must be between devices behind the same root port. (Typically behind a network of PCIe switches). + Enabling this option will also disable ACS on all ports behind + any PCIe switch. This effectively puts all devices behind any + switch heirarchy into the same IOMMU group. Which implies thats/heirarchy/hierarchy/ (also above in changelog)
Quoted 18 lines
drivers/pci/Kconfig +6
-0+ individual devices behind any switch will not be able to be + assigned to separate VMs because there is no isolation between + them. Additionally, any malicious PCIe devices will be able to + DMA to memory exposed by other EPs in the same domain as TLPs + will not be checked by the IOMMU. + If unsure, say N. config PCI_LABELdrivers/pci/p2pdma.c +0
-1@@ -240,27 +240,42 @@ static struct pci_dev *find_parent_pci_dev(struct device *dev) }/* -* If a device is behind a switch, we try to find the upstream bridge drivers/pci/p2pdma.c static struct pci_dev *find_parent_pci_dev(struct device *dev) · line 248
Quoted 10 lines
drivers/pci/p2pdma.c +6
-4-* port of the switch. This requires two calls to pci_upstream_bridge(): -* one for the upstream port on the switch, one on the upstream port -* for the next level in the hierarchy. Because of this, devices connected -* to the root port will be rejected. +* pci_p2pdma_disable_acs - disable ACS flags for all PCI bridges +* @pdev: device to disable ACS flags for +* +* The ACS flags for P2P Request Redirect and P2P Completion Redirect need +* to be disabled on any PCI bridge in order for the TLPS to not be forwarded +* up to the RC which is not what we want for P2P. s/PCI bridge/PCIe switch/ (ACS doesn't apply to conventional PCI)
Quoted 93 lines
drivers/pci/p2pdma.c +24
-10+* +* This function is called when the devices are first enumerated and +* will result in all devices behind any bridge to be in the same IOMMU +* group. At this time, there is no way to "hotplug" IOMMU groups so we rely +* on this largish hammer. If you need the devices to be in separate groups +* don't enable CONFIG_PCI_P2PDMA. +* +* Returns 1 if the ACS bits for this device was cleared, otherwise 0. */ -static struct pci_dev *get_upstream_bridge_port (struct pci_dev *pdev) +int pci_p2pdma_disable_acs (struct pci_dev *pdev) { -struct pci_dev *up1, *up2; +int pos; +u16 ctrl; -if (!pdev) -return NULL ; +if (!pci_is_bridge (pdev)) +return 0 ; - up1 =pci_dev_get (pci_upstream_bridge (pdev)); -if (!up1) -return NULL ; + pos =pci_find_ext_capability (pdev,PCI_EXT_CAP_ID_ACS ); +if (!pos) +return 0 ; + +pci_info (pdev,"disabling ACS flags for peer-to-peer DMA\n" ); + +pci_read_config_word (pdev, pos +PCI_ACS_CTRL , &ctrl); + + ctrl &= ~(PCI_ACS_RR |PCI_ACS_CR ); - up2 =pci_dev_get (pci_upstream_bridge (up1)); -pci_dev_put (up1); +pci_write_config_word (pdev, pos +PCI_ACS_CTRL , ctrl); -return up2; +return 1 ; }/* drivers/pci/pci.c +6
-0@@ -16,6 +16,7 @@#include <linux/of.h> #include <linux/of_pci.h> #include <linux/pci.h> +#include <linux/pci-p2pdma.h> #include <linux/pm.h> #include <linux/slab.h> #include <linux/module.h> @@ -2835,6 +2836,11 @@ static void pci_std_enable_acs(struct pci_dev *dev)*/ void pci_enable_acs (struct pci_dev *dev) { +#ifdef CONFIG_PCI_P2PDMA +if (pci_p2pdma_disable_acs (dev)) +return ; +#endif +if (!pci_acs_enable)return ;include/linux/pci-p2pdma.h +5
-0@@ -18,6 +18,7 @@ struct block_device;struct scatterlist ;#ifdef CONFIG_PCI_P2PDMA +int pci_p2pdma_disable_acs (struct pci_dev *pdev);int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset);int pci_p2pdma_add_client (struct list_head *head,struct device *dev);@@ -40,6 +41,10 @@ int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,void pci_p2pdma_unmap_sg (struct device *dev,struct scatterlist *sg,int nents,enum dma_data_direction dir);#else /* CONFIG_PCI_P2PDMA */ +static inline int pci_p2pdma_disable_acs (struct pci_dev *pdev) +{ +return 0 ; +}static inline int pci_p2pdma_add_resource (struct pci_dev *pdev,int bar,size_t size,u64 offset) {Signature · 1 line
2.11.0
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
ICAgIA0KSGkgQ2hyaXN0aWFuDQoNCj4gQU1EIEFQVXMgbWFuZGF0b3J5IG5lZWQgdGhlIEFDUyBm bGFnIHNldCBmb3IgdGhlIEdQVSBpbnRlZ3JhdGVkIGluIHRoZSANCj4gQ1BVIHdoZW4gSU9NTVUg aXMgZW5hYmxlZCBvciBvdGhlcndpc2UgeW91IHdpbGwgYnJlYWsgU1ZNLg0KDQpPSyBidXQgaW4g dGhpcyBjYXNlIGFyZW4ndCB5b3UgbG9zaW5nIChtYW55IG9mKSB0aGUgYmVuZWZpdHMgb2YgUDJQ IHNpbmNlIGFsbCBETUFzIHdpbGwgbm93IGdldCByb3V0ZWQgdXAgdG8gdGhlIElPTU1VIGJlZm9y ZSBiZWluZyBwYXNzZWQgZG93biB0byB0aGUgZGVzdGluYXRpb24gUENJZSBFUD8NCg0KPiBTaW1p bGFyIHByb2JsZW1zIGFyaXNlIHdoZW4geW91IGRvIHRoaXMgZm9yIGRlZGljYXRlZCBHUFUsIGJ1 dCB3ZSANCj4gaGF2ZW4ndCB1cHN0cmVhbWVkIHRoZSBzdXBwb3J0IGZvciB0aGlzIHlldC4NCg0K SG1tLCBhcyBhYm92ZS4gV2l0aCBBQ1MgZW5hYmxlZCBvbiBhbGwgZG93bnN0cmVhbSBwb3J0cyBh bnkgUDJQIGVuYWJsZWQgRE1BIHdpbGwgYmUgcm91dGVkIHRvIHRoZSBJT01NVSB3aGljaCByZW1v dmVzIGEgbG90IG9mIHRoZSBiZW5lZml0LiANCiAgICANCj4gU28gdGhhdCBpcyBhIGNsZWFyIE5B SyBmcm9tIG15IHNpZGUgZm9yIHRoZSBhcHByb2FjaC4NCg0KRG8geW91IGhhdmUgYW4gYWx0ZXJu YXRpdmU/IFRoaXMgaXMgdGhlIGFwcHJvYWNoIHdlIGFycml2ZWQgaXQgYWZ0ZXIgYSByZWFzb25h Ymx5IGxlbmd0aHkgZGlzY3Vzc2lvbiBvbiB0aGUgbWFpbGluZyBsaXN0cy4gQWxleCwgYXJlIHlv dSBzdGlsbCBjb21mb3J0YWJsZSB3aXRoIHRoaXMgYXBwcm9hY2g/DQogICAgDQo+IEFuZCB3aGF0 IGV4YWN0bHkgaXMgdGhlIHByb2JsZW0gaGVyZT8NCiANCldlIGhhZCBhIHByZXR0eSBsZW5ndGh5 IGRpc2N1c3Npb24gb24gdGhpcyB0b3BpYyBvbiBvbmUgb2YgdGhlIHByZXZpb3VzIHJldmlzaW9u cy4gVGhlIGlzc3VlIGlzIHRoYXQgY3VycmVudGx5IHRoZXJlIGlzIG5vIG1lY2hhbmlzbSBpbiB0 aGUgSU9NTVUgY29kZSB0byBpbmZvcm0gVk1zIGlmIElPTU1VIGdyb3VwaW5ncyBjaGFuZ2UuIFNp bmNlIHAycGRtYSBjYW4gZHluYW1pY2FsbHkgY2hhbmdlIGl0cyB0b3BvbG9neSAoZHVlIHRvIFBD SSBob3RwbHVnKSB3ZSBoYWQgdG8gYmUgY29nbml6YW50IG9mIHRoZSBmYWN0IHRoYXQgQUNTIHNl dHRpbmdzIGNvdWxkIGNoYW5nZS4gU2luY2UgdGhlcmUgaXMgbm8gd2F5IHRvIGN1cnJlbnRseSBo YW5kbGUgY2hhbmdpbmcgQUNTIHNldHRpbmdzIGFuZCBoZW5jZSBJT01NVSBncm91cGluZ3MgdGhl IGNvbnNlbnN1cyB3YXMgdG8gc2ltcGx5IGRpc2FibGUgQUNTIG9uIGFsbCBwb3J0cyBpbiBhIHAy cGRtYSBkb21haW4uIFRoaXMgZWZmZWN0aXZlbHkgbWFrZXMgYWxsIHRoZSBkZXZpY2VzIGluIHRo ZSBwMnBkbWEgZG9tYWluIHBhcnQgb2YgdGhlIHNhbWUgSU9NTVUgZ3JvdXBpbmcuIFRoZSBwbGFu IHdpbGwgYmUgdG8gYWRkcmVzcyB0aGlzIGluIHRpbWUgYW5kIGFkZCBhIG1lY2hhbmlzbSBmb3Ig SU9NTVUgZ3JvdXBpbmcgY2hhbmdlcyBhbmQgbm90aWZpY2F0aW9uIHRvIFZNcyBidXQgdGhhdCdz IG5vdCBwYXJ0IG9mIHRoaXMgc2VyaWVzLiBOb3RlIHlvdSBhcmUgc3RpbGwgYWxsb3dlZCB0byBo YXZlIEFDUyBmdW5jdGlvbmluZyBvbiBvdGhlciBQQ0kgZG9tYWlucyBzbyBpZiB5b3UgZG8gbm90 IGEgcGx1cmFsaXR5IG9mIElPTU1VIGdyb3VwaW5ncyB5b3UgY2FuIHN0aWxsIGFjaGlldmUgaXQg KGJ1dCB5b3UgY2FuJ3QgZG8gcDJwZG1hIGFjcm9zcyBJT01NVSBncm91cGluZ3MsIHdoaWNoIGlz IHNhZmUpLg0KDQo+IEknbSBjdXJyZW50bHkgdGVzdGluZyBQMlAgd2l0aCAgR1BVcyBpbiBkaWZm ZXJlbnQgSU9NTVUgZG9tYWlucyBhbmQgYXQgbGVhc3Qgd2l0aCBBTUQgSU9NTVVzIHRoYXQgd29y a3MgcGVyZmVjdGx5IGZpbmUuDQoNCll1cCB0aGF0IHNob3VsZCB3b3JrIHRob3VnaCBhZ2FpbiBJ IGhhdmUgdG8gYXNrIGFyZSB5b3UgZGlzYWJsaW5nIEFDUyBvbiB0aGUgcG9ydHMgYmV0d2VlbiB0 aGUgdHdvIHBlZXIgZGV2aWNlcyB0byBnZXQgdGhlIHAycCBiZW5lZml0PyBJZiBub3QgeW91IGFy ZSBub3QgZ2V0dGluZyBhbGwgdGhlIHBlcmZvcm1hbmNlIGJlbmVmaXQgKGR1ZSB0byBJT01NVSBy b3V0aW5nKSwgaWYgeW91IGFyZSB0aGVuIHRoZXJlIGFyZSBvYnZpb3VzbHkgc2VjdXJpdHkgaW1w bGljYXRpb25zIGJldHdlZW4gdGhvc2UgSU9NTVUgZG9tYWlucyBpZiB0aGV5IGFyZSBhc3NpZ25l ZCB0byBkaWZmZXJlbnQgVk1zLiBBbmQgbm93IHRoZSBpc3N1ZSBpcyBpZiBuZXcgZGV2aWNlcyBh cmUgYWRkZWQgYW5kIHRoZSBwMnAgdG9wb2xvZ3kgbmVlZGVkIHRvIGNoYW5nZSB0aGVyZSB3b3Vs ZCBiZSBubyB3YXkgdG8gaW5mb3JtIHRoZSBWTXMgb2YgYW55IElPTU1VIGdyb3VwIGNoYW5nZS4g DQoNCkNoZWVycw0KDQpTdGVwaGVuDQogICAgDQoNCg==
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Am 08.05.2018 um 16:25 schrieb Stephen Bates:
Quoted 6 lines
Hi Christian
Quoted 2 lines
AMD APUs mandatory need the ACS flag set for the GPU integrated in the CPU when IOMMU is enabled or otherwise you will break SVM.
OK but in this case aren't you losing (many of) the benefits of P2P since all DMAs will now get routed up to the IOMMU before being passed down to the destination PCIe EP?
Well I'm not an expert on this, but I think that is an incorrect assumption you guys use here.
At least in the default configuration even with IOMMU enabled P2P transactions does NOT necessary travel up to the root complex for translation.
It's already late here, but if nobody beats me I'm going to dig up the necessary documentation tomorrow.
Regards,
Christian.
Quoted 20 lines
Quoted 3 lines
Similar problems arise when you do this for dedicated GPU, but we haven't upstreamed the support for this yet.
Hmm, as above. With ACS enabled on all downstream ports any P2P enabled DMA will be routed to the IOMMU which removes a lot of the benefit.
Quoted 1 line
So that is a clear NAK from my side for the approach.
Do you have an alternative? This is the approach we arrived it after a reasonably lengthy discussion on the mailing lists. Alex, are you still comfortable with this approach?
Quoted 1 line
And what exactly is the problem here?
We had a pretty lengthy discussion on this topic on one of the previous revisions. The issue is that currently there is no mechanism in the IOMMU code to inform VMs if IOMMU groupings change. Since p2pdma can dynamically change its topology (due to PCI hotplug) we had to be cognizant of the fact that ACS settings could change. Since there is no way to currently handle changing ACS settings and hence IOMMU groupings the consensus was to simply disable ACS on all ports in a p2pdma domain. This effectively makes all the devices in the p2pdma domain part of the same IOMMU grouping. The plan will be to address this in time and add a mechanism for IOMMU grouping changes and notification to VMs but that's not part of this series. Note you are still allowed to have ACS functioning on other PCI domains so if you do not a plurality of IOMMU groupings you can still achieve it (but you can't do p2pdma across IOMMU groupings, which is safe).
Quoted 1 line
I'm currently testing P2P with GPUs in different IOMMU domains and at least with AMD IOMMUs that works perfectly fine.
Yup that should work though again I have to ask are you disabling ACS on the ports between the two peer devices to get the p2p benefit? If not you are not getting all the performance benefit (due to IOMMU routing), if you are then there are obviously security implications between those IOMMU domains if they are assigned to different VMs. And now the issue is if new devices are added and the p2p topology needed to change there would be no way to inform the VMs of any IOMMU group change.
Cheers
Stephen
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Christian KönigQuoted 2 lines · Christian König
AMD APUs mandatory need the ACS flag set for the GPU integrated in the CPU when IOMMU is enabled or otherwise you will break SVM.
Well, given that the current set only disables ACS bits on bridges (previous versions were only on switches) this shouldn't be an issue for integrated devices. We do not disable ACS flags globally.
Quoted 3 lines
And what exactly is the problem here? I'm currently testing P2P with GPUs in different IOMMU domains and at least with AMD IOMMUs that works perfectly fine.
In addition to Stephen's comments, seeing we've established a general need to avoid the root complex (until we have a whitelist at least) we must have ACS disabled along the path between the devices. Otherwise, all TLPs will go through the root complex and if there is no support it will fail.
If the consensus is we want a command line option, then so be it. But we'll have to deny pretty much all P2P transactions unless the user correctly disables ACS along the path using the command line option and this is really annoying for users of this functionality to understand how to do that correctly.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Am 08.05.2018 um 18:27 schrieb Logan Gunthorpe:
Quoted 7 lines · Christian König
Quoted 2 lines
AMD APUs mandatory need the ACS flag set for the GPU integrated in the CPU when IOMMU is enabled or otherwise you will break SVM.
Well, given that the current set only disables ACS bits on bridges (previous versions were only on switches) this shouldn't be an issue for integrated devices. We do not disable ACS flags globally.
Ok, that is at least a step in the right direction. But I think we seriously need to test that for side effects.
Quoted 9 lines
Quoted 4 lines
And what exactly is the problem here? I'm currently testing P2P with GPUs in different IOMMU domains and at least with AMD IOMMUs that works perfectly fine.
In addition to Stephen's comments, seeing we've established a general need to avoid the root complex (until we have a whitelist at least) we must have ACS disabled along the path between the devices. Otherwise, all TLPs will go through the root complex and if there is no support it will fail.
Well I'm not an expert on this, but if I'm not completely mistaken that is not correct.
E.g. transactions are initially send to the root complex for translation, that's for sure. But at least for AMD GPUs the root complex answers with the translated address which is then cached in the device.
So further transactions for the same address range then go directly to the destination.
What you don't want is device isolation, cause in this case the root complex handles the transaction themselves. IIRC there where also something like "force_isolation" and "nobypass" parameters for the IOMMU to control that behavior.
It's already late here, but going to dig up the documentation for that tomorrow and/or contact a hardware engineer involved in the ACS spec.
Regards,
Christian.
Quoted 8 lines
If the consensus is we want a command line option, then so be it. But we'll have to deny pretty much all P2P transactions unless the user correctly disables ACS along the path using the command line option and this is really annoying for users of this functionality to understand how to do that correctly.
Logan
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Christian König
E.g. transactions are initially send to the root complex for translation, that's for sure. But at least for AMD GPUs the root complex answers with the translated address which is then cached in the device.
So further transactions for the same address range then go directly to the destination.
Sounds like you are referring to Address Translation Services (ATS). This is quite separate from ACS and, to my knowledge, isn't widely supported by switch hardware.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 3 lines · On Tue, 8 May 2018 13:13:40 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 2 lines · On 08/05/18 10:50 AM, Christian K=C3=B6nig wrote:
E.g. transactions are initially send to the root complex for=20 translation, that's for sure. But at least for AMD GPUs the root comple=
x=20
Quoted 3 lines
Quoted 3 lines
answers with the translated address which is then cached in the device. =20
So further transactions for the same address range then go directly to=
=20
Quoted 5 lines
Quoted 1 line
the destination. =20
=20
Sounds like you are referring to Address Translation Services (ATS). This is quite separate from ACS and, to my knowledge, isn't widely supported by switch hardware.
They are not so unrelated, see the ACS Direct Translated P2P capability, which in fact must be implemented by switch downstream ports implementing ACS and works specifically with ATS. This appears to be the way the PCI SIG would intend for P2P to occur within an IOMMU managed topology, routing pre-translated DMA directly between peer devices while requiring non-translated requests to bounce through the IOMMU. Really, what's the value of having an I/O virtual address space provided by an IOMMU if we're going to allow physical DMA between downstream devices, couldn't we just turn off the IOMMU altogether? Of course ATS is not without holes itself, basically that we trust the endpoint's implementation of ATS implicitly. Thanks,
Alex
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 11 lines · Alex Williamson
They are not so unrelated, see the ACS Direct Translated P2P capability, which in fact must be implemented by switch downstream ports implementing ACS and works specifically with ATS. This appears to be the way the PCI SIG would intend for P2P to occur within an IOMMU managed topology, routing pre-translated DMA directly between peer devices while requiring non-translated requests to bounce through the IOMMU. Really, what's the value of having an I/O virtual address space provided by an IOMMU if we're going to allow physical DMA between downstream devices, couldn't we just turn off the IOMMU altogether? Of course ATS is not without holes itself, basically that we trust the endpoint's implementation of ATS implicitly. Thanks,
I agree that this is what the SIG intends, but I don't think hardware fully supports this methodology yet. The Direct Translated capability just requires switches to forward packets that have the AT request type set. It does not require them to do the translation or to support ATS such that P2P requests can be translated by the IOMMU. I expect this is so that an downstream device can implement ATS and not get messed up by an upstream switch that doesn't support it.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 13 lines · On Tue, 8 May 2018 13:45:50 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 11 lines · Alex Williamson
They are not so unrelated, see the ACS Direct Translated P2P capability, which in fact must be implemented by switch downstream ports implementing ACS and works specifically with ATS. This appears to be the way the PCI SIG would intend for P2P to occur within an IOMMU managed topology, routing pre-translated DMA directly between peer devices while requiring non-translated requests to bounce through the IOMMU. Really, what's the value of having an I/O virtual address space provided by an IOMMU if we're going to allow physical DMA between downstream devices, couldn't we just turn off the IOMMU altogether? Of course ATS is not without holes itself, basically that we trust the endpoint's implementation of ATS implicitly. Thanks,
Quoted 7 lines
I agree that this is what the SIG intends, but I don't think hardware fully supports this methodology yet. The Direct Translated capability just requires switches to forward packets that have the AT request type set. It does not require them to do the translation or to support ATS such that P2P requests can be translated by the IOMMU. I expect this is so that an downstream device can implement ATS and not get messed up by an upstream switch that doesn't support it.
Well, I'm a bit confused, this patch series is specifically disabling ACS on switches, but per the spec downstream switch ports implementing ACS MUST implement direct translated P2P. So it seems the only potential gap here is the endpoint, which must support ATS or else there's nothing for direct translated P2P to do. The switch port plays no part in the actual translation of the request, ATS on the endpoint has already cached the translation and is now attempting to use it. For the switch port, this only becomes a routing decision, the request is already translated, therefore ACS RR and EC can be ignored to perform "normal" (direct) routing, as if ACS were not present. It would be a shame to go to all the trouble of creating this no-ACS mode to find out the target hardware supports ATS and should have simply used it, or we should have disabled the IOMMU altogether, which leaves ACS disabled. Thanks,
Alex
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 5 lines · Alex Williamson
Well, I'm a bit confused, this patch series is specifically disabling ACS on switches, but per the spec downstream switch ports implementing ACS MUST implement direct translated P2P. So it seems the only potential gap here is the endpoint, which must support ATS or else there's nothing for direct translated P2P to do. The switch port plays
Quoted 8 lines
no part in the actual translation of the request, ATS on the endpoint has already cached the translation and is now attempting to use it. For the switch port, this only becomes a routing decision, the request is already translated, therefore ACS RR and EC can be ignored to perform "normal" (direct) routing, as if ACS were not present. It would be a shame to go to all the trouble of creating this no-ACS mode to find out the target hardware supports ATS and should have simply used it, or we should have disabled the IOMMU altogether, which leaves ACS disabled.
Ah, ok, I didn't think it was the endpoint that had to implement ATS. But in that case, for our application, we need NVMe cards and RDMA NICs to all have ATS support and I expect that is just as unlikely. At least none of the endpoints on my system support it. Maybe only certain GPUs have this support.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 15 lines · On Tue, 8 May 2018 14:19:05 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 5 lines · Alex Williamson
Well, I'm a bit confused, this patch series is specifically disabling ACS on switches, but per the spec downstream switch ports implementing ACS MUST implement direct translated P2P. So it seems the only potential gap here is the endpoint, which must support ATS or else there's nothing for direct translated P2P to do. The switch port plays
Quoted 8 lines
no part in the actual translation of the request, ATS on the endpoint has already cached the translation and is now attempting to use it. For the switch port, this only becomes a routing decision, the request is already translated, therefore ACS RR and EC can be ignored to perform "normal" (direct) routing, as if ACS were not present. It would be a shame to go to all the trouble of creating this no-ACS mode to find out the target hardware supports ATS and should have simply used it, or we should have disabled the IOMMU altogether, which leaves ACS disabled.
Quoted 5 lines
Ah, ok, I didn't think it was the endpoint that had to implement ATS. But in that case, for our application, we need NVMe cards and RDMA NICs to all have ATS support and I expect that is just as unlikely. At least none of the endpoints on my system support it. Maybe only certain GPUs have this support.
Yes, GPUs seem to be leading the pack in implementing ATS. So now the dumb question, why not simply turn off the IOMMU and thus ACS? The argument of using the IOMMU for security is rather diminished if we're specifically enabling devices to poke one another directly and clearly this isn't favorable for device assignment either. Are there target systems where this is not a simple kernel commandline option? Thanks,
Alex
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Alex Williamson
Yes, GPUs seem to be leading the pack in implementing ATS. So now the dumb question, why not simply turn off the IOMMU and thus ACS? The argument of using the IOMMU for security is rather diminished if we're specifically enabling devices to poke one another directly and clearly this isn't favorable for device assignment either. Are there target systems where this is not a simple kernel commandline option? Thanks,
Well, turning off the IOMMU doesn't necessarily turn off ACS. We've run into some bios's that set the bits on boot (which is annoying).
I also don't expect people will respond well to making the IOMMU and P2P exclusive. The IOMMU is often used for more than just security and on many platforms it's enabled by default. I'd much rather allow IOMMU use but have fewer isolation groups in much the same way as if you had PCI bridges that didn't support ACS.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 10 lines · On Tue, 8 May 2018 14:49:23 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 6 lines · Alex Williamson
Yes, GPUs seem to be leading the pack in implementing ATS. So now the dumb question, why not simply turn off the IOMMU and thus ACS? The argument of using the IOMMU for security is rather diminished if we're specifically enabling devices to poke one another directly and clearly this isn't favorable for device assignment either. Are there target systems where this is not a simple kernel commandline option? Thanks,
Well, turning off the IOMMU doesn't necessarily turn off ACS. We've run into some bios's that set the bits on boot (which is annoying).
But it would be a much easier proposal to disable ACS when the IOMMU is not enabled, ACS has no real purpose in that case.
Quoted 5 lines
I also don't expect people will respond well to making the IOMMU and P2P exclusive. The IOMMU is often used for more than just security and on many platforms it's enabled by default. I'd much rather allow IOMMU use but have fewer isolation groups in much the same way as if you had PCI bridges that didn't support ACS.
The IOMMU and P2P are already not exclusive, we can bounce off the IOMMU or make use of ATS as we've previously discussed. We were previously talking about a build time config option that you didn't expect distros to use, so I don't think intervention for the user to disable the IOMMU if it's enabled by default is a serious concern either.
What you're trying to do is enabled direct peer-to-peer for endpoints which do not support ATS when the IOMMU is enabled, which is not something that necessarily makes sense to me. As I mentioned in a previous reply, the IOMMU provides us with an I/O virtual address space for devices, ACS is meant to fill the topology based gaps in that virtual address space, making transactions follow IOMMU compliant routing rules to avoid aliases between the IOVA and physical address spaces. But this series specifically wants to leave those gaps open for direct P2P access.
So we compromise the P2P aspect of security, still protecting RAM, but potentially only to the extent that a device cannot hop through or interfere with other devices to do its bidding. Device assignment is mostly tossed out the window because not only are bigger groups more difficult to deal with, the IOVA space is riddled with gaps, which is not really a solved problem. So that leaves avoiding bounce buffers as the remaining IOMMU feature, but we're dealing with native express devices and relatively high end devices that are probably installed in modern systems, so that seems like a non-issue.
Are there other uses I'm forgetting? We can enable interrupt remapping separate from DMA translation, so we can exclude that one. I'm still not seeing why it's terribly undesirable to require devices to support ATS if they want to do direct P2P with an IOMMU enabled. Thanks,
Alex
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgQWxleA0KDQo+ICAgIEJ1dCBpdCB3b3VsZCBiZSBhIG11Y2ggZWFzaWVyIHByb3Bvc2FsIHRv IGRpc2FibGUgQUNTIHdoZW4gdGhlIElPTU1VIGlzDQo+ICAgIG5vdCBlbmFibGVkLCBBQ1MgaGFz IG5vIHJlYWwgcHVycG9zZSBpbiB0aGF0IGNhc2UuDQoNCkkgZ3Vlc3Mgb25lIGlzc3VlIEkgaGF2 ZSB3aXRoIHRoaXMgaXMgdGhhdCBpdCBkaXNhYmxlcyBJT01NVSBncm91cHMgZm9yIGFsbCBSb290 IFBvcnRzIGFuZCBub3QganVzdCB0aGUgb25lKHMpIHdlIHdpc2ggdG8gZG8gcDJwZG1hIG9uLiAN CiAgICANCj4gICAgVGhlIElPTU1VIGFuZCBQMlAgYXJlIGFscmVhZHkgbm90IGV4Y2x1c2l2ZSwg d2UgY2FuIGJvdW5jZSBvZmYgdGhlDQo+ICAgIElPTU1VIG9yIG1ha2UgdXNlIG9mIEFUUyBhcyB3 ZSd2ZSBwcmV2aW91c2x5IGRpc2N1c3NlZC4gIFdlIHdlcmUNCj4gICAgcHJldmlvdXNseSB0YWxr aW5nIGFib3V0IGEgYnVpbGQgdGltZSBjb25maWcgb3B0aW9uIHRoYXQgeW91IGRpZG4ndA0KPiAg ICBleHBlY3QgZGlzdHJvcyB0byB1c2UsIHNvIEkgZG9uJ3QgdGhpbmsgaW50ZXJ2ZW50aW9uIGZv ciB0aGUgdXNlciB0bw0KPiAgICBkaXNhYmxlIHRoZSBJT01NVSBpZiBpdCdzIGVuYWJsZWQgYnkg ZGVmYXVsdCBpcyBhIHNlcmlvdXMgY29uY2Vybg0KPiAgICBlaXRoZXIuDQoNCkFUUyBkZWZpbml0 ZWx5IG1ha2VzIHRoaW5ncyBtb3JlIGludGVyZXN0aW5nIGZvciB0aGUgY2FzZXMgd2hlcmUgdGhl IEVQcyBzdXBwb3J0IGl0LiBIb3dldmVyIEkgZG9uJ3QgcmVhbGx5IGhhdmUgYSBoYW5kbGUgb24g aG93IGNvbW1vbiBBVFMgc3VwcG9ydCBpcyBnb2luZyB0byBiZSBpbiB0aGUga2luZHMgb2YgZGV2 aWNlcyB3ZSBoYXZlIGJlZW4gZm9jdXNlZCBvbiAoTlZNZSBTU0RzIGFuZCBSRE1BIE5JQ3MgbW9z dGx5KS4gDQogICAgDQo+IFdoYXQgeW91J3JlIHRyeWluZyB0byBkbyBpcyBlbmFibGVkIGRpcmVj dCBwZWVyLXRvLXBlZXIgZm9yIGVuZHBvaW50cw0KPiAgd2hpY2ggZG8gbm90IHN1cHBvcnQgQVRT IHdoZW4gdGhlIElPTU1VIGlzIGVuYWJsZWQsIHdoaWNoIGlzIG5vdA0KPiAgc29tZXRoaW5nIHRo YXQgbmVjZXNzYXJpbHkgbWFrZXMgc2Vuc2UgdG8gbWUuIA0KDQpBcyBhYm92ZSB0aGUgYWR2YW50 YWdlIG9mIGxlYXZpbmcgdGhlIElPTU1VIG9uIGlzIHRoYXQgaXQgYWxsb3dzIGZvciBib3RoIHAy cGRtYSBQQ0kgZG9tYWlucyBhbmQgSU9NTVUgZ3JvdXBpbmdzIFBDSSBkb21haW5zIGluIHRoZSBz YW1lIHN5c3RlbS4gSXQgaXMganVzdCB0aGF0IHRoZXNlIGRvbWFpbnMgd2lsbCBiZSBzZXBhcmF0 ZSB0byBlYWNoIG90aGVyLg0KDQo+ICBTbyB0aGF0IGxlYXZlcyBhdm9pZGluZyBib3VuY2UgYnVm ZmVycyBhcyB0aGUgcmVtYWluaW5nIElPTU1VIGZlYXR1cmUNCg0KSSBhZ3JlZSB3aXRoIHlvdSBo ZXJlIHRoYXQgdGhlIGRldmljZXMgd2Ugd2lsbCB3YW50IHRvIHVzZSBmb3IgcDJwIHdpbGwgcHJv YmFibHkgbm90IHJlcXVpcmUgYSBib3VuY2UgYnVmZmVyIGFuZCB3aWxsIHN1cHBvcnQgNjQgYml0 IERNQSBhZGRyZXNzaW5nLg0KICAgIA0KPiBJJ20gc3RpbGwgbm90IHNlZWluZyB3aHkgaXQncyB0 ZXJyaWJseSB1bmRlc2lyYWJsZSB0byByZXF1aXJlIGRldmljZXMgdG8gc3VwcG9ydA0KPiBBVFMg aWYgdGhleSB3YW50IHRvIGRvIGRpcmVjdCBQMlAgd2l0aCBhbiBJT01NVSBlbmFibGVkLg0KDQpJ IHRoaW5rIHRoZSBvbmUgcmVhc29uIGlzIGZvciB0aGUgdXNlLWNhc2UgYWJvdmUuIEFsbG93aW5n IElPTU1VIGdyb3VwaW5ncyBvbiBvbmUgZG9tYWluIGFuZCBwMnBkbWEgb24gYW5vdGhlciBkb21h aW4uLi4uDQogICAgDQpTdGVwaGVuDQogICAgDQoNCg==
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 7 lines · On Tue, 8 May 2018 21:42:27 +0000 "Stephen Bates" <[email protected]> wrote:
Hi Alex
Quoted 2 lines
But it would be a much easier proposal to disable ACS when the
IOMMU is not enabled, ACS has no real purpose in that case.I guess one issue I have with this is that it disables IOMMU groups for all Root Ports and not just the one(s) we wish to do p2pdma on.
But as I understand this series, we're not really targeting specific sets of devices either. It's more of a shotgun approach that we disable ACS on downstream switch ports and hope that we get the right set of devices, but with the indecisiveness that we might later white-list select root ports to further increase the blast radius.
Quoted 12 lines
Quoted 6 lines
The IOMMU and P2P are already not exclusive, we can bounce off
the IOMMU or make use of ATS as we've previously discussed. We were
previously talking about a build time config option that you
didn't expect distros to use, so I don't think intervention for the user to disable the IOMMU if it's enabled by default is a serious concern either.ATS definitely makes things more interesting for the cases where the EPs support it. However I don't really have a handle on how common ATS support is going to be in the kinds of devices we have been focused on (NVMe SSDs and RDMA NICs mostly).
Quoted 7 lines
Quoted 3 lines
What you're trying to do is enabled direct peer-to-peer for endpoints which do not support ATS when the IOMMU is enabled, which is not something that necessarily makes sense to me.
As above the advantage of leaving the IOMMU on is that it allows for both p2pdma PCI domains and IOMMU groupings PCI domains in the same system. It is just that these domains will be separate to each other.
That argument makes sense if we had the ability to select specific sets of devices, but that's not the case here, right? With the shotgun approach, we're clearly favoring one at the expense of the other and it's not clear why we don't simple force the needle all the way in that direction such that the results are at least predictable.
Quoted 7 lines
Quoted 2 lines
So that leaves avoiding bounce buffers as the remaining IOMMU
featureI agree with you here that the devices we will want to use for p2p will probably not require a bounce buffer and will support 64 bit DMA addressing.
Quoted 6 lines
Quoted 3 lines
I'm still not seeing why it's terribly undesirable to require devices to support ATS if they want to do direct P2P with an IOMMU enabled.
I think the one reason is for the use-case above. Allowing IOMMU groupings on one domain and p2pdma on another domain....
If IOMMU grouping implies device assignment (because nobody else uses it to the same extent as device assignment) then the build-time option falls to pieces, we need a single kernel that can do both. I think we need to get more clever about allowing the user to specify exactly at which points in the topology they want to disable isolation. Thanks,
Alex
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 5 lines · Alex Williamson
If IOMMU grouping implies device assignment (because nobody else uses it to the same extent as device assignment) then the build-time option falls to pieces, we need a single kernel that can do both. I think we need to get more clever about allowing the user to specify exactly at which points in the topology they want to disable isolation. Thanks,
Yeah, so based on the discussion I'm leaning toward just having a command line option that takes a list of BDFs and disables ACS for them. (Essentially as Dan has suggested.) This avoids the shotgun.
Then, the pci_p2pdma_distance command needs to check that ACS is disabled for all bridges between the two devices. If this is not the case, it returns -1. Future work can check if the EP has ATS support, in which case it has to check for the ACS direct translated bit.
A user then needs to either disable the IOMMU and/or add the command line option to disable ACS for the specific downstream ports in the PCI hierarchy. This means the IOMMU groups will be less granular but presumably the person adding the command line argument understands this.
We may also want to do some work so that there's informative dmesgs on which BDFs need to be specified on the command line so it's not so difficult for the user to figure out.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
PiAgICBZZWFoLCBzbyBiYXNlZCBvbiB0aGUgZGlzY3Vzc2lvbiBJJ20gbGVhbmluZyB0b3dhcmQg anVzdCBoYXZpbmcgYQ0KPiAgICBjb21tYW5kIGxpbmUgb3B0aW9uIHRoYXQgdGFrZXMgYSBsaXN0 IG9mIEJERnMgYW5kIGRpc2FibGVzIEFDUyBmb3IgdGhlbS4NCj4gICAgKEVzc2VudGlhbGx5IGFz IERhbiBoYXMgc3VnZ2VzdGVkLikgVGhpcyBhdm9pZHMgdGhlIHNob3RndW4uDQoNCkkgY29uY3Vy IHRoYXQgdGhpcyBzZWVtcyB0byBiZSB3aGVyZSB0aGUgY29udmVyc2F0aW9uIGlzIHRha2luZyB1 cy4NCg0KQEFsZXggLSBCZWZvcmUgd2UgZ28gZG8gdGhpcyBjYW4geW91IHByb3ZpZGUgaW5wdXQg b24gdGhlIGFwcHJvYWNoPyBJIGRvbid0IHdhbnQgdG8gcmUtc3BpbiBvbmx5IHRvIGZpbmQgd2Ug YXJlIHN0aWxsIG5vdCBjb252ZXJnaW5nIG9uIHRoZSBBQ1MgaXNzdWUuLi4uDQoNClRoYW5rcw0K DQpTdGVwaGVuDQogICAgDQoNCg==
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 10 lines · On Tue, 8 May 2018 22:25:06 +0000 "Stephen Bates" <[email protected]> wrote:
Quoted 4 lines
Yeah, so based on the discussion I'm leaning toward just having a command line option that takes a list of BDFs and disables ACS
for them. (Essentially as Dan has suggested.) This avoids the shotgun.I concur that this seems to be where the conversation is taking us.
@Alex - Before we go do this can you provide input on the approach? I don't want to re-spin only to find we are still not converging on the ACS issue....
I can envision numerous implementation details that makes this less trivial than it sounds, but it seems like the thing we need to decide first is if intentionally leaving windows between devices with the intention of exploiting them for direct P2P DMA in an otherwise IOMMU managed address space is something we want to do. From a security perspective, we already handle this with IOMMU groups because many devices do not support ACS, the new thing is embracing this rather than working around it. It makes me a little twitchy, but so long as the IOMMU groups match the expected worst case routing between devices, it's really no different than if we could wipe the ACS capability from the device.
On to the implementation details... I already mentioned the BDF issue in my other reply. If we had a way to persistently identify a device, would we specify the downstream points at which we want to disable ACS or the endpoints that we want to connect? The latter has a problem that the grouping upstream of an endpoint is already set by the time we discover the endpoint, so we might need to unwind to get the grouping correct. The former might be more difficult for users to find the necessary nodes, but easier for the kernel to deal with during discovery. A runtime, sysfs approach has some benefits here, especially in identifying the device assuming we're ok with leaving the persistence problem to userspace tools. I'm still a little fond of the idea of exposing an acs_flags attribute for devices in sysfs where a write would do a soft unplug and re-add of all affected devices to automatically recreate the proper grouping. Any dynamic change in routing and grouping would require all DMA be re-established anyway and a soft hotplug seems like an elegant way of handling it. Thanks,
Alex
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 9 lines · Alex Williamson
On to the implementation details... I already mentioned the BDF issue in my other reply. If we had a way to persistently identify a device, would we specify the downstream points at which we want to disable ACS or the endpoints that we want to connect? The latter has a problem that the grouping upstream of an endpoint is already set by the time we discover the endpoint, so we might need to unwind to get the grouping correct. The former might be more difficult for users to find the necessary nodes, but easier for the kernel to deal with during discovery.
I was envisioning the former with kernel helping by printing a dmesg in certain circumstances to help with figuring out which devices need to be specified. Specifying a list of endpoints on the command line and having the kernel try to figure out which downstream ports need to be adjusted while we are in the middle of enumerating the bus is, like you said, a nightmare.
Quoted 8 lines
A runtime, sysfs approach has some benefits here,
especially in identifying the device assuming we're ok with leaving the persistence problem to userspace tools. I'm still a little fond of the idea of exposing anacs_flagsattribute for devices in sysfs where a write would do a soft unplug and re-add of all affected devices to automatically recreate the proper grouping. Any dynamic change in routing and grouping would require all DMA be re-established anyway and a soft hotplug seems like an elegant way of handling it. Thanks,
This approach sounds like it has a lot more issues to contend with:
For starters, a soft unplug/re-add of all the devices behind a switch is going to be difficult if a lot of those devices have had drivers installed and their respective resources are now mounted or otherwise in use.
Then, do we have to redo a the soft-replace every time we change the ACS bit for every downstream port? That could mean you have to do dozens soft-replaces before you have all the ACS bits set which means you have a storm of drivers being added and removed.
This would require some kind of fancy custom setup software that runs at just the right time in the boot sequence or a lot of work on the users part to unbind all the resources, setup the ACS bits and then rebind everything (assuming the soft re-add doesn't rebind it every time you adjust one ACS bit). Ugly.
IMO, if we need to do the sysfs approach then we need to be able to adjust the groups dynamically in a sensible way and not through the large hammer that is soft-replaces. I think this would be great but I don't think we will be tackling that with this patch set.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 17 lines · On Tue, 8 May 2018 17:31:48 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 8 lines · Alex Williamson
A runtime, sysfs approach has some benefits here,
especially in identifying the device assuming we're ok with leaving the persistence problem to userspace tools. I'm still a little fond of the idea of exposing anacs_flagsattribute for devices in sysfs where a write would do a soft unplug and re-add of all affected devices to automatically recreate the proper grouping. Any dynamic change in routing and grouping would require all DMA be re-established anyway and a soft hotplug seems like an elegant way of handling it. Thanks,This approach sounds like it has a lot more issues to contend with:
For starters, a soft unplug/re-add of all the devices behind a switch is going to be difficult if a lot of those devices have had drivers installed and their respective resources are now mounted or otherwise in use.
Quoted 4 lines
Then, do we have to redo a the soft-replace every time we change the ACS bit for every downstream port? That could mean you have to do dozens soft-replaces before you have all the ACS bits set which means you have a storm of drivers being added and removed.
True, anything requiring tweaking multiple downstream ports would induce a hot-unplug/replug for each. A better sysfs interface would allow multiple downstream ports to be updated in a single shot.
Quoted 10 lines
This would require some kind of fancy custom setup software that runs at just the right time in the boot sequence or a lot of work on the users part to unbind all the resources, setup the ACS bits and then rebind everything (assuming the soft re-add doesn't rebind it every time you adjust one ACS bit). Ugly.
IMO, if we need to do the sysfs approach then we need to be able to adjust the groups dynamically in a sensible way and not through the large hammer that is soft-replaces. I think this would be great but I don't think we will be tackling that with this patch set.
OTOH, I think the only sensible way to dynamically adjust groups is through hotplug, we cannot have running drivers attached to downstream endpoints as we're adjusting the routing. Thanks,
Alex
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Logan GunthorpeQuoted 17 lines · On Tue, 8 May 2018 16:10:19 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 5 lines · Alex Williamson
If IOMMU grouping implies device assignment (because nobody else uses it to the same extent as device assignment) then the build-time option falls to pieces, we need a single kernel that can do both. I think we need to get more clever about allowing the user to specify exactly at which points in the topology they want to disable isolation. Thanks,
Yeah, so based on the discussion I'm leaning toward just having a command line option that takes a list of BDFs and disables ACS for them. (Essentially as Dan has suggested.) This avoids the shotgun.
Then, the
pci_p2pdma_distancecommand needs to check that ACS is disabled for all bridges between the two devices. If this is not the case, it returns -1. Future work can check if the EP has ATS support, in which case it has to check for the ACS direct translated bit.
Quoted 8 lines
A user then needs to either disable the IOMMU and/or add the command line option to disable ACS for the specific downstream ports in the PCI hierarchy. This means the IOMMU groups will be less granular but presumably the person adding the command line argument understands this.
We may also want to do some work so that there's informative dmesgs on which BDFs need to be specified on the command line so it's not so difficult for the user to figure out.
I'd advise caution with a user supplied BDF approach, we have no guaranteed persistence for a device's PCI address. Adding a device might renumber the buses, replacing a device with one that consumes more/less bus numbers can renumber the buses, motherboard firmware updates could renumber the buses, pci=assign-buses can renumber the buses, etc. This is why the VT-d spec makes use of device paths when describing PCI hierarchies, firmware can't know what bus number will be assigned to a device, but it does know the base bus number and the path of devfns needed to get to it. I don't know how we come up with an option that's easy enough for a user to understand, but reasonably robust against hardware changes. Thanks,
Alex
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 29 lines · Alex Williamson
Quoted 17 lines · On Tue, 8 May 2018 16:10:19 -0600 Logan Gunthorpe <[email protected]> wrote:
Quoted 5 lines · Alex Williamson
If IOMMU grouping implies device assignment (because nobody else uses it to the same extent as device assignment) then the build-time option falls to pieces, we need a single kernel that can do both. I think we need to get more clever about allowing the user to specify exactly at which points in the topology they want to disable isolation. Thanks,
Yeah, so based on the discussion I'm leaning toward just having a command line option that takes a list of BDFs and disables ACS for them. (Essentially as Dan has suggested.) This avoids the shotgun.
Then, the
pci_p2pdma_distancecommand needs to check that ACS is disabled for all bridges between the two devices. If this is not the case, it returns -1. Future work can check if the EP has ATS support, in which case it has to check for the ACS direct translated bit.Quoted 8 lines
A user then needs to either disable the IOMMU and/or add the command line option to disable ACS for the specific downstream ports in the PCI hierarchy. This means the IOMMU groups will be less granular but presumably the person adding the command line argument understands this.
We may also want to do some work so that there's informative dmesgs on which BDFs need to be specified on the command line so it's not so difficult for the user to figure out.
Quoted 11 lines
I'd advise caution with a user supplied BDF approach, we have no guaranteed persistence for a device's PCI address. Adding a device might renumber the buses, replacing a device with one that consumes more/less bus numbers can renumber the buses, motherboard firmware updates could renumber the buses, pci=assign-buses can renumber the buses, etc. This is why the VT-d spec makes use of device paths when describing PCI hierarchies, firmware can't know what bus number will be assigned to a device, but it does know the base bus number and the path of devfns needed to get to it. I don't know how we come up with an option that's easy enough for a user to understand, but reasonably robust against hardware changes. Thanks,
True, but at the same time this feature is for "users with custom hardware designed for purpose", I assume they would be willing to take on the bus renumbering risk. It's already the case that /sys/bus/pci/drivers/<x>/bind takes BDF, which is why it seemed to make a similar interface for the command line. Ideally we could later get something into ACPI or other platform firmware to arrange for bridges to disable ACS by default if we see p2p becoming a common-off-the-shelf feature. I.e. a BIOS switch to enable p2p in a given PCI-E sub-domain.
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 12 lines · Dan Williams
Quoted 11 lines
I'd advise caution with a user supplied BDF approach, we have no guaranteed persistence for a device's PCI address. Adding a device might renumber the buses, replacing a device with one that consumes more/less bus numbers can renumber the buses, motherboard firmware updates could renumber the buses, pci=assign-buses can renumber the buses, etc. This is why the VT-d spec makes use of device paths when describing PCI hierarchies, firmware can't know what bus number will be assigned to a device, but it does know the base bus number and the path of devfns needed to get to it. I don't know how we come up with an option that's easy enough for a user to understand, but reasonably robust against hardware changes. Thanks,
Quoted 9 lines
True, but at the same time this feature is for "users with custom hardware designed for purpose", I assume they would be willing to take on the bus renumbering risk. It's already the case that /sys/bus/pci/drivers/<x>/bind takes BDF, which is why it seemed to make a similar interface for the command line. Ideally we could later get something into ACPI or other platform firmware to arrange for bridges to disable ACS by default if we see p2p becoming a common-off-the-shelf feature. I.e. a BIOS switch to enable p2p in a given PCI-E sub-domain.
Yeah, I'm having a hard time coming up with an easy enough solution for the user. I agree with Dan though, the bus renumbering risk would be fairly low in the custom hardware seeing the switches are likely going to be directly soldered to the same board with the CPU.
That being said, I supposed we could allow the command line to take both a BDF or a BaseBus/DF/DF/DF path. Though, implementing this sounds like a bit of a challenge.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgTG9nYW4NCg0KPiAgICBZZWFoLCBJJ20gaGF2aW5nIGEgaGFyZCB0aW1lIGNvbWluZyB1cCB3 aXRoIGFuIGVhc3kgZW5vdWdoIHNvbHV0aW9uIGZvcg0KPiAgICB0aGUgdXNlci4gSSBhZ3JlZSB3 aXRoIERhbiB0aG91Z2gsIHRoZSBidXMgcmVudW1iZXJpbmcgcmlzayB3b3VsZCBiZQ0KPiAgICBm YWlybHkgbG93IGluIHRoZSBjdXN0b20gaGFyZHdhcmUgc2VlaW5nIHRoZSBzd2l0Y2hlcyBhcmUg bGlrZWx5IGdvaW5nDQo+ICAgIHRvIGJlIGRpcmVjdGx5IHNvbGRlcmVkIHRvIHRoZSBzYW1lIGJv YXJkIHdpdGggdGhlIENQVS4NCiAgICANCkkgYW0gYWZyYWlkIHRoYXQgc29sZGVyZWQgZG93biBh c3N1bXB0aW9uIG1heSBub3QgYmUgdmFsaWQuIE1vcmUgYW5kIG1vcmUgUENJZSBjYXJkcyB3aXRo IFBDSWUgc3dpdGNoZXMgb24gdGhlbSBhcmUgYmVjb21pbmcgYXZhaWxhYmxlIGFuZCBwZW9wbGUg YXJlIHVzaW5nIHRoZXNlIHRvIGNvbm5lY3Qgc2VydmVycyB0byBhcnJheXMgb2YgTlZNZSBTU0Rz IHdoaWNoIG1heSBtYWtlIHRoZSB0b3BvbG9neSBtb3JlIGR5bmFtaWMuDQoNClN0ZXBoZW4NCg0K
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Alex WilliamsonQuoted 57 lines · Alex Williamson
Quoted 7 lines · On Tue, 8 May 2018 21:42:27 +0000 "Stephen Bates" <[email protected]> wrote:
Hi Alex
Quoted 2 lines
But it would be a much easier proposal to disable ACS when the
IOMMU is not enabled, ACS has no real purpose in that case.I guess one issue I have with this is that it disables IOMMU groups for all Root Ports and not just the one(s) we wish to do p2pdma on.
But as I understand this series, we're not really targeting specific sets of devices either. It's more of a shotgun approach that we disable ACS on downstream switch ports and hope that we get the right set of devices, but with the indecisiveness that we might later white-list select root ports to further increase the blast radius.
Quoted 12 lines
Quoted 6 lines
The IOMMU and P2P are already not exclusive, we can bounce off
the IOMMU or make use of ATS as we've previously discussed. We were
previously talking about a build time config option that you
didn't expect distros to use, so I don't think intervention for the user to disable the IOMMU if it's enabled by default is a serious concern either.ATS definitely makes things more interesting for the cases where the EPs support it. However I don't really have a handle on how common ATS support is going to be in the kinds of devices we have been focused on (NVMe SSDs and RDMA NICs mostly).
Quoted 7 lines
Quoted 3 lines
What you're trying to do is enabled direct peer-to-peer for endpoints which do not support ATS when the IOMMU is enabled, which is not something that necessarily makes sense to me.
As above the advantage of leaving the IOMMU on is that it allows for both p2pdma PCI domains and IOMMU groupings PCI domains in the same system. It is just that these domains will be separate to each other.
That argument makes sense if we had the ability to select specific sets of devices, but that's not the case here, right? With the shotgun approach, we're clearly favoring one at the expense of the other and it's not clear why we don't simple force the needle all the way in that direction such that the results are at least predictable.
Quoted 7 lines
Quoted 2 lines
So that leaves avoiding bounce buffers as the remaining IOMMU
featureI agree with you here that the devices we will want to use for p2p will probably not require a bounce buffer and will support 64 bit DMA addressing.
Quoted 6 lines
Quoted 3 lines
I'm still not seeing why it's terribly undesirable to require devices to support ATS if they want to do direct P2P with an IOMMU enabled.
I think the one reason is for the use-case above. Allowing IOMMU groupings on one domain and p2pdma on another domain....
Quoted 7 lines
If IOMMU grouping implies device assignment (because nobody else uses it to the same extent as device assignment) then the build-time option falls to pieces, we need a single kernel that can do both. I think we need to get more clever about allowing the user to specify exactly at which points in the topology they want to disable isolation. Thanks,
Alex
+1/ack
RDMA VFs lend themselves to NVMEoF w/device-assignment.... need a way to put NVME 'resources' into an assignable/manageable object for 'IOMMU-grouping', which is really a 'DMA security domain' and less an 'IOMMU grouping domain'.
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgRG9uDQoNCj4gICAgUkRNQSBWRnMgbGVuZCB0aGVtc2VsdmVzIHRvIE5WTUVvRiB3L2Rldmlj ZS1hc3NpZ25tZW50Li4uLiBuZWVkIGEgd2F5IHRvDQo+ICAgIHB1dCBOVk1FICdyZXNvdXJjZXMn IGludG8gYW4gYXNzaWduYWJsZS9tYW5hZ2VhYmxlIG9iamVjdCBmb3IgJ0lPTU1VLWdyb3VwaW5n JywNCj4gICAgd2hpY2ggaXMgcmVhbGx5IGEgJ0RNQSBzZWN1cml0eSBkb21haW4nIGFuZCBsZXNz IGFuICdJT01NVSBncm91cGluZyBkb21haW4nLg0KICAgIA0KSGEsIEkgbGlrZSB5b3VyIHRlcm0g IkRNQSBTZWN1cml0eSBEb21haW4iIHdoaWNoIHNvdW5kcyBhYm91dCByaWdodCBmb3Igd2hhdCB3 ZSBhcmUgZGlzY3Vzc2luZyB3aXRoIHAycGRtYSBhbmQgQUNTIGRpc2FibGVtZW50IDstKS4gVGhl IHByb2JsZW0gaXMgdGhhdCBBQ1MgaXMsIGluIHNvbWUgd2F5cywgdG9vIGJpZyBvZiBoYW1tZXIg Zm9yIHdoYXQgd2Ugd2FudCBoZXJlIGluIHRoZSBzZW5zZSB0aGF0IGl0IGlzIGVpdGhlciBvbiBv ciBvZmYgZm9yIHRoZSBicmlkZ2Ugb3IgTUYgRVAgd2UgZW5hYmxlL2Rpc2FibGUgaXQgZm9yLiBB Q1MgY2FuJ3QgZmlsdGVyIHRoZSBUTFBzIGJ5IGFkZHJlc3Mgb3IgSUQgdGhvdWdoIFBDSS1TSUcg YXJlIGhhdmluZyBzb21lIGRpc2N1c3Npb25zIG9uIGV4dGVuZGluZyBBQ1MuIFRoYXQncyBhIGxv bmcgdGVybSBzb2x1dGlvbiBhbmQgd29uJ3QgYmUgYXBwbGljYWJsZSB0byB1cyBmb3Igc29tZSB0 aW1lLg0KDQpOVk1lIFNTRHMgdGhhdCBzdXBwb3J0IFNSLUlPViBhcmUgY29taW5nIHRvIG1hcmtl dCBidXQgd2UgY2FuJ3QgYXNzdW1lIGFsbCBOVk1lIFNTRHMgd2l0aCBzdXBwb3J0IFNSLUlPVi4g VGhhdCB3aWxsIHByb2JhYmx5IGJlIGEgcHJldHR5IGhpZ2ggZW5kLWZlYXR1cmUuLi4NCg0KU3Rl cGhlbg0KICAgIA0KICAgIA0KDQo=
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Stephen Bates
Hi Don
Quoted 3 lines
RDMA VFs lend themselves to NVMEoF w/device-assignment.... need a way to put NVME 'resources' into an assignable/manageable object for 'IOMMU-grouping', which is really a 'DMA security domain' and less an 'IOMMU grouping domain'.
Quoted 8 lines
Ha, I like your term "DMA Security Domain" which sounds about right for what we are discussing with p2pdma and ACS disablement ;-). The problem is that ACS is, in some ways, too big of hammer for what we want here in the sense that it is either on or off for the bridge or MF EP we enable/disable it for. ACS can't filter the TLPs by address or ID though PCI-SIG are having some discussions on extending ACS. That's a long term solution and won't be applicable to us for some time.
NVMe SSDs that support SR-IOV are coming to market but we can't assume all NVMe SSDs with support SR-IOV. That will probably be a pretty high end-feature...
Stephen
Sure, we could provide unsecure enablement for development and kick-the-tires deployment .. device-assignment started that way (no ACS, no intr-remapping, etc.), but for secure setups, VF's for both p2p EPs is the best security model.
So, we should have a design goal for the secure configuration.
workarounds/unsecure modes to deal with near-term what-we-have-to-work-with can be employed, but they shoudn't be the only/defacto/final-solution.
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Logan GunthorpeQuoted 17 lines · Logan Gunthorpe
Quoted 5 lines · Alex Williamson
Well, I'm a bit confused, this patch series is specifically disabling ACS on switches, but per the spec downstream switch ports implementing ACS MUST implement direct translated P2P. So it seems the only potential gap here is the endpoint, which must support ATS or else there's nothing for direct translated P2P to do. The switch port plays
Quoted 8 lines
no part in the actual translation of the request, ATS on the endpoint has already cached the translation and is now attempting to use it. For the switch port, this only becomes a routing decision, the request is already translated, therefore ACS RR and EC can be ignored to perform "normal" (direct) routing, as if ACS were not present. It would be a shame to go to all the trouble of creating this no-ACS mode to find out the target hardware supports ATS and should have simply used it, or we should have disabled the IOMMU altogether, which leaves ACS disabled.
Quoted 5 lines
Ah, ok, I didn't think it was the endpoint that had to implement ATS. But in that case, for our application, we need NVMe cards and RDMA NICs to all have ATS support and I expect that is just as unlikely. At least none of the endpoints on my system support it. Maybe only certain GPUs have this support.
I think there is confusion here, Alex properly explained the scheme PCIE-device do a ATS request to the IOMMU which returns a valid translation for a virtual address. Device can then use that address directly without going through IOMMU for translation.
ATS is implemented by the IOMMU not by the device (well device implement the client side of it). Also ATS is meaningless without something like PASID as far as i know.
Cheers,
J�r�me
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgSmVyb21lDQoNCj4gICAgSSB0aGluayB0aGVyZSBpcyBjb25mdXNpb24gaGVyZSwgQWxleCBw cm9wZXJseSBleHBsYWluZWQgdGhlIHNjaGVtZQ0KPiAgIFBDSUUtZGV2aWNlIGRvIGEgQVRTIHJl cXVlc3QgdG8gdGhlIElPTU1VIHdoaWNoIHJldHVybnMgYSB2YWxpZA0KPiAgICB0cmFuc2xhdGlv biBmb3IgYSB2aXJ0dWFsIGFkZHJlc3MuIERldmljZSBjYW4gdGhlbiB1c2UgdGhhdCBhZGRyZXNz DQo+ICAgIGRpcmVjdGx5IHdpdGhvdXQgZ29pbmcgdGhyb3VnaCBJT01NVSBmb3IgdHJhbnNsYXRp b24uDQoNClRoaXMgbWFrZXMgc2Vuc2UgYW5kIHRvIGJlIGhvbmVzdCBJIG5vdyB1bmRlcnN0YW5k IEFUUyBhbmQgaXRzIGludGVyYWN0aW9uIHdpdGggQUNTIGEgbG90IGJldHRlciB0aGFuIEkgZGlk IDI0IGhvdXJzIGFnbyA7LSkuDQoNCj4gICAgQVRTIGlzIGltcGxlbWVudGVkIGJ5IHRoZSBJT01N VSBub3QgYnkgdGhlIGRldmljZSAod2VsbCBkZXZpY2UgaW1wbGVtZW50DQo+ICAgIHRoZSBjbGll bnQgc2lkZSBvZiBpdCkuIEFsc28gQVRTIGlzIG1lYW5pbmdsZXNzIHdpdGhvdXQgc29tZXRoaW5n IGxpa2UNCj4gICAgUEFTSUQgYXMgZmFyIGFzIGkga25vdy4NCiAgICANCkkgdGhpbmsgaXQncyB0 aGUgY2xpZW50IHNpZGUgdGhhdCBpcyB3aGF0IGlzIGltcG9ydGFudCB0byB1cy4gTm90IG1hbnkg RVBzIHN1cHBvcnQgQVRTIHRvZGF5IGFuZCBpdCdzIG5vdCBjbGVhciBpZiBtYW55IHdpbGwgaW4g dGhlIGZ1dHVyZS4gIFNvIGFzc3VtaW5nIHdlIHdhbnQgdG8gZG8gcDJwZG1hIGJldHdlZW4gZGV2 aWNlcyAoc29tZSBvZikgd2hpY2ggZG8gTk9UIHN1cHBvcnQgQVRTIGhvdyBiZXN0IGRvIHdlIGhh bmRsZSB0aGUgQUNTIGlzc3VlPyBEaXNhYmxpbmcgdGhlIElPTU1VIHNlZW1zIGEgYml0IHN0cm9u ZyB0byBtZSBnaXZlbiB0aGlzIGltcGFjdHMgYWxsIHRoZSBQQ0kgZG9tYWlucyBpbiB0aGUgc3lz dGVtIGFuZCBub3QganVzdCB0aGUgZG9tYWluIHdlIHdpc2ggdG8gZG8gUDJQIG9uLg0KDQpTdGVw aGVuDQoNCg==
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Jerome GlisseSmVyb21lIGFuZCBDaHJpc3RpYW4NCiAgICANCj4gSSB0aGluayB0aGVyZSBpcyBjb25mdXNpb24g aGVyZSwgQWxleCBwcm9wZXJseSBleHBsYWluZWQgdGhlIHNjaGVtZQ0KPiBQQ0lFLWRldmljZSBk byBhIEFUUyByZXF1ZXN0IHRvIHRoZSBJT01NVSB3aGljaCByZXR1cm5zIGEgdmFsaWQNCj4gdHJh bnNsYXRpb24gZm9yIGEgdmlydHVhbCBhZGRyZXNzLiBEZXZpY2UgY2FuIHRoZW4gdXNlIHRoYXQg YWRkcmVzcw0KPiBkaXJlY3RseSB3aXRob3V0IGdvaW5nIHRocm91Z2ggSU9NTVUgZm9yIHRyYW5z bGF0aW9uLg0KDQpTbyBJIHdlbnQgdGhyb3VnaCBBVFMgaW4gdmVyc2lvbiA0LjByMSBvZiB0aGUg UENJIHNwZWMuIEl0IGxvb2tzIGxpa2UgZXZlbiBhIEFUUyB0cmFuc2xhdGVkIFRMUCBpcyBzdGls bCBpbXBhY3RlZCBieSBBQ1MgdGhvdWdoIGl0IGhhcyBhIHNlcGFyYXRlIGNvbnRyb2wga25vYiBm b3IgdHJhbnNsYXRlZCBhZGRyZXNzIFRMUHMgKHNlZSA3LjcuNy4yIG9mIDQuMHIxIG9mIHRoZSBz cGVjKS4gU28gZXZlbiBpZiB5b3VyIGRldmljZSBzdXBwb3J0cyBBVFMgYSBQMlAgRE1BIHdpbGwg c3RpbGwgYmUgcm91dGVkIHRvIHRoZSBhc3NvY2lhdGVkIFJQIG9mIHRoZSBkb21haW4gYW5kIGRv d24gYWdhaW4gdW5sZXNzIHdlIGRpc2FibGUgQUNTIERUIFAyUCBvbiBhbGwgYnJpZGdlcyBiZXR3 ZWVuIHRoZSB0d28gZGV2aWNlcyBpbnZvbHZlZCBpbiB0aGUgUDJQIERNQS4gDQoNClNvIHdlIHN0 aWxsIGRvbid0IGdldCBmaW5lIGdyYWluZWQgY29udHJvbCB3aXRoIEFUUyBhbmQgSSBndWVzcyB3 ZSBzdGlsbCBoYXZlIHNlY3VyaXR5IGlzc3VlcyBiZWNhdXNlIGEgcm9ndWUgb3IgbWFsZnVuY3Rp b25pbmcgRVAgY291bGQganVzdCBhcyBlYXNpbHkgaXNzdWUgVExQcyB3aXRoIFRBIHNldCB2cyBu b3Qgc2V0Lg0KDQo+IEFsc28gQVRTIGlzIG1lYW5pbmdsZXNzIHdpdGhvdXQgc29tZXRoaW5nIGxp a2UgUEFTSUQgYXMgZmFyIGFzIGkga25vdy4NCiAgICANCkFUUyBpcyBzdGlsbCBzb21ld2hhdCB2 YWx1YWJsZSB3aXRob3V0IFBTQUlEIGluIHRoZSBzZW5zZSB5b3UgY2FuIGNhY2hlIElPTU1VIGFk ZHJlc3MgdHJhbnNsYXRpb25zIGF0IHRoZSBFUC4gVGhpcyBzYXZlcyBoYW1tZXJpbmcgb24gdGhl IElPTU1VIGFzIG11Y2ggaW4gY2VydGFpbiB3b3JrbG9hZHMuDQoNCkludGVyZXN0aW5nbHkgU2Vj dGlvbiA3LjcuNy4yIGFsbW9zdCBtZW50aW9ucyB0aGF0IFJvb3QgUG9ydHMgdGhhdCBzdXBwb3J0 IEFUUyBBTkQgY2FuIGltcGxlbWVudCBQMlAgYmV0d2VlbiByb290IHBvcnRzIHNob3VsZCBhZHZl cnRpc2UgIkFDUyBEaXJlY3QgVHJhbnNsYXRlZCBQMlAgKFQpIiBjYXBhYmlsaXR5LiBUaGlzIHRp ZXMgaW50byB0aGUgZGlzY3Vzc2lvbiBhcm91bmQgUDJQIGJldHdlZW4gcm91dGUgcG9ydHMgd2Ug aGFkIGEgZmV3IHdlZWtzIGFnby4uLg0KDQpTdGVwaGVuICAgIA0KDQo=
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Am 09.05.2018 um 15:12 schrieb Stephen Bates:
Quoted 9 lines
Jerome and Christian
Quoted 4 lines
I think there is confusion here, Alex properly explained the scheme PCIE-device do a ATS request to the IOMMU which returns a valid translation for a virtual address. Device can then use that address directly without going through IOMMU for translation.
So I went through ATS in version 4.0r1 of the PCI spec. It looks like even a ATS translated TLP is still impacted by ACS though it has a separate control knob for translated address TLPs (see 7.7.7.2 of 4.0r1 of the spec). So even if your device supports ATS a P2P DMA will still be routed to the associated RP of the domain and down again unless we disable ACS DT P2P on all bridges between the two devices involved in the P2P DMA.
So we still don't get fine grained control with ATS and I guess we still have security issues because a rogue or malfunctioning EP could just as easily issue TLPs with TA set vs not set.
Still need to double check the specification (had a busy morning today), but that sounds about correct.
The key takeaway is that when any device has ATS enabled you can't disable ACS without breaking it (even if you unplug and replug it).
Quoted 5 lines
Quoted 1 line
Also ATS is meaningless without something like PASID as far as i know.
ATS is still somewhat valuable without PSAID in the sense you can cache IOMMU address translations at the EP. This saves hammering on the IOMMU as much in certain workloads.
Interestingly Section 7.7.7.2 almost mentions that Root Ports that support ATS AND can implement P2P between root ports should advertise "ACS Direct Translated P2P (T)" capability. This ties into the discussion around P2P between route ports we had a few weeks ago...
Interesting point, give me a moment to check that. That finally makes all the hardware I have standing around here valuable :)
Christian.
Quoted 3 lines
Stephen
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Q2hyaXN0aWFuDQoNCj4gICAgSW50ZXJlc3RpbmcgcG9pbnQsIGdpdmUgbWUgYSBtb21lbnQgdG8g Y2hlY2sgdGhhdC4gVGhhdCBmaW5hbGx5IG1ha2VzIA0KPiAgICBhbGwgdGhlIGhhcmR3YXJlIEkg aGF2ZSBzdGFuZGluZyBhcm91bmQgaGVyZSB2YWx1YWJsZSA6KQ0KICAgIA0KWWVzLiBBdCB0aGUg dmVyeSBsZWFzdCBpdCBwcm92aWRlcyBhbiBpbml0aWFsIHN0YW5kYXJkcyBiYXNlZCBwYXRoIGZv ciBQMlAgRE1BcyBhY3Jvc3MgUlBzIHdoaWNoIGlzIHNvbWV0aGluZyB3ZSBoYXZlIGRpc2N1c3Nl ZCBvbiB0aGlzIGxpc3QgaW4gdGhlIHBhc3QgYXMgYmVpbmcgZGVzaXJhYmxlLg0KDQpCVFcgSSBh bSB0cnlpbmcgdG8gdW5kZXJzdGFuZCBob3cgYW4gQVRTIGNhcGFibGUgRVAgZnVuY3Rpb24gZGV0 ZXJtaW5lcyB3aGVuIHRvIHBlcmZvcm0gYW4gQVRTIFRyYW5zbGF0aW9uIFJlcXVlc3QgKEFUUyBU UikuIElzIHRoZXJlIGFuIHVwc3RyZWFtIGV4YW1wbGUgb2YgdGhlIGRyaXZlciBmb3IgeW91ciBB UFUgdGhhdCB1c2VzIEFUUz8gSWYgc28sIGNhbiB5b3UgcHJvdmlkZSBhIHBvaW50ZXIgdG8gaXQu IERvIHlvdSBwcm92aWRlIHNvbWUgdHlwZSBvZiBlbnRyeSBpbiB0aGUgc3VibWlzc2lvbiBxdWV1 ZXMgZm9yIGNvbW1hbmRzIGdvaW5nIHRvIHRoZSBBUFUgdG8gaW5kaWNhdGUgaWYgdGhlIGFkZHJl c3MgYXNzb2NpYXRlZCB3aXRoIGEgc3BlY2lmaWMgY29tbWFuZCBzaG91bGQgYmUgdHJhbnNsYXRl ZCB1c2luZyBBVFMgb3Igbm90PyBPciBkbyB5b3Ugc2ltcGx5IGVuYWJsZSBBVFMgYW5kIHRoZW4g YWxsIGFkZHJlc3NlcyBwYXNzZWQgdG8geW91ciBBUFUgdGhhdCBtaXNzIHRoZSBsb2NhbCBjYWNo ZSByZXN1bHQgaW4gYSBBVFMgVFI/DQoNCllvdXIgZmVlZGJhY2sgd291bGQgYmUgdXNlZnVsIGFu ZCBJIGluaXRpYXRlIGRpc2N1c3Npb25zIHdpdGhpbiB0aGUgTlZNZSBjb21tdW5pdHkgb24gd2hl cmUgd2UgbWlnaHQgZ28gd2l0aCBBVFMuLi4NCg0KVGhhbmtzDQoNClN0ZXBoZW4NCg0K
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 9 lines · Stephen Bates
Christian
Quoted 2 lines
Interesting point, give me a moment to check that. That finally makes all the hardware I have standing around here valuable :)
Yes. At the very least it provides an initial standards based path for P2P DMAs across RPs which is something we have discussed on this list in the past as being desirable.
Quoted 8 lines
BTW I am trying to understand how an ATS capable EP function determines when to perform an ATS Translation Request (ATS TR). Is there an upstream example of the driver for your APU that uses ATS? If so, can you provide a pointer to it. Do you provide some type of entry in the submission queues for commands going to the APU to indicate if the address associated with a specific command should be translated using ATS or not? Or do you simply enable ATS and then all addresses passed to your APU that miss the local cache result in a ATS TR?
On GPU ATS is always tie to a PASID. You do not do the former without the latter (AFAICT this is not doable, maybe through some JTAG but not in normal operation).
GPU are like CPU, so you have GPU threads that run against an address space. This address space use a page table (very much like the CPU page table). Now inside that page table you can point GPU virtual address to use GPU memory or use system memory. Those system memory entry can also be mark as ATS against a given PASID.
On some GPU you define a window of GPU virtual address that goes through PASID & ATS (so access in that window do not go through the page table but directly through PASID & ATS).
J�r�me
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgSmVyb21lDQoNCj4gTm93IGluc2lkZSB0aGF0IHBhZ2UgdGFibGUgeW91IGNhbiBwb2ludCBH UFUgdmlydHVhbCBhZGRyZXNzDQo+IHRvIHVzZSBHUFUgbWVtb3J5IG9yIHVzZSBzeXN0ZW0gbWVt b3J5LiBUaG9zZSBzeXN0ZW0gbWVtb3J5IGVudHJ5IGNhbg0KPiBhbHNvIGJlIG1hcmsgYXMgQVRT IGFnYWluc3QgYSBnaXZlbiBQQVNJRC4NCiAgICANClRoYW5rcy4gVGhpcyBhbGwgbWFrZXMgc2Vu c2UuIA0KDQpCdXQgZG8geW91IGhhdmUgZXhhbXBsZXMgb2YgdGhpcyBpbiBhIGtlcm5lbCBkcml2 ZXIgKGlmIHNvIGNhbiB5b3UgcG9pbnQgbWUgdG9vIGl0KSBvciBpcyB0aGlzIGFsbCBkb25lIHZp YSB1c2VyLXNwYWNlPyBCYXNlZCBvbiBteSBncmVwcGluZyBvZiB0aGUga2VybmVsIGNvZGUgSSBz ZWUgemVybyBFUCBkcml2ZXJzIHVzaW5nIGluLWtlcm5lbCBBVFMgZnVuY3Rpb25hbGl0eSByaWdo dCBub3cuLi4NCg0KU3RlcGhlbg0KICAgIA0KDQo=
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 10 lines · Stephen Bates
Hi Jerome
Quoted 3 lines
Now inside that page table you can point GPU virtual address to use GPU memory or use system memory. Those system memory entry can also be mark as ATS against a given PASID.
Thanks. This all makes sense.
But do you have examples of this in a kernel driver (if so can you point me too it) or is this all done via user-space? Based on my grepping of the kernel code I see zero EP drivers using in-kernel ATS functionality right now...
As it is tie to PASID this is done using IOMMU so looks for caller of amd_iommu_bind_pasid() or intel_svm_bind_mm() in GPU the existing user is the AMD GPU driver see:
drivers/gpu/drm/amd/drivers/gpu/drm/amd/amdkfd/drivers/gpu/drm/amd/amdgpu/
Lot of codes there. The GPU code details do not really matter for this discussions thought. You do not need to do much to use PASID.
Cheers,
J�r�me
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgSmVyb21lDQoNCj4gQXMgaXQgaXMgdGllIHRvIFBBU0lEIHRoaXMgaXMgZG9uZSB1c2luZyBJ T01NVSBzbyBsb29rcyBmb3IgY2FsbGVyDQo+IG9mIGFtZF9pb21tdV9iaW5kX3Bhc2lkKCkgb3Ig aW50ZWxfc3ZtX2JpbmRfbW0oKSBpbiBHUFUgdGhlIGV4aXN0aW5nDQo+ICB1c2VyIGlzIHRoZSBB TUQgR1BVIGRyaXZlciBzZWU6DQogICAgDQpBaCB0aGFua3MuIFRoaXMgY2xlYXJlZCB0aGluZ3Mg dXAgZm9yIG1lLiBBIHF1aWNrIHNlYXJjaCBzaG93cyB0aGVyZSBhcmUgc3RpbGwgbm8gdXNlcnMg b2YgaW50ZWxfc3ZtX2JpbmRfbW0oKSBidXQgSSBzZWUgdGhlIEFNRCB2ZXJzaW9uIHVzZWQgaW4g dGhhdCBHUFUgZHJpdmVyLg0KDQpPbmUgdGhpbmcgSSBjb3VsZCBub3QgZ3JvayBmcm9tIHRoZSBj b2RlIGhvdyB0aGUgR1BVIGRyaXZlciBpbmRpY2F0ZXMgd2hpY2ggRE1BIGV2ZW50cyByZXF1aXJl IEFUUyB0cmFuc2xhdGlvbnMgYW5kIHdoaWNoIGRvIG5vdC4gSSBhbSBhc3N1bWluZyB0aGUgZHJp dmVyIGltcGxlbWVudHMgc29tZXdheSBvZiBpbmRpY2F0aW5nIHRoYXQgYW5kIGl0cyBub3QganVz dCBhIGdsb2JhbCBPTiBvciBPRkYgZm9yIGFsbCBETUFzPyBUaGUgcmVhc29uIEkgYXNrIGlzIHRo YXQgSSBsb29raW5nIGF0IGlmIE5WTWUgd2FzIHRvIHN1cHBvcnQgQVRTIHdoYXQgd291bGQgbmVl ZCB0byBiZSBhZGRlZCBpbiB0aGUgTlZNZSBzcGVjIGFib3ZlIGFuZCBiZXlvbmQgd2hhdCB3ZSBo YXZlIGluIFBDSSBBVFMgdG8gc3VwcG9ydCBlZmZpY2llbnQgdXNlIG9mIEFUUyAoZm9yIGV4YW1w bGUgd291bGQgd2UgbmVlZCBhIGZsYWcgaW4gdGhlIHN1Ym1pc3Npb24gcXVldWUgZW50cmllcyB0 byBpbmRpY2F0ZSBhIHBhcnRpY3VsYXIgSU8ncyBTR0wvUFJQIHNob3VsZCB1bmRlcmdvIEFUUyku DQoNCkNoZWVycw0KDQpTdGVwaGVuICAgIA0KDQo=
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Am 10.05.2018 um 16:20 schrieb Stephen Bates:
Quoted 7 lines
Hi Jerome
Quoted 3 lines
As it is tie to PASID this is done using IOMMU so looks for caller of
amd_iommu_bind_pasid()orintel_svm_bind_mm()in GPU the existing
user is the AMD GPU driver see:Ah thanks. This cleared things up for me. A quick search shows there are still no users of
intel_svm_bind_mm()but I see the AMD version used in that GPU driver.
Just FYI: There is also another effort ongoing to give both the AMD, Intel as well as ARM IOMMUs a common interface so that drivers can use whatever the platform offers fro SVM support.
Quoted 1 line
One thing I could not grok from the code how the GPU driver indicates which DMA events require ATS translations and which do not. I am assuming the driver implements someway of indicating that and its not just a global ON or OFF for all DMAs? The reason I ask is that I looking at if NVMe was to support ATS what would need to be added in the NVMe spec above and beyond what we have in PCI ATS to support efficient use of ATS (for example would we need a flag in the submission queue entries to indicate a particular IO's SGL/PRP should undergo ATS).
Oh, well that is complicated at best.
On very old hardware it wasn't a window, but instead you had to use special commands in your shader which indicated that you want to use an ATS transaction instead of a normal PCIe transaction for your read/write/atomic.
As Jerome explained on most hardware we have a window inside the internal GPU address space which when accessed issues a ATS transaction with a configurable PASID.
But on very newer hardware that window became a bit in the GPUVM page tables, so in theory we now can control it on a 4K granularity basis for the internal 48bit GPU address space.
Christian.
Quoted 5 lines
Cheers
Stephen
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 20 lines · Christian K�nig
Am 10.05.2018 um 16:20 schrieb Stephen Bates:
Quoted 6 lines
Hi Jerome
Quoted 3 lines
As it is tie to PASID this is done using IOMMU so looks for caller of
amd_iommu_bind_pasid()orintel_svm_bind_mm()in GPU the existing
user is the AMD GPU driver see:Ah thanks. This cleared things up for me. A quick search shows there are still no users of
intel_svm_bind_mm()but I see the AMD version used in that GPU driver.Just FYI: There is also another effort ongoing to give both the AMD, Intel as well as ARM IOMMUs a common interface so that drivers can use whatever the platform offers fro SVM support.
Quoted 1 line
One thing I could not grok from the code how the GPU driver indicates which DMA events require ATS translations and which do not. I am assuming the driver implements someway of indicating that and its not just a global ON or OFF for all DMAs? The reason I ask is that I looking at if NVMe was to support ATS what would need to be added in the NVMe spec above and beyond what we have in PCI ATS to support efficient use of ATS (for example would we need a flag in the submission queue entries to indicate a particular IO's SGL/PRP should undergo ATS).
Oh, well that is complicated at best.
On very old hardware it wasn't a window, but instead you had to use special commands in your shader which indicated that you want to use an ATS transaction instead of a normal PCIe transaction for your read/write/atomic.
Quoted 8 lines
As Jerome explained on most hardware we have a window inside the internal GPU address space which when accessed issues a ATS transaction with a configurable PASID.
But on very newer hardware that window became a bit in the GPUVM page tables, so in theory we now can control it on a 4K granularity basis for the internal 48bit GPU address space.
To complete this a 50 lines primer on GPU:
GPUVA - GPU virtual address
GPUPA - GPU physical address
GPU run programs very much like CPU program expect a program will have many thousands of threads running concurrently. There is a hierarchy of groups for a given program ie threads are grouped together, the lowest hierarchy level have a group size in <= 64 threads on most GPUs.
Those programs (call shader for graphic program think OpenGL, Vulkan or compute for GPGPU think OpenCL CUDA) are submited by the userspace against a given address space. In the "old" days (couple years back when dinausor were still roaming the earth) this address space was specific to the GPU and each user space program could create multiple GPU address space. All the memory operation done by the program was against this address space. Hence all PCIE transactions are spawn from a program + address space.
GPU use page table + window aperture (the window aperture is going away so you can focus on page table). To translate GPU virtual address into a physical address. The physical address can point to GPU local memory or to system memory or to another PCIE device memory (ie some PCIE BAR).
So all PCIE transaction are spawn through this process of GPUVA to GPUPA then GPUPA is handled by the GPU mmu unit that either spawn a PCIE transaction for non local GPUPA or access local memory otherwise.
So per say the kernel driver does not configure which transaction is using ATS or peer to peer. Userspace program create a GPU virtual address space and bind object into it. This object can be system memory or some other PCIE device memory in which case we would to do a peer to peer.
So you won't find any logic in the kernel. What you find is creating virtual address space and binding object.
Above i talk about the old days, nowadays we want the GPU virtual address space to be exactly the same as the CPU virtual address space as the process which initiate the GPU program is using. This is where we use the PASID and ATS. So here userspace create a special "GPU context" that says that the GPU virtual address space will be the same as the program that create the GPU context. A process ID is then allocated and the mm_struct is bind to this process ID in the IOMMU driver. Then all program executed on the GPU use the process ID to identify the address space against which they are running.
All of the above i did not talk about DMA engine which are on the "side" of the GPU to copy memory around. GPU have multiple DMA engines with different capabilities, some of those DMA engine use the same GPU address space as describe above, other use directly GPUPA.
Hopes this helps understanding the big picture. I over simplify thing and devils is in the details.
Cheers,
J�r�me
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgSmVyb21lDQoNCj4gICAgSG9wZXMgdGhpcyBoZWxwcyB1bmRlcnN0YW5kaW5nIHRoZSBiaWcg cGljdHVyZS4gSSBvdmVyIHNpbXBsaWZ5IHRoaW5nIGFuZA0KPiAgICBkZXZpbHMgaXMgaW4gdGhl IGRldGFpbHMuDQogICAgDQpUaGlzIHdhcyBhIGdyZWF0IHByaW1lciB0aGFua3MgZm9yIHB1dHRp bmcgaXQgdG9nZXRoZXIuIEFuIExXTi5uZXQgYXJ0aWNsZSBwZXJoYXBzIDstKT8/DQoNClN0ZXBo ZW4NCiAgICANCg0K
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Christian KönigQuoted 2 lines · Christian König
The key takeaway is that when any device has ATS enabled you can't disable ACS without breaking it (even if you unplug and replug it).
I don't follow how you came to this conclusion...
The ACS bits we'd be turning off are the ones that force TLPs addressed
at a peer to go to the RC. However, ATS translation packets will be addressed to an untranslated address which a switch will not identify as a peer address so it should send upstream regardless the state of the ACS Req/Comp redirect bits.
Once the translation comes back, the ATS endpoint should send the TLP to the peer address with the AT packet type and it will be directed to the peer provided the Direct Translated bit is set (or the redirect bits are unset).
I can't see how turning off the Req/Comp redirect bits could break anything except for the isolation they provide.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Am 09.05.2018 um 18:45 schrieb Logan Gunthorpe:
Quoted 10 lines · Christian König
Quoted 2 lines
The key takeaway is that when any device has ATS enabled you can't disable ACS without breaking it (even if you unplug and replug it).
I don't follow how you came to this conclusion...
The ACS bits we'd be turning off are the ones that force TLPs addressed
at a peer to go to the RC. However, ATS translation packets will be addressed to an untranslated address which a switch will not identify as a peer address so it should send upstream regardless the state of the ACS Req/Comp redirect bits.
Why would a switch not identify that as a peer address? We use the PASID together with ATS to identify the address space which a transaction should use.
If I'm not completely mistaken when you disable ACS it is perfectly possible that a bridge identifies a transaction as belonging to a peer address, which isn't what we want here.
Christian.
Quoted 10 lines
Once the translation comes back, the ATS endpoint should send the TLP to the peer address with the AT packet type and it will be directed to the peer provided the Direct Translated bit is set (or the redirect bits are unset).
I can't see how turning off the Req/Comp redirect bits could break anything except for the isolation they provide.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgQ2hyaXN0aWFuDQoNCj4gV2h5IHdvdWxkIGEgc3dpdGNoIG5vdCBpZGVudGlmeSB0aGF0IGFz IGEgcGVlciBhZGRyZXNzPyBXZSB1c2UgdGhlIFBBU0lEIA0KPiAgICB0b2dldGhlciB3aXRoIEFU UyB0byBpZGVudGlmeSB0aGUgYWRkcmVzcyBzcGFjZSB3aGljaCBhIHRyYW5zYWN0aW9uIA0KPiAg ICBzaG91bGQgdXNlLg0KDQpJIHRoaW5rIHlvdSBhcmUgY29uZmxhdGluZyB0d28gdHlwZXMgb2Yg VExQcyBoZXJlLiBJZiB0aGUgZGV2aWNlIHN1cHBvcnRzIEFUUyB0aGVuIGl0IHdpbGwgaXNzdWUg YSBUUiBUTFAgdG8gb2J0YWluIGEgdHJhbnNsYXRlZCBhZGRyZXNzIGZyb20gdGhlIElPTU1VLiBU aGlzIFRSIFRMUCB3aWxsIGJlIGFkZHJlc3NlZCB0byB0aGUgUlAgYW5kIHNvIHJlZ2FyZGxlc3Mg b2YgQUNTIGl0IGlzIGdvaW5nIHVwIHRvIHRoZSBSb290IFBvcnQuIFdoZW4gaXQgZ2V0cyB0aGUg cmVzcG9uc2UgaXQgZ2V0cyB0aGUgcGh5c2ljYWwgYWRkcmVzcyBhbmQgY2FuIHVzZSB0aGF0IHdp dGggdGhlIFRBIGJpdCBzZXQgZm9yIHRoZSBwMnBkbWEuIEluIHRoZSBjYXNlIG9mIEFUUyBzdXBw b3J0IHdlIGFsc28gaGF2ZSBtb3JlIGNvbnRyb2wgb3ZlciBBQ1MgYXMgd2UgY2FuIGRpc2FibGUg aXQganVzdCBmb3IgVEEgYWRkcmVzc2VzIChhcyBwZXIgNy43LjcuNy4yIG9mIHRoZSBzcGVjKS4N CiAgICANCiA+ICAgSWYgSSdtIG5vdCBjb21wbGV0ZWx5IG1pc3Rha2VuIHdoZW4geW91IGRpc2Fi bGUgQUNTIGl0IGlzIHBlcmZlY3RseSANCiA+ICAgcG9zc2libGUgdGhhdCBhIGJyaWRnZSBpZGVu dGlmaWVzIGEgdHJhbnNhY3Rpb24gYXMgYmVsb25naW5nIHRvIGEgcGVlciANCiA+ICAgYWRkcmVz cywgd2hpY2ggaXNuJ3Qgd2hhdCB3ZSB3YW50IGhlcmUuDQogICANCllvdSBhcmUgcmlnaHQgaGVy ZSBhbmQgSSB0aGluayB0aGlzIGlsbHVzdHJhdGVzIGEgcHJvYmxlbSBmb3IgdXNpbmcgdGhlIElP TU1VIGF0IGFsbCB3aGVuIFAyUERNQSBkZXZpY2VzIGRvIG5vdCBzdXBwb3J0IEFUUy4gTGV0IG1l IGV4cGxhaW46DQoNCklmIHdlIHdhbnQgdG8gZG8gYSBQMlBETUEgYW5kIHRoZSBETUEgZGV2aWNl IGRvZXMgbm90IHN1cHBvcnQgQVRTIHRoZW4gSSB0aGluayB3ZSBoYXZlIHRvIGRpc2FibGUgdGhl IElPTU1VIChzb21ldGhpbmcgTWlrZSBzdWdnZXN0ZWQgZWFybGllcikuIFRoZSByZWFzb24gaXMg dGhhdCBzaW5jZSBBVFMgaXMgbm90IGFuIG9wdGlvbiB0aGUgRVAgbXVzdCBpbml0aWF0ZSB0aGUg RE1BIHVzaW5nIHRoZSBhZGRyZXNzZXMgcGFzc2VkIGRvd24gdG8gaXQuIElmIHRoZSBJT01NVSBp cyBvbiB0aGVuIHRoaXMgaXMgYW4gSU9WQSB0aGF0IGNvdWxkICh3aXRoIHNvbWUgbm9uLXplcm8g cHJvYmFiaWxpdHkpIHBvaW50IHRvIGFuIElPIE1lbW9yeSBhZGRyZXNzIGluIHRoZSBzYW1lIFBD SSBkb21haW4uIFNvIGlmIHdlIGRpc2FibGUgQUNTIHdlIGFyZSBpbiB0cm91YmxlIGFzIHdlIG1p Z2h0IE1lbVdyIHRvIHRoZSB3cm9uZyBwbGFjZSBidXQgaWYgd2UgZW5hYmxlIEFDUyB3ZSBsb3Nl IG11Y2ggb2YgdGhlIGJlbmVmaXQgb2YgUDJQRE1BLiBEaXNhYmxpbmcgdGhlIElPTU1VIHJlbW92 ZXMgdGhlIElPVkEgcmlzayBhbmQgaXJvbmljYWxseSBhbHNvIHJlc29sdmVzIHRoZSBJT01NVSBn cm91cGluZyBpc3N1ZXMuDQoNClNvIEkgdGhpbmsgaWYgd2Ugd2FudCB0byBzdXBwb3J0IHBlcmZv cm1hbnQgUDJQRE1BIGZvciBkZXZpY2VzIHRoYXQgZG9uJ3QgaGF2ZSBBVFMgKGFuZCBubyBOVk1l IFNTRHMgdG9kYXkgc3VwcG9ydCBBVFMpIHRoZW4gd2UgaGF2ZSB0byBkaXNhYmxlIHRoZSBJT01N VS4gSSBrbm93IHRoaXMgaXMgcHJvYmxlbWF0aWMgZm9yIEFNRHMgdXNlIGNhc2Ugc28gcGVyaGFw cyB3ZSBhbHNvIG5lZWQgdG8gY29uc2lkZXIgYSBtb2RlIGZvciBQMlBETUEgZm9yIGRldmljZXMg dGhhdCBETyBzdXBwb3J0IEFUUyB3aGVyZSB3ZSBjYW4gZW5hYmxlIHRoZSBJT01NVSAoYnV0IGlu IHRoaXMgY2FzZSBFUHMgd2l0aG91dCBBVFMgY2Fubm90IHBhcnRpY2lwYXRlIGFzIFAyUERNQSBE TUEgaW5pYXRvcnMpLg0KDQpNYWtlIHNlbnNlPw0KDQpTdGVwaGVuDQogDQogICAgDQogICAgDQoN Cg==
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 12 lines · Stephen Bates
Hi Christian
Quoted 3 lines
Why would a switch not identify that as a peer address? We use the PASID
together with ATS to identify the address space which a transaction should use.I think you are conflating two types of TLPs here. If the device supports ATS then it will issue a TR TLP to obtain a translated address from the IOMMU. This TR TLP will be addressed to the RP and so regardless of ACS it is going up to the Root Port. When it gets the response it gets the physical address and can use that with the TA bit set for the p2pdma. In the case of ATS support we also have more control over ACS as we can disable it just for TA addresses (as per 7.7.7.7.2 of the spec).
Quoted 3 lines
If I'm not completely mistaken when you disable ACS it is perfectly possible that a bridge identifies a transaction as belonging to a peer address, which isn't what we want here.
Quoted 8 lines
You are right here and I think this illustrates a problem for using the IOMMU at all when P2PDMA devices do not support ATS. Let me explain:
If we want to do a P2PDMA and the DMA device does not support ATS then I think we have to disable the IOMMU (something Mike suggested earlier). The reason is that since ATS is not an option the EP must initiate the DMA using the addresses passed down to it. If the IOMMU is on then this is an IOVA that could (with some non-zero probability) point to an IO Memory address in the same PCI domain. So if we disable ACS we are in trouble as we might MemWr to the wrong place but if we enable ACS we lose much of the benefit of P2PDMA. Disabling the IOMMU removes the IOVA risk and ironically also resolves the IOMMU grouping issues.
So I think if we want to support performant P2PDMA for devices that don't have ATS (and no NVMe SSDs today support ATS) then we have to disable the IOMMU. I know this is problematic for AMDs use case so perhaps we also need to consider a mode for P2PDMA for devices that DO support ATS where we can enable the IOMMU (but in this case EPs without ATS cannot participate as P2PDMA DMA iniators).
Make sense?
Note on GPU we do would not rely on ATS for peer to peer. Some part of the GPU (DMA engines) do not necessarily support ATS. Yet those are the part likely to be use in peer to peer.
However here this is a distinction in objective that i believe is lost. We (ake GPU people aka the good guys ;)) do no want to do peer to peer for performance reasons ie we do not care having our transaction going to the root complex and back down the destination. At least in use case i am working on this is fine.
Reasons is that GPU are giving up on PCIe (see all specialize link like NVlink that are popping up in GPU space). So for fast GPU inter-connect we have this new links. Yet for legacy and inter-operability we would like to do peer to peer with other devices like RDMA ... going through the root complex would be fine from performance point of view. Worst case is that it is slower than existing design where system memory is use as bounce buffer.
Also the IOMMU isolation do matter a lot to us. Think someone using this peer to peer to gain control of a server in the cloud.
Cheers,
J�r�me
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgSmVyb21lDQoNCj4gICAgTm90ZSBvbiBHUFUgd2UgZG8gd291bGQgbm90IHJlbHkgb24gQVRT IGZvciBwZWVyIHRvIHBlZXIuIFNvbWUgcGFydA0KPiAgICBvZiB0aGUgR1BVIChETUEgZW5naW5l cykgZG8gbm90IG5lY2Vzc2FyaWx5IHN1cHBvcnQgQVRTLiBZZXQgdGhvc2UNCj4gICAgYXJlIHRo ZSBwYXJ0IGxpa2VseSB0byBiZSB1c2UgaW4gcGVlciB0byBwZWVyLg0KDQpPSyB0aGlzIGlzIGdv b2QgdG8ga25vdy4gSSBhZ3JlZSB0aGUgRE1BIGVuZ2luZSBpcyBwcm9iYWJseSBvbmUgb2YgdGhl IEdQVSBjb21wb25lbnRzIG1vc3QgYXBwbGljYWJsZSB0byBwMnBkbWEuDQogICAgDQo+ICAgIFdl IChha2UgR1BVIHBlb3BsZSBha2EgdGhlIGdvb2QgZ3V5cyA7KSkgZG8gbm8gd2FudCB0byBkbyBw ZWVyIHRvIHBlZXINCj4gICAgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMgaWUgd2UgZG8gbm90IGNh cmUgaGF2aW5nIG91ciB0cmFuc2FjdGlvbiBnb2luZw0KPiAgICB0byB0aGUgcm9vdCBjb21wbGV4 IGFuZCBiYWNrIGRvd24gdGhlIGRlc3RpbmF0aW9uLiBBdCBsZWFzdCBpbiB1c2UgY2FzZQ0KPiAg ICBpIGFtIHdvcmtpbmcgb24gdGhpcyBpcyBmaW5lLg0KDQpJZiB0aGUgR1BVIHBlb3BsZSBhcmUg dGhlIGdvb2QgZ3V5cyBkb2VzIHRoYXQgbWFrZSB0aGUgTlZNZSBwZW9wbGUgdGhlIGJhZCBndXlz IDstKS4gSWYgc28sIHdoYXQgYXJlIHRoZSBSRE1BIHBlb3BsZT8/PyBBZ2FpbiBnb29kIHRvIGtu b3cuDQogICAgDQo+ICAgIFJlYXNvbnMgaXMgdGhhdCBHUFUgYXJlIGdpdmluZyB1cCBvbiBQQ0ll IChzZWUgYWxsIHNwZWNpYWxpemUgbGluayBsaWtlDQo+ICAgIE5WbGluayB0aGF0IGFyZSBwb3Bw aW5nIHVwIGluIEdQVSBzcGFjZSkuIFNvIGZvciBmYXN0IEdQVSBpbnRlci1jb25uZWN0DQo+ICAg IHdlIGhhdmUgdGhpcyBuZXcgbGlua3MuIA0KDQpJIGxvb2sgZm9yd2FyZCB0byBOdmlkaWEgb3Bl bi1saWNlbnNpbmcgTlZMaW5rIHRvIGFueW9uZSB3aG8gd2FudHMgdG8gdXNlIGl0IDstKS4gT3Ig bWF5YmUgd2UnbGwgYWxsIGp1c3Qgc3dpdGNoIHRvIE9wZW5HZW5DQ0lYIHdoZW4gdGhlIHRpbWUg Y29tZXMuDQogICAgDQo+ICAgIEFsc28gdGhlIElPTU1VIGlzb2xhdGlvbiBkbyBtYXR0ZXIgYSBs b3QgdG8gdXMuIFRoaW5rIHNvbWVvbmUgdXNpbmcgdGhpcw0KPiAgICBwZWVyIHRvIHBlZXIgdG8g Z2FpbiBjb250cm9sIG9mIGEgc2VydmVyIGluIHRoZSBjbG91ZC4NCiAgICANCkkgYWdyZWUgdGhh dCBJT01NVSBpc29sYXRpb24gaXMgdmVyeSBkZXNpcmFibGUuIEhlbmNlIHRoZSBkZXNpcmUgdG8g ZW5zdXJlIHdlIGNhbiBrZWVwIHRoZSBJT01NVSBvbiB3aGlsZSBkb2luZyBwMnBkbWEgaWYgYXQg YWxsIHBvc3NpYmxlIHdoaWxzdCBzdGlsbCBkZWxpdmVyaW5nIHRoZSBkZXNpcmVkIHBlcmZvcm1h bmNlIHRvIHRoZSB1c2VyLg0KDQpTdGVwaGVuICAgIA0KDQo=
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Stephen Bates
Hi Jerome
Quoted 3 lines
Note on GPU we do would not rely on ATS for peer to peer. Some part of the GPU (DMA engines) do not necessarily support ATS. Yet those are the part likely to be use in peer to peer.
Quoted 8 lines
OK this is good to know. I agree the DMA engine is probably one of the GPU components most applicable to p2pdma.
Quoted 4 lines
We (ake GPU people aka the good guys ;)) do no want to do peer to peer for performance reasons ie we do not care having our transaction going to the root complex and back down the destination. At least in use case i am working on this is fine.
If the GPU people are the good guys does that make the NVMe people the bad guys ;-). If so, what are the RDMA people??? Again good to know.
The NVMe people are the Nice Neighbors, the RDMA people are the Righteous Romantics and the PCI people are the Pleasant Protagonists...
Obviously.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Stephen BatesOn Thu, 10 May 2018 18:41:09 +0000
"Stephen Bates" <[email protected]> wrote: =20
Quoted 1 line
Quoted 1 line
Reasons is that GPU are giving up on PCIe (see all specialize link l=
ike
Quoted 1 line
Quoted 1 line
NVlink that are popping up in GPU space). So for fast GPU inter-conn=
ect
Quoted 3 lines
Quoted 1 line
we have this new links. =20
=20
I look forward to Nvidia open-licensing NVLink to anyone who wants to use=
it ;-).
No doubt, the marketing for it is quick to point out the mesh topology of NVLink, but I haven't seen any technical documents that describe the isolation capabilities or IOMMU interaction. Whether this is included or an afterthought, I have no idea.
Quoted 1 line
Quoted 1 line
Also the IOMMU isolation do matter a lot to us. Think someone using =
this
Quoted 1 line
Quoted 1 line
peer to peer to gain control of a server in the cloud. =20
=46rom that perspective, do we have any idea what NVLink means for topology and IOMMU provided isolation and translation? I've seen a device assignment user report that seems to suggest it might pretend to be PCIe compatible, but the assigned GPU ultimately doesn't work correctly in a VM, so perhaps the software compatibility is only so deep. Thanks,
Alex
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Alex Williamson
Quoted 4 lines · On Thu, 10 May 2018 18:41:09 +0000 "Stephen Bates" <[email protected]> wrote:
Quoted 3 lines
Reasons is that GPU are giving up on PCIe (see all specialize link like NVlink that are popping up in GPU space). So for fast GPU inter-connect we have this new links.
Quoted 6 lines
Quoted 1 line
I look forward to Nvidia open-licensing NVLink to anyone who wants to use it ;-).
No doubt, the marketing for it is quick to point out the mesh topology of NVLink, but I haven't seen any technical documents that describe the isolation capabilities or IOMMU interaction. Whether this is included or an afterthought, I have no idea.
AFAIK there is no IOMMU on NVLink between devices, walking a page table and being able to sustain 80GB/s or 160GB/s is hard to achieve :) I think idea behind those interconnect is that devices in the mesh are inherently secure ie each single device is suppose to make sure that no one can abuse it.
GPU with their virtual address space and contextualize program executions unit are suppose to be secure (a specter like bug might be lurking on those but i doubt it).
So for those interconnect you program physical address directly in the page table of the devices and those physical address are un-translated from hard- ware perspective.
Note that the kernel driver that do the actual GPU page table programming can do sanity check on value it is setting. So checks can also happens at setup time. But after that assumption is hardware is secure and no one can abuse it AFAICT.
Quoted 10 lines
Quoted 3 lines
Quoted 3 lines
Also the IOMMU isolation do matter a lot to us. Think someone using this peer to peer to gain control of a server in the cloud.
From that perspective, do we have any idea what NVLink means for topology and IOMMU provided isolation and translation? I've seen a device assignment user report that seems to suggest it might pretend to be PCIe compatible, but the assigned GPU ultimately doesn't work correctly in a VM, so perhaps the software compatibility is only so deep. Thanks,
Note that each single GPU (in configurations i am aware of) also have a PCIE link with the CPU/main memory. So from that point of view they very much behave like a regular PCIE devices. It is just that each GPUs in the mesh can access each other memory through high bandwidth interconnect.
I am not sure how much is public beyond that, i will ask NVidia to try to have someone chime in this thread and shed light on this, if possible.
Cheers,
J�r�me
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Stephen BatesQuoted 7 lines · Stephen Bates
Hi Christian
Quoted 3 lines
Why would a switch not identify that as a peer address? We use the PASID
together with ATS to identify the address space which a transaction should use.I think you are conflating two types of TLPs here. If the device supports ATS then it will issue a TR TLP to obtain a translated address from the IOMMU. This TR TLP will be addressed to the RP and so regardless of ACS it is going up to the Root Port. When it gets the response it gets the physical address and can use that with the TA bit set for the p2pdma. In the case of ATS support we also have more control over ACS as we can disable it just for TA addresses (as per 7.7.7.7.2 of the spec).
Yes. Remember if we are using the IOMMU the EP is being programmed (regardless of whether it's a DMA engine, NTB window or GPUVA) with an IOVA address which is separate from the device's PCI bus address. Any packet addressed to an IOVA address is going to go back to the root complex no matter what the ACS bits say. Only once ATS translates the addres back into the PCI bus address will the EP send packets to the peer and the switch will attempt to root them to the peer and only then do the ACS bits apply. And the direct translated ACS bit allows packets that have purportedly been translated through.
Quoted 10 lines
Quoted 3 lines
If I'm not completely mistaken when you disable ACS it is perfectly possible that a bridge identifies a transaction as belonging to a peer address, which isn't what we want here.
You are right here and I think this illustrates a problem for using the IOMMU at all when P2PDMA devices do not support ATS. Let me explain:
If we want to do a P2PDMA and the DMA device does not support ATS then I think we have to disable the IOMMU (something Mike suggested earlier). The reason is that since ATS is not an option the EP must initiate the DMA using the addresses passed down to it. If the IOMMU is on then this is an IOVA that could (with some non-zero probability) point to an IO Memory address in the same PCI domain. So if we disable ACS we are in trouble as we might MemWr to the wrong place but if we enable ACS we lose much of the benefit of P2PDMA. Disabling the IOMMU removes the IOVA risk and ironically also resolves the IOMMU grouping issues. So I think if we want to support performant P2PDMA for devices that don't have ATS (and no NVMe SSDs today support ATS) then we have to disable the IOMMU. I know this is problematic for AMDs use case so perhaps we also need to consider a mode for P2PDMA for devices that DO support ATS where we can enable the IOMMU (but in this case EPs without ATS cannot participate as P2PDMA DMA iniators).
Make sense?
Not to me. In the p2pdma code we specifically program DMA engines with the PCI bus address. So regardless of whether we are using the IOMMU or not, the packets will be forwarded directly to the peer. If the ACS Redir bits are on they will be forced back to the RC by the switch and the transaction will fail. If we clear the ACS bits, the TLPs will go where we want and everything will work (but we lose the isolation of ACS).
For EPs that support ATS, we should (but don't necessarily have to) program them with the IOVA address so they can go through the translation process which will allow P2P without disabling the ACS Redir bits -- provided the ACS direct translation bit is set. (And btw, if it is, then we lose the benefit of ACS protecting against malicious EPs). But, per above, the ATS transaction should involve only the IOVA address so the ACS bits not being set should not break ATS.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
PiBOb3QgdG8gbWUuIEluIHRoZSBwMnBkbWEgY29kZSB3ZSBzcGVjaWZpY2FsbHkgcHJvZ3JhbSBE TUEgZW5naW5lcyB3aXRoDQo+IHRoZSBQQ0kgYnVzIGFkZHJlc3MuIA0KDQpBaCB5ZXMgb2YgY291 cnNlLiBCcmFpbiBmYXJ0IG9uIG15IHBhcnQuIFdlIGFyZSBub3QgcHJvZ3JhbW1pbmcgdGhlIFAy UERNQSBpbml0aWF0b3Igd2l0aCBhbiBJT1ZBIGJ1dCB3aXRoIHRoZSBQQ0kgYnVzIGFkZHJlc3Mu Li4NCg0KPiBTbyByZWdhcmRsZXNzIG9mIHdoZXRoZXIgd2UgYXJlIHVzaW5nIHRoZSBJT01NVSBv cg0KPiBub3QsIHRoZSBwYWNrZXRzIHdpbGwgYmUgZm9yd2FyZGVkIGRpcmVjdGx5IHRvIHRoZSBw ZWVyLiBJZiB0aGUgQUNTDQo+ICBSZWRpciBiaXRzIGFyZSBvbiB0aGV5IHdpbGwgYmUgZm9yY2Vk IGJhY2sgdG8gdGhlIFJDIGJ5IHRoZSBzd2l0Y2ggYW5kDQo+ICB0aGUgdHJhbnNhY3Rpb24gd2ls bCBmYWlsLiBJZiB3ZSBjbGVhciB0aGUgQUNTIGJpdHMsIHRoZSBUTFBzIHdpbGwgZ28NCj4gIHdo ZXJlIHdlIHdhbnQgYW5kIGV2ZXJ5dGhpbmcgd2lsbCB3b3JrIChidXQgd2UgbG9zZSB0aGUgaXNv bGF0aW9uIG9mIEFDUykuDQoNCkFncmVlZC4NCiAgICANCj4gICAgRm9yIEVQcyB0aGF0IHN1cHBv cnQgQVRTLCB3ZSBzaG91bGQgKGJ1dCBkb24ndCBuZWNlc3NhcmlseSBoYXZlIHRvKQ0KPiAgICBw cm9ncmFtIHRoZW0gd2l0aCB0aGUgSU9WQSBhZGRyZXNzIHNvIHRoZXkgY2FuIGdvIHRocm91Z2gg dGhlDQo+ICAgIHRyYW5zbGF0aW9uIHByb2Nlc3Mgd2hpY2ggd2lsbCBhbGxvdyBQMlAgd2l0aG91 dCBkaXNhYmxpbmcgdGhlIEFDUyBSZWRpcg0KPiAgICBiaXRzIC0tIHByb3ZpZGVkIHRoZSBBQ1Mg ZGlyZWN0IHRyYW5zbGF0aW9uIGJpdCBpcyBzZXQuIChBbmQgYnR3LCBpZiBpdA0KPiAgICBpcywg dGhlbiB3ZSBsb3NlIHRoZSBiZW5lZml0IG9mIEFDUyBwcm90ZWN0aW5nIGFnYWluc3QgbWFsaWNp b3VzIEVQcykuDQo+ICAgIEJ1dCwgcGVyIGFib3ZlLCB0aGUgQVRTIHRyYW5zYWN0aW9uIHNob3Vs ZCBpbnZvbHZlIG9ubHkgdGhlIElPVkEgYWRkcmVzcw0KPiAgICBzbyB0aGUgQUNTIGJpdHMgbm90 IGJlaW5nIHNldCBzaG91bGQgbm90IGJyZWFrIEFUUy4NCiAgICANCldlbGwgd2Ugd291bGQgc3Rp bGwgaGF2ZSB0byBjbGVhciBzb21lIEFDUyBiaXRzIGJ1dCBub3cgd2UgY2FuIGNsZWFyIG9ubHkg Zm9yIHRyYW5zbGF0ZWQgYWRkcmVzc2VzLg0KDQpTdGVwaGVuDQogICAgDQoNCg==
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 21 lines · Stephen Bates
Quoted 2 lines
Not to me. In the p2pdma code we specifically program DMA engines with the PCI bus address.
Ah yes of course. Brain fart on my part. We are not programming the P2PDMA initiator with an IOVA but with the PCI bus address...
Quoted 5 lines
So regardless of whether we are using the IOMMU or
not, the packets will be forwarded directly to the peer. If the ACS
Redir bits are on they will be forced back to the RC by the switch and the transaction will fail. If we clear the ACS bits, the TLPs will go where we want and everything will work (but we lose the isolation of ACS).Agreed.
Quoted 7 lines
For EPs that support ATS, we should (but don't necessarily have to) program them with the IOVA address so they can go through the translation process which will allow P2P without disabling the ACS Redir bits -- provided the ACS direct translation bit is set. (And btw, if it is, then we lose the benefit of ACS protecting against malicious EPs). But, per above, the ATS transaction should involve only the IOVA address so the ACS bits not being set should not break ATS.
Quoted 1 line
Well we would still have to clear some ACS bits but now we can clear only for translated addresses.
We don't have to clear the ACS Redir bits as we did in the first case. We just have to make sure the ACS Direct Translated bit is set.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Am 10.05.2018 um 19:15 schrieb Logan Gunthorpe:
Quoted 5 lines · Stephen Bates
Quoted 3 lines
Quoted 2 lines
Not to me. In the p2pdma code we specifically program DMA engines with the PCI bus address.
Ah yes of course. Brain fart on my part. We are not programming the P2PDMA initiator with an IOVA but with the PCI bus address...
By disabling the ACS bits on the intermediate bridges you turn their address routing from IOVA addresses (which are to be resolved by the root complex) back to PCI bus addresses (which are resolved locally in the bridge).
This only works when the IOVA and the PCI bus addresses never overlap. I'm not sure how the IOVA allocation works but I don't think we guarantee that on Linux.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
So regardless of whether we are using the IOMMU or
not, the packets will be forwarded directly to the peer. If the ACS
Redir bits are on they will be forced back to the RC by the switch and the transaction will fail. If we clear the ACS bits, the TLPs will go where we want and everything will work (but we lose the isolation of ACS).Agreed.
If we really want to enable P2P without ATS and IOMMU enabled I think we should probably approach it like this:
a) Make double sure that IOVA in an IOMMU group never overlap with PCI BARs in that group.
b) Add configuration options to put a whole PCI branch of devices (e.g. a bridge) into a single IOMMU group.
c) Add a configuration option to disable the ACS bit on bridges in the same IOMMU group.
I agree that we have a rather special case here, but I still find that approach rather brave and would vote for disabling P2P without ATS when IOMMU is enabled.
BTW: I can't say anything about other implementations, but at least for the AMD-IOMMU the transaction won't fail when it is send to the root complex.
Instead the root complex would send it to the correct device. I already tested that on an AMD Ryzen with IOMMU enabled and P2P between two GPUs (but could be that this only works because of ATS).
Regards,
Christian.
Quoted 13 lines
Quoted 9 lines
Quoted 7 lines
For EPs that support ATS, we should (but don't necessarily have to) program them with the IOVA address so they can go through the translation process which will allow P2P without disabling the ACS Redir bits -- provided the ACS direct translation bit is set. (And btw, if it is, then we lose the benefit of ACS protecting against malicious EPs). But, per above, the ATS transaction should involve only the IOVA address so the ACS bits not being set should not break ATS.
Well we would still have to clear some ACS bits but now we can clear only for translated addresses.
We don't have to clear the ACS Redir bits as we did in the first case. We just have to make sure the ACS Direct Translated bit is set.
Logan
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 1 line · Christian König
This only works when the IOVA and the PCI bus addresses never overlap. I'm not sure how the IOVA allocation works but I don't think we guarantee that on Linux.
I find this hard to believe. There's always the possibility that some part of the system doesn't support ACS so if the PCI bus addresses and IOVA overlap there's a good chance that P2P and ATS won't work at all on some hardware.
Quoted 7 lines
If we really want to enable P2P without ATS and IOMMU enabled I think we should probably approach it like this:
a) Make double sure that IOVA in an IOMMU group never overlap with PCI BARs in that group.
b) Add configuration options to put a whole PCI branch of devices (e.g. a bridge) into a single IOMMU group.
c) Add a configuration option to disable the ACS bit on bridges in the same IOMMU group.
I think a configuration option to manage IOMMU groups as you suggest would be a very complex interface and difficult to implement. I prefer the option to disable the ACS bit on boot and let the existing code put the devices into their own IOMMU group (as it should already do to support hardware that doesn't have ACS support).
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
PiAgICBJIGZpbmQgdGhpcyBoYXJkIHRvIGJlbGlldmUuIFRoZXJlJ3MgYWx3YXlzIHRoZSBwb3Nz aWJpbGl0eSB0aGF0IHNvbWUgDQo+ICAgIHBhcnQgb2YgdGhlIHN5c3RlbSBkb2Vzbid0IHN1cHBv cnQgQUNTIHNvIGlmIHRoZSBQQ0kgYnVzIGFkZHJlc3NlcyBhbmQgDQo+ICAgIElPVkEgb3Zlcmxh cCB0aGVyZSdzIGEgZ29vZCBjaGFuY2UgdGhhdCBQMlAgYW5kIEFUUyB3b24ndCB3b3JrIGF0IGFs bCBvbiANCj4gICAgc29tZSBoYXJkd2FyZS4NCg0KSSB0ZW5kIHRvIGFncmVlIGJ1dCB0aGlzIGNv bWVzIGRvd24gdG8gaG93IElPVkEgYWRkcmVzc2VzIGFyZSBnZW5lcmF0ZWQgaW4gdGhlIGtlcm5l bC4gQWxleCAob3IgYW55b25lIGVsc2UpIGNhbiB5b3UgcG9pbnQgdG8gd2hlcmUgSU9WQSBhZGRy ZXNzZXMgYXJlIGdlbmVyYXRlZD8gQXMgTG9nYW4gc3RhdGVkIGVhcmxpZXIsIHAycGRtYSBieXBh c3NlcyB0aGlzIGFuZCBwcm9ncmFtcyB0aGUgUENJIGJ1cyBhZGRyZXNzIGRpcmVjdGx5IGJ1dCBv dGhlciBJTyBnb2luZyB0byB0aGUgc2FtZSBQQ0kgRVAgbWF5IGZsb3cgdGhyb3VnaCB0aGUgSU9N TVUgYW5kIGJlIHByb2dyYW1tZWQgd2l0aCBJT1ZBIHJhdGhlciB0aGFuIFBDSSBidXMgYWRkcmVz c2VzLg0KICAgIA0KPiBJIHByZWZlciANCj4gICAgdGhlIG9wdGlvbiB0byBkaXNhYmxlIHRoZSBB Q1MgYml0IG9uIGJvb3QgYW5kIGxldCB0aGUgZXhpc3RpbmcgY29kZSBwdXQgDQo+ICAgIHRoZSBk ZXZpY2VzIGludG8gdGhlaXIgb3duIElPTU1VIGdyb3VwIChhcyBpdCBzaG91bGQgYWxyZWFkeSBk byB0byANCj4gICAgc3VwcG9ydCBoYXJkd2FyZSB0aGF0IGRvZXNuJ3QgaGF2ZSBBQ1Mgc3VwcG9y dCkuDQogICAgDQorMQ0KDQpTdGVwaGVuDQogICAgDQoNCg==
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
All
Quoted 1 line
=A0Alex (or anyone else) can you point to where IOVA addresses are generat=
ed?
A case of RTFM perhaps (though a pointer to the code would still be appreci= ated).
https://www.kernel.org/doc/Documentation/Intel-IOMMU.txt
Some exceptions to IOVA
-----------------------
Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff). The same is true for peer to peer transactions. Hence we reserve the address from PCI MMIO ranges so they are not allocated for IOVA addresses.
Cheers
Stephen
Logan Gunthorpe
maintainerRe: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Stephen Bates
All
Quoted 1 line
?Alex (or anyone else) can you point to where IOVA addresses are generated?
A case of RTFM perhaps (though a pointer to the code would still be appreciated).
Quoted 7 lines
https://www.kernel.org/doc/Documentation/Intel-IOMMU.txt
Some exceptions to IOVA
-----------------------
Interrupt ranges are not address translated, (0xfee00000-0xfeefffff). The same is true for peer to peer transactions. Hence we reserve the address from PCI MMIO ranges so they are not allocated for IOVA addresses.
Hmm, except I'm not sure how to interpret that. It sounds like there can't be an IOVA address that overlaps with the PCI MMIO range which is good and what I'd expect.
But for peer to peer they say they don't translate the address which implies to me that the intention is for a peer to peer address to not be mapped in the same way using the dma_map interface (of course though if you were using ATS you'd want this for sure). Unless the existing dma_map command's notice a PCI MMIO address and handle them differently, but I don't see how.
Logan
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Logan GunthorpeQuoted 40 lines · Logan Gunthorpe
For peer-to-peer transactions to work the downstream ports in each switch must not have the ACS flags set. At this time there is no way to dynamically change the flags and update the corresponding IOMMU groups so this is done at enumeration time before the groups are assigned.
This effectively means that if
CONFIG_PCI_P2PDMAis selected then all devices behind any PCIe switch heirarchy will be in the same IOMMU group. Which implies that individual devices behind any switch heirarchy will not be able to be assigned to separate VMs because there is no isolation between them. Additionally, any malicious PCIe devices will be able to DMA to memory exposed by other EPs in the same domain as TLPs will not be checked by the IOMMU.Given that the intended use case of P2P Memory is for users with custom hardware designed for purpose, we do not expect distributors to ever need to enable this option. Users that want to use P2P must have compiled a custom kernel with this configuration option and understand the implications regarding ACS. They will either not require ACS or will have design the system in such a way that devices that require isolation will be separate from those using P2P transactions.
Signed-off-by Logan Gunthorpe <[email protected]>--- drivers/pci/Kconfig | 9 +++++++++ drivers/pci/p2pdma.c | 45 ++++++++++++++++++++++++++++++--------------- drivers/pci/pci.c | 6 ++++++ include/linux/pci-p2pdma.h | 5 +++++ 4 files changed, 50 insertions(+), 15 deletions(-)drivers/pci/Kconfig +0
-0@@ -139,6 +139,15 @@ config PCI_P2PDMA transations must be between devices behind the same root port. (Typically behind a network of PCIe switches).
drivers/pci/Kconfig config PCI_P2PDMA · line 151
Quoted 10 lines
drivers/pci/Kconfig +9
-0+ Enabling this option will also disable ACS on all ports behind + any PCIe switch. This effectively puts all devices behind any + switch heirarchy into the same IOMMU group. Which implies that + individual devices behind any switch will not be able to be + assigned to separate VMs because there is no isolation between + them. Additionally, any malicious PCIe devices will be able to + DMA to memory exposed by other EPs in the same domain as TLPs + will not be checked by the IOMMU. + If unsure, say N.
It seems unwieldy that this is a compile time option and not a runtime option. Can't we have a kernel command line option to opt-in to this behavior rather than require a wholly separate kernel image?
Why is this text added in a follow on patch and not the patch that introduced the config option?
I'm also wondering if that command line option can take a 'bus device function' address of a switch to limit the scope of where ACS is disabled.
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgRGFuDQoNCj4gICAgSXQgc2VlbXMgdW53aWVsZHkgdGhhdCB0aGlzIGlzIGEgY29tcGlsZSB0 aW1lIG9wdGlvbiBhbmQgbm90IGEgcnVudGltZQ0KPiAgICBvcHRpb24uIENhbid0IHdlIGhhdmUg YSBrZXJuZWwgY29tbWFuZCBsaW5lIG9wdGlvbiB0byBvcHQtaW4gdG8gdGhpcw0KPiAgICBiZWhh dmlvciByYXRoZXIgdGhhbiByZXF1aXJlIGEgd2hvbGx5IHNlcGFyYXRlIGtlcm5lbCBpbWFnZT8N CiAgDQpJIHRoaW5rIGJlY2F1c2Ugb2YgdGhlIHNlY3VyaXR5IGltcGxpY2F0aW9ucyBhc3NvY2lh dGVkIHdpdGggcDJwZG1hIGFuZCBBQ1Mgd2Ugd2FudGVkIHRvIG1ha2UgaXQgdmVyeSBjbGVhciBw ZW9wbGUgd2VyZSBjaG9vc2luZyBvbmUgKHAycGRtYSkgb3IgdGhlIG90aGVyIChJT01NVSBncm91 cGluZ3MgYW5kIGlzb2xhdGlvbikuIEhvd2V2ZXIgcGVyc29uYWxseSBJIHdvdWxkIHByZWZlciBp bmNsdWRpbmcgdGhlIG9wdGlvbiBvZiBhIHJ1bi10aW1lIGtlcm5lbCBwYXJhbWV0ZXIgdG9vLiBJ biBmYWN0IGEgZmV3IG1vbnRocyBhZ28gSSBwcm9wb3NlZCBhIHNtYWxsIHBhdGNoIHRoYXQgZGlk IGp1c3QgdGhhdCBbMV0uIEl0IG5ldmVyIHJlYWxseSB3ZW50IGFueXdoZXJlIGJ1dCBpZiBwZW9w bGUgd2VyZSBvcGVuIHRvIHRoZSBpZGVhIHdlIGNvdWxkIGxvb2sgYXQgYWRkaW5nIGl0IHRvIHRo ZSBzZXJpZXMuDQogIA0KPiBXaHkgaXMgdGhpcyB0ZXh0IGFkZGVkIGluIGEgZm9sbG93IG9uIHBh dGNoIGFuZCBub3QgdGhlIHBhdGNoIHRoYXQNCj4gIGludHJvZHVjZWQgdGhlIGNvbmZpZyBvcHRp b24/DQoNCkJlY2F1c2UgdGhlIEFDUyBzZWN0aW9uIHdhcyBhZGRlZCBsYXRlciBpbiB0aGUgc2Vy aWVzIGFuZCB0aGlzIGluZm9ybWF0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGF0IGFkZGl0aW9u YWwgZnVuY3Rpb25hbGl0eS4NCiAgICANCj4gSSdtIGFsc28gd29uZGVyaW5nIGlmIHRoYXQgY29t bWFuZCBsaW5lIG9wdGlvbiBjYW4gdGFrZSBhICdidXMgZGV2aWNlDQo+IGZ1bmN0aW9uJyBhZGRy ZXNzIG9mIGEgc3dpdGNoIHRvIGxpbWl0IHRoZSBzY29wZSBvZiB3aGVyZSBBQ1MgaXMNCj4gZGlz YWJsZWQuDQoNCkJ5IHRoaXMgeW91IG1lYW4gdGhlIGFkZHJlc3MgZm9yIGVpdGhlciBhIFJQLCBE U1AsIFVTUCBvciBNRiBFUCBiZWxvdyB3aGljaCB3ZSBkaXNhYmxlIEFDUz8gV2UgY291bGQgZG8g dGhhdCBidXQgSSBkb24ndCB0aGluayBpdCBhdm9pZHMgdGhlIGlzc3VlIG9mIGNoYW5nZXMgaW4g SU9NTVUgZ3JvdXBpbmdzIGFzIGRldmljZXMgYXJlIGFkZGVkL3JlbW92ZWQuIEl0IHNpbXBseSBj aGFuZ2VzIHRoZSBwcm9ibGVtIGZyb20gYWZmZWN0aW5nIGFuZCBlbnRpcmUgUENJIGRvbWFpbiB0 byBhIHN1Yi1zZXQgb2YgdGhlIGRvbWFpbi4gV2UgY2FuIGFscmVhZHkgaGFuZGxlIHRoaXMgYnkg ZG9pbmcgcDJwZG1hIG9uIG9uZSBSUCBhbmQgbm9ybWFsIElPTU1VIGlzb2xhdGlvbiBvbiB0aGUg b3RoZXIgUlBzIGluIHRoZSBzeXN0ZW0uDQoNClN0ZXBoZW4NCg0KWzFdIGh0dHBzOi8vbWFyYy5p bmZvLz9sPWxpbnV4LWRvYyZtPTE1MDkwNzE4ODMxMDgzOCZ3PTINCiAgICANCg0K
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 8 lines · Stephen Bates
Hi Dan
Quoted 3 lines
It seems unwieldy that this is a compile time option and not a runtime option. Can't we have a kernel command line option to opt-in to this behavior rather than require a wholly separate kernel image?
I think because of the security implications associated with p2pdma and ACS we wanted to make it very clear people were choosing one (p2pdma) or the other (IOMMU groupings and isolation). However personally I would prefer including the option of a run-time kernel parameter too. In fact a few months ago I proposed a small patch that did just that [1]. It never really went anywhere but if people were open to the idea we could look at adding it to the series.
It is clear if it is a kernel command-line option or a CONFIG option.
One does not have access to the kernel command-line w/o a few privs.
A CONFIG option prevents a distribution to have a default, locked-down kernel _and_ the ability to be 'unlocked' if the customer/site is 'secure' via other means. A run/boot-time option is more flexible and achieves the best of both.
Quoted 9 lines
Quoted 2 lines
Why is this text added in a follow on patch and not the patch that
introduced the config option?Because the ACS section was added later in the series and this information is associated with that additional functionality.
Quoted 3 lines
I'm also wondering if that command line option can take a 'bus device function' address of a switch to limit the scope of where ACS is disabled.
Well, p2p DMA is a function of a cooperating 'agent' somewhere above the two devices.
That agent should 'request' to the kernel that ACS be removed/circumvented (p2p enabled) btwn two endpoints. I recommend doing so via a sysfs method.
That way, the system can limit the 'unsecure' space btwn two devices, likely configured on a separate switch, from the rest of the still-secured/ACS-enabled PCIe tree. PCIe is pt-to-pt, effectively; maybe one would have multiple nics/fabrics p2p to/from NVME, but one could look at it as a list of pairs (nic1<->nvme1; nic2<->nvme2; ....). A pair-listing would be optimal, allowing the kernel to figure out the ACS path, and not making it endpoint-switch-switch...-switch-endpt error-entry prone. Additionally, systems that can/prefer to do so via a RP's IOMMU, albeit not optimal, but better then all the way to/from memory, and a security/iova-check possible, can modify the pt-to-pt ACS algorithm to accomodate over time (e.g., cap bits be they hw or device-driver/extension/quirk defined for each bridge/RP in a PCI domain).
Kernels that never want to support P2P could build w/o it enabled.... cmdline option is moot.
Kernels built with it on, *still* need cmdline option, to be blunt that the kernel is enabling a feature that could render the entire (IO sub)system unsecure.
Quoted 2 lines
By this you mean the address for either a RP, DSP, USP or MF EP below which we disable ACS? We could do that but I don't think it avoids the issue of changes in IOMMU groupings as devices are added/removed. It simply changes the problem from affecting and entire PCI domain to a sub-set of the domain. We can already handle this by doing p2pdma on one RP and normal IOMMU isolation on the other RPs in the system.
as devices are added, they start in ACS-enabled, secured mode. As sysfs entry modifies p2p ability, IOMMU group is modified as well.
btw -- IOMMU grouping is a host/HV control issue, not a VM control/knowledge issue.
So I don't understand the comments why VMs should need to know.
-- configure p2p _before_ assigning devices to VMs. ... iommu groups are checked at assignment time.
-- so even if hot-add, separate iommu group, then enable p2p, becomes same IOMMU group, then can only assign to same VM.
-- VMs don't know IOMMU's & ACS are involved now, and won't later, even if device's dynamically added/removed
Is there a thread I need to read up to explain /clear-up the thoughts above?
Quoted 5 lines
Stephen
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgRG9uDQoNCj5XZWxsLCBwMnAgRE1BIGlzIGEgZnVuY3Rpb24gb2YgYSBjb29wZXJhdGluZyAn YWdlbnQnIHNvbWV3aGVyZSBhYm92ZSB0aGUgdHdvIGRldmljZXMuDQo+ICAgIFRoYXQgYWdlbnQg c2hvdWxkICdyZXF1ZXN0JyB0byB0aGUga2VybmVsIHRoYXQgQUNTIGJlIHJlbW92ZWQvY2lyY3Vt dmVudGVkIChwMnAgZW5hYmxlZCkgYnR3biB0d28gZW5kcG9pbnRzLg0KPiAgICBJIHJlY29tbWVu ZCBkb2luZyBzbyB2aWEgYSBzeXNmcyBtZXRob2QuDQoNClllcyB3ZSBsb29rZWQgYXQgc29tZXRo aW5nIGxpa2UgdGhpcyBpbiB0aGUgcGFzdCBidXQgaXQgZG9lcyBoaXQgdGhlIElPTU1VIGdyb3Vw aW5nIGlzc3VlIEkgZGlzY3Vzc2VkIGVhcmxpZXIgdG9kYXkgd2hpY2ggaXMgbm90IGFjY2VwdGFi bGUgcmlnaHQgbm93LiBJbiB0aGUgbG9uZyB0ZXJtLCBvbmNlIHdlIGdldCBJT01NVSBncm91cGlu ZyBjYWxsYmFja3MgdG8gVk1zIHdlIGNhbiBsb29rIGF0IGV4dGVuZGluZyBwMnBkbWEgaW4gdGhp cyB3YXkuIEJ1dCBJIGRvbid0IHRoaW5rIHRoaXMgaXMgdmlhYmxlIGZvciB0aGUgaW5pdGlhbCBz ZXJpZXMuIA0KDQogICAgDQo+ICAgICAgICAgICAgU28gSSBkb24ndCB1bmRlcnN0YW5kIHRoZSBj b21tZW50cyB3aHkgVk1zIHNob3VsZCBuZWVkIHRvIGtub3cuDQoNCkFzIEkgdW5kZXJzdGFuZCBp dCBWTXMgbmVlZCB0byBrbm93IGJlY2F1c2UgVkZJTyBwYXNzZXMgSU9NTVUgZ3JvdXBpbmcgdXAg aW50byB0aGUgVk1zLiBTbyBpZiBhIElPTU1VIGdyb3VwaW5nIGNoYW5nZXMgdGhlIFZNJ3Mgdmll dyBvZiBpdHMgUENJZSB0b3BvbG9neSBjaGFuZ2VzLiBJIHRoaW5rIHdlIGV2ZW4gaGF2ZSB0byBi ZSBjb2duaXphbnQgb2YgdGhlIGZhY3QgdGhlIE9TIHJ1bm5pbmcgb24gdGhlIFZNIG1heSBub3Qg ZXZlbiBzdXBwb3J0IGhvdC1wbHVnIG9mIFBDSSBkZXZpY2VzLg0KICAgIA0KPiBJcyB0aGVyZSBh IHRocmVhZCBJIG5lZWQgdG8gcmVhZCB1cCB0byBleHBsYWluIC9jbGVhci11cCB0aGUgdGhvdWdo dHMgYWJvdmU/DQoNCklmIHlvdSBzZWFyY2ggZm9yIHAycGRtYSB5b3Ugc2hvdWxkIGZpbmQgdGhl IHByZXZpb3VzIGRpc2N1c3Npb25zLiBUaGFua3MgZm9yIHRoZSBpbnB1dCENCg0KU3RlcGhlbg0K ICAgIA0KICAgIA0KDQo=
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · Stephen Bates
Hi Don
Quoted 3 lines
Well, p2p DMA is a function of a cooperating 'agent' somewhere above the two devices.
That agent should 'request' to the kernel that ACS be removed/circumvented (p2p enabled) btwn two endpoints. I recommend doing so via a sysfs method.
Quoted 6 lines
Yes we looked at something like this in the past but it does hit the IOMMU grouping issue I discussed earlier today which is not acceptable right now. In the long term, once we get IOMMU grouping callbacks to VMs we can look at extending p2pdma in this way. But I don't think this is viable for the initial series.
Quoted 1 line
So I don't understand the comments why VMs should need to know.
As I understand it VMs need to know because VFIO passes IOMMU grouping up into the VMs. So if a IOMMU grouping changes the VM's view of its PCIe topology changes. I think we even have to be cognizant of the fact the OS running on the VM may not even support hot-plug of PCI devices.
Alex:
Really? IOMMU groups are created by the kernel, so don't know how they would be passed into the VMs, unless indirectly via PCI(e) layout. At best, twiddling w/ACS enablement (emulation) would cause VMs to see different IOMMU groups, but again, VMs are not the security point/level, the host/HV's are.
Quoted 9 lines
Quoted 2 lines
Is there a thread I need to read up to explain /clear-up the thoughts above?
If you search for p2pdma you should find the previous discussions. Thanks for the input!
Stephen
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 6 lines · On Tue, 8 May 2018 19:06:17 -0400 Don Dutile <[email protected]> wrote:
Quoted 5 lines · Stephen Bates
As I understand it VMs need to know because VFIO passes IOMMU grouping up into the VMs. So if a IOMMU grouping changes the VM's view of its PCIe topology changes. I think we even have to be cognizant of the fact the OS running on the VM may not even support hot-plug of PCI devices.
Quoted 6 lines
Alex:
Really? IOMMU groups are created by the kernel, so don't know how they would be passed into the VMs, unless indirectly via PCI(e) layout. At best, twiddling w/ACS enablement (emulation) would cause VMs to see different IOMMU groups, but again, VMs are not the security point/level, the host/HV's are.
Correct, the VM has no concept of the host's IOMMU groups, only the hypervisor knows about the groups, but really only to the extent of which device belongs to which group and whether the group is viable. Any runtime change to grouping though would require DMA mapping updates, which I don't see how we can reasonably do with drivers, vfio-pci or native host drivers, bound to the affected devices. Thanks,
Alex
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
SGkgQWxleCBhbmQgRG9uDQoNCj4gICAgQ29ycmVjdCwgdGhlIFZNIGhhcyBubyBjb25jZXB0IG9m IHRoZSBob3N0J3MgSU9NTVUgZ3JvdXBzLCBvbmx5IHRoZQ0KPiAgIGh5cGVydmlzb3Iga25vd3Mg YWJvdXQgdGhlIGdyb3VwcywgDQoNCkJ1dCBhcyBJIHVuZGVyc3RhbmQgaXQgdGhlc2UgZ3JvdXBz IGFyZSB1c3VhbGx5IHBhc3NlZCB0aHJvdWdoIHRvIFZNcyBvbiBhIHByZS1ncm91cCBiYXNpcyBi eSB0aGUgaHlwZXJ2aXNvcj8gU28gSU9NTVUgZ3JvdXAgMSBtaWdodCBiZSBwYXNzZWQgdG8gVk0g QSBhbmQgSU9NTVUgZ3JvdXAgMiBwYXNzZWQgdG8gVk0gQi4gU28gSSBhZ3JlZSB0aGUgVk0gaXMg bm90IGF3YXJlIG9mIElPTU1VIGdyb3VwaW5ncyBidXQgaXQgaXMgaW1wYWN0ZWQgYnkgdGhlbSBp biB0aGUgc2Vuc2UgdGhhdCBpZiB0aGUgZ3JvdXBpbmdzIGNoYW5nZSB0aGUgUENJIHRvcG9sb2d5 IHByZXNlbnRlZCB0byB0aGUgVk0gbmVlZHMgdG8gY2hhbmdlIHRvby4NCg0KU3RlcGhlbg0KDQo=
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 11 lines · On Wed, 9 May 2018 12:35:56 +0000 "Stephen Bates" <[email protected]> wrote:
Hi Alex and Don
Quoted 2 lines
Correct, the VM has no concept of the host's IOMMU groups, only
the hypervisor knows about the groups,But as I understand it these groups are usually passed through to VMs on a pre-group basis by the hypervisor? So IOMMU group 1 might be passed to VM A and IOMMU group 2 passed to VM B. So I agree the VM is not aware of IOMMU groupings but it is impacted by them in the sense that if the groupings change the PCI topology presented to the VM needs to change too.
Hypervisors don't currently expose any topology based on the grouping, the only case where such a concept even makes sense is when a vIOMMU is present as devices within the same group cannot have separate address spaces. Our options for exposing such information is also limited, our only real option would seem to be placing devices within the same group together on a conventional PCI bus to denote the address space granularity. Currently we strongly recommend singleton groups for this case and leave any additional configuration constraints to the admin.
The case you note of a group passed to VM A and another passed to VM B is exactly an example of why any sort of dynamic routing change needs to have the groups fully released, such as via hot-unplug. For instance, a routing change at a shared node above groups 1 & 2 could result in the merging of these groups and there is absolutely no way to handle that with portions of the group being owned by two separate VMs after the merge. Thanks,
Alex
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
Quoted 32 lines · Alex Williamson
Quoted 11 lines · On Wed, 9 May 2018 12:35:56 +0000 "Stephen Bates" <[email protected]> wrote:
Hi Alex and Don
Quoted 2 lines
Correct, the VM has no concept of the host's IOMMU groups, only
the hypervisor knows about the groups,But as I understand it these groups are usually passed through to VMs on a pre-group basis by the hypervisor? So IOMMU group 1 might be passed to VM A and IOMMU group 2 passed to VM B. So I agree the VM is not aware of IOMMU groupings but it is impacted by them in the sense that if the groupings change the PCI topology presented to the VM needs to change too.
Hypervisors don't currently expose any topology based on the grouping, the only case where such a concept even makes sense is when a vIOMMU is present as devices within the same group cannot have separate address spaces. Our options for exposing such information is also limited, our only real option would seem to be placing devices within the same group together on a conventional PCI bus to denote the address space granularity. Currently we strongly recommend singleton groups for this case and leave any additional configuration constraints to the admin.
The case you note of a group passed to VM A and another passed to VM B is exactly an example of why any sort of dynamic routing change needs to have the groups fully released, such as via hot-unplug. For instance, a routing change at a shared node above groups 1 & 2 could result in the merging of these groups and there is absolutely no way to handle that with portions of the group being owned by two separate VMs after the merge. Thanks,
Quoted 2 lines
Alex
The above is why I stated the host/HV has to do p2p setup *before* device-assignment is done.
Now, that could be done at boot time (with a mod.conf-like config in host/HV, before VM startup) as well.
Dynamically, if such a feature is needed, requires a hot-unplug/plug cycling as Alex states.
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Alex WilliamsonQuoted 15 lines · Alex Williamson
Quoted 6 lines · On Tue, 8 May 2018 19:06:17 -0400 Don Dutile <[email protected]> wrote:
Quoted 5 lines · Stephen Bates
As I understand it VMs need to know because VFIO passes IOMMU grouping up into the VMs. So if a IOMMU grouping changes the VM's view of its PCIe topology changes. I think we even have to be cognizant of the fact the OS running on the VM may not even support hot-plug of PCI devices.
Quoted 6 lines
Alex:
Really? IOMMU groups are created by the kernel, so don't know how they would be passed into the VMs, unless indirectly via PCI(e) layout. At best, twiddling w/ACS enablement (emulation) would cause VMs to see different IOMMU groups, but again, VMs are not the security point/level, the host/HV's are.
Quoted 9 lines
Correct, the VM has no concept of the host's IOMMU groups, only the hypervisor knows about the groups, but really only to the extent of which device belongs to which group and whether the group is viable. Any runtime change to grouping though would require DMA mapping updates, which I don't see how we can reasonably do with drivers, vfio-pci or native host drivers, bound to the affected devices. Thanks,
Alex
A change in iommu groups would/could require a device remove/add cycle to get an updated DMA-mapping (yet-another-overused-term: iommu 'domain').
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
Re: [PATCH v4 04/14] PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
In reply to Stephen BatesQuoted 9 lines · Stephen Bates
Hi Don
Quoted 3 lines
Well, p2p DMA is a function of a cooperating 'agent' somewhere above the two devices.
That agent should 'request' to the kernel that ACS be removed/circumvented (p2p enabled) btwn two endpoints. I recommend doing so via a sysfs method.Yes we looked at something like this in the past but it does hit the IOMMU grouping issue I discussed earlier today which is not acceptable right now. In the long term, once we get IOMMU grouping callbacks to VMs we can look at extending p2pdma in this way. But I don't think this is viable for the initial series.
Quoted 8 lines
Quoted 1 line
So I don't understand the comments why VMs should need to know.
As I understand it VMs need to know because VFIO passes IOMMU grouping up into the VMs. So if a IOMMU grouping changes the VM's view of its PCIe topology changes. I think we even have to be cognizant of the fact the OS running on the VM may not even support hot-plug of PCI devices.
Quoted 1 line
Is there a thread I need to read up to explain /clear-up the thoughts above?
If you search for p2pdma you should find the previous discussions. Thanks for the input!
under linux-pci I'm assuming...
you cc'd a number of upstream lists; I picked this thread up via rdma-list.
Quoted 4 lines
Stephen
Logan Gunthorpe
maintainerPATCH v4 5/14 docs-rst: Add a new directory for PCI documentation
In reply to Logan GunthorpeAdd a new directory in the driver API guide for PCI specific documentation.
This is in preparation for adding a new PCI P2P DMA driver writers guide which will go in this directory.
---
Documentation/driver-api/index.rst | 2 +-
Documentation/driver-api/pci/index.rst | 19 +++++++++++++++++++
Documentation/driver-api/{ => pci}/pci.rst | 0
3 files changed, 20 insertions(+), 1 deletion(-)
create mode 100644 Documentation/driver-api/pci/index.rst
rename Documentation/driver-api/{ => pci}/pci.rst (100%)Documentation/driver-api/index.rst +1 -1
@@ -27,7 +27,7 @@ available subsections can be seen below. iio/index input usb/index - pci + pci/index spi i2c hsi
Documentation/driver-api/pci/index.rst new file +19 -0
@@ -0,0 +1,19 @@ +============================================ +The Linux PCI driver implementer's API guide +============================================ + +.. class:: toc-title + + Table of contents + +.. toctree:: + :maxdepth: 2 + + pci + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex`
Documentation/driver-api/pci/pci.rst renamed from Documentation/driver-api/pci.rst +0 -0
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 6/14 PCI/P2PDMA: Add P2P DMA driver writer's documentation
In reply to Logan GunthorpeAdd a restructured text file describing how to write drivers with support for P2P DMA transactions. The document describes how to use the APIs that were added in the previous few commits.
Also adds an index for the PCI documentation tree even though this is the only PCI document that has been converted to restructured text at this time.
--- Documentation/PCI/index.rst | 14 +++ Documentation/driver-api/pci/index.rst | 1 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++++++++++++++++++++++++++++ Documentation/index.rst | 3 +- 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 Documentation/PCI/index.rst create mode 100644 Documentation/driver-api/pci/p2pdma.rst
Documentation/PCI/index.rst new file +14 -0
@@ -0,0 +1,14 @@ +================================== +Linux PCI Driver Developer's Guide +================================== + +.. toctree:: + + p2pdma + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex`
Documentation/driver-api/pci/index.rst +1 -0
@@ -10,6 +10,7 @@ The Linux PCI driver implementer's API guide :maxdepth: 2 pci + p2pdma .. only:: subproject and html
Documentation/driver-api/pci/p2pdma.rst new file +166 -0
166 lines not on this page · raw message
Documentation/index.rst +2 -1
@@ -45,7 +45,7 @@ the kernel interface as seen by application developers. .. toctree:: :maxdepth: 2 - userspace-api/index + userspace-api/index Introduction to kernel development
@@ -89,6 +89,7 @@ needed). sound/index crypto/index filesystems/index + PCI/index Architecture-specific documentation -----------------------------------
Signature · 7 lines
2.11.0 _______________________________________________ Linux-nvme mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-nvme
Re: [PATCH v4 06/14] PCI/P2PDMA: Add P2P DMA driver writer's documentation
Quoted 58 lines · Logan Gunthorpe
Add a restructured text file describing how to write drivers with support for P2P DMA transactions. The document describes how to use the APIs that were added in the previous few commits.
Also adds an index for the PCI documentation tree even though this is the only PCI document that has been converted to restructured text at this time.
Signed-off-by Logan Gunthorpe <[email protected]>Cc Jonathan Corbet <[email protected]>--- Documentation/PCI/index.rst | 14 +++ Documentation/driver-api/pci/index.rst | 1 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++++++++++++++++++++++++++++ Documentation/index.rst | 3 +- 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 Documentation/PCI/index.rst create mode 100644 Documentation/driver-api/pci/p2pdma.rstDocumentation/PCI/index.rst new file +14
-0@@ -0,0 +1,14 @@ +================================== +Linux PCI Driver Developer's Guide +================================== + +.. toctree:: + + p2pdma + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex`Documentation/driver-api/pci/index.rst +1
-0@@ -10,6 +10,7 @@ The Linux PCI driver implementer's API guide :maxdepth: 2 pci + p2pdma .. only:: subproject and htmlDocumentation/driver-api/pci/p2pdma.rst new file +0
-0
Documentation/driver-api/pci/p2pdma.rst line 6
Quoted 6 lines
Documentation/driver-api/pci/p2pdma.rst new file +6
-0@@ -0,0 +1,166 @@ +============================ +PCI Peer-to-Peer DMA Support +============================ + +The PCI bus has pretty decent support for performing DMA transfers +between two endpoints on the bus. This type of transaction is
s/endpoints/devices/
Documentation/driver-api/pci/p2pdma.rst line 10
Quoted 4 lines
Documentation/driver-api/pci/p2pdma.rst new file +4
-0+henceforth called Peer-to-Peer (or P2P). However, there are a number of +issues that make P2P transactions tricky to do in a perfectly safe way. + +One of the biggest issues is that PCI Root Complexes are not required
s/PCI Root Complexes .../
PCI doesn't require forwarding transactions between hierarchy domains,
and in PCIe, each Root Port defines a separate hierarchy domain./
Documentation/driver-api/pci/p2pdma.rst line 17
Quoted 7 lines
Documentation/driver-api/pci/p2pdma.rst new file +7
-0+to support forwarding packets between Root Ports. To make things worse, +there is no simple way to determine if a given Root Complex supports +this or not. (See PCIe r4.0, sec 1.3.1). Therefore, as of this writing, +the kernel only supports doing P2P when the endpoints involved are all +behind the same PCIe root port as the spec guarantees that all +packets will always be routable but does not require routing between +root ports.
s/endpoints involved .../
devices involved are all behind the same PCI bridge, as such devices are all in the same PCI hierarchy domain, and the spec guarantees that all transactions within the hierarchy will be routable, but it does not require routing between hierarchies./
Quoted 6 lines
Documentation/driver-api/pci/p2pdma.rst new file +6
-0+ +The second issue is that to make use of existing interfaces in Linux, +memory that is used for P2P transactions needs to be backed by struct +pages. However, PCI BARs are not typically cache coherent so there are +a few corner case gotchas with these pages so developers need to +be careful about what they do with them.
Randy Dunlap
reviewerRe: [PATCH v4 06/14] PCI/P2PDMA: Add P2P DMA driver writer's documentation
In reply to Logan GunthorpeQuoted 49 lines · Logan Gunthorpe
Add a restructured text file describing how to write drivers with support for P2P DMA transactions. The document describes how to use the APIs that were added in the previous few commits.
Also adds an index for the PCI documentation tree even though this is the only PCI document that has been converted to restructured text at this time.
Signed-off-by Logan Gunthorpe <[email protected]>Cc Jonathan Corbet <[email protected]>--- Documentation/PCI/index.rst | 14 +++ Documentation/driver-api/pci/index.rst | 1 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++++++++++++++++++++++++++++ Documentation/index.rst | 3 +- 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 Documentation/PCI/index.rst create mode 100644 Documentation/driver-api/pci/p2pdma.rstDocumentation/driver-api/pci/p2pdma.rst new file +22
-0@@ -0,0 +1,166 @@ +============================ +PCI Peer-to-Peer DMA Support +============================ + +The PCI bus has pretty decent support for performing DMA transfers +between two endpoints on the bus. This type of transaction is +henceforth called Peer-to-Peer (or P2P). However, there are a number of +issues that make P2P transactions tricky to do in a perfectly safe way. + +One of the biggest issues is that PCI Root Complexes are not required +to support forwarding packets between Root Ports. To make things worse, +there is no simple way to determine if a given Root Complex supports +this or not. (See PCIe r4.0, sec 1.3.1). Therefore, as of this writing, +the kernel only supports doing P2P when the endpoints involved are all +behind the same PCIe root port as the spec guarantees that all +packets will always be routable but does not require routing between +root ports. + +The second issue is that to make use of existing interfaces in Linux, +memory that is used for P2P transactions needs to be backed by struct +pages. However, PCI BARs are not typically cache coherent so there are +a few corner case gotchas with these pages so developers need to
Documentation/driver-api/pci/p2pdma.rst line 32
Quoted 10 lines
Documentation/driver-api/pci/p2pdma.rst new file +10
-0+be careful about what they do with them. + + +Driver Writer's Guide +===================== + +In a given P2P implementation there may be three or more different +types of kernel drivers in play: + +* Providers - A driver which provides or publishes P2P resources like
* Provider -
Documentation/driver-api/pci/p2pdma.rst line 34
Quoted 2 lines
Documentation/driver-api/pci/p2pdma.rst new file +2
-0+ memory or doorbell registers to other drivers. +* Clients - A driver which makes use of a resource by setting up a
* Client -
Documentation/driver-api/pci/p2pdma.rst line 36
Quoted 2 lines
Documentation/driver-api/pci/p2pdma.rst new file +2
-0+ DMA transaction to or from it. +* Orchestrators - A driver which orchestrates the flow of data between
* Orchestrator -
Documentation/driver-api/pci/p2pdma.rst line 39
Quoted 3 lines
Documentation/driver-api/pci/p2pdma.rst new file +3
-0+ clients and providers + +In many cases there could be overlap between these three types (ie.
(i.e.,
Quoted 53 lines
Documentation/driver-api/pci/p2pdma.rst new file +53
-0+it may be typical for a driver to be both a provider and a client). + +For example, in the NVMe Target Copy Offload implementation: + +* The NVMe PCI driver is both a client, provider and orchestrator + in that it exposes any CMB (Controller Memory Buffer) as a P2P memory + resource (provider), it accepts P2P memory pages as buffers in requests + to be used directly (client) and it can also make use the CMB as + submission queue entries. +* The RDMA driver is a client in this arrangement so that an RNIC + can DMA directly to the memory exposed by the NVMe device. +* The NVMe Target driver (nvmet) can orchestrate the data from the RNIC + to the P2P memory (CMB) and then to the NVMe device (and vice versa). + +This is currently the only arrangement supported by the kernel but +one could imagine slight tweaks to this that would allow for the same +functionality. For example, if a specific RNIC added a BAR with some +memory behind it, its driver could add support as a P2P provider and +then the NVMe Target could use the RNIC's memory instead of the CMB +in cases where the NVMe cards in use do not have CMB support. + + +Provider Drivers +---------------- + +A provider simply needs to register a BAR (or a portion of a BAR) +as a P2P DMA resource using :c:func:`pci_p2pdma_add_resource()`. +This will register struct pages for all the specified memory. + +After that it may optionally publish all of its resources as +P2P memory using :c:func:`pci_p2pmem_publish()`. This will allow +any orchestrator drivers to find and use the memory. When marked in +this way, the resource must be regular memory with no side effects. + +For the time being this is fairly rudimentary in that all resources +are typically going to be P2P memory. Future work will likely expand +this to include other types of resources like doorbells. + + +Client Drivers +-------------- + +A client driver typically only has to conditionally change its DMA map +routine to use the mapping functions :c:func:`pci_p2pdma_map_sg()` and +:c:func:`pci_p2pdma_unmap_sg()` instead of the usual :c:func:`dma_map_sg()` +functions. + +The client may also, optionally, make use of +:c:func:`is_pci_p2pdma_page()` to determine when to use the P2P mapping +functions and when to use the regular mapping functions. In some +situations, it may be more appropriate to use a flag to indicate a +given request is P2P memory and map appropriately (for example the +block layer uses a flag to keep P2P memory out of queues that do not
Documentation/driver-api/pci/p2pdma.rst line 102
Quoted 10 lines
Documentation/driver-api/pci/p2pdma.rst new file +10
-0+have P2P client support). It is important to ensure that struct pages that +back P2P memory stay out of code that does not have support for them. + + +Orchestrator Drivers +-------------------- + +The first task an orchestrator driver must do is compile a list of +all client drivers that will be involved in a given transaction. For +example, the NVMe Target driver creates a list including all NVMe drives
^^^^^^
or drivers ?
Could be either, I guess, but the previous sentence says "compile a list of drivers."
Documentation/driver-api/pci/p2pdma.rst line 114
Quoted 12 lines
Documentation/driver-api/pci/p2pdma.rst new file +12
-0+and the RNIC in use. The list is stored as an anonymous struct +list_head which must be initialized with the usual INIT_LIST_HEAD. +The following functions may then be used to add to, remove from and free +the list of clients with the functions :c:func:`pci_p2pdma_add_client()`, +:c:func:`pci_p2pdma_remove_client()` and +:c:func:`pci_p2pdma_client_list_free()`. + +With the client list in hand, the orchestrator may then call +:c:func:`pci_p2pmem_find()` to obtain a published P2P memory provider +that is supported (behind the same root port) as all the clients. If more +than one provider is supported, the one nearest to all the clients will +be chosen first. If there are more than one provider is an equal distance
there is
Quoted 4 lines
Documentation/driver-api/pci/p2pdma.rst new file +4
-0+away, the one returned will be chosen at random. This function returns the PCI +device to use for the provider with a reference taken and therefore +when it's no longer needed it should be returned with pci_dev_put(). +
Documentation/driver-api/pci/p2pdma.rst line 128
Quoted 10 lines
Documentation/driver-api/pci/p2pdma.rst new file +10
-0+Alternatively, if the orchestrator knows (via some other means) +which provider it wants to use it may use :c:func:`pci_has_p2pmem()` +to determine if it has P2P memory and :c:func:`pci_p2pdma_distance()` +to determine the cumulative distance between it and a potential +list of clients. + +With a supported provider in hand, the driver can then call +:c:func:`pci_p2pdma_assign_provider()` to assign the provider +to the client list. This function returns false if any of the +clients are unsupported by the provider.
[I would say:]
is unsupported
Quoted 38 lines
Documentation/driver-api/pci/p2pdma.rst new file +38
-0+ +Once a provider is assigned to a client list via either +:c:func:`pci_p2pmem_find()` or :c:func:`pci_p2pdma_assign_provider()`, +the list is permanently bound to the provider such that any new clients +added to the list must be supported by the already selected provider. +If they are not supported, :c:func:`pci_p2pdma_add_client()` will return +an error. In this way, orchestrators are free to add and remove devices +without having to recheck support or tear down existing transfers to +change P2P providers. + +Once a provider is selected, the orchestrator can then use +:c:func:`pci_alloc_p2pmem()` and :c:func:`pci_free_p2pmem()` to +allocate P2P memory from the provider. :c:func:`pci_p2pmem_alloc_sgl()` +and :c:func:`pci_p2pmem_free_sgl()` are convenience functions for +allocating scatter-gather lists with P2P memory. + +Struct Page Caveats +------------------- + +Driver writers should be very careful about not passing these special +struct pages to code that isn't prepared for it. At this time, the kernel +interfaces do not have any checks for ensuring this. This obviously +precludes passing these pages to userspace. + +P2P memory is also technically IO memory but should never have any side +effects behind it. Thus, the order of loads and stores should not be important +and ioreadX(), iowriteX() and friends should not be necessary. +However, as the memory is not cache coherent, if access ever needs to +be protected by a spinlock then :c:func:`mmiowb()` must be used before +unlocking the lock. (See ACQUIRES VS I/O ACCESSES in +Documentation/memory-barriers.txt) + + +P2P DMA Support Library +===================== + +.. kernel-doc:: drivers/pci/p2pdma.c + :export:
Signature · 1 line
~Randy
Logan Gunthorpe
maintainerRe: [PATCH v4 06/14] PCI/P2PDMA: Add P2P DMA driver writer's documentation
Thanks for the review Randy! I'll make the changes for the next time we post the series.
Quoted 6 lines · Randy Dunlap
Documentation/driver-api/pci/p2pdma.rst line 102
Quoted 3 lines
Documentation/driver-api/pci/p2pdma.rst new file +3
-0+The first task an orchestrator driver must do is compile a list of +all client drivers that will be involved in a given transaction. For +example, the NVMe Target driver creates a list including all NVMe drives^^^^^^
or drivers ?
Could be either, I guess, but the previous sentence says "compile a list of drivers."
I did mean "drives". But perhaps "devices" would be more clear. A list of all NVMe drivers doesn't make much sense as I'm pretty sure there is only one NVMe driver.
Logan
Logan Gunthorpe
maintainerPATCH v4 7/14 block: Introduce PCI P2P flags for request and request queue
In reply to Logan GunthorpeQUEUE_FLAG_PCI_P2P is introduced meaning a driver's request queue supports targeting P2P memory.
REQ_PCI_P2P is introduced to indicate a particular bio request is directed to/from PCI P2P memory. A request with this flag is not accepted unless the corresponding queues have the QUEUE_FLAG_PCI_P2P flag set.
--- block/blk-core.c | 3 +++ include/linux/blk_types.h | 18 +++++++++++++++++- include/linux/blkdev.h | 3 +++ 3 files changed, 23 insertions(+), 1 deletion(-)
block/blk-core.c +3 -0
@@ -2270,6 +2270,9 @@ generic_make_request_checks(struct bio *bio)if ((bio->bi_opf &REQ_NOWAIT ) && !queue_is_rq_based (q)) goto not_supported; +if ((bio->bi_opf &REQ_PCI_P2PDMA ) && !blk_queue_pci_p2pdma (q)) + goto not_supported; +if (should_fail_bio (bio)) goto end_io;
include/linux/blk_types.h +17 -1
@@ -279,6 +279,10 @@ enum req_flag_bits { __REQ_BACKGROUND, /* background IO */ __REQ_NOWAIT, /* Don't wait if request will block */ +#ifdef CONFIG_PCI_P2PDMA + __REQ_PCI_P2PDMA,/* request is to/from P2P memory */ +#endif +/* command specific flags for REQ_OP_WRITE_ZEROES: */ __REQ_NOUNMAP, /* do not free blocks when zeroing */
@@ -303,6 +307,18 @@ enum req_flag_bits {#define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)#define REQ_NOWAIT (1ULL << __REQ_NOWAIT) +#ifdef CONFIG_PCI_P2PDMA +/* +* Currently SGLs do not support mixed P2P and regular memory so +* requests with P2P memory must not be merged. +*/ +#define REQ_PCI_P2PDMA (1ULL << __REQ_PCI_P2PDMA) +#define REQ_IS_PCI_P2PDMA (req) ((req)->cmd_flags & REQ_PCI_P2PDMA) +#else +#define REQ_PCI_P2PDMA 0 +#define REQ_IS_PCI_P2PDMA (req) 0 +#endif /* CONFIG_PCI_P2PDMA */ +#define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP)#define REQ_DRV (1ULL << __REQ_DRV)
@@ -311,7 +327,7 @@ enum req_flag_bits { (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)#define REQ_NOMERGE_FLAGS \ - (REQ_NOMERGE | REQ_PREFLUSH | REQ_FUA) + (REQ_NOMERGE | REQ_PREFLUSH | REQ_FUA | REQ_PCI_P2PDMA)#define bio_op (bio) \ ((bio)->bi_opf & REQ_OP_MASK)
include/linux/blkdev.h +3 -0
@@ -698,6 +698,7 @@ struct request_queue {#define QUEUE_FLAG_SCSI_PASSTHROUGH 27/* queue supports SCSI commands */ #define QUEUE_FLAG_QUIESCED 28/* queue has been quiesced */ #define QUEUE_FLAG_PREEMPT_ONLY 29/* only process REQ_PREEMPT requests */ +#define QUEUE_FLAG_PCI_P2PDMA 30/* device supports pci p2p requests */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_SAME_COMP) | \
@@ -730,6 +731,8 @@ bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q);#define blk_queue_dax (q) test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags)#define blk_queue_scsi_passthrough (q) \ test_bit(QUEUE_FLAG_SCSI_PASSTHROUGH, &(q)->queue_flags) +#define blk_queue_pci_p2pdma (q) \ + test_bit(QUEUE_FLAG_PCI_P2PDMA, &(q)->queue_flags)#define blk_noretry_request (rq) \ ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 8/14 IB/core: Ensure we map P2P memory correctly in rdma_rw_ctx_[init|destroy]()
In reply to Logan GunthorpeIn order to use PCI P2P memory pci_p2pmem_[un]map_sg() functions must be called to map the correct PCI bus address.
To do this, check the first page in the scatter list to see if it is P2P memory or not. At the moment, scatter lists that contain P2P memory must be homogeneous so if the first page is P2P the entire SGL should be P2P.
--- drivers/infiniband/core/rw.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/infiniband/core/rw.c +11 -2
@@ -12,6 +12,7 @@*/ #include <linux/moduleparam.h> #include <linux/slab.h> +#include <linux/pci-p2pdma.h> #include <rdma/mr_pool.h> #include <rdma/rw.h>
@@ -280,7 +281,11 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,struct ib_device *dev = qp->pd->device;int ret; - ret =ib_dma_map_sg (dev, sg, sg_cnt, dir); +if (is_pci_p2pdma_page (sg_page (sg))) + ret =pci_p2pdma_map_sg (dev->dma_device, sg, sg_cnt, dir); +else + ret =ib_dma_map_sg (dev, sg, sg_cnt, dir); +if (!ret)return -ENOMEM ; sg_cnt = ret;
@@ -602,7 +607,11 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,break ; } -ib_dma_unmap_sg (qp->pd->device, sg, sg_cnt, dir); +if (is_pci_p2pdma_page (sg_page (sg))) +pci_p2pdma_unmap_sg (qp->pd->device->dma_device, sg, + sg_cnt, dir); +else +ib_dma_unmap_sg (qp->pd->device, sg, sg_cnt, dir); }EXPORT_SYMBOL (rdma_rw_ctx_destroy);
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 9/14 nvme-pci: Use PCI p2pmem subsystem to manage the CMB
In reply to Logan GunthorpeRegister the CMB buffer as p2pmem and use the appropriate allocation functions to create and destroy the IO submission queues.
If the CMB supports WDS and RDS, publish it for use as P2P memory by other devices.
We can now drop the __iomem safety on the buffer seeing that, by convention, devm_memremap_pages() allocates regular memory without side effects that's accessible without the iomem accessors.
--- drivers/nvme/host/pci.c | 75 +++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 34 deletions(-)
drivers/nvme/host/pci.c +41 -34
@@ -29,6 +29,7 @@#include <linux/types.h> #include <linux/io-64-nonatomic-lo-hi.h> #include <linux/sed-opal.h> +#include <linux/pci-p2pdma.h> #include "nvme.h"
@@ -92,9 +93,8 @@ struct nvme_dev {struct work_struct remove_work;struct mutex shutdown_lock;bool subsystem; -void __iomem *cmb; -pci_bus_addr_t cmb_bus_addr;u64 cmb_size; +bool cmb_use_sqes;u32 cmbsz;u32 cmbloc;struct nvme_ctrl ctrl;
@@ -149,7 +149,7 @@ struct nvme_queue {struct nvme_dev *dev;spinlock_t q_lock;struct nvme_command *sq_cmds; -struct nvme_command __iomem *sq_cmds_io; +bool sq_cmds_is_io;volatile struct nvme_completion *cqes;struct blk_mq_tags **tags;dma_addr_t sq_dma_addr;
@@ -431,10 +431,7 @@ static void __nvme_submit_cmd(struct nvme_queue *nvmeq, {u16 tail = nvmeq->sq_tail; -if (nvmeq->sq_cmds_io) -memcpy_toio (&nvmeq->sq_cmds_io[tail], cmd,sizeof (*cmd)); -else -memcpy (&nvmeq->sq_cmds[tail], cmd,sizeof (*cmd)); +memcpy (&nvmeq->sq_cmds[tail], cmd,sizeof (*cmd));if (++tail == nvmeq->q_depth) tail =0 ;
@@ -1289,9 +1286,18 @@ static void nvme_free_queue(struct nvme_queue *nvmeq) {dma_free_coherent (nvmeq->q_dmadev,CQ_SIZE (nvmeq->q_depth), (void *)nvmeq->cqes, nvmeq->cq_dma_addr); -if (nvmeq->sq_cmds) -dma_free_coherent (nvmeq->q_dmadev,SQ_SIZE (nvmeq->q_depth), - nvmeq->sq_cmds, nvmeq->sq_dma_addr); + +if (nvmeq->sq_cmds) { +if (nvmeq->sq_cmds_is_io) +pci_free_p2pmem (to_pci_dev (nvmeq->q_dmadev), + nvmeq->sq_cmds, +SQ_SIZE (nvmeq->q_depth)); +else +dma_free_coherent (nvmeq->q_dmadev, +SQ_SIZE (nvmeq->q_depth), + nvmeq->sq_cmds, + nvmeq->sq_dma_addr); + } }static void nvme_free_queues (struct nvme_dev *dev,int lowest)
@@ -1371,12 +1377,21 @@ static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues,static int nvme_alloc_sq_cmds (struct nvme_dev *dev,struct nvme_queue *nvmeq,int qid,int depth) { -/* CMB SQEs will be mapped before creation */ -if (qid && dev->cmb && use_cmb_sqes && (dev->cmbsz &NVME_CMBSZ_SQS )) -return 0 ; +struct pci_dev *pdev =to_pci_dev (dev->dev); + +if (qid && dev->cmb_use_sqes && (dev->cmbsz &NVME_CMBSZ_SQS )) { + nvmeq->sq_cmds =pci_alloc_p2pmem (pdev,SQ_SIZE (depth)); + nvmeq->sq_dma_addr =pci_p2pmem_virt_to_bus (pdev, + nvmeq->sq_cmds); + nvmeq->sq_cmds_is_io = true; + } + +if (!nvmeq->sq_cmds) { + nvmeq->sq_cmds =dma_alloc_coherent (dev->dev,SQ_SIZE (depth), + &nvmeq->sq_dma_addr,GFP_KERNEL ); + nvmeq->sq_cmds_is_io = false; + } - nvmeq->sq_cmds =dma_alloc_coherent (dev->dev,SQ_SIZE (depth), - &nvmeq->sq_dma_addr,GFP_KERNEL );if (!nvmeq->sq_cmds)return -ENOMEM ;return 0 ;
@@ -1451,13 +1466,6 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)struct nvme_dev *dev = nvmeq->dev;int result; -if (dev->cmb && use_cmb_sqes && (dev->cmbsz &NVME_CMBSZ_SQS )) { -unsigned offset = (qid -1 ) *roundup (SQ_SIZE (nvmeq->q_depth), - dev->ctrl.page_size); - nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset; - nvmeq->sq_cmds_io = dev->cmb + offset; - } -/* * A queue's vector matches the queue identifier unless the controller * has only one vector available.
@@ -1691,9 +1699,6 @@ static void nvme_map_cmb(struct nvme_dev *dev)return ; dev->cmbloc =readl (dev->bar +NVME_REG_CMBLOC ); -if (!use_cmb_sqes) -return ; - size =nvme_cmb_size_unit (dev) *nvme_cmb_size (dev); offset =nvme_cmb_size_unit (dev) *NVME_CMB_OFST (dev->cmbloc); bar =NVME_CMB_BIR (dev->cmbloc);
@@ -1710,11 +1715,15 @@ static void nvme_map_cmb(struct nvme_dev *dev)if (size > bar_size - offset) size = bar_size - offset; - dev->cmb =ioremap_wc (pci_resource_start (pdev, bar) + offset, size); -if (!dev->cmb) +if (pci_p2pdma_add_resource (pdev, bar, size, offset))return ; - dev->cmb_bus_addr =pci_bus_address (pdev, bar) + offset; + dev->cmb_size = size; + dev->cmb_use_sqes = use_cmb_sqes && (dev->cmbsz &NVME_CMBSZ_SQS ); + +if ((dev->cmbsz & (NVME_CMBSZ_WDS |NVME_CMBSZ_RDS )) == + (NVME_CMBSZ_WDS |NVME_CMBSZ_RDS )) +pci_p2pmem_publish (pdev, true);if (sysfs_add_file_to_group (&dev->ctrl.device->kobj, &dev_attr_cmb.attr,NULL ))
@@ -1724,12 +1733,10 @@ static void nvme_map_cmb(struct nvme_dev *dev)static inline void nvme_release_cmb (struct nvme_dev *dev) { -if (dev->cmb) { -iounmap (dev->cmb); - dev->cmb =NULL ; +if (dev->cmb_size) {sysfs_remove_file_from_group (&dev->ctrl.device->kobj, &dev_attr_cmb.attr,NULL ); - dev->cmbsz =0 ; + dev->cmb_size =0 ; } }
@@ -1928,13 +1935,13 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)if (nr_io_queues ==0 )return 0 ; -if (dev->cmb && (dev->cmbsz &NVME_CMBSZ_SQS )) { +if (dev->cmb_use_sqes) { result =nvme_cmb_qdepth (dev, nr_io_queues,sizeof (struct nvme_command ));if (result >0 ) dev->q_depth = result;else -nvme_release_cmb (dev); + dev->cmb_use_sqes = false; } do {
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 10/14 nvme-pci: Add support for P2P memory in requests
In reply to Logan GunthorpeFor P2P requests, we must use the pci_p2pmem_[un]map_sg() functions instead of the dma_map_sg functions.
With that, we can then indicate PCI_P2P support in the request queue. For this, we create an NVME_F_PCI_P2P flag which tells the core to set QUEUE_FLAG_PCI_P2P in the request queue.
--- drivers/nvme/host/core.c | 4 ++++ drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/pci.c | 19 +++++++++++++++---- 3 files changed, 20 insertions(+), 4 deletions(-)
drivers/nvme/host/core.c +4 -0
@@ -2977,7 +2977,11 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) ns->queue =blk_mq_init_queue (ctrl->tagset);if (IS_ERR (ns->queue)) goto out_free_ns; +blk_queue_flag_set (QUEUE_FLAG_NONROT , ns->queue); +if (ctrl->ops->flags &NVME_F_PCI_P2PDMA ) +blk_queue_flag_set (QUEUE_FLAG_PCI_P2PDMA , ns->queue); + ns->queue->queuedata = ns; ns->ctrl = ctrl;
drivers/nvme/host/nvme.h +1 -0
@@ -306,6 +306,7 @@ struct nvme_ctrl_ops {unsigned int flags;#define NVME_F_FABRICS (1 << 0)#define NVME_F_METADATA_SUPPORTED (1 << 1) +#define NVME_F_PCI_P2PDMA (1 << 2)int (*reg_read32)(struct nvme_ctrl *ctrl,u32 off,u32 *val);int (*reg_write32)(struct nvme_ctrl *ctrl,u32 off,u32 val);int (*reg_read64)(struct nvme_ctrl *ctrl,u32 off,u64 *val);
drivers/nvme/host/pci.c +15 -4
@@ -798,8 +798,13 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, goto out; ret =BLK_STS_RESOURCE ; - nr_mapped =dma_map_sg_attrs (dev->dev, iod->sg, iod->nents, dma_dir, -DMA_ATTR_NO_WARN ); + +if (REQ_IS_PCI_P2PDMA (req)) + nr_mapped =pci_p2pdma_map_sg (dev->dev, iod->sg, iod->nents, + dma_dir); +else + nr_mapped =dma_map_sg_attrs (dev->dev, iod->sg, iod->nents, + dma_dir,DMA_ATTR_NO_WARN );if (!nr_mapped) goto out;
@@ -844,7 +849,12 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req) DMA_TO_DEVICE :DMA_FROM_DEVICE ;if (iod->nents) { -dma_unmap_sg (dev->dev, iod->sg, iod->nents, dma_dir); +if (REQ_IS_PCI_P2PDMA (req)) +pci_p2pdma_unmap_sg (dev->dev, iod->sg, iod->nents, + dma_dir); +else +dma_unmap_sg (dev->dev, iod->sg, iod->nents, dma_dir); +if (blk_integrity_rq (req)) {if (req_op (req) ==REQ_OP_READ )nvme_dif_remap (req, nvme_dif_complete);
@@ -2439,7 +2449,8 @@ static int nvme_pci_get_address(struct nvme_ctrl *ctrl, char *buf, int size)static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = { .name ="pcie" , .module =THIS_MODULE , - .flags =NVME_F_METADATA_SUPPORTED , + .flags =NVME_F_METADATA_SUPPORTED | +NVME_F_PCI_P2PDMA , .reg_read32 = nvme_pci_reg_read32, .reg_write32 = nvme_pci_reg_write32, .reg_read64 = nvme_pci_reg_read64,
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 11/14 nvme-pci: Add a quirk for a pseudo CMB
In reply to Logan GunthorpeIntroduce a quirk to use CMB-like memory on older devices that have an exposed BAR but do not advertise support for using CMBLOC and CMBSIZE.
We'd like to use some of these older cards to test P2P memory.
--- drivers/nvme/host/nvme.h | 7 +++++++ drivers/nvme/host/pci.c | 24 ++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-)
drivers/nvme/host/nvme.h +7 -0
@@ -84,6 +84,13 @@ enum nvme_quirks {* Supports the LighNVM command set if indicated in vs[1]. */ NVME_QUIRK_LIGHTNVM = (1 <<6 ), + +/* +* Pseudo CMB Support on BAR 4. For adapters like the Microsemi +* NVRAM that have CMB-like memory on a BAR but does not set +* CMBLOC or CMBSZ. +*/ + NVME_QUIRK_PSEUDO_CMB_BAR4 = (1 << 7), };/*
drivers/nvme/host/pci.c +20 -4
@@ -1685,6 +1685,13 @@ static ssize_t nvme_cmb_show(struct device *dev, } static DEVICE_ATTR(cmb, S_IRUGO, nvme_cmb_show, NULL); +static u32 nvme_pseudo_cmbsz (struct pci_dev *pdev,int bar) +{ +return NVME_CMBSZ_WDS |NVME_CMBSZ_RDS | + (((ilog2 (SZ_16M ) -12 ) /4 ) <<NVME_CMBSZ_SZU_SHIFT ) | + ((pci_resource_len (pdev, bar) /SZ_16M ) <<NVME_CMBSZ_SZ_SHIFT ); +} +static u64 nvme_cmb_size_unit (struct nvme_dev *dev) {u8 szu = (dev->cmbsz >>NVME_CMBSZ_SZU_SHIFT ) &NVME_CMBSZ_SZU_MASK ;
@@ -1704,10 +1711,15 @@ static void nvme_map_cmb(struct nvme_dev *dev)struct pci_dev *pdev =to_pci_dev (dev->dev);int bar; - dev->cmbsz =readl (dev->bar +NVME_REG_CMBSZ ); -if (!dev->cmbsz) -return ; - dev->cmbloc =readl (dev->bar +NVME_REG_CMBLOC ); +if (dev->ctrl.quirks &NVME_QUIRK_PSEUDO_CMB_BAR4 ) { + dev->cmbsz =nvme_pseudo_cmbsz (pdev,4 ); + dev->cmbloc =4 ; + }else { + dev->cmbsz =readl (dev->bar +NVME_REG_CMBSZ ); +if (!dev->cmbsz) +return ; + dev->cmbloc =readl (dev->bar +NVME_REG_CMBLOC ); + } size =nvme_cmb_size_unit (dev) *nvme_cmb_size (dev); offset =nvme_cmb_size_unit (dev) *NVME_CMB_OFST (dev->cmbloc);
@@ -2736,6 +2748,10 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_LIGHTNVM, }, { PCI_DEVICE(0x1d1d, 0x2807), /* CNEX WL */ .driver_data = NVME_QUIRK_LIGHTNVM, }, + { PCI_DEVICE(0x11f8, 0xf117), /* Microsemi NVRAM adaptor */ + .driver_data = NVME_QUIRK_PSEUDO_CMB_BAR4, }, + { PCI_DEVICE(0x1db1, 0x0002), /* Everspin nvNitro adaptor */ + .driver_data = NVME_QUIRK_PSEUDO_CMB_BAR4, }, { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 12/14 nvmet: Introduce helper functions to allocate and free request SGLs
In reply to Logan GunthorpeAdd helpers to allocate and free the SGL in a struct nvmet_req:
int nvmet_req_alloc_sgl(struct nvmet_req *req, struct nvmet_sq *sq) void nvmet_req_free_sgl(struct nvmet_req *req)
This will be expanded in a future patch to implement peer-to-peer memory DMAs and should be common with all target drivers. The presently unused 'sq' argument in the alloc function will be necessary to decide whether to use peer-to-peer memory and obtain the correct provider to allocate the memory.
--- drivers/nvme/target/core.c | 18 ++++++++++++++++++ drivers/nvme/target/nvmet.h | 2 ++ 2 files changed, 20 insertions(+)
drivers/nvme/target/core.c +18 -0
@@ -575,6 +575,24 @@ void nvmet_req_execute(struct nvmet_req *req) }EXPORT_SYMBOL_GPL (nvmet_req_execute); +int nvmet_req_alloc_sgl (struct nvmet_req *req,struct nvmet_sq *sq) +{ + req->sg =sgl_alloc (req->transfer_len,GFP_KERNEL , &req->sg_cnt); +if (!req->sg) +return -ENOMEM ; + +return 0 ; +} +EXPORT_SYMBOL_GPL (nvmet_req_alloc_sgl); + +void nvmet_req_free_sgl (struct nvmet_req *req) +{ +sgl_free (req->sg); + req->sg =NULL ; + req->sg_cnt =0 ; +} +EXPORT_SYMBOL_GPL (nvmet_req_free_sgl); +static inline bool nvmet_cc_en (u32 cc) {return (cc >>NVME_CC_EN_SHIFT ) &0x1 ;
drivers/nvme/target/nvmet.h +2 -0
@@ -273,6 +273,8 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,void nvmet_req_uninit (struct nvmet_req *req);void nvmet_req_execute (struct nvmet_req *req);void nvmet_req_complete (struct nvmet_req *req,u16 status); +int nvmet_req_alloc_sgl (struct nvmet_req *req,struct nvmet_sq *sq); +void nvmet_req_free_sgl (struct nvmet_req *req);void nvmet_cq_setup (struct nvmet_ctrl *ctrl,struct nvmet_cq *cq,u16 qid,u16 size);
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 13/14 nvmet-rdma: Use new SGL alloc/free helper for requests
In reply to Logan GunthorpeUse the new helpers introduced in the previous patch to allocate the SGLs for the request.
Seeing we use req.transfer_len as the length of the SGL it is set earlier and cleared on any error. It also seems to be unnecessary to accumulate the length as the map_sgl functions should only ever be called once.
--- drivers/nvme/target/rdma.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
drivers/nvme/target/rdma.c +12 -8
@@ -430,7 +430,7 @@ static void nvmet_rdma_release_rsp(struct nvmet_rdma_rsp *rsp) }if (rsp->req.sg != &rsp->cmd->inline_sg) -sgl_free (rsp->req.sg); +nvmet_req_free_sgl (&rsp->req);if (unlikely (!list_empty_careful (&queue->rsp_wr_wait_list)))nvmet_rdma_process_wr_wait_list (queue);
@@ -564,24 +564,24 @@ static u16 nvmet_rdma_map_sgl_keyed(struct nvmet_rdma_rsp *rsp, {struct rdma_cm_id *cm_id = rsp->queue->cm_id;u64 addr =le64_to_cpu (sgl->addr); -u32 len =get_unaligned_le24 (sgl->length);u32 key =get_unaligned_le32 (sgl->key);int ret; + rsp->req.transfer_len =get_unaligned_le24 (sgl->length); +/* no data command? */ -if (!len) +if (!rsp->req.transfer_len)return 0 ; - rsp->req.sg =sgl_alloc (len,GFP_KERNEL , &rsp->req.sg_cnt); -if (!rsp->req.sg) -return NVME_SC_INTERNAL ; + ret =nvmet_req_alloc_sgl (&rsp->req, &rsp->queue->nvme_sq); +if (ret <0 ) + goto error_out; ret =rdma_rw_ctx_init (&rsp->rw, cm_id->qp, cm_id->port_num, rsp->req.sg, rsp->req.sg_cnt,0 , addr, key,nvmet_data_dir (&rsp->req));if (ret <0 ) -return NVME_SC_INTERNAL ; - rsp->req.transfer_len += len; + goto error_out; rsp->n_rdma += ret;if (invalidate) {
@@ -590,6 +590,10 @@ static u16 nvmet_rdma_map_sgl_keyed(struct nvmet_rdma_rsp *rsp, }return 0 ; + +error_out: + rsp->req.transfer_len =0 ; +return NVME_SC_INTERNAL ; }static u16 nvmet_rdma_map_sgl (struct nvmet_rdma_rsp *rsp)
Signature · 1 line
2.11.0
Logan Gunthorpe
maintainerPATCH v4 14/14 nvmet: Optionally use PCI P2P memory
In reply to Logan GunthorpeWe create a configfs attribute in each nvme-fabrics target port to enable p2p memory use. When enabled, the port will only then use the p2p memory if a p2p memory device can be found which is behind the same switch heirarchy as the RDMA port and all the block devices in use. If the user enabled it and no devices are found, then the system will silently fall back on using regular memory.
If appropriate, that port will allocate memory for the RDMA buffers for queues from the p2pmem device falling back to system memory should anything fail.
Ideally, we'd want to use an NVME CMB buffer as p2p memory. This would save an extra PCI transfer as the NVME card could just take the data out of it's own memory. However, at this time, only a limited number of cards with CMB buffers seem to be available.
--- drivers/nvme/target/configfs.c | 67 ++++++++++++++++++++++ drivers/nvme/target/core.c | 127 ++++++++++++++++++++++++++++++++++++++++- drivers/nvme/target/io-cmd.c | 3 + drivers/nvme/target/nvmet.h | 13 +++++ drivers/nvme/target/rdma.c | 2 + 5 files changed, 210 insertions(+), 2 deletions(-)
drivers/nvme/target/configfs.c +67 -0
@@ -17,6 +17,8 @@#include <linux/slab.h> #include <linux/stat.h> #include <linux/ctype.h> +#include <linux/pci.h> +#include <linux/pci-p2pdma.h> #include "nvmet.h"
@@ -864,12 +866,77 @@ static void nvmet_port_release(struct config_item *item)kfree (port); } +#ifdef CONFIG_PCI_P2PDMA +static ssize_t nvmet_p2pmem_show (struct config_item *item,char *page) +{ +struct nvmet_port *port =to_nvmet_port (item); + +if (!port->use_p2pmem) +return sprintf (page,"none\n" ); + +if (!port->p2p_dev) +return sprintf (page,"auto\n" ); + +return sprintf (page,"%s\n" ,pci_name (port->p2p_dev)); +} + +static ssize_t nvmet_p2pmem_store (struct config_item *item, +const char *page,size_t count) +{ +struct nvmet_port *port =to_nvmet_port (item); +struct device *dev; +struct pci_dev *p2p_dev =NULL ; +bool use_p2pmem; + + dev =bus_find_device_by_name (&pci_bus_type,NULL , page); +if (dev) { + use_p2pmem = true; + p2p_dev =to_pci_dev (dev); + +if (!pci_has_p2pmem (p2p_dev)) { +pr_err ("PCI device has no peer-to-peer memory: %s\n" , + page); +pci_dev_put (p2p_dev); +return -ENODEV ; + } + }else if (sysfs_streq (page,"auto" )) { + use_p2pmem =1 ; + }else if ((page[0 ] =='0' || page[0 ] =='1' ) && !iscntrl (page[1 ])) { +/* +* If the user enters a PCI device that doesn't exist +* like "0000:01:00.1", we don't want strtobool to think +* it's a '0' when it's clearly not what the user wanted. +* So we require 0's and 1's to be exactly one character. +*/ + goto no_such_pci_device; + }else if (strtobool (page, &use_p2pmem)) { + goto no_such_pci_device; + } + +down_write (&nvmet_config_sem); + port->use_p2pmem = use_p2pmem; +pci_dev_put (port->p2p_dev); + port->p2p_dev = p2p_dev; +up_write (&nvmet_config_sem); + +return count; + +no_such_pci_device: +pr_err ("No such PCI device: %s\n" , page); +return -ENODEV ; +} +CONFIGFS_ATTR (nvmet_, p2pmem); +#endif /* CONFIG_PCI_P2PDMA */ +static struct configfs_attribute *nvmet_port_attrs[] = { &nvmet_attr_addr_adrfam, &nvmet_attr_addr_treq, &nvmet_attr_addr_traddr, &nvmet_attr_addr_trsvcid, &nvmet_attr_addr_trtype, +#ifdef CONFIG_PCI_P2PDMA + &nvmet_attr_p2pmem, +#endifNULL , };
drivers/nvme/target/core.c +125 -2
194 lines not on this page · raw message
drivers/nvme/target/io-cmd.c +3 -0
@@ -56,6 +56,9 @@ static void nvmet_execute_rw(struct nvmet_req *req) op =REQ_OP_READ ; } +if (is_pci_p2pdma_page (sg_page (req->sg))) + op_flags |=REQ_PCI_P2PDMA ; + sector =le64_to_cpu (req->cmd->rw.slba); sector <<= (req->ns->blksize_shift -9 );
drivers/nvme/target/nvmet.h +13 -0
@@ -64,6 +64,11 @@ static inline struct nvmet_ns *to_nvmet_ns(struct config_item *item) return container_of(to_config_group(item), struct nvmet_ns, group); } +static inline struct device *nvmet_ns_dev (struct nvmet_ns *ns) +{ +return disk_to_dev (ns->bdev->bd_disk); +} +struct nvmet_cq {u16 qid;u16 size;
@@ -98,6 +103,8 @@ struct nvmet_port {struct list_head referrals;void *priv;bool enabled; +bool use_p2pmem; +struct pci_dev *p2p_dev; };static inline struct nvmet_port *to_nvmet_port (struct config_item *item)
@@ -132,6 +139,9 @@ struct nvmet_ctrl {const struct nvmet_fabrics_ops *ops; +struct pci_dev *p2p_dev; +struct list_head p2p_clients; +char subsysnqn[NVMF_NQN_FIELD_LEN ];char hostnqn[NVMF_NQN_FIELD_LEN ]; };
@@ -234,6 +244,9 @@ struct nvmet_req {void (*execute)(struct nvmet_req *req);const struct nvmet_fabrics_ops *ops; + +struct pci_dev *p2p_dev; +struct device *p2p_client; };static inline void nvmet_set_status (struct nvmet_req *req,u16 status)
drivers/nvme/target/rdma.c +2 -0
@@ -661,6 +661,8 @@ static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue, cmd->send_sge.addr, cmd->send_sge.length, DMA_TO_DEVICE); + cmd->req.p2p_client = &queue->dev->device->dev; +if (!nvmet_req_init (&cmd->req, &queue->nvme_cq, &queue->nvme_sq, &nvmet_rdma_ops))return ;
Signature · 1 line
2.11.0
Hi Logan,
it would be rather nice to have if you could separate out the functions to detect if peer2peer is possible between two devices.
That would allow me to reuse the same logic for GPU peer2peer where I don't really have ZONE_DEVICE.
Regards,
Christian.
Am 24.04.2018 um 01:30 schrieb Logan Gunthorpe:
Quoted 206 lines
Hi Everyone,
Here's v4 of our series to introduce P2P based copy offload to NVMe fabrics. This version has been rebased onto v4.17-rc2. A git repo is here:
https://github.com/sbates130272/linux-p2pmem pci-p2p-v4
Thanks,
Logan
Changes in v4:
* Change the original
upstream_bridges_match()function toupstream_bridge_distance()which calculates the distance between two devices as long as they are behind the same root port. This should address Bjorn's concerns that the code was to focused on being behind a single switch.* The disable ACS function now disables ACS for all bridge ports instead of switch ports (ie. those that had two
upstream_bridgeports).* Change the
pci_p2pmem_alloc_sgl()andpci_p2pmem_free_sgl()API to be more likesgl_alloc()in that the alloc function returns the allocated scatterlist and nents is not required bythe free function.* Moved the new documentation into the driver-api tree as requested by Jonathan
* Add SGL alloc and free helpers in the nvmet code so that the individual drivers can share the code that allocates P2P memory. As requested by Christoph.
* Cleanup the
nvmet_p2pmem_store()function as Christoph thought my first attempt was ugly.* Numerous commit message and comment fix-ups
Changes in v3:
* Many more fixes and minor cleanups that were spotted by Bjorn
* Additional explanation of the ACS change in both the commit message and
Kconfigdoc. Also, the code that disables the ACS bits is surrounded explicitly by an #ifdef* Removed the flag we added to
rdma_rw_ctx()in favour of usingis_pci_p2pdma_page(), as suggested by Sagi.* Adjust
pci_p2pmem_find()so that it prefers P2P providers that are closest to (or the same as) the clients using them. In cases of ties, the provider is randomly chosen.* Modify the NVMe Target code so that the PCI device name of the provider may be explicitly specified, bypassing the logic in
pci_p2pmem_find(). (Note: it's still enforced that the provider must be behind the same switch as the clients).* As requested by Bjorn, added documentation for driver writers.
Changes in v2:
* Renamed everything to 'p2pdma' per the suggestion from Bjorn as well as a bunch of cleanup and spelling fixes he pointed out in the last series.
* To address Alex's ACS concerns, we change to a simpler method of just disabling ACS behind switches for any kernel that has
CONFIG_PCI_P2PDMA.* We also reject using devices that employ '
dma_virt_ops' which should fairly simply handle Jason's concerns that this work might break with the HFI, QIB and rxe drivers that use the virtual ops to implement their own special DMA operations.--
This is a continuation of our work to enable using Peer-to-Peer PCI memory in the kernel with initial support for the NVMe fabrics target subsystem. Many thanks go to Christoph Hellwig who provided valuable feedback to get these patches to where they are today.
The concept here is to use memory that's exposed on a PCI BAR as data buffers in the NVMe target code such that data can be transferred from an RDMA NIC to the special memory and then directly to an NVMe device avoiding system memory entirely. The upside of this is better QoS for applications running on the CPU utilizing memory and lower PCI bandwidth required to the CPU (such that systems could be designed with fewer lanes connected to the CPU).
Due to these trade-offs we've designed the system to only enable using the PCI memory in cases where the NIC, NVMe devices and memory are all behind the same PCI switch hierarchy. This will mean many setups that could likely work well will not be supported so that we can be more confident it will work and not place any responsibility on the user to understand their topology. (We chose to go this route based on feedback we received at the last LSF). Future work may enable these transfers using a white list of known good root complexes. However, at this time, there is no reliable way to ensure that Peer-to-Peer transactions are permitted between PCI Root Ports.
In order to enable this functionality, we introduce a few new PCI functions such that a driver can register P2P memory with the system. Struct pages are created for this memory using
devm_memremap_pages()and the PCI bus offset is stored in the corresponding pagemap structure.When the PCI P2PDMA config option is selected the ACS bits in every bridge port in the system are turned off to allow traffic to pass freely behind the root port. At this time, the bit must be disabled at boot so the IOMMU subsystem can correctly create the groups, though this could be addressed in the future. There is no way to dynamically disable the bit and alter the groups.
Another set of functions allow a client driver to create a list of client devices that will be used in a given P2P transactions and then use that list to find any P2P memory that is supported by all the client devices.
In the block layer, we also introduce a P2P request flag to indicate a given request targets P2P memory as well as a flag for a request queue to indicate a given queue supports targeting P2P memory. P2P requests will only be accepted by queues that support it. Also, P2P requests are marked to not be merged seeing a non-homogenous request would complicate the DMA mapping requirements.
In the PCI NVMe driver, we modify the existing CMB support to utilize the new PCI P2P memory infrastructure and also add support for P2P memory in its request queue. When a P2P request is received it uses the
pci_p2pmem_map_sg()function which applies the necessary transformation to get the correntpci_bus_addr_tfor the DMA transactions.In the RDMA core, we also adjust
rdma_rw_ctx_init()andrdma_rw_ctx_destroy()to take a flags argument which indicates whether to use the PCI P2P mapping functions or not. To avoid odd RDMA devices that don't use the proper DMA infrastructure this code rejects using any device that employs thevirt_dma_opsimplementation.Finally, in the NVMe fabrics target port we introduce a new configuration boolean: '
allow_p2pmem'. When set, the port will attempt to find P2P memory supported by the RDMA NIC and all namespaces. If supported memory is found, it will be used in all IO transfers. And if a port is using P2P memory, adding new namespaces that are not supported by that memory will fail.These patches have been tested on a number of Intel based systems and for a variety of RDMA NICs (Mellanox, Broadcomm, Chelsio) and NVMe SSDs (Intel, Seagate, Samsung) and p2pdma devices (Eideticom, Microsemi, Chelsio and Everspin) using switches from both Microsemi and Broadcomm.
Logan Gunthorpe (14):
PCI/P2PDMA: Support peer-to-peer memory
PCI/P2PDMA: Add sysfs group to display p2pmem stats PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
docs-rst: Add a new directory for PCI documentation PCI/P2PDMA: Add P2P DMA driver writer's documentation
block: Introduce PCI P2P flags for request and request queue IB/core: Ensure we map P2P memory correctly inrdma_rw_ctx_[init|destroy]()nvme-pci: Use PCI p2pmem subsystem to manage the CMB
nvme-pci: Add support for P2P memory in requests
nvme-pci: Add a quirk for a pseudo CMB
nvmet: Introduce helper functions to allocate and free request SGLs
nvmet-rdma: Use new SGL alloc/free helper for requests
nvmet: Optionally use PCI P2P memoryDocumentation/ABI/testing/sysfs-bus-pci | 25 + Documentation/PCI/index.rst | 14 + Documentation/driver-api/index.rst | 2 +- Documentation/driver-api/pci/index.rst | 20 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++ Documentation/driver-api/{ => pci}/pci.rst | 0 Documentation/index.rst | 3 +- block/blk-core.c | 3 + drivers/infiniband/core/rw.c | 13 +- drivers/nvme/host/core.c | 4 + drivers/nvme/host/nvme.h | 8 + drivers/nvme/host/pci.c | 118 +++-- drivers/nvme/target/configfs.c | 67 +++ drivers/nvme/target/core.c | 143 ++++- drivers/nvme/target/io-cmd.c | 3 + drivers/nvme/target/nvmet.h | 15 + drivers/nvme/target/rdma.c | 22 +- drivers/pci/Kconfig | 26 + drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 814 +++++++++++++++++++++++++++++ drivers/pci/pci.c | 6 + include/linux/blk_types.h | 18 +- include/linux/blkdev.h | 3 + include/linux/memremap.h | 19 + include/linux/pci-p2pdma.h | 118 +++++ include/linux/pci.h | 4 + 26 files changed, 1579 insertions(+), 56 deletions(-)create mode 100644
Documentation/PCI/index.rstcreate mode 100644Documentation/driver-api/pci/index.rstcreate mode 100644Documentation/driver-api/pci/p2pdma.rstrenameDocumentation/driver-api/{=>pci}/pci.rst(100%) create mode 100644drivers/pci/p2pdma.c
create mode 100644include/linux/pci-p2pdma.h--
2.11.0
Logan Gunthorpe
maintainerHi Christian,
Quoted 1 line · Christian König
it would be rather nice to have if you could separate out the functions to detect if peer2peer is possible between two devices.
This would essentially be pci_p2pdma_distance() in the existing patchset. It returns the sum of the distance between a list of clients and a P2PDMA provider. It returns -1 if peer2peer is not possible between the devices (presently this means they are not behind the same root port).
Logan
Am 02.05.2018 um 17:56 schrieb Logan Gunthorpe:
Quoted 6 lines
Hi Christian,
Quoted 1 line · Christian König
it would be rather nice to have if you could separate out the functions to detect if peer2peer is possible between two devices.
This would essentially be
pci_p2pdma_distance()in the existing patchset. It returns the sum of the distance between a list of clients and a P2PDMA provider. It returns -1 if peer2peer is not possible between the devices (presently this means they are not behind the same root port).
Ok, I'm still missing the big picture here. First question is what is the P2PDMA provider?
Second question is how to you want to handle things when device are not behind the same root port (which is perfectly possible in the cases I deal with)?
Third question why multiple clients? That feels a bit like you are pushing something special to your use case into the common PCI subsystem. Something which usually isn't a good idea.
As far as I can see we need a function which return the distance between a initiator and target device. This function then returns -1 if the transaction can't be made and a positive value otherwise.
We also need to give the direction of the transaction and have a whitelist root complex PCI-IDs which can handle P2P transactions from different ports for a certain DMA direction.
Christian.
Quoted 2 lines
Logan
Logan Gunthorpe
maintainerQuoted 2 lines · Christian König
Ok, I'm still missing the big picture here. First question is what is the P2PDMA provider?
Well there's some pretty good documentation in the patchset for this, but in short, a provider is a device that provides some kind of P2P resource (ie. BAR memory, or perhaps a doorbell register -- only memory is supported at this time).
Quoted 3 lines
Second question is how to you want to handle things when device are not behind the same root port (which is perfectly possible in the cases I deal with)?
I think we need to implement a whitelist. If both root ports are in the white list and are on the same bus then we return a larger distance instead of -1.
Quoted 3 lines
Third question why multiple clients? That feels a bit like you are pushing something special to your use case into the common PCI subsystem. Something which usually isn't a good idea.
No, I think this will be pretty standard. In the simple general case you are going to have one provider and at least two clients (one which writes the memory and one which reads it). However, one client is likely, but not necessarily, the same as the provider.
In the NVMeof case, we might have N clients: 1 RDMA device and N-1 block devices. The code doesn't care which device provides the memory as it could be the RDMA device or one/all of the block devices (or, in theory, a completely separate device with P2P-able memory). However, it does require that all devices involved are accessible per pci_p2pdma_distance() or it won't use P2P transactions.
I could also imagine other use cases: ie. an RDMA NIC sends data to a GPU for processing and then sends the data to an NVMe device for storage (or vice-versa). In this case we have 3 clients and one provider.
Quoted 3 lines
As far as I can see we need a function which return the distance between a initiator and target device. This function then returns -1 if the transaction can't be made and a positive value otherwise.
If you need to make a simpler convenience function for your use case I'm not against it.
Quoted 3 lines
We also need to give the direction of the transaction and have a whitelist root complex PCI-IDs which can handle P2P transactions from different ports for a certain DMA direction.
Yes. In the NVMeof case we need all devices to be able to DMA in both directions so we did not need the DMA direction. But I can see this being useful once we add the whitelist.
Logan
Am 03.05.2018 um 17:59 schrieb Logan Gunthorpe:
Quoted 7 lines · Christian König
Quoted 3 lines
Second question is how to you want to handle things when device are not behind the same root port (which is perfectly possible in the cases I deal with)?
I think we need to implement a whitelist. If both root ports are in the white list and are on the same bus then we return a larger distance instead of -1.
Sounds good.
Quoted 7 lines
Quoted 3 lines
Third question why multiple clients? That feels a bit like you are pushing something special to your use case into the common PCI subsystem. Something which usually isn't a good idea.
No, I think this will be pretty standard. In the simple general case you are going to have one provider and at least two clients (one which writes the memory and one which reads it). However, one client is likely, but not necessarily, the same as the provider.
Ok, that is the point where I'm stuck. Why do we need that in one function call in the PCIe subsystem?
The problem at least with GPUs is that we seriously don't have that information here, cause the PCI subsystem might not be aware of all the interconnections.
For example it isn't uncommon to put multiple GPUs on one board. To the PCI subsystem that looks like separate devices, but in reality all GPUs are interconnected and can access each others memory directly without going over the PCIe bus.
I seriously don't want to model that in the PCI subsystem, but rather the driver. That's why it feels like a mistake to me to push all that into the PCI function.
Quoted 10 lines
In the NVMeof case, we might have N clients: 1 RDMA device and N-1 block devices. The code doesn't care which device provides the memory as it could be the RDMA device or one/all of the block devices (or, in theory, a completely separate device with P2P-able memory). However, it does require that all devices involved are accessible per
pci_p2pdma_distance()or it won't use P2P transactions.I could also imagine other use cases: ie. an RDMA NIC sends data to a GPU for processing and then sends the data to an NVMe device for storage (or vice-versa). In this case we have 3 clients and one provider.
Why can't we model that as two separate transactions?
E.g. one from the RDMA NIC to the GPU memory. And another one from the GPU memory to the NVMe device.
That would also match how I get this information from userspace.
Quoted 5 lines
Quoted 3 lines
As far as I can see we need a function which return the distance between a initiator and target device. This function then returns -1 if the transaction can't be made and a positive value otherwise.
If you need to make a simpler convenience function for your use case I'm not against it.
Yeah, same for me. If Bjorn is ok with that specialized NVM functions that I'm fine with that as well.
I think it would just be more convenient when we can come up with functions which can handle all use cases, cause there still seems to be a lot of similarities.
Quoted 7 lines
Quoted 4 lines
We also need to give the direction of the transaction and have a whitelist root complex PCI-IDs which can handle P2P transactions from different ports for a certain DMA direction.
Yes. In the NVMeof case we need all devices to be able to DMA in both directions so we did not need the DMA direction. But I can see this being useful once we add the whitelist.
Ok, I agree that can be added later on. For simplicity let's assume for now we always to bidirectional transfers.
Thanks for the explanation,
Christian.
Quoted 2 lines
Logan
Logan Gunthorpe
maintainerQuoted 7 lines · Christian König
Ok, that is the point where I'm stuck. Why do we need that in one function call in the PCIe subsystem?
The problem at least with GPUs is that we seriously don't have that information here, cause the PCI subsystem might not be aware of all the interconnections.
Quoted 8 lines
For example it isn't uncommon to put multiple GPUs on one board. To the PCI subsystem that looks like separate devices, but in reality all GPUs are interconnected and can access each others memory directly without going over the PCIe bus.
I seriously don't want to model that in the PCI subsystem, but rather the driver. That's why it feels like a mistake to me to push all that into the PCI function.
Huh? I'm lost. If you have a bunch of PCI devices you can send them as a list to this API, if you want. If the driver is _sure_ they are all the same, you only have to send one. In your terminology, you'd just have to call the interface with:
pci_p2pdma_distance(target, [initiator, target])
Quoted 1 line
Why can't we model that as two separate transactions?
You could, but this is more convenient for users of the API that need to deal with multiple devices (and manage devices that may be added or removed at any time).
Quoted 6 lines
Yeah, same for me. If Bjorn is ok with that specialized NVM functions that I'm fine with that as well.
I think it would just be more convenient when we can come up with functions which can handle all use cases, cause there still seems to be a lot of similarities.
The way it's implemented is more general and can handle all use cases. You are arguing for a function that can handle your case (albeit with a bit more fuss) but can't handle mine and is therefore less general. Calling my interface specialized is wrong.
Logan
Am 03.05.2018 um 20:43 schrieb Logan Gunthorpe:
Quoted 17 lines · Christian König
Quoted 7 lines
Ok, that is the point where I'm stuck. Why do we need that in one function call in the PCIe subsystem?
The problem at least with GPUs is that we seriously don't have that information here, cause the PCI subsystem might not be aware of all the interconnections.
Quoted 8 lines
For example it isn't uncommon to put multiple GPUs on one board. To the PCI subsystem that looks like separate devices, but in reality all GPUs are interconnected and can access each others memory directly without going over the PCIe bus.
I seriously don't want to model that in the PCI subsystem, but rather the driver. That's why it feels like a mistake to me to push all that into the PCI function.
Quoted 6 lines
Huh? I'm lost. If you have a bunch of PCI devices you can send them as a list to this API, if you want. If the driver is _sure_ they are all the same, you only have to send one. In your terminology, you'd just have to call the interface with:
pci_p2pdma_distance(target, [initiator, target])
Ok, I expected that something like that would do it.
So just to confirm: When I have a bunch of GPUs which could be the initiator I only need to do "pci_p2pdma_distance(target, [first GPU, target]);" and not "pci_p2pdma_distance(target, [first GPU, second GPU, third GPU, forth...., target])" ?
Quoted 4 lines
Quoted 1 line
Why can't we model that as two separate transactions?
You could, but this is more convenient for users of the API that need to deal with multiple devices (and manage devices that may be added or removed at any time).
Are you sure that this is more convenient? At least on first glance it feels overly complicated.
I mean what's the difference between the two approaches?
sum = pci_p2pdma_distance(target, [A, B, C, target]);
and
sum = pci_p2pdma_distance(target, A);
sum += pci_p2pdma_distance(target, B);
sum += pci_p2pdma_distance(target, C);
Quoted 10 lines
Quoted 6 lines
Yeah, same for me. If Bjorn is ok with that specialized NVM functions that I'm fine with that as well.
I think it would just be more convenient when we can come up with functions which can handle all use cases, cause there still seems to be a lot of similarities.
The way it's implemented is more general and can handle all use cases. You are arguing for a function that can handle your case (albeit with a bit more fuss) but can't handle mine and is therefore less general. Calling my interface specialized is wrong.
Well at the end of the day you only need to convince Bjorn of the interface, so I'm perfectly fine with it as long as it serves my use case as well :)
But I still would like to understand your intention, cause that really helps not to accidentally break something in the long term.
Now when I take a look at the pure PCI hardware level, what I have is a transaction between an initiator and a target, and not multiple devices in one operation.
I mean you must have a very good reason that you now want to deal with multiple devices in the software layer, but neither from the code nor from your explanation that reason becomes obvious to me.
Thanks,
Christian.
Quoted 2 lines
Logan
Logan Gunthorpe
maintainerQuoted 5 lines · Christian König
Are you sure that this is more convenient? At least on first glance it feels overly complicated.
I mean what's the difference between the two approaches?
Quoted 7 lines
sum =
pci_p2pdma_distance(target, [A, B, C, target]);and
sum =
pci_p2pdma_distance(target, A);
sum +=pci_p2pdma_distance(target, B);
sum +=pci_p2pdma_distance(target, C);
Well, it's more for consistency with the pci_p2pdma_find() which has to take a list of devices to find a resource which matches all of them. (You can't use multiple calls in that case because all the devices in the list might not have the same set of compatible providers.) That way we can use the same list to check the distance (when the user specifies a device) as we do to find a compatible device (when the user wants to automatically find one.
Logan
Quoted 51 lines · Logan Gunthorpe
Hi Everyone,
Here's v4 of our series to introduce P2P based copy offload to NVMe fabrics. This version has been rebased onto v4.17-rc2. A git repo is here:
https://github.com/sbates130272/linux-p2pmem pci-p2p-v4
...Logan Gunthorpe (14):
PCI/P2PDMA: Support peer-to-peer memory
PCI/P2PDMA: Add sysfs group to display p2pmem stats PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
docs-rst: Add a new directory for PCI documentation PCI/P2PDMA: Add P2P DMA driver writer's documentation
block: Introduce PCI P2P flags for request and request queue IB/core: Ensure we map P2P memory correctly inrdma_rw_ctx_[init|destroy]()nvme-pci: Use PCI p2pmem subsystem to manage the CMB
nvme-pci: Add support for P2P memory in requests
nvme-pci: Add a quirk for a pseudo CMB
nvmet: Introduce helper functions to allocate and free request SGLs
nvmet-rdma: Use new SGL alloc/free helper for requests
nvmet: Optionally use PCI P2P memoryDocumentation/ABI/testing/sysfs-bus-pci | 25 + Documentation/PCI/index.rst | 14 + Documentation/driver-api/index.rst | 2 +- Documentation/driver-api/pci/index.rst | 20 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++ Documentation/driver-api/{ => pci}/pci.rst | 0 Documentation/index.rst | 3 +- block/blk-core.c | 3 + drivers/infiniband/core/rw.c | 13 +- drivers/nvme/host/core.c | 4 + drivers/nvme/host/nvme.h | 8 + drivers/nvme/host/pci.c | 118 +++-- drivers/nvme/target/configfs.c | 67 +++ drivers/nvme/target/core.c | 143 ++++- drivers/nvme/target/io-cmd.c | 3 + drivers/nvme/target/nvmet.h | 15 + drivers/nvme/target/rdma.c | 22 +- drivers/pci/Kconfig | 26 + drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 814 +++++++++++++++++++++++++++++ drivers/pci/pci.c | 6 + include/linux/blk_types.h | 18 +- include/linux/blkdev.h | 3 + include/linux/memremap.h | 19 + include/linux/pci-p2pdma.h | 118 +++++
Quoted 8 lines
include/linux/pci.h | 4 +
26 files changed, 1579 insertions(+), 56 deletions(-)
create mode 100644 Documentation/PCI/index.rst
create mode 100644 Documentation/driver-api/pci/index.rst
create mode 100644 Documentation/driver-api/pci/p2pdma.rst
rename Documentation/driver-api/{ => pci}/pci.rst (100%)
create mode 100644 drivers/pci/p2pdma.c
create mode 100644 include/linux/pci-p2pdma.hHow do you envison merging this? There's a big chunk in drivers/pci, but really no opportunity for conflicts there, and there's significant stuff in block and nvme that I don't really want to merge.
If Alex is OK with the ACS situation, I can ack the PCI parts and you could merge it elsewhere?
Bjorn
Logan Gunthorpe
maintainerQuoted 7 lines
How do you envison merging this? There's a big chunk in
drivers/pci, but really no opportunity for conflicts there, and there's significant stuff in block and nvme that I don't really want to merge.If Alex is OK with the ACS situation, I can ack the PCI parts and you could merge it elsewhere?
Honestly, I don't know. I guess with your ACK on the PCI parts, the vast balance is NVMe stuff so we could look at merging it through that tree. The block patch and IB patch are pretty small.
Thanks,
Logan
Quoted 61 lines · On Mon, 7 May 2018 18:23:46 -0500 Bjorn Helgaas <[email protected]> wrote:
Quoted 51 lines · Logan Gunthorpe
Hi Everyone,
Here's v4 of our series to introduce P2P based copy offload to NVMe fabrics. This version has been rebased onto v4.17-rc2. A git repo is here:
https://github.com/sbates130272/linux-p2pmem pci-p2p-v4
...Logan Gunthorpe (14):
PCI/P2PDMA: Support peer-to-peer memory
PCI/P2PDMA: Add sysfs group to display p2pmem stats PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
docs-rst: Add a new directory for PCI documentation PCI/P2PDMA: Add P2P DMA driver writer's documentation
block: Introduce PCI P2P flags for request and request queue IB/core: Ensure we map P2P memory correctly inrdma_rw_ctx_[init|destroy]()nvme-pci: Use PCI p2pmem subsystem to manage the CMB
nvme-pci: Add support for P2P memory in requests
nvme-pci: Add a quirk for a pseudo CMB
nvmet: Introduce helper functions to allocate and free request SGLs
nvmet-rdma: Use new SGL alloc/free helper for requests
nvmet: Optionally use PCI P2P memoryDocumentation/ABI/testing/sysfs-bus-pci | 25 + Documentation/PCI/index.rst | 14 + Documentation/driver-api/index.rst | 2 +- Documentation/driver-api/pci/index.rst | 20 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++ Documentation/driver-api/{ => pci}/pci.rst | 0 Documentation/index.rst | 3 +- block/blk-core.c | 3 + drivers/infiniband/core/rw.c | 13 +- drivers/nvme/host/core.c | 4 + drivers/nvme/host/nvme.h | 8 + drivers/nvme/host/pci.c | 118 +++-- drivers/nvme/target/configfs.c | 67 +++ drivers/nvme/target/core.c | 143 ++++- drivers/nvme/target/io-cmd.c | 3 + drivers/nvme/target/nvmet.h | 15 + drivers/nvme/target/rdma.c | 22 +- drivers/pci/Kconfig | 26 + drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 814 +++++++++++++++++++++++++++++ drivers/pci/pci.c | 6 + include/linux/blk_types.h | 18 +- include/linux/blkdev.h | 3 + include/linux/memremap.h | 19 + include/linux/pci-p2pdma.h | 118 +++++Quoted 8 lines
include/linux/pci.h | 4 + 26 files changed, 1579 insertions(+), 56 deletions(-) create mode 100644 Documentation/PCI/index.rst create mode 100644 Documentation/driver-api/pci/index.rst create mode 100644 Documentation/driver-api/pci/p2pdma.rst rename Documentation/driver-api/{ => pci}/pci.rst (100%) create mode 100644 drivers/pci/p2pdma.c create mode 100644 include/linux/pci-p2pdma.h
Quoted 6 lines
How do you envison merging this? There's a big chunk in
drivers/pci, but really no opportunity for conflicts there, and there's significant stuff in block and nvme that I don't really want to merge.If Alex is OK with the ACS situation, I can ack the PCI parts and you could merge it elsewhere?
AIUI from previously questioning this, the change is hidden behind a build-time config option and only custom kernels or distros optimized for this sort of support would enable that build option. I'm more than a little dubious though that we're not going to have a wave of distros enabling this only to get user complaints that they can no longer make effective use of their devices for assignment due to the resulting span of the IOMMU groups, nor is there any sort of compromise, configure the kernel for p2p or device assignment, not both. Is this really such a unique feature that distro users aren't going to be asking for both features? Thanks,
Alex
Logan Gunthorpe
maintainerQuoted 10 lines · Alex Williamson
AIUI from previously questioning this, the change is hidden behind a build-time config option and only custom kernels or distros optimized for this sort of support would enable that build option. I'm more than a little dubious though that we're not going to have a wave of distros enabling this only to get user complaints that they can no longer make effective use of their devices for assignment due to the resulting span of the IOMMU groups, nor is there any sort of compromise, configure the kernel for p2p or device assignment, not both. Is this really such a unique feature that distro users aren't going to be asking for both features? Thanks,
I think it is. But it sounds like the majority want this to be a command line option. So we will look at doing that for v5.
Logan
Quoted 82 lines · Alex Williamson
Quoted 61 lines · On Mon, 7 May 2018 18:23:46 -0500 Bjorn Helgaas <[email protected]> wrote:
Quoted 53 lines · Logan Gunthorpe
Hi Everyone,
Here's v4 of our series to introduce P2P based copy offload to NVMe fabrics. This version has been rebased onto v4.17-rc2. A git repo is here:
https://github.com/sbates130272/linux-p2pmem pci-p2p-v4
...Logan Gunthorpe (14):
PCI/P2PDMA: Support peer-to-peer memory
PCI/P2PDMA: Add sysfs group to display p2pmem stats PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
docs-rst: Add a new directory for PCI documentation PCI/P2PDMA: Add P2P DMA driver writer's documentation
block: Introduce PCI P2P flags for request and request queue IB/core: Ensure we map P2P memory correctly inrdma_rw_ctx_[init|destroy]()nvme-pci: Use PCI p2pmem subsystem to manage the CMB
nvme-pci: Add support for P2P memory in requests
nvme-pci: Add a quirk for a pseudo CMB
nvmet: Introduce helper functions to allocate and free request SGLs
nvmet-rdma: Use new SGL alloc/free helper for requests
nvmet: Optionally use PCI P2P memoryDocumentation/ABI/testing/sysfs-bus-pci | 25 + Documentation/PCI/index.rst | 14 + Documentation/driver-api/index.rst | 2 +- Documentation/driver-api/pci/index.rst | 20 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++ Documentation/driver-api/{ => pci}/pci.rst | 0 Documentation/index.rst | 3 +- block/blk-core.c | 3 + drivers/infiniband/core/rw.c | 13 +- drivers/nvme/host/core.c | 4 + drivers/nvme/host/nvme.h | 8 + drivers/nvme/host/pci.c | 118 +++-- drivers/nvme/target/configfs.c | 67 +++ drivers/nvme/target/core.c | 143 ++++- drivers/nvme/target/io-cmd.c | 3 + drivers/nvme/target/nvmet.h | 15 + drivers/nvme/target/rdma.c | 22 +- drivers/pci/Kconfig | 26 + drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 814 +++++++++++++++++++++++++++++ drivers/pci/pci.c | 6 + include/linux/blk_types.h | 18 +- include/linux/blkdev.h | 3 + include/linux/memremap.h | 19 + include/linux/pci-p2pdma.h | 118 +++++ include/linux/pci.h | 4 + 26 files changed, 1579 insertions(+), 56 deletions(-)Quoted 6 lines
create mode 100644
Documentation/PCI/index.rstcreate mode 100644Documentation/driver-api/pci/index.rstcreate mode 100644Documentation/driver-api/pci/p2pdma.rstrenameDocumentation/driver-api/{=>pci}/pci.rst(100%) create mode 100644drivers/pci/p2pdma.c
create mode 100644include/linux/pci-p2pdma.hQuoted 6 lines
How do you envison merging this? There's a big chunk in
drivers/pci, but really no opportunity for conflicts there, and there's significant stuff in block and nvme that I don't really want to merge.If Alex is OK with the ACS situation, I can ack the PCI parts and you could merge it elsewhere?
AIUI from previously questioning this, the change is hidden behind a build-time config option and only custom kernels or distros optimized for this sort of support would enable that build option. I'm more than a little dubious though that we're not going to have a wave of distros enabling this only to get user complaints that they can no longer make effective use of their devices for assignment due to the resulting span of the IOMMU groups, nor is there any sort of compromise, configure the kernel for p2p or device assignment, not both. Is this really such a unique feature that distro users aren't going to be asking for both features? Thanks,
Quoted 1 line
Alex
At least 1/2 the cases presented to me by existing customers want it in a tunable kernel,
and tunable btwn two points, if the hw allows it to be 'contained' in that manner, which
a (layer of) switch(ing) provides.
To me, that means a kernel cmdline parameter to _enable_, and another sysfs (configfs? ... i'm not a configfs afficionato to say which is best), method to make two points p2p dma capable.
Worse case, the whole system is one large IOMMU group (current mindset of this static or run-time config option),
or best case (over time, more hw), a secure set of the primary system with p2p-enabled sections, that are deemed 'safe' or 'self-inflicting-unsecure', the latter the case of today's VM with an assigned device -- can scribble all over the VM, but no other VM and not the host/HV.
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 83 lines · On Tue, 8 May 2018 17:25:24 -0400 Don Dutile <[email protected]> wrote:
Quoted 82 lines · Alex Williamson
Quoted 61 lines · On Mon, 7 May 2018 18:23:46 -0500 Bjorn Helgaas <[email protected]> wrote:
Quoted 53 lines · Logan Gunthorpe
Hi Everyone,
Here's v4 of our series to introduce P2P based copy offload to NVMe fabrics. This version has been rebased onto v4.17-rc2. A git repo is here:
https://github.com/sbates130272/linux-p2pmem pci-p2p-v4
...Logan Gunthorpe (14):
PCI/P2PDMA: Support peer-to-peer memory
PCI/P2PDMA: Add sysfs group to display p2pmem stats PCI/P2PDMA: Add PCI p2pmem dma mappings to adjust the bus offset PCI/P2PDMA: Clear ACS P2P flags for all devices behind switches
docs-rst: Add a new directory for PCI documentation PCI/P2PDMA: Add P2P DMA driver writer's documentation
block: Introduce PCI P2P flags for request and request queue IB/core: Ensure we map P2P memory correctly inrdma_rw_ctx_[init|destroy]()nvme-pci: Use PCI p2pmem subsystem to manage the CMB
nvme-pci: Add support for P2P memory in requests
nvme-pci: Add a quirk for a pseudo CMB
nvmet: Introduce helper functions to allocate and free request SGLs
nvmet-rdma: Use new SGL alloc/free helper for requests
nvmet: Optionally use PCI P2P memoryDocumentation/ABI/testing/sysfs-bus-pci | 25 + Documentation/PCI/index.rst | 14 + Documentation/driver-api/index.rst | 2 +- Documentation/driver-api/pci/index.rst | 20 + Documentation/driver-api/pci/p2pdma.rst | 166 ++++++ Documentation/driver-api/{ => pci}/pci.rst | 0 Documentation/index.rst | 3 +- block/blk-core.c | 3 + drivers/infiniband/core/rw.c | 13 +- drivers/nvme/host/core.c | 4 + drivers/nvme/host/nvme.h | 8 + drivers/nvme/host/pci.c | 118 +++-- drivers/nvme/target/configfs.c | 67 +++ drivers/nvme/target/core.c | 143 ++++- drivers/nvme/target/io-cmd.c | 3 + drivers/nvme/target/nvmet.h | 15 + drivers/nvme/target/rdma.c | 22 +- drivers/pci/Kconfig | 26 + drivers/pci/Makefile | 1 + drivers/pci/p2pdma.c | 814 +++++++++++++++++++++++++++++ drivers/pci/pci.c | 6 + include/linux/blk_types.h | 18 +- include/linux/blkdev.h | 3 + include/linux/memremap.h | 19 + include/linux/pci-p2pdma.h | 118 +++++ include/linux/pci.h | 4 + 26 files changed, 1579 insertions(+), 56 deletions(-)Quoted 6 lines
create mode 100644
Documentation/PCI/index.rstcreate mode 100644Documentation/driver-api/pci/index.rstcreate mode 100644Documentation/driver-api/pci/p2pdma.rstrenameDocumentation/driver-api/{=>pci}/pci.rst(100%) create mode 100644drivers/pci/p2pdma.c
create mode 100644include/linux/pci-p2pdma.hQuoted 6 lines
How do you envison merging this? There's a big chunk in
drivers/pci, but really no opportunity for conflicts there, and there's significant stuff in block and nvme that I don't really want to merge.If Alex is OK with the ACS situation, I can ack the PCI parts and you could merge it elsewhere?
AIUI from previously questioning this, the change is hidden behind a build-time config option and only custom kernels or distros optimized for this sort of support would enable that build option. I'm more than a little dubious though that we're not going to have a wave of distros enabling this only to get user complaints that they can no longer make effective use of their devices for assignment due to the resulting span of the IOMMU groups, nor is there any sort of compromise, configure the kernel for p2p or device assignment, not both. Is this really such a unique feature that distro users aren't going to be asking for both features? Thanks,
Quoted 6 lines
Quoted 1 line
Alex
At least 1/2 the cases presented to me by existing customers want it in a tunable kernel,
and tunable btwn two points, if the hw allows it to be 'contained' in that manner, which
a (layer of) switch(ing) provides.
To me, that means a kernel cmdline parameter to _enable_, and another sysfs (configfs? ... i'm not a configfs afficionato to say which is best), method to make two points p2p dma capable.
That's not what's done here AIUI. There are also some complications to making IOMMU groups dynamic, for instance could a downstream endpoint already be in use by a userspace tool as ACS is being twiddled in sysfs? Probably the easiest solution would be that all devices affected by the ACS change are soft unplugged before and re-added after the ACS change. Note that "affected" is not necessarily only the downstream devices if the downstream port at which we're playing with ACS is part of a multifunction device. Thanks,
Alex