The current IO page fault handling framework is tightly coupled with the SVA implementation, as SVA is the only use case that requires IO page fault handling. However, with the introduction of nested translation, the first level page table is now managed by userspace. This means that any IO page fault generated for this first level IO address should be routed to userspace and handled there.
To support this, we need to split the IO page fault handling framework from the SVA implementation, and make it generic for all use cases.
Signed-off-by: Lu Baolu baolu.lu@linux.intel.com --- include/linux/iommu.h | 8 ++++++ drivers/iommu/{iommu-sva.h => io-pgfault.h} | 26 +++++-------------- .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- drivers/iommu/intel/iommu.c | 2 +- drivers/iommu/intel/svm.c | 2 +- drivers/iommu/io-pgfault.c | 2 +- drivers/iommu/iommu-sva.c | 2 +- drivers/iommu/iommu.c | 2 +- drivers/iommu/Kconfig | 4 +++ drivers/iommu/Makefile | 3 ++- drivers/iommu/intel/Kconfig | 1 + 12 files changed, 29 insertions(+), 27 deletions(-) rename drivers/iommu/{iommu-sva.h => io-pgfault.h} (69%)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f69ac54dc583..c201704f9aea 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -1399,6 +1399,9 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm); void iommu_sva_unbind_device(struct iommu_sva *handle); u32 iommu_sva_get_pasid(struct iommu_sva *handle); +enum iommu_page_response_code +iommu_sva_handle_iopf(struct iommu_fault *fault, + struct device *dev, void *data); #else static inline struct iommu_sva * iommu_sva_bind_device(struct device *dev, struct mm_struct *mm) @@ -1417,6 +1420,11 @@ static inline u32 iommu_sva_get_pasid(struct iommu_sva *handle) static inline void mm_pasid_init(struct mm_struct *mm) {} static inline bool mm_valid_pasid(struct mm_struct *mm) { return false; } static inline void mm_pasid_drop(struct mm_struct *mm) {} +static inline enum iommu_page_response_code +iommu_sva_handle_iopf(struct iommu_fault *fault, struct device *dev, void *data) +{ + return IOMMU_PAGE_RESP_INVALID; +} #endif /* CONFIG_IOMMU_SVA */
#endif /* __LINUX_IOMMU_H */ diff --git a/drivers/iommu/iommu-sva.h b/drivers/iommu/io-pgfault.h similarity index 69% rename from drivers/iommu/iommu-sva.h rename to drivers/iommu/io-pgfault.h index 5333d6a26047..587844e36554 100644 --- a/drivers/iommu/iommu-sva.h +++ b/drivers/iommu/io-pgfault.h @@ -1,18 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * SVA library for IOMMU drivers + * I/O page fault helpers for IOMMU drivers */ -#ifndef _IOMMU_SVA_H -#define _IOMMU_SVA_H +#ifndef _IOMMU_PGFAULT_H +#define _IOMMU_PGFAULT_H
-#include <linux/mm_types.h> - -/* I/O Page fault */ struct device; struct iommu_fault; struct iopf_queue;
-#ifdef CONFIG_IOMMU_SVA +#ifdef CONFIG_IOMMU_PGFAULT int iommu_queue_iopf(struct iommu_fault *fault, void *cookie);
int iopf_queue_add_device(struct iopf_queue *queue, struct device *dev); @@ -22,11 +19,8 @@ int iopf_queue_flush_dev(struct device *dev); struct iopf_queue *iopf_queue_alloc(const char *name); void iopf_queue_free(struct iopf_queue *queue); int iopf_queue_discard_partial(struct iopf_queue *queue); -enum iommu_page_response_code -iommu_sva_handle_iopf(struct iommu_fault *fault, - struct device *dev, void *data);
-#else /* CONFIG_IOMMU_SVA */ +#else /* CONFIG_IOMMU_PGFAULT */ static inline int iommu_queue_iopf(struct iommu_fault *fault, void *cookie) { return -ENODEV; @@ -62,11 +56,5 @@ static inline int iopf_queue_discard_partial(struct iopf_queue *queue) { return -ENODEV; } - -static inline enum iommu_page_response_code -iommu_sva_handle_iopf(struct iommu_fault *fault, struct device *dev, void *data) -{ - return IOMMU_PAGE_RESP_INVALID; -} -#endif /* CONFIG_IOMMU_SVA */ -#endif /* _IOMMU_SVA_H */ +#endif /* CONFIG_IOMMU_PGFAULT */ +#endif /* _IOMMU_PGFAULT_H */ diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c index a5a63b1c947e..a6401500585b 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c @@ -10,7 +10,7 @@ #include <linux/slab.h>
#include "arm-smmu-v3.h" -#include "../../iommu-sva.h" +#include "../../io-pgfault.h" #include "../../io-pgtable-arm.h"
struct arm_smmu_mmu_notifier { diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 8ec4ee5270b1..021e72eade5f 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -30,7 +30,7 @@
#include "arm-smmu-v3.h" #include "../../dma-iommu.h" -#include "../../iommu-sva.h" +#include "../../io-pgfault.h"
static bool disable_bypass = true; module_param(disable_bypass, bool, 0444); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 42288bd449a0..7473531c7568 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -26,7 +26,7 @@ #include "iommu.h" #include "../dma-iommu.h" #include "../irq_remapping.h" -#include "../iommu-sva.h" +#include "../io-pgfault.h" #include "pasid.h" #include "cap_audit.h" #include "perfmon.h" diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index e95b339e9cdc..243edc81db75 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -22,7 +22,7 @@ #include "iommu.h" #include "pasid.h" #include "perf.h" -#include "../iommu-sva.h" +#include "../io-pgfault.h" #include "trace.h"
static irqreturn_t prq_event_thread(int irq, void *d); diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c index dedc2ea70970..7e735369a041 100644 --- a/drivers/iommu/io-pgfault.c +++ b/drivers/iommu/io-pgfault.c @@ -11,7 +11,7 @@ #include <linux/slab.h> #include <linux/workqueue.h>
-#include "iommu-sva.h" +#include "io-pgfault.h"
/** * struct iopf_queue - IO Page Fault queue diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index 02574a49275a..585ee56e29d9 100644 --- a/drivers/iommu/iommu-sva.c +++ b/drivers/iommu/iommu-sva.c @@ -7,7 +7,7 @@ #include <linux/sched/mm.h> #include <linux/iommu.h>
-#include "iommu-sva.h" +#include "io-pgfault.h"
static DEFINE_MUTEX(iommu_sva_lock); static DEFINE_IDA(iommu_global_pasid_ida); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index fd65ed1d3642..cace57c066f4 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -36,7 +36,7 @@ #include "dma-iommu.h" #include "iommu-priv.h"
-#include "iommu-sva.h" +#include "io-pgfault.h"
#include "iommu-priv.h"
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index db98c3f86e8c..92ecaf21b355 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -157,6 +157,9 @@ config IOMMU_DMA config IOMMU_SVA bool
+config IOMMU_PGFAULT + bool + config FSL_PAMU bool "Freescale IOMMU support" depends on PCI @@ -402,6 +405,7 @@ config ARM_SMMU_V3_SVA bool "Shared Virtual Addressing support for the ARM SMMUv3" depends on ARM_SMMU_V3 select IOMMU_SVA + select IOMMU_PGFAULT select MMU_NOTIFIER help Support for sharing process address spaces with devices using the diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 769e43d780ce..ff5c69c7cb02 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o obj-$(CONFIG_S390_IOMMU) += s390-iommu.o obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o -obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o io-pgfault.o +obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o +obj-$(CONFIG_IOMMU_PGFAULT) += io-pgfault.o obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o obj-$(CONFIG_APPLE_DART) += apple-dart.o diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig index 2e56bd79f589..0c2d9202f8ff 100644 --- a/drivers/iommu/intel/Kconfig +++ b/drivers/iommu/intel/Kconfig @@ -15,6 +15,7 @@ config INTEL_IOMMU select DMA_OPS select IOMMU_API select IOMMU_IOVA + select IOMMU_PGFAULT select NEED_DMA_MAP_STATE select DMAR_TABLE select SWIOTLB