--- v11
+++ v10
@@ -31,7 +31,6 @@
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
[aw: for the vfio related changes]
Acked-by: Alex Williamson <alex.williamson@redhat.com>
-Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
Changes:
v10:
@@ -52,22 +51,22 @@
arch/powerpc/kernel/iommu.c | 12 -----
arch/powerpc/platforms/powernv/pci-ioda.c | 73 ++++++++++++++++++-------------
drivers/vfio/vfio_iommu_spapr_tce.c | 70 ++++++++++++++++++++++++++---
- 4 files changed, 118 insertions(+), 48 deletions(-)
+ 4 files changed, 116 insertions(+), 50 deletions(-)
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
-index 44a20cc..489133c 100644
+index 664beeb..c5375c5 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
-@@ -93,7 +93,6 @@ struct iommu_table {
- unsigned long it_page_shift;/* table iommu page size */
+@@ -95,7 +95,6 @@ struct iommu_table {
struct list_head it_group_list;/* List of iommu_table_group_link */
+ #endif
struct iommu_table_ops *it_ops;
- void (*set_bypass)(struct iommu_table *tbl, bool enable);
};
/* Pure 2^n version of get_order */
-@@ -126,6 +125,15 @@ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
- int nid);
+@@ -130,6 +129,15 @@ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
+
#define IOMMU_TABLE_GROUP_MAX_TABLES 1
+struct iommu_table_group;
@@ -82,19 +81,19 @@
struct iommu_table_group_link {
struct list_head next;
struct rcu_head rcu;
-@@ -135,6 +143,7 @@ struct iommu_table_group_link {
+@@ -139,6 +147,7 @@ struct iommu_table_group_link {
struct iommu_table_group {
struct iommu_group *group;
struct iommu_table *tables[IOMMU_TABLE_GROUP_MAX_TABLES];
+ struct iommu_table_group_ops *ops;
};
- #ifdef CONFIG_IOMMU_API
+ extern void iommu_register_group(struct iommu_table_group *table_group,
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
-index e305a8f..b6a397a 100644
+index bdf19c6..7e54714 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
-@@ -1047,14 +1047,6 @@ int iommu_take_ownership(struct iommu_table *tbl)
+@@ -1044,14 +1044,6 @@ int iommu_take_ownership(struct iommu_table *tbl)
memset(tbl->it_map, 0xff, sz);
@@ -109,7 +108,7 @@
return 0;
}
EXPORT_SYMBOL_GPL(iommu_take_ownership);
-@@ -1068,10 +1060,6 @@ void iommu_release_ownership(struct iommu_table *tbl)
+@@ -1065,10 +1057,6 @@ void iommu_release_ownership(struct iommu_table *tbl)
/* Restore bit#0 set by iommu_init_table() */
if (tbl->it_offset == 0)
set_bit(0, tbl->it_map);
@@ -121,7 +120,7 @@
EXPORT_SYMBOL_GPL(iommu_release_ownership);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
-index 44dce79..1d0bb5b 100644
+index 53bf242b..35ab19c8 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1918,13 +1918,8 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
@@ -231,10 +230,10 @@
return;
fail:
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
-index ed3310b..627d5a2 100644
+index ed3310b..2ead291 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
-@@ -486,6 +486,61 @@ static long tce_iommu_ioctl(void *iommu_data,
+@@ -486,6 +486,47 @@ static long tce_iommu_ioctl(void *iommu_data,
return -ENOTTY;
}
@@ -279,38 +278,37 @@
+ return 0;
+}
+
-+static void tce_iommu_release_ownership_ddw(struct tce_container *container,
-+ struct iommu_table_group *table_group)
-+{
-+ table_group->ops->release_ownership(table_group);
-+}
-+
-+static long tce_iommu_take_ownership_ddw(struct tce_container *container,
-+ struct iommu_table_group *table_group)
-+{
-+ table_group->ops->take_ownership(table_group);
-+
-+ return 0;
-+}
-+
static int tce_iommu_attach_group(void *iommu_data,
struct iommu_group *iommu_group)
{
-@@ -518,7 +573,12 @@ static int tce_iommu_attach_group(void *iommu_data,
+@@ -518,9 +559,23 @@ static int tce_iommu_attach_group(void *iommu_data,
goto unlock_exit;
}
- ret = iommu_take_ownership(table_group->tables[0]);
+- if (!ret)
+- container->grp = iommu_group;
+ if (!table_group->ops || !table_group->ops->take_ownership ||
-+ !table_group->ops->release_ownership)
++ !table_group->ops->release_ownership) {
+ ret = tce_iommu_take_ownership(container, table_group);
-+ else
-+ ret = tce_iommu_take_ownership_ddw(container, table_group);
-+
- if (!ret)
- container->grp = iommu_group;
-
-@@ -533,7 +593,6 @@ static void tce_iommu_detach_group(void *iommu_data,
++ } else {
++ /*
++ * Disable iommu bypass, otherwise the user can DMA to all of
++ * our physical memory via the bypass window instead of just
++ * the pages that has been explicitly mapped into the iommu
++ */
++ table_group->ops->take_ownership(table_group);
++ ret = 0;
++ }
++
++ if (ret)
++ goto unlock_exit;
++
++ container->grp = iommu_group;
+
+ unlock_exit:
+ mutex_unlock(&container->lock);
+@@ -533,7 +588,6 @@ static void tce_iommu_detach_group(void *iommu_data,
{
struct tce_container *container = iommu_data;
struct iommu_table_group *table_group;
@@ -318,17 +316,18 @@
mutex_lock(&container->lock);
if (iommu_group != container->grp) {
-@@ -556,9 +615,10 @@ static void tce_iommu_detach_group(void *iommu_data,
+@@ -556,9 +610,11 @@ static void tce_iommu_detach_group(void *iommu_data,
table_group = iommu_group_get_iommudata(iommu_group);
BUG_ON(!table_group);
- tbl = table_group->tables[0];
- tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
- iommu_release_ownership(tbl);
++ /* Kernel owns the device now, we can restore bypass */
+ if (!table_group->ops || !table_group->ops->release_ownership)
+ tce_iommu_release_ownership(container, table_group);
+ else
-+ tce_iommu_release_ownership_ddw(container, table_group);
++ table_group->ops->release_ownership(table_group);
unlock_exit:
mutex_unlock(&container->lock);