IOASIDs associated with user processes are subject to resource
restrictions. However, in-kernel usages can target only one global
kernel virtual address mapping. Reserve a special IOASID for the devices
that perform DMA requests with PASID. This global PASID is excluded from
the IOASID allocator.

Signed-off-by: Jacob Pan <[email protected]>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +-
 drivers/iommu/ioasid.c                          | 2 ++
 drivers/iommu/iommu-sva-lib.c                   | 1 +
 include/linux/ioasid.h                          | 4 ++++
 4 files changed, 8 insertions(+), 1 deletion(-)

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 bb251cab61f3..c5fb89bd6229 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
@@ -329,7 +329,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct 
*mm)
                return ERR_PTR(-ENOMEM);
 
        /* Allocate a PASID for this mm if necessary */
-       ret = iommu_sva_alloc_pasid(mm, 1, (1U << master->ssid_bits) - 1);
+       ret = iommu_sva_alloc_pasid(mm, IOASID_ALLOC_START, (1U << 
master->ssid_bits) - 1);
        if (ret)
                goto err_free_bond;
 
diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c
index 50ee27bbd04e..89c6132bf1ec 100644
--- a/drivers/iommu/ioasid.c
+++ b/drivers/iommu/ioasid.c
@@ -317,6 +317,8 @@ ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, 
ioasid_t max,
        data->private = private;
        refcount_set(&data->refs, 1);
 
+       if (min < IOASID_ALLOC_BASE)
+               min = IOASID_ALLOC_BASE;
        /*
         * Custom allocator needs allocator data to perform platform specific
         * operations.
diff --git a/drivers/iommu/iommu-sva-lib.c b/drivers/iommu/iommu-sva-lib.c
index bd41405d34e9..4f56843517e5 100644
--- a/drivers/iommu/iommu-sva-lib.c
+++ b/drivers/iommu/iommu-sva-lib.c
@@ -28,6 +28,7 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, 
ioasid_t max)
        int ret = 0;
        ioasid_t pasid;
 
+       /* TODO: no need to check!! reserved range is checked in ioasid_alloc() 
*/
        if (min == INVALID_IOASID || max == INVALID_IOASID ||
            min == 0 || max < min)
                return -EINVAL;
diff --git a/include/linux/ioasid.h b/include/linux/ioasid.h
index e9dacd4b9f6b..4d435cbd48b8 100644
--- a/include/linux/ioasid.h
+++ b/include/linux/ioasid.h
@@ -6,6 +6,10 @@
 #include <linux/errno.h>
 
 #define INVALID_IOASID ((ioasid_t)-1)
+#define IOASID_DMA_NO_PASID    0 /* For DMA request w/o PASID */
+#define IOASID_DMA_PASID       1 /* For in-kernel DMA w/ PASID */
+#define IOASID_ALLOC_BASE      2 /* Start of the allocation */
+
 typedef unsigned int ioasid_t;
 typedef ioasid_t (*ioasid_alloc_fn_t)(ioasid_t min, ioasid_t max, void *data);
 typedef void (*ioasid_free_fn_t)(ioasid_t ioasid, void *data);
-- 
2.25.1

_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to