Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1647143 > unrolled thread
| Started by | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| First post | 2017-05-22 18:50 +0200 |
| Last post | 2017-05-23 07:10 +0200 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v7 0/3] PCI/IOMMU: Reserve IOVAs for PCI inbound memory Oza Pawandeep <oza.oza@broadcom.com> - 2017-05-22 18:50 +0200
[PATCH v7 3/3] IOMMU/PCI: Reserve IOVA for inbound memory for PCI masters Oza Pawandeep <oza.oza@broadcom.com> - 2017-05-22 18:50 +0200
[PATCH v7 2/3] PCI: Add support for PCI inbound windows resources Oza Pawandeep <oza.oza@broadcom.com> - 2017-05-22 18:50 +0200
Re: [PATCH v7 0/3] PCI/IOMMU: Reserve IOVAs for PCI inbound memory Alex Williamson <alex.williamson@redhat.com> - 2017-05-22 21:20 +0200
Re: [PATCH v7 0/3] PCI/IOMMU: Reserve IOVAs for PCI inbound memory Oza Oza <oza.oza@broadcom.com> - 2017-05-23 07:10 +0200
| From | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| Date | 2017-05-22 18:50 +0200 |
| Subject | [PATCH v7 0/3] PCI/IOMMU: Reserve IOVAs for PCI inbound memory |
| Message-ID | <tJYGR-86U-7@gated-at.bofh.it> |
iproc based PCI RC and Stingray SOC has limitaiton of addressing only 512GB memory at once. IOVA allocation honors device's coherent_dma_mask/dma_mask. In PCI case, current code honors DMA mask set by EP, there is no concept of PCI host bridge dma-mask, should be there and hence could truly reflect the limitation of PCI host bridge. However assuming Linux takes care of largest possible dma_mask, still the limitation could exist, because of the way memory banks are implemented. for e.g. memory banks: <0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */ <0x00000008 0x80000000 0x3 0x80000000>, /* 14G @ 34G */ <0x00000090 0x00000000 0x4 0x00000000>, /* 16G @ 576G */ <0x000000a0 0x00000000 0x4 0x00000000>; /* 16G @ 640G */ When run User space (SPDK) which internally uses vfio in order to access PCI EndPoint directly. Vfio uses huge-pages which could come from 640G/0x000000a0. And the way vfio maps the hugepage is to have phys addr as iova, and ends up calling VFIO_IOMMU_MAP_DMA ends up calling iommu_map, inturn arm_lpae_map mapping iovas out of range. So the way kernel allocates IOVA (where it honours device dma_mask) and the way userspace gets IOVA is different. dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>; will not work. Instead we have to go for scattered dma-ranges leaving holes. Hence, we have to reserve IOVA allocations for inbound memory. The patch-set caters to only addressing IOVA allocation problem. Changes since v7: - Robin's comment addressed where he wanted to remove depedency between IOMMU and OF layer. - Bjorn Helgaas's comments addressed. Changes since v6: - Robin's comments addressed. Changes since v5: Changes since v4: Changes since v3: Changes since v2: - minor changes, redudant checkes removed - removed internal review Changes since v1: - address Rob's comments. - Add a get_dma_ranges() function to of_bus struct.. - Convert existing contents of of_dma_get_range function to of_bus_default_dma_get_ranges and adding that to the default of_bus struct. - Make of_dma_get_range call of_bus_match() and then bus->get_dma_ranges. Oza Pawandeep (3): OF/PCI: expose inbound memory interface to PCI RC drivers. IOMMU/PCI: reserve IOVA for inbound memory for PCI masters PCI: add support for inbound windows resources drivers/iommu/dma-iommu.c | 44 ++++++++++++++++++++-- drivers/of/of_pci.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/probe.c | 30 +++++++++++++-- include/linux/of_pci.h | 7 ++++ include/linux/pci.h | 1 + 5 files changed, 170 insertions(+), 8 deletions(-) -- 1.9.1
[toc] | [next] | [standalone]
| From | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| Date | 2017-05-22 18:50 +0200 |
| Subject | [PATCH v7 3/3] IOMMU/PCI: Reserve IOVA for inbound memory for PCI masters |
| Message-ID | <tJYGR-86U-15@gated-at.bofh.it> |
| In reply to | #1647143 |
This patch reserves the inbound memory holes for PCI masters.
ARM64 based SOCs may have scattered memory banks.
For e.g as iproc based SOC has
<0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */
<0x00000008 0x80000000 0x3 0x80000000>, /* 14G @ 34G */
<0x00000090 0x00000000 0x4 0x00000000>, /* 16G @ 576G */
<0x000000a0 0x00000000 0x4 0x00000000>; /* 16G @ 640G */
But incoming PCI transaction addressing capability is limited
by host bridge, for example if max incoming window capability
is 512 GB, then 0x00000090 and 0x000000a0 will fall beyond it.
To address this problem, iommu has to avoid allocating IOVA which
are reserved.
Which in turn does not allocate IOVA if it falls into hole.
and the holes should be reserved before any of the IOVA allocations
can happen.
Signed-off-by: Oza Pawandeep <oza.oza@broadcom.com>
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 8348f366..efe3d07 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -171,16 +171,15 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
{
struct pci_host_bridge *bridge;
struct resource_entry *window;
+ struct iommu_resv_region *region;
+ phys_addr_t start, end;
+ size_t length;
if (!dev_is_pci(dev))
return;
bridge = pci_find_host_bridge(to_pci_dev(dev)->bus);
resource_list_for_each_entry(window, &bridge->windows) {
- struct iommu_resv_region *region;
- phys_addr_t start;
- size_t length;
-
if (resource_type(window->res) != IORESOURCE_MEM)
continue;
@@ -193,6 +192,43 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
list_add_tail(®ion->list, list);
}
+
+ /* PCI inbound memory reservation. */
+ start = length = 0;
+ resource_list_for_each_entry(window, &bridge->inbound_windows) {
+ end = window->res->start - window->offset;
+
+ if (start > end) {
+ /* multiple ranges assumed sorted. */
+ pr_warn("PCI: failed to reserve iovas\n");
+ return;
+ }
+
+ if (start != end) {
+ length = end - start - 1;
+ region = iommu_alloc_resv_region(start, length, 0,
+ IOMMU_RESV_RESERVED);
+ if (!region)
+ return;
+
+ list_add_tail(®ion->list, list);
+ }
+
+ start += end + length + 1;
+ }
+ /*
+ * the last dma-range should honour based on the
+ * 32/64-bit dma addresses.
+ */
+ if ((start) && (start < DMA_BIT_MASK(sizeof(dma_addr_t) * 8))) {
+ length = DMA_BIT_MASK((sizeof(dma_addr_t) * 8)) - 1;
+ region = iommu_alloc_resv_region(start, length, 0,
+ IOMMU_RESV_RESERVED);
+ if (!region)
+ return;
+
+ list_add_tail(®ion->list, list);
+ }
}
EXPORT_SYMBOL(iommu_dma_get_resv_regions);
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| Date | 2017-05-22 18:50 +0200 |
| Subject | [PATCH v7 2/3] PCI: Add support for PCI inbound windows resources |
| Message-ID | <tJYGS-86U-27@gated-at.bofh.it> |
| In reply to | #1647143 |
This patch adds support for inbound memory window
for PCI RC drivers.
It defines new function pci_create_root_bus2 which
takes inbound resources as an argument and fills in the
memory resource to PCI internal host bridge structure
as inbound_windows.
Legacy RC driver could continue to use pci_create_root_bus,
but any RC driver who wants to reseve IOVAS for their
inbound memory holes, should use new API pci_create_root_bus2.
Signed-off-by: Oza Pawandeep <oza.oza@broadcom.com>
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 19c8950..a95b9bb 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -531,6 +531,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
return NULL;
INIT_LIST_HEAD(&bridge->windows);
+ INIT_LIST_HEAD(&bridge->inbound_windows);
return bridge;
}
@@ -726,6 +727,7 @@ int pci_register_host_bridge(struct pci_host_bridge *bridge)
struct pci_bus *bus, *b;
resource_size_t offset;
LIST_HEAD(resources);
+ LIST_HEAD(inbound_resources);
struct resource *res;
char addr[64], *fmt;
const char *name;
@@ -739,6 +741,8 @@ int pci_register_host_bridge(struct pci_host_bridge *bridge)
/* temporarily move resources off the list */
list_splice_init(&bridge->windows, &resources);
+ list_splice_init(&bridge->inbound_windows, &inbound_resources);
+
bus->sysdata = bridge->sysdata;
bus->msi = bridge->msi;
bus->ops = bridge->ops;
@@ -794,6 +798,10 @@ int pci_register_host_bridge(struct pci_host_bridge *bridge)
else
pr_info("PCI host bridge to bus %s\n", name);
+ /* Add inbound mem resource. */
+ resource_list_for_each_entry_safe(window, n, &inbound_resources)
+ list_move_tail(&window->node, &bridge->inbound_windows);
+
/* Add initial resources to the bus */
resource_list_for_each_entry_safe(window, n, &resources) {
list_move_tail(&window->node, &bridge->windows);
@@ -2300,7 +2308,8 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata,
- struct list_head *resources, struct msi_controller *msi)
+ struct list_head *resources, struct list_head *in_res,
+ struct msi_controller *msi)
{
int error;
struct pci_host_bridge *bridge;
@@ -2313,6 +2322,9 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
bridge->dev.release = pci_release_host_bridge_dev;
list_splice_init(resources, &bridge->windows);
+ if (in_res)
+ list_splice_init(in_res, &bridge->inbound_windows);
+
bridge->sysdata = sysdata;
bridge->busnr = bus;
bridge->ops = ops;
@@ -2329,11 +2341,20 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
return NULL;
}
+struct pci_bus *pci_create_root_bus2(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources,
+ struct list_head *in_res)
+{
+ return pci_create_root_bus_msi(parent, bus, ops, sysdata,
+ resources, in_res, NULL);
+}
+EXPORT_SYMBOL_GPL(pci_create_root_bus2);
+
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
- return pci_create_root_bus_msi(parent, bus, ops, sysdata, resources,
- NULL);
+ return pci_create_root_bus_msi(parent, bus, ops, sysdata,
+ resources, NULL, NULL);
}
EXPORT_SYMBOL_GPL(pci_create_root_bus);
@@ -2415,7 +2436,8 @@ struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
break;
}
- b = pci_create_root_bus_msi(parent, bus, ops, sysdata, resources, msi);
+ b = pci_create_root_bus_msi(parent, bus, ops, sysdata,
+ resources, NULL, msi);
if (!b)
return NULL;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33c2b0b..d2df107 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -432,6 +432,7 @@ struct pci_host_bridge {
void *sysdata;
int busnr;
struct list_head windows; /* resource_entry */
+ struct list_head inbound_windows; /* inbound memory */
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
struct msi_controller *msi;
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Alex Williamson <alex.williamson@redhat.com> |
|---|---|
| Date | 2017-05-22 21:20 +0200 |
| Message-ID | <tK122-1cI-21@gated-at.bofh.it> |
| In reply to | #1647143 |
On Mon, 22 May 2017 22:09:39 +0530 Oza Pawandeep <oza.oza@broadcom.com> wrote: > iproc based PCI RC and Stingray SOC has limitaiton of addressing only 512GB > memory at once. > > IOVA allocation honors device's coherent_dma_mask/dma_mask. > In PCI case, current code honors DMA mask set by EP, there is no > concept of PCI host bridge dma-mask, should be there and hence > could truly reflect the limitation of PCI host bridge. > > However assuming Linux takes care of largest possible dma_mask, still the > limitation could exist, because of the way memory banks are implemented. > > for e.g. memory banks: > <0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */ > <0x00000008 0x80000000 0x3 0x80000000>, /* 14G @ 34G */ > <0x00000090 0x00000000 0x4 0x00000000>, /* 16G @ 576G */ > <0x000000a0 0x00000000 0x4 0x00000000>; /* 16G @ 640G */ > > When run User space (SPDK) which internally uses vfio in order to access > PCI EndPoint directly. > > Vfio uses huge-pages which could come from 640G/0x000000a0. > And the way vfio maps the hugepage is to have phys addr as iova, > and ends up calling VFIO_IOMMU_MAP_DMA ends up calling iommu_map, > inturn arm_lpae_map mapping iovas out of range. > > So the way kernel allocates IOVA (where it honours device dma_mask) and > the way userspace gets IOVA is different. > > dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>; will not work. > > Instead we have to go for scattered dma-ranges leaving holes. > Hence, we have to reserve IOVA allocations for inbound memory. > The patch-set caters to only addressing IOVA allocation problem. The description here confuses me, with vfio the user owns the iova allocation problem. Mappings are only identity mapped if the user chooses to do so. The dma_mask of the device is set by the driver and only relevant to the DMA-API. vfio is a meta-driver and doesn't know the dma_mask of any particular device, that's the user's job. Is the net result of what's happening here for the vfio case simply to expose extra reserved regions in sysfs, which the user can then consume to craft a compatible iova? Thanks, Alex > > Changes since v7: > - Robin's comment addressed > where he wanted to remove depedency between IOMMU and OF layer. > - Bjorn Helgaas's comments addressed. > > Changes since v6: > - Robin's comments addressed. > > Changes since v5: > Changes since v4: > Changes since v3: > Changes since v2: > - minor changes, redudant checkes removed > - removed internal review > > Changes since v1: > - address Rob's comments. > - Add a get_dma_ranges() function to of_bus struct.. > - Convert existing contents of of_dma_get_range function to > of_bus_default_dma_get_ranges and adding that to the > default of_bus struct. > - Make of_dma_get_range call of_bus_match() and then bus->get_dma_ranges. > > > Oza Pawandeep (3): > OF/PCI: expose inbound memory interface to PCI RC drivers. > IOMMU/PCI: reserve IOVA for inbound memory for PCI masters > PCI: add support for inbound windows resources > > drivers/iommu/dma-iommu.c | 44 ++++++++++++++++++++-- > drivers/of/of_pci.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ > drivers/pci/probe.c | 30 +++++++++++++-- > include/linux/of_pci.h | 7 ++++ > include/linux/pci.h | 1 + > 5 files changed, 170 insertions(+), 8 deletions(-) >
[toc] | [prev] | [next] | [standalone]
| From | Oza Oza <oza.oza@broadcom.com> |
|---|---|
| Date | 2017-05-23 07:10 +0200 |
| Message-ID | <tKaeZ-77l-9@gated-at.bofh.it> |
| In reply to | #1647285 |
On Tue, May 23, 2017 at 12:48 AM, Alex Williamson <alex.williamson@redhat.com> wrote: > On Mon, 22 May 2017 22:09:39 +0530 > Oza Pawandeep <oza.oza@broadcom.com> wrote: > >> iproc based PCI RC and Stingray SOC has limitaiton of addressing only 512GB >> memory at once. >> >> IOVA allocation honors device's coherent_dma_mask/dma_mask. >> In PCI case, current code honors DMA mask set by EP, there is no >> concept of PCI host bridge dma-mask, should be there and hence >> could truly reflect the limitation of PCI host bridge. >> >> However assuming Linux takes care of largest possible dma_mask, still the >> limitation could exist, because of the way memory banks are implemented. >> >> for e.g. memory banks: >> <0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */ >> <0x00000008 0x80000000 0x3 0x80000000>, /* 14G @ 34G */ >> <0x00000090 0x00000000 0x4 0x00000000>, /* 16G @ 576G */ >> <0x000000a0 0x00000000 0x4 0x00000000>; /* 16G @ 640G */ >> >> When run User space (SPDK) which internally uses vfio in order to access >> PCI EndPoint directly. >> >> Vfio uses huge-pages which could come from 640G/0x000000a0. >> And the way vfio maps the hugepage is to have phys addr as iova, >> and ends up calling VFIO_IOMMU_MAP_DMA ends up calling iommu_map, >> inturn arm_lpae_map mapping iovas out of range. >> >> So the way kernel allocates IOVA (where it honours device dma_mask) and >> the way userspace gets IOVA is different. >> >> dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>; will not work. >> >> Instead we have to go for scattered dma-ranges leaving holes. >> Hence, we have to reserve IOVA allocations for inbound memory. >> The patch-set caters to only addressing IOVA allocation problem. > > > The description here confuses me, with vfio the user owns the iova > allocation problem. Mappings are only identity mapped if the user > chooses to do so. The dma_mask of the device is set by the driver and > only relevant to the DMA-API. vfio is a meta-driver and doesn't know > the dma_mask of any particular device, that's the user's job. Is the > net result of what's happening here for the vfio case simply to expose > extra reserved regions in sysfs, which the user can then consume to > craft a compatible iova? Thanks, > > Alex Hi Alex, this is not a VFIO problem, the reason I have mentioned VFIO because, wanted to bring problem statement as a whole (which includes both kernel space and user space). The way SPDK pipeline is set, yes mapping are identity mapped, and whatever user space passes down IOVA, VFIO use is as is. which is fine and expected. But the problem is, user space physical memory (hugepages) reside high enough in memory, which could be beyond PCI RC's capability. Again, this is not VFIO's problem, neither is of user-space. In-fact both have nothing to do with dma-mask as well. My reference of dma-mask was for Linux IOMMU framework (not for VFIO) Regards, Oza. > >> >> Changes since v7: >> - Robin's comment addressed >> where he wanted to remove depedency between IOMMU and OF layer. >> - Bjorn Helgaas's comments addressed. >> >> Changes since v6: >> - Robin's comments addressed. >> >> Changes since v5: >> Changes since v4: >> Changes since v3: >> Changes since v2: >> - minor changes, redudant checkes removed >> - removed internal review >> >> Changes since v1: >> - address Rob's comments. >> - Add a get_dma_ranges() function to of_bus struct.. >> - Convert existing contents of of_dma_get_range function to >> of_bus_default_dma_get_ranges and adding that to the >> default of_bus struct. >> - Make of_dma_get_range call of_bus_match() and then bus->get_dma_ranges. >> >> >> Oza Pawandeep (3): >> OF/PCI: expose inbound memory interface to PCI RC drivers. >> IOMMU/PCI: reserve IOVA for inbound memory for PCI masters >> PCI: add support for inbound windows resources >> >> drivers/iommu/dma-iommu.c | 44 ++++++++++++++++++++-- >> drivers/of/of_pci.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/pci/probe.c | 30 +++++++++++++-- >> include/linux/of_pci.h | 7 ++++ >> include/linux/pci.h | 1 + >> 5 files changed, 170 insertions(+), 8 deletions(-) >> >
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web