Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1446420 > unrolled thread
| Started by | Eric Auger <eric.auger@redhat.com> |
|---|---|
| First post | 2016-07-19 15:00 +0200 |
| Last post | 2016-07-20 13:10 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v11 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 1/3: iommu changes Eric Auger <eric.auger@redhat.com> - 2016-07-19 15:00 +0200
[PATCH v11 3/8] iommu: introduce an msi cookie Eric Auger <eric.auger@redhat.com> - 2016-07-19 15:00 +0200
[PATCH v11 8/8] iommu/arm-smmu: get/put the msi cookie Eric Auger <eric.auger@redhat.com> - 2016-07-19 15:00 +0200
[PATCH v11 1/8] iommu: Add iommu_domain_msi_geometry and DOMAIN_ATTR_MSI_GEOMETRY Eric Auger <eric.auger@redhat.com> - 2016-07-19 15:00 +0200
[PATCH v11 5/8] iommu/msi-iommu: iommu_msi_[get,put]_doorbell_iova Eric Auger <eric.auger@redhat.com> - 2016-07-19 15:00 +0200
Re: [PATCH v11 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 1/3: iommu changes Auger Eric <eric.auger@redhat.com> - 2016-07-20 13:10 +0200
| From | Eric Auger <eric.auger@redhat.com> |
|---|---|
| Date | 2016-07-19 15:00 +0200 |
| Subject | [PATCH v11 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 1/3: iommu changes |
| Message-ID | <rWCMV-47Q-3@gated-at.bofh.it> |
This series introduces the msi-iommu api used to:
- allocate/free resources for MSI IOMMU mapping
- set the MSI iova window aperture
- map/unmap physical addresses onto MSI IOVAs.
- determine whether an msi needs to be iommu mapped
- overwrite an msi_msg PA address with its pre-allocated/mapped IOVA
Also a new iommu domain attribute, DOMAIN_ATTR_MSI_GEOMETRY is introduced
to report the MSI iova window geometry (aperture and iommu-msi API support).
Currently:
- iommu driver is supposed to allocate/free MSI mapping resources
- VFIO subsystem is supposed to set the MSI IOVA aperture.
- The MSI layer is supposed to allocate/free iova mappings and overwrite
msi_msg with IOVA at composition time
More details & context can be found at:
http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
Best Regards
Eric
Git: complete series available at
https://github.com/eauger/linux/tree/v4.7-rc7-passthrough-v11
see part III for wrap-up details.
History:
v10 -> v11:
- no change in the series, just incremented for consistency
- added a temporary patch in the branch:
"iommu/iova: FIXUP! validate iova_domain input to put_iova_domain"
originally sent by Nate and adapted for this use case. This is currently
under discussion on the ML. The crash typically occurs in case unsafe
interrupts are discovered while allow_unsafe_interrupts is not set.
v9 -> v10:
- split error management in iommu_msi_set_aperture
v8 -> v9:
- rename iommu_domain_msi_geometry programmable flag into iommu_msi_supported
- introduce msi_apperture_valid helper and use this instead of is_aperture_set
v7 -> v8:
- The API is retargetted for MSI: renamed msi-iommu
all "dma-reserved" namings removed
- now implemented upon dma-iommu (get, put, init), ie. reuse iova_cookie,
and iova API
- msi mapping resources now are guaranteed to exist during the whole iommu
domain's lifetime. No need to lock to garantee the cookie integrity
- removed alloc/free_reserved_reserved_iova_domain. We now have a single
function that sets the aperture, looking like iommu_dma_init_domain.
- we now use a list instead of an RB-tree
- prot is not propagated anymore at domain creation due to the retargetting
for MSI
- iommu_domain pointer removed from doorbell_mapping struct
- replaced DOMAIN_ATTR_MSI_MAPPING by DOMAIN_ATTR_MSI_GEOMETRY
v6 -> v7:
- fixed known lock bugs and multiple page sized slots matching
(I only have a single MSI frame made of a single page)
- reserved_iova_cookie now pointing to a struct that encapsulates the
iova domain handle + protection attribute passed from VFIO (Alex' req)
- 2 new functions exposed: iommu_msi_mapping_translate_msg,
iommu_msi_mapping_desc_to_domain: not sure this is the right location/proto
though
- iommu_put_reserved_iova now takes a phys_addr_t
- everything now is cleanup on iommu_domain destruction
RFC v5 -> patch v6:
- split to ease the review process
- in dma-reserved-api use a spin lock instead of a mutex (reported by
Jean-Philippe)
- revisit iommu_get_reserved_iova API to pass a size parameter upon
Marc's request
- Consistently use the page order passed when creating the iova domain.
- init reserved_binding_list (reported by Julien)
RFC v4 -> RFC v5:
- take into account Thomas' comments on MSI related patches
- split "msi: IOMMU map the doorbell address when needed"
- increase readability and add comments
- fix style issues
- split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
- platform ITS now advertises IOMMU_CAP_INTR_REMAP
- fix compilation issue with CONFIG_IOMMU API unset
- arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
RFC v3 -> v4:
- Move doorbell mapping/unmapping in msi.c
- fix ref count issue on set_affinity: in case of a change in the address
the previous address is decremented
- doorbell map/unmap now is done on msi composition. Should allow the use
case for platform MSI controllers
- create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
to reserved IOVA management (looking like dma-iommu glue)
- series reordering to ease the review:
- first part is related to IOMMU
- second related to MSI sub-system
- third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
- expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
[this partially addresses Marc's comments on iommu_get/put_single_reserved
size/alignment problematic - which I did not ignore - but I don't know
how much I can do at the moment]
RFC v2 -> RFC v3:
- should fix wrong handling of some CONFIG combinations:
CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
- fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
PATCH v1 -> RFC v2:
- reverted to RFC since it looks more reasonable ;-) the code is split
between VFIO, IOMMU, MSI controller and I am not sure I did the right
choices. Also API need to be further discussed.
- iova API usage in arm-smmu.c.
- MSI controller natively programs the MSI addr with either the PA or IOVA.
This is not done anymore in vfio-pci driver as suggested by Alex.
- check irq remapping capability of the group
RFC v1 [2] -> PATCH v1:
- use the existing dma map/unmap ioctl interface with a flag to register a
reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
- a single reserved IOVA contiguous region now is allowed
- use of an RB tree indexed by PA to store allocated reserved slots
- use of a vfio_domain iova_domain to manage iova allocation within the
window provided by the userspace
- vfio alloc_map/unmap_free take a vfio_group handle
- vfio_group handle is cached in vfio_pci_device
- add ref counting to bindings
- user modality enabled at the end of the series
Eric Auger (8):
iommu: Add iommu_domain_msi_geometry and DOMAIN_ATTR_MSI_GEOMETRY
iommu/arm-smmu: initialize the msi geometry and advertise iommu-msi
support
iommu: introduce an msi cookie
iommu/msi-iommu: initialization
iommu/msi-iommu: iommu_msi_[get,put]_doorbell_iova
iommu/msi-iommu: iommu_msi_domain
iommu/msi-iommu: iommu_msi_msg_pa_to_va
iommu/arm-smmu: get/put the msi cookie
drivers/iommu/Kconfig | 7 +
drivers/iommu/Makefile | 1 +
drivers/iommu/arm-smmu-v3.c | 18 ++-
drivers/iommu/arm-smmu.c | 18 ++-
drivers/iommu/iommu.c | 5 +
drivers/iommu/msi-iommu.c | 322 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/iommu.h | 15 +++
include/linux/msi-iommu.h | 144 ++++++++++++++++++++
8 files changed, 522 insertions(+), 8 deletions(-)
create mode 100644 drivers/iommu/msi-iommu.c
create mode 100644 include/linux/msi-iommu.h
--
1.9.1
[toc] | [next] | [standalone]
| From | Eric Auger <eric.auger@redhat.com> |
|---|---|
| Date | 2016-07-19 15:00 +0200 |
| Subject | [PATCH v11 3/8] iommu: introduce an msi cookie |
| Message-ID | <rWCN1-47Q-23@gated-at.bofh.it> |
| In reply to | #1446420 |
This opaque pointer will enable to store information about msi
iommu mappings.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v7 -> v8:
remove spinlock and RB tree
v5 -> v6:
- initialize reserved_binding_list
- use a spinlock instead of a mutex
---
include/linux/iommu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 1b553ee..f7a5d13 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -91,6 +91,7 @@ struct iommu_domain {
struct iommu_domain_geometry geometry;
struct iommu_domain_msi_geometry msi_geometry;
void *iova_cookie;
+ void *msi_cookie;
};
enum iommu_cap {
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Eric Auger <eric.auger@redhat.com> |
|---|---|
| Date | 2016-07-19 15:00 +0200 |
| Subject | [PATCH v11 8/8] iommu/arm-smmu: get/put the msi cookie |
| Message-ID | <rWCN1-47Q-25@gated-at.bofh.it> |
| In reply to | #1446420 |
For IOMMU_DOMAIN_UNMANAGED type we now also get the msi
cookie in both arm-smmu and arm-smmu-v3. This initializes
resources for MSI doorbell mapping.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
drivers/iommu/arm-smmu-v3.c | 16 ++++++++++++----
drivers/iommu/arm-smmu.c | 15 +++++++++++----
2 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 066d92c..960d377 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/dma-iommu.h>
+#include <linux/msi-iommu.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/iommu.h>
@@ -1412,15 +1413,21 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
return NULL;
if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&smmu_domain->domain)) {
- kfree(smmu_domain);
- return NULL;
- }
+ iommu_get_dma_cookie(&smmu_domain->domain))
+ goto err;
+
+ if (type == IOMMU_DOMAIN_UNMANAGED &&
+ iommu_get_msi_cookie(&smmu_domain->domain))
+ goto err;
+
smmu_domain->domain.msi_geometry = msi_geometry;
mutex_init(&smmu_domain->init_mutex);
spin_lock_init(&smmu_domain->pgtbl_lock);
return &smmu_domain->domain;
+err:
+ kfree(smmu_domain);
+ return NULL;
}
static int arm_smmu_bitmap_alloc(unsigned long *map, int span)
@@ -1446,6 +1453,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
+ iommu_put_msi_cookie(domain);
iommu_put_dma_cookie(domain);
free_io_pgtable_ops(smmu_domain->pgtbl_ops);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 9755a1b..867910b 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/dma-iommu.h>
+#include <linux/msi-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
@@ -1052,10 +1053,12 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
return NULL;
if (type == IOMMU_DOMAIN_DMA &&
- iommu_get_dma_cookie(&smmu_domain->domain)) {
- kfree(smmu_domain);
- return NULL;
- }
+ iommu_get_dma_cookie(&smmu_domain->domain))
+ goto err;
+
+ if (type == IOMMU_DOMAIN_UNMANAGED &&
+ iommu_get_msi_cookie(&smmu_domain->domain))
+ goto err;
smmu_domain->domain.msi_geometry = msi_geometry;
@@ -1063,6 +1066,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
spin_lock_init(&smmu_domain->pgtbl_lock);
return &smmu_domain->domain;
+err:
+ kfree(smmu_domain);
+ return NULL;
}
static void arm_smmu_domain_free(struct iommu_domain *domain)
@@ -1073,6 +1079,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
* Free the domain resources. We assume that all devices have
* already been detached.
*/
+ iommu_put_msi_cookie(domain);
iommu_put_dma_cookie(domain);
arm_smmu_destroy_domain_context(domain);
kfree(smmu_domain);
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Eric Auger <eric.auger@redhat.com> |
|---|---|
| Date | 2016-07-19 15:00 +0200 |
| Subject | [PATCH v11 1/8] iommu: Add iommu_domain_msi_geometry and DOMAIN_ATTR_MSI_GEOMETRY |
| Message-ID | <rWCN1-47Q-31@gated-at.bofh.it> |
| In reply to | #1446420 |
Introduce a new DOMAIN_ATTR_MSI_GEOMETRY domain attribute. It enables
to query the aperture of the IOVA window dedicated to MSIs and
test whether the MSIs must be mapped with the IOMMU-MSI API.
x86 IOMMUs will typically expose an MSI aperture matching the 1MB
region [FEE0_0000h - FEF0_000h] corresponding to the the APIC
configuration space and no support of the IOMMU-MSI API.
On ARM, the support of the IOMMU-MSI API will be advertised. Aperture
will refect the setting performed with the IOMMU-MSI API.
A helper function is added to allow testing if the aperture is valid.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Suggested-by: Alex Williamson <alex.williamson@redhat.com>
---
v8 -> v9:
- rename programmable into iommu_msi_supported
- add iommu_domain_msi_aperture_valid
v8: creation
- deprecates DOMAIN_ATTR_MSI_MAPPING flag
---
drivers/iommu/iommu.c | 5 +++++
include/linux/iommu.h | 14 ++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3000051..feab3cc 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1496,6 +1496,7 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
enum iommu_attr attr, void *data)
{
struct iommu_domain_geometry *geometry;
+ struct iommu_domain_msi_geometry *msi_geometry;
bool *paging;
int ret = 0;
u32 *count;
@@ -1506,6 +1507,10 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
*geometry = domain->geometry;
break;
+ case DOMAIN_ATTR_MSI_GEOMETRY:
+ msi_geometry = data;
+ *msi_geometry = domain->msi_geometry;
+ break;
case DOMAIN_ATTR_PAGING:
paging = data;
*paging = (domain->pgsize_bitmap != 0UL);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 664683a..1b553ee 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -52,6 +52,12 @@ struct iommu_domain_geometry {
bool force_aperture; /* DMA only allowed in mappable range? */
};
+struct iommu_domain_msi_geometry {
+ dma_addr_t aperture_start; /* First address used for MSI IOVA */
+ dma_addr_t aperture_end; /* Last address used for MSI IOVA */
+ bool iommu_msi_supported; /* Is MSI mapping supported? */
+};
+
/* Domain feature flags */
#define __IOMMU_DOMAIN_PAGING (1U << 0) /* Support for iommu_map/unmap */
#define __IOMMU_DOMAIN_DMA_API (1U << 1) /* Domain for use in DMA-API
@@ -83,6 +89,7 @@ struct iommu_domain {
iommu_fault_handler_t handler;
void *handler_token;
struct iommu_domain_geometry geometry;
+ struct iommu_domain_msi_geometry msi_geometry;
void *iova_cookie;
};
@@ -108,6 +115,7 @@ enum iommu_cap {
enum iommu_attr {
DOMAIN_ATTR_GEOMETRY,
+ DOMAIN_ATTR_MSI_GEOMETRY,
DOMAIN_ATTR_PAGING,
DOMAIN_ATTR_WINDOWS,
DOMAIN_ATTR_FSL_PAMU_STASH,
@@ -328,6 +336,12 @@ extern struct iommu_group *pci_device_group(struct device *dev);
/* Generic device grouping function */
extern struct iommu_group *generic_device_group(struct device *dev);
+static inline bool iommu_domain_msi_aperture_valid(struct iommu_domain *domain)
+{
+ return (domain->msi_geometry.aperture_end >
+ domain->msi_geometry.aperture_start);
+}
+
#else /* CONFIG_IOMMU_API */
struct iommu_ops {};
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Eric Auger <eric.auger@redhat.com> |
|---|---|
| Date | 2016-07-19 15:00 +0200 |
| Subject | [PATCH v11 5/8] iommu/msi-iommu: iommu_msi_[get,put]_doorbell_iova |
| Message-ID | <rWCN1-47Q-37@gated-at.bofh.it> |
| In reply to | #1446420 |
iommu_msi_get_doorbell_iova allows to iommu map an MSI doorbell contiguous
physical region onto a reserved contiguous IOVA region. The physical
region base address does not need to be iommu page size aligned. iova
pages are allocated and mapped so that they cover all the physical region.
This mapping is tracked as a whole (and cannot be split).
In case a mapping already exists for the physical pages, the IOVA mapped
to the PA base is directly returned.
Each time the get succeeds a binding ref count is incremented.
iommu_put_reserved_iova decrements the ref count and when this latter
is null, the mapping is destroyed and the IOVAs are released.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v9:
- use iommu_domain_msi_aperture_valid
v8:
- function renaming
- new design based on the assumption the iova domain cannot disappear
- free_iova outside of doorbell_mapping_release (iommu_domain * was
removed from doorbell_mapping)
v7:
- change title and rework commit message with new name of the functions
and size parameter
- fix locking
- rework header doc comments
- put now takes a phys_addr_t
- check prot argument against reserved_iova_domain prot flags
v5 -> v6:
- revisit locking with spin_lock instead of mutex
- do not kref_get on 1st get
- add size parameter to the get function following Marc's request
- use the iova domain shift instead of using the smallest supported page siz
v3 -> v4:
- formerly in iommu: iommu_get/put_single_reserved &
iommu/arm-smmu: implement iommu_get/put_single_reserved
- Attempted to address Marc's doubts about missing size/alignment
at VFIO level (user-space knows the IOMMU page size and the number
of IOVA pages to provision)
v2 -> v3:
- remove static implementation of iommu_get_single_reserved &
iommu_put_single_reserved when CONFIG_IOMMU_API is not set
v1 -> v2:
- previously a VFIO API, named vfio_alloc_map/unmap_free_reserved_iova
---
drivers/iommu/msi-iommu.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/msi-iommu.h | 39 ++++++++++++
2 files changed, 189 insertions(+)
diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
index de02ede..57017cb 100644
--- a/drivers/iommu/msi-iommu.c
+++ b/drivers/iommu/msi-iommu.c
@@ -98,3 +98,153 @@ int iommu_msi_set_aperture(struct iommu_domain *domain,
}
EXPORT_SYMBOL_GPL(iommu_msi_set_aperture);
+/* called with info->lock held */
+static struct doorbell_mapping *
+search_msi_doorbell_mapping(struct doorbell_mapping_info *info,
+ phys_addr_t addr, size_t size)
+{
+ struct doorbell_mapping *mapping;
+
+ list_for_each_entry(mapping, &info->list, next) {
+ if ((addr >= mapping->addr) &&
+ (addr + size <= mapping->addr + mapping->size))
+ return mapping;
+ }
+ return NULL;
+}
+
+int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
+ phys_addr_t addr, size_t size, int prot,
+ dma_addr_t *iova)
+{
+ struct doorbell_mapping_info *dmi = domain->msi_cookie;
+ struct iova_domain *iovad = domain->iova_cookie;
+ struct doorbell_mapping *new_mapping, *mapping;
+ phys_addr_t aligned_base, offset;
+ size_t binding_size;
+ struct iova *p_iova;
+ dma_addr_t new_iova;
+ int ret = -EINVAL;
+ bool unmap = false;
+
+ if (!dmi)
+ return -ENODEV;
+
+ if (!iommu_domain_msi_aperture_valid(domain))
+ return -EINVAL;
+
+ offset = iova_offset(iovad, addr);
+ aligned_base = addr - offset;
+ binding_size = iova_align(iovad, size + offset);
+
+ spin_lock(&dmi->lock);
+
+ mapping = search_msi_doorbell_mapping(dmi, aligned_base, binding_size);
+ if (mapping) {
+ *iova = mapping->iova + offset + aligned_base - mapping->addr;
+ kref_get(&mapping->kref);
+ ret = 0;
+ goto unlock;
+ }
+
+ spin_unlock(&dmi->lock);
+
+ new_mapping = kzalloc(sizeof(*new_mapping), GFP_KERNEL);
+ if (!new_mapping)
+ return -ENOMEM;
+
+ p_iova = alloc_iova(iovad, binding_size >> iova_shift(iovad),
+ iovad->dma_32bit_pfn, true);
+ if (!p_iova) {
+ kfree(new_mapping);
+ return -ENOMEM;
+ }
+
+ new_iova = iova_dma_addr(iovad, p_iova);
+ *iova = new_iova;
+
+ /* iommu_map is not supposed to be atomic */
+ ret = iommu_map(domain, *iova, aligned_base, binding_size, prot);
+
+ spin_lock(&dmi->lock);
+
+ if (ret)
+ goto free_iova;
+ /*
+ * check again the doorbell mapping was not added while the lock
+ * was released
+ */
+ mapping = search_msi_doorbell_mapping(dmi, aligned_base, binding_size);
+ if (mapping) {
+ *iova = mapping->iova + offset + aligned_base - mapping->addr;
+ kref_get(&mapping->kref);
+ ret = 0;
+ unmap = true;
+ goto free_iova;
+ }
+
+ kref_init(&new_mapping->kref);
+ new_mapping->addr = aligned_base;
+ new_mapping->iova = *iova;
+ new_mapping->size = binding_size;
+
+ list_add(&new_mapping->next, &dmi->list);
+
+ *iova += offset;
+ goto unlock;
+free_iova:
+ free_iova(iovad, p_iova->pfn_lo);
+ kfree(new_mapping);
+unlock:
+ spin_unlock(&dmi->lock);
+ if (unmap)
+ iommu_unmap(domain, new_iova, binding_size);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_msi_get_doorbell_iova);
+
+static void doorbell_mapping_release(struct kref *kref)
+{
+ struct doorbell_mapping *mapping =
+ container_of(kref, struct doorbell_mapping, kref);
+
+ list_del(&mapping->next);
+ kfree(mapping);
+}
+
+void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr)
+{
+ struct doorbell_mapping_info *dmi = domain->msi_cookie;
+ struct iova_domain *iovad = domain->iova_cookie;
+ phys_addr_t aligned_addr, page_size, offset;
+ struct doorbell_mapping *mapping;
+ dma_addr_t iova;
+ size_t size;
+ int ret = 0;
+
+ if (!dmi)
+ return;
+
+ page_size = (uint64_t)1 << iova_shift(iovad);
+ offset = iova_offset(iovad, addr);
+ aligned_addr = addr - offset;
+
+ spin_lock(&dmi->lock);
+
+ mapping = search_msi_doorbell_mapping(dmi, aligned_addr, page_size);
+ if (!mapping)
+ goto unlock;
+
+ iova = mapping->iova;
+ size = mapping->size;
+
+ ret = kref_put(&mapping->kref, doorbell_mapping_release);
+
+unlock:
+ spin_unlock(&dmi->lock);
+ if (ret) {
+ iommu_unmap(domain, iova, size);
+ free_iova(iovad, iova_pfn(iovad, iova));
+ }
+}
+EXPORT_SYMBOL_GPL(iommu_msi_put_doorbell_iova);
diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
index 392aa6f..1cd115f 100644
--- a/include/linux/msi-iommu.h
+++ b/include/linux/msi-iommu.h
@@ -52,6 +52,35 @@ void iommu_put_msi_cookie(struct iommu_domain *domain);
int iommu_msi_set_aperture(struct iommu_domain *domain,
dma_addr_t start, dma_addr_t end);
+/**
+ * iommu_msi_get_doorbell_iova: allocate a contiguous set of iova pages and
+ * map them to the MSI doorbell's physical range defined by @addr and @size.
+ *
+ * @domain: iommu domain handle
+ * @addr: physical address to bind
+ * @size: size of the binding
+ * @prot: mapping protection attribute
+ * @iova: returned iova
+ *
+ * Mapped physical pfns are within [@addr >> order, (@addr + size -1) >> order]
+ * where order corresponds to the iova domain order.
+ * This mapping is tracked and reference counted with the minimal granularity
+ * of @size.
+ */
+int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
+ phys_addr_t addr, size_t size, int prot,
+ dma_addr_t *iova);
+
+/**
+ * iommu_msi_put_doorbell_iova: decrement a ref count of the doorbell's mapping
+ *
+ * @domain: iommu domain handle
+ * @addr: physical address whose binding ref count is decremented
+ *
+ * if the binding ref count is null, destroy the MSI doorbell's mapping
+ */
+void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr);
+
#else
static inline int
@@ -61,5 +90,15 @@ iommu_msi_set_aperture(struct iommu_domain *domain,
return -ENOENT;
}
+static inline int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
+ phys_addr_t addr, size_t size,
+ int prot, dma_addr_t *iova)
+{
+ return -ENOENT;
+}
+
+static inline void iommu_msi_put_doorbell_iova(struct iommu_domain *domain,
+ phys_addr_t addr) {}
+
#endif /* CONFIG_IOMMU_MSI */
#endif /* __MSI_IOMMU_H */
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Auger Eric <eric.auger@redhat.com> |
|---|---|
| Date | 2016-07-20 13:10 +0200 |
| Subject | Re: [PATCH v11 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 1/3: iommu changes |
| Message-ID | <rWXy2-Dc-29@gated-at.bofh.it> |
| In reply to | #1446420 |
Hi Dennis On 20/07/2016 11:56, Dennis Chen wrote: > Hi Eric, > > On Tue, Jul 19, 2016 at 12:55:03PM +0000, Eric Auger wrote: >> This series introduces the msi-iommu api used to: >> >> - allocate/free resources for MSI IOMMU mapping >> - set the MSI iova window aperture >> - map/unmap physical addresses onto MSI IOVAs. >> - determine whether an msi needs to be iommu mapped >> - overwrite an msi_msg PA address with its pre-allocated/mapped IOVA >> >> Also a new iommu domain attribute, DOMAIN_ATTR_MSI_GEOMETRY is introduced >> to report the MSI iova window geometry (aperture and iommu-msi API support). >> >> Currently: >> - iommu driver is supposed to allocate/free MSI mapping resources >> - VFIO subsystem is supposed to set the MSI IOVA aperture. >> - The MSI layer is supposed to allocate/free iova mappings and overwrite >> msi_msg with IOVA at composition time >> >> More details & context can be found at: >> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/ >> >> Best Regards >> >> Eric >> >> Git: complete series available at >> https://github.com/eauger/linux/tree/v4.7-rc7-passthrough-v11 >> > Why can't I find this new series on your git tree: > https://git.linaro.org/people/eric.auger/linux.git you are not looking at the right git repo: see github one above. > ? > Also, do I need to download all the 3-part patches to test the PCIe NIC passthru > as I did on your v9 series? Yes you need to take the 3 parts. You should have everything that is needed on the above branch. In case you do not work on Cavium, you should not cherry-pick "vfio: pci: HACK! workaround thunderx pci_try_reset_bus crash" Thanks Eric > > Thanks, > Dennis >> >> see part III for wrap-up details. >> >> History: >> v10 -> v11: >> - no change in the series, just incremented for consistency >> - added a temporary patch in the branch: >> "iommu/iova: FIXUP! validate iova_domain input to put_iova_domain" >> originally sent by Nate and adapted for this use case. This is currently >> under discussion on the ML. The crash typically occurs in case unsafe >> interrupts are discovered while allow_unsafe_interrupts is not set. >> >> v9 -> v10: >> - split error management in iommu_msi_set_aperture >> >> v8 -> v9: >> - rename iommu_domain_msi_geometry programmable flag into iommu_msi_supported >> - introduce msi_apperture_valid helper and use this instead of is_aperture_set >> >> v7 -> v8: >> - The API is retargetted for MSI: renamed msi-iommu >> all "dma-reserved" namings removed >> - now implemented upon dma-iommu (get, put, init), ie. reuse iova_cookie, >> and iova API >> - msi mapping resources now are guaranteed to exist during the whole iommu >> domain's lifetime. No need to lock to garantee the cookie integrity >> - removed alloc/free_reserved_reserved_iova_domain. We now have a single >> function that sets the aperture, looking like iommu_dma_init_domain. >> - we now use a list instead of an RB-tree >> - prot is not propagated anymore at domain creation due to the retargetting >> for MSI >> - iommu_domain pointer removed from doorbell_mapping struct >> - replaced DOMAIN_ATTR_MSI_MAPPING by DOMAIN_ATTR_MSI_GEOMETRY >> >> v6 -> v7: >> - fixed known lock bugs and multiple page sized slots matching >> (I only have a single MSI frame made of a single page) >> - reserved_iova_cookie now pointing to a struct that encapsulates the >> iova domain handle + protection attribute passed from VFIO (Alex' req) >> - 2 new functions exposed: iommu_msi_mapping_translate_msg, >> iommu_msi_mapping_desc_to_domain: not sure this is the right location/proto >> though >> - iommu_put_reserved_iova now takes a phys_addr_t >> - everything now is cleanup on iommu_domain destruction >> >> RFC v5 -> patch v6: >> - split to ease the review process >> - in dma-reserved-api use a spin lock instead of a mutex (reported by >> Jean-Philippe) >> - revisit iommu_get_reserved_iova API to pass a size parameter upon >> Marc's request >> - Consistently use the page order passed when creating the iova domain. >> - init reserved_binding_list (reported by Julien) >> >> RFC v4 -> RFC v5: >> - take into account Thomas' comments on MSI related patches >> - split "msi: IOMMU map the doorbell address when needed" >> - increase readability and add comments >> - fix style issues >> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute" >> - platform ITS now advertises IOMMU_CAP_INTR_REMAP >> - fix compilation issue with CONFIG_IOMMU API unset >> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING >> >> RFC v3 -> v4: >> - Move doorbell mapping/unmapping in msi.c >> - fix ref count issue on set_affinity: in case of a change in the address >> the previous address is decremented >> - doorbell map/unmap now is done on msi composition. Should allow the use >> case for platform MSI controllers >> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated >> to reserved IOVA management (looking like dma-iommu glue) >> - series reordering to ease the review: >> - first part is related to IOMMU >> - second related to MSI sub-system >> - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal) >> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO >> [this partially addresses Marc's comments on iommu_get/put_single_reserved >> size/alignment problematic - which I did not ignore - but I don't know >> how much I can do at the moment] >> >> RFC v2 -> RFC v3: >> - should fix wrong handling of some CONFIG combinations: >> CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN >> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested) >> >> PATCH v1 -> RFC v2: >> - reverted to RFC since it looks more reasonable ;-) the code is split >> between VFIO, IOMMU, MSI controller and I am not sure I did the right >> choices. Also API need to be further discussed. >> - iova API usage in arm-smmu.c. >> - MSI controller natively programs the MSI addr with either the PA or IOVA. >> This is not done anymore in vfio-pci driver as suggested by Alex. >> - check irq remapping capability of the group >> >> RFC v1 [2] -> PATCH v1: >> - use the existing dma map/unmap ioctl interface with a flag to register a >> reserved IOVA range. Use the legacy Rb to store this special vfio_dma. >> - a single reserved IOVA contiguous region now is allowed >> - use of an RB tree indexed by PA to store allocated reserved slots >> - use of a vfio_domain iova_domain to manage iova allocation within the >> window provided by the userspace >> - vfio alloc_map/unmap_free take a vfio_group handle >> - vfio_group handle is cached in vfio_pci_device >> - add ref counting to bindings >> - user modality enabled at the end of the series >> >> >> Eric Auger (8): >> iommu: Add iommu_domain_msi_geometry and DOMAIN_ATTR_MSI_GEOMETRY >> iommu/arm-smmu: initialize the msi geometry and advertise iommu-msi >> support >> iommu: introduce an msi cookie >> iommu/msi-iommu: initialization >> iommu/msi-iommu: iommu_msi_[get,put]_doorbell_iova >> iommu/msi-iommu: iommu_msi_domain >> iommu/msi-iommu: iommu_msi_msg_pa_to_va >> iommu/arm-smmu: get/put the msi cookie >> >> drivers/iommu/Kconfig | 7 + >> drivers/iommu/Makefile | 1 + >> drivers/iommu/arm-smmu-v3.c | 18 ++- >> drivers/iommu/arm-smmu.c | 18 ++- >> drivers/iommu/iommu.c | 5 + >> drivers/iommu/msi-iommu.c | 322 ++++++++++++++++++++++++++++++++++++++++++++ >> include/linux/iommu.h | 15 +++ >> include/linux/msi-iommu.h | 144 ++++++++++++++++++++ >> 8 files changed, 522 insertions(+), 8 deletions(-) >> create mode 100644 drivers/iommu/msi-iommu.c >> create mode 100644 include/linux/msi-iommu.h >> >> -- >> 1.9.1 >> >> _______________________________________________ >> kvmarm mailing list >> kvmarm@lists.cs.columbia.edu >> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm >> >
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web