iommu/sva: Tighten SVA bind API with explicit flags
Subsystems (8)
PATCH 1/2 iommu/sva: Tighten SVA bind API with explicit flags
The void* drvdata parameter isn't really used in iommu_sva_bind_device() API, the current IDXD code "borrows" the drvdata for a VT-d private flag for supervisor SVA usage.
Supervisor/Privileged mode request is a generic feature. It should be promoted from the VT-d vendor driver to the generic code.
This patch replaces void* drvdata with a unsigned int flags parameter and adjusts callers accordingly.
--- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 6 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 ++-- drivers/iommu/intel/Kconfig | 1 + drivers/iommu/intel/svm.c | 18 ++++++------------ drivers/iommu/iommu.c | 9 ++++++--- drivers/misc/uacce/uacce.c | 2 +- include/linux/intel-iommu.h | 2 +- include/linux/intel-svm.h | 17 ++--------------- include/linux/iommu.h | 19 ++++++++++++++++--- 11 files changed, 40 insertions(+), 42 deletions(-)
drivers/dma/idxd/cdev.c +1 -1
@@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx;if (device_pasid_enabled (idxd)) { - sva =iommu_sva_bind_device (dev, current->mm,NULL ); + sva =iommu_sva_bind_device (dev, current->mm,0 );if (IS_ERR (sva)) { rc =PTR_ERR (sva);dev_err (dev,"pasid allocation failed: %d\n" , rc);
drivers/dma/idxd/init.c +3 -3
@@ -300,13 +300,13 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev)static int idxd_enable_system_pasid (struct idxd_device *idxd) { -int flags; +unsigned int flags;unsigned int pasid;struct iommu_sva *sva; - flags =SVM_FLAG_SUPERVISOR_MODE ; + flags =IOMMU_SVA_BIND_SUPERVISOR ; - sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , &flags); + sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , flags);if (IS_ERR (sva)) {dev_warn (&idxd->pdev->dev,"iommu sva bind failed: %ld\n" ,PTR_ERR (sva));
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +1 -1
@@ -354,7 +354,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) }struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_sva *handle;struct iommu_domain *domain =iommu_get_domain_for_dev (dev);
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +2 -2
@@ -711,7 +711,7 @@ bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);int arm_smmu_master_enable_sva (struct arm_smmu_master *master);int arm_smmu_master_disable_sva (struct arm_smmu_master *master);struct iommu_sva *arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void arm_smmu_sva_unbind (struct iommu_sva *handle);u32 arm_smmu_sva_get_pasid (struct iommu_sva *handle);void arm_smmu_sva_notifier_synchronize (void );
@@ -742,7 +742,7 @@ static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) }static inline struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {return ERR_PTR (-ENODEV ); }
drivers/iommu/intel/Kconfig +1 -0
@@ -41,6 +41,7 @@ config INTEL_IOMMU_SVM select PCI_PRI select MMU_NOTIFIER select IOASID + select IOMMU_SVA_LIB help Shared Virtual Memory (SVM) provides a facility for devices to access DMA resources through process address space by
drivers/iommu/intel/svm.c +6 -12
@@ -486,12 +486,9 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, }else pasid_max =1 <<20 ; -/* Bind supervisor PASID shuld have mm = NULL */ -if (flags &SVM_FLAG_SUPERVISOR_MODE ) { -if (!ecap_srs (iommu->ecap) || mm) { -pr_err ("Supervisor PASID with user provided mm.\n" ); -return -EINVAL ; - } +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && !ecap_srs (iommu->ecap)) { +pr_err ("Supervisor PASID not supported.\n" ); +return -EINVAL ; }if (!(flags &SVM_FLAG_PRIVATE_PASID )) {
@@ -593,7 +590,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret =intel_pasid_setup_first_level (iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid,FLPT_DEFAULT_DID , - (mm ?0 :PASID_FLAG_SUPERVISOR_MODE ) | + (mm ?0 :IOMMU_SVA_BIND_SUPERVISOR ) | (cpu_feature_enabled (X86_FEATURE_LA57 ) ?PASID_FLAG_FL5LP :0 ));spin_unlock_irqrestore (&iommu->lock, iflags);
@@ -620,7 +617,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret =intel_pasid_setup_first_level (iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid,FLPT_DEFAULT_DID , - (mm ?0 :PASID_FLAG_SUPERVISOR_MODE ) | + (mm ?0 :IOMMU_SVA_BIND_SUPERVISOR ) | (cpu_feature_enabled (X86_FEATURE_LA57 ) ?PASID_FLAG_FL5LP :0 ));spin_unlock_irqrestore (&iommu->lock, iflags);
@@ -1059,11 +1056,10 @@ static irqreturn_t prq_event_thread(int irq, void *d)#define to_intel_svm_dev (handle) container_of(handle, struct intel_svm_dev, sva)struct iommu_sva * -intel_svm_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +intel_svm_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_sva *sva =ERR_PTR (-EINVAL );struct intel_svm_dev *sdev =NULL ; -unsigned int flags =0 ;int ret;/*
@@ -1071,8 +1067,6 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata)* It will require shared SVM data structures, i.e. combine io_mm * and intel_svm etc. */ -if (drvdata) - flags = *(unsigned int *)drvdata;mutex_lock (&pasid_mutex); ret =intel_svm_bind_mm (dev, flags,NULL , mm, &sdev);if (ret)
drivers/iommu/iommu.c +6 -3
@@ -2962,6 +2962,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* iommu_sva_bind_device() - Bind a process address space to a device * @dev: the device * @mm: the mm to bind, caller must hold a reference to it +* @flags: options for the bind operation * * Create a bond between device and address space, allowing the device to access * the mm using the returned PASID. If a bond already exists between @device and
@@ -2974,7 +2975,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* On error, returns an ERR_PTR value. */ struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_group *group;struct iommu_sva *handle =ERR_PTR (-EINVAL );
@@ -2987,6 +2988,9 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)if (!group)return ERR_PTR (-ENODEV ); +/* Supervisor SVA does not need the current mm */ +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) +return ERR_PTR (-EINVAL );/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);
@@ -2999,8 +3003,7 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)if (iommu_group_device_count (group) !=1 ) goto out_unlock; - handle = ops->sva_bind (dev, mm, drvdata); - + handle = ops->sva_bind (dev, mm, flags); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);
drivers/misc/uacce/uacce.c +1 -1
@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)if (!(uacce->flags &UACCE_DEV_SVA ))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm,NULL ); + handle =iommu_sva_bind_device (uacce->parent, current->mm,0 );if (IS_ERR (handle))return PTR_ERR (handle);
include/linux/intel-iommu.h +1 -1
@@ -757,7 +757,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, struct iommu_gpasid_bind_data *data);int intel_svm_unbind_gpasid (struct device *dev,u32 pasid);struct iommu_sva *intel_svm_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void intel_svm_unbind (struct iommu_sva *handle);u32 intel_svm_get_pasid (struct iommu_sva *handle); int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt,
include/linux/intel-svm.h +2 -15
@@ -30,30 +30,17 @@ struct svm_dev_ops {* if there is no other way to do so. It should be used sparingly, if at all. */ #define SVM_FLAG_PRIVATE_PASID (1<<0) - -/* -* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only -* for access to kernel addresses. No IOTLB flushes are automatically done -* for kernel mappings; it is valid only for access to the kernel's static -* 1:1 mapping of physical memory — not to vmalloc or even module mappings. -* A future API addition may permit the use of such ranges, by means of an -* explicit IOTLB flush call (akin to the DMA API's unmap method). -* -* It is unlikely that we will ever hook into flush_tlb_kernel_range() to -* do such IOTLB flushes automatically. -*/ -#define SVM_FLAG_SUPERVISOR_MODE (1<<1)/* * The SVM_FLAG_GUEST_MODE flag is used when a PASID bind is for guest * processes. Compared to the host bind, the primary differences are: * 1. mm life cycle management * 2. fault reporting */ -#define SVM_FLAG_GUEST_MODE (1<<2) +#define SVM_FLAG_GUEST_MODE (1<<1)/* * The SVM_FLAG_GUEST_PASID flag is used when a guest has its own PASID space, * which requires guest and host PASID translation at both directions. */ -#define SVM_FLAG_GUEST_PASID (1<<3) +#define SVM_FLAG_GUEST_PASID (1<<2)#endif /* __INTEL_SVM_H__ */
include/linux/iommu.h +16 -3
@@ -166,6 +166,19 @@ enum iommu_dev_features {#ifdef CONFIG_IOMMU_API +/* +* The IOMMU_SVA_BIND_SUPERVISOR flag requests a PASID which can be used only +* for access to kernel addresses. No IOTLB flushes are automatically done +* for kernel mappings; it is valid only for access to the kernel's static +* 1:1 mapping of physical memory — not to vmalloc or even module mappings. +* A future API addition may permit the use of such ranges, by means of an +* explicit IOTLB flush call (akin to the DMA API's unmap method). +* +* It is unlikely that we will ever hook into flush_tlb_kernel_range() to +* do such IOTLB flushes automatically. +*/ +#define IOMMU_SVA_BIND_SUPERVISOR BIT(0) +/** * struct iommu_iotlb_gather - Range information for a pending IOTLB flush *
@@ -287,7 +300,7 @@ struct iommu_ops {int (*aux_get_pasid)(struct iommu_domain *domain,struct device *dev);struct iommu_sva *(*sva_bind)(struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void (*sva_unbind)(struct iommu_sva *handle);u32 (*sva_get_pasid)(struct iommu_sva *handle);
@@ -640,7 +653,7 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);
@@ -1015,7 +1028,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) {return NULL ; }
Signature · 1 line
2.7.4
PATCH 2/2 iommu/sva: Remove mm parameter from SVA bind API
The mm parameter in iommu_sva_bind_device() is intended for privileged process perform bind() on behalf of other processes. This use case has yet to be materialized, let alone potential security implications of adding kernel hooks without explicit user consent.
In addition, with the agreement that IOASID allocation shall be subject cgroup limit. It will be inline with misc cgroup proposal if IOASID allocation as part of the SVA bind is limited to the current task.
--- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 6 ++--- drivers/iommu/iommu-sva-lib.c | 30 +++++++++++++++++++------ drivers/iommu/iommu-sva-lib.h | 4 ++-- drivers/iommu/iommu.c | 16 ++++++++----- drivers/misc/uacce/uacce.c | 2 +- include/linux/iommu.h | 7 +++--- 8 files changed, 45 insertions(+), 24 deletions(-)
drivers/dma/idxd/cdev.c +1 -1
@@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx;if (device_pasid_enabled (idxd)) { - sva =iommu_sva_bind_device (dev, current->mm,0 ); + sva =iommu_sva_bind_device (dev,0 );if (IS_ERR (sva)) { rc =PTR_ERR (sva);dev_err (dev,"pasid allocation failed: %d\n" , rc);
drivers/dma/idxd/init.c +1 -1
@@ -306,7 +306,7 @@ static int idxd_enable_system_pasid(struct idxd_device *idxd) flags =IOMMU_SVA_BIND_SUPERVISOR ; - sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , flags); + sva =iommu_sva_bind_device (&idxd->pdev->dev, flags);if (IS_ERR (sva)) {dev_warn (&idxd->pdev->dev,"iommu sva bind failed: %ld\n" ,PTR_ERR (sva));
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +3 -3
@@ -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 (1 , (1U << master->ssid_bits) -1 );if (ret) goto err_free_bond;
@@ -347,7 +347,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)return &bond->sva; err_free_pasid: -iommu_sva_free_pasid (mm); +iommu_sva_free_pasid (); err_free_bond:kfree (bond);return ERR_PTR (ret);
@@ -377,7 +377,7 @@ void arm_smmu_sva_unbind(struct iommu_sva *handle)if (refcount_dec_and_test (&bond->refs)) {list_del (&bond->list);arm_smmu_mmu_notifier_put (bond->smmu_mn); -iommu_sva_free_pasid (bond->mm); +iommu_sva_free_pasid ();kfree (bond); }mutex_unlock (&sva_lock);
drivers/iommu/iommu-sva-lib.c +23 -7
@@ -12,27 +12,33 @@ static DECLARE_IOASID_SET(iommu_sva_pasid);/** * iommu_sva_alloc_pasid - Allocate a PASID for the mm -* @mm: the mm * @min: minimum PASID value (inclusive) * @max: maximum PASID value (inclusive) * -* Try to allocate a PASID for this mm, or take a reference to the existing one -* provided it fits within the [@min, @max] range. On success the PASID is -* available in mm->pasid, and must be released with iommu_sva_free_pasid(). +* Try to allocate a PASID for the current mm, or take a reference to the +* existing one provided it fits within the [@min, @max] range. On success +* the PASID is available in the current mm->pasid, and must be released with +* iommu_sva_free_pasid(). * @min must be greater than 0, because 0 indicates an unused mm->pasid. * * Returns 0 on success and < 0 on error. */ -int iommu_sva_alloc_pasid (struct mm_struct *mm,ioasid_t min,ioasid_t max) +int iommu_sva_alloc_pasid (ioasid_t min,ioasid_t max) {int ret =0 ;ioasid_t pasid; +struct mm_struct *mm;if (min ==INVALID_IOASID || max ==INVALID_IOASID || min ==0 || max < min)return -EINVAL ;mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current); +if (!mm) { + ret = -EINVAL ; + goto out_unlock; + }if (mm->pasid) {if (mm->pasid >= min && mm->pasid <= max)ioasid_get (mm->pasid);
@@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max)else mm->pasid = pasid; } +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock);return ret; }EXPORT_SYMBOL_GPL (iommu_sva_alloc_pasid);/** -* iommu_sva_free_pasid - Release the mm's PASID +* iommu_sva_free_pasid - Release the current mm's PASID * @mm: the mm * * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid() */ -void iommu_sva_free_pasid (struct mm_struct *mm) +void iommu_sva_free_pasid (void ) { +struct mm_struct *mm; +mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current); +if (!mm) + goto out_unlock; +if (ioasid_put (mm->pasid)) mm->pasid =0 ; +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock); }EXPORT_SYMBOL_GPL (iommu_sva_free_pasid);
drivers/iommu/iommu-sva-lib.h +2 -2
@@ -8,8 +8,8 @@#include <linux/ioasid.h> #include <linux/mm_types.h> -int iommu_sva_alloc_pasid (struct mm_struct *mm,ioasid_t min,ioasid_t max); -void iommu_sva_free_pasid (struct mm_struct *mm); +int iommu_sva_alloc_pasid (ioasid_t min,ioasid_t max); +void iommu_sva_free_pasid (void );struct mm_struct *iommu_sva_find (ioasid_t pasid);#endif /* _IOMMU_SVA_LIB_H */
drivers/iommu/iommu.c +11 -5
@@ -23,6 +23,7 @@#include <linux/property.h> #include <linux/fsl/mc.h> #include <linux/module.h> +#include <linux/sched/mm.h> #include <trace/events/iommu.h> static struct kset *iommu_group_kset;
@@ -2959,9 +2960,8 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)EXPORT_SYMBOL_GPL (iommu_aux_get_pasid);/** -* iommu_sva_bind_device() - Bind a process address space to a device +* iommu_sva_bind_device() - Bind the current process address space to a device * @dev: the device -* @mm: the mm to bind, caller must hold a reference to it * @flags: options for the bind operation * * Create a bond between device and address space, allowing the device to access
@@ -2975,9 +2975,10 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* On error, returns an ERR_PTR value. */ struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) +iommu_sva_bind_device (struct device *dev,unsigned int flags) {struct iommu_group *group; +struct mm_struct *mm =NULL ;struct iommu_sva *handle =ERR_PTR (-EINVAL );const struct iommu_ops *ops = dev->bus->iommu_ops;
@@ -2989,8 +2990,11 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, unsigned int flareturn ERR_PTR (-ENODEV );/* Supervisor SVA does not need the current mm */ -if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) -return ERR_PTR (-EINVAL ); +if (!(flags &IOMMU_SVA_BIND_SUPERVISOR )) { + mm =get_task_mm (current); +if (!mm) +return ERR_PTR (-EINVAL ); + }/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);
@@ -3004,6 +3008,8 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, unsigned int fla goto out_unlock; handle = ops->sva_bind (dev, mm, flags); +if (mm) +mmput (mm); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);
drivers/misc/uacce/uacce.c +1 -1
@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)if (!(uacce->flags &UACCE_DEV_SVA ))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm,0 ); + handle =iommu_sva_bind_device (uacce->parent,0 );if (IS_ERR (handle))return PTR_ERR (handle);
include/linux/iommu.h +3 -4
@@ -231,8 +231,8 @@ struct iommu_iotlb_gather {* @dev_feat_enabled: check enabled feature * @aux_attach/detach_dev: aux-domain specific attach/detach entries. * @aux_get_pasid: get the pasid given an aux-domain -* @sva_bind: Bind process address space to device -* @sva_unbind: Unbind process address space from device +* @sva_bind: Bind the current process address space to device +* @sva_unbind: Unbind the current process address space from device * @sva_get_pasid: Get PASID associated to a SVA handle * @page_response: handle page request response * @cache_invalidate: invalidate translation caches
@@ -652,7 +652,6 @@ void iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev);int iommu_aux_get_pasid (struct iommu_domain *domain,struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev, -struct mm_struct *mm,unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);
@@ -1028,7 +1027,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) +iommu_sva_bind_device (struct device *dev,unsigned int flags) {return NULL ; }
Signature · 1 line
2.7.4
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Quoted 30 lines · Jacob Pan
drivers/iommu/iommu-sva-lib.c +6
-5@@ -12,27 +12,33 @@ static DECLARE_IOASID_SET(iommu_sva_pasid);/** * iommu_sva_alloc_pasid - Allocate a PASID for the mm -* @mm: the mm * @min: minimum PASID value (inclusive) * @max: maximum PASID value (inclusive) * -* Try to allocate a PASID for this mm, or take a reference to the existing one -* provided it fits within the [@min, @max] range. On success the PASID is -* available in mm->pasid, and must be released with iommu_sva_free_pasid(). +* Try to allocate a PASID for the current mm, or take a reference to the +* existing one provided it fits within the [@min, @max] range. On success +* the PASID is available in the current mm->pasid, and must be released with +* iommu_sva_free_pasid(). * @min must be greater than 0, because 0 indicates an unused mm->pasid. * * Returns 0 on success and < 0 on error. */ -int iommu_sva_alloc_pasid (struct mm_struct *mm,ioasid_t min,ioasid_t max) +int iommu_sva_alloc_pasid (ioasid_t min,ioasid_t max) {int ret =0 ;ioasid_t pasid; +struct mm_struct *mm;
drivers/iommu/iommu-sva-lib.c static DECLARE_IOASID_SET(iommu_sva_pasid); · line 41
Quoted 10 lines
drivers/iommu/iommu-sva-lib.c +5
-0if (min ==INVALID_IOASID || max ==INVALID_IOASID || min ==0 || max < min)return -EINVAL ;mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current); +if (!mm) { + ret = -EINVAL ; + goto out_unlock; + }
I still think it would be more elegant to keep the choice of context in iommu_sva_bind_device() and pass it down to leaf functions such as iommu_sva_alloc_pasid(). The patch is trying to solve two separate problems:
* We don't have a use-case for binding the mm of a remote process (and it's supposedly difficult for device drivers to do it securely). So OK, we remove the mm argument from iommu_sva_bind_device() and use the current mm. But the IOMMU driver isn't going to do get_task_mm(current) every time it needs the mm being bound, it will take it from iommu_sva_bind_device(). Likewise iommu_sva_alloc_pasid() shouldn't need to bother with get_task_mm().
* cgroup accounting for IOASIDs needs to be on the current task. Removing the mm parameter from iommu_sva_alloc_pasid() doesn't help with that. Sure it indicates that iommu_sva_alloc_pasid() needs a specific task context but that's only for cgroup purpose, and I'd rather pass the cgroup down from iommu_sva_bind_device() anyway (but am fine with keeping it within ioasid_alloc() for now). Plus it's an internal helper, easy for us to check that the callers are doing the right thing.
Quoted 21 lines
drivers/iommu/iommu-sva-lib.c +3
-1if (mm->pasid) {if (mm->pasid >= min && mm->pasid <= max)ioasid_get (mm->pasid);@@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max)else mm->pasid = pasid; } +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock);return ret; }EXPORT_SYMBOL_GPL (iommu_sva_alloc_pasid);/** -* iommu_sva_free_pasid - Release the mm's PASID +* iommu_sva_free_pasid - Release the current mm's PASID * @mm: the mm * * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid() */
drivers/iommu/iommu-sva-lib.c int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) · line 75
Quoted 10 lines
drivers/iommu/iommu-sva-lib.c +7
-1-void iommu_sva_free_pasid (struct mm_struct *mm) +void iommu_sva_free_pasid (void ) { +struct mm_struct *mm; +mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current); +if (!mm) + goto out_unlock; +
More importantly, could we at least dissociate free_pasid() from the current process? Otherwise drivers can't clean up from a workqueue (as amdkfd does) or from an rcu callback. Given that iommu_sva_unbind_device() takes the SVA handle owned by whomever did bind(), there shouldn't be any security issue. For the cgroup problem, ioasid.c could internally keep track of the cgroup used during allocation rather than assuming the context of ioasid_put() is the same as ioasid_get()
Quoted 35 lines
drivers/iommu/iommu-sva-lib.c +2
-0if (ioasid_put (mm->pasid)) mm->pasid =0 ; +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock); }EXPORT_SYMBOL_GPL (iommu_sva_free_pasid);drivers/iommu/iommu-sva-lib.h +2
-2@@ -8,8 +8,8 @@#include <linux/ioasid.h> #include <linux/mm_types.h> -int iommu_sva_alloc_pasid (struct mm_struct *mm,ioasid_t min,ioasid_t max); -void iommu_sva_free_pasid (struct mm_struct *mm); +int iommu_sva_alloc_pasid (ioasid_t min,ioasid_t max); +void iommu_sva_free_pasid (void );struct mm_struct *iommu_sva_find (ioasid_t pasid);#endif /* _IOMMU_SVA_LIB_H */ drivers/iommu/iommu.c +1
-0@@ -23,6 +23,7 @@#include <linux/property.h> #include <linux/fsl/mc.h> #include <linux/module.h> +#include <linux/sched/mm.h> #include <trace/events/iommu.h> static struct kset *iommu_group_kset;
drivers/iommu/iommu.c int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) · line 2967
Quoted 10 lines
drivers/iommu/iommu.c +1
-2@@ -2959,9 +2960,8 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)EXPORT_SYMBOL_GPL (iommu_aux_get_pasid);/** -* iommu_sva_bind_device() - Bind a process address space to a device +* iommu_sva_bind_device() - Bind the current process address space to a device * @dev: the device -* @mm: the mm to bind, caller must hold a reference to it * @flags: options for the bind operation * * Create a bond between device and address space, allowing the device to access
There is another reference to @mm to remove in the function description
Quoted 53 lines
drivers/iommu/iommu.c +9
-3@@ -2975,9 +2975,10 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* On error, returns an ERR_PTR value. */ struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) +iommu_sva_bind_device (struct device *dev,unsigned int flags) {struct iommu_group *group; +struct mm_struct *mm =NULL ;struct iommu_sva *handle =ERR_PTR (-EINVAL );const struct iommu_ops *ops = dev->bus->iommu_ops;@@ -2989,8 +2990,11 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, unsigned int flareturn ERR_PTR (-ENODEV );/* Supervisor SVA does not need the current mm */ -if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) -return ERR_PTR (-EINVAL ); +if (!(flags &IOMMU_SVA_BIND_SUPERVISOR )) { + mm =get_task_mm (current); +if (!mm) +return ERR_PTR (-EINVAL ); + }/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);@@ -3004,6 +3008,8 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, unsigned int fla goto out_unlock; handle = ops->sva_bind (dev, mm, flags); +if (mm) +mmput (mm); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);drivers/misc/uacce/uacce.c +1
-1@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)if (!(uacce->flags &UACCE_DEV_SVA ))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm,0 ); + handle =iommu_sva_bind_device (uacce->parent,0 );if (IS_ERR (handle))return PTR_ERR (handle);include/linux/iommu.h +0
-0
include/linux/iommu.h struct iommu_iotlb_gather { · line 235
Quoted 7 lines
include/linux/iommu.h +2
-2@@ -231,8 +231,8 @@ struct iommu_iotlb_gather {* @dev_feat_enabled: check enabled feature * @aux_attach/detach_dev: aux-domain specific attach/detach entries. * @aux_get_pasid: get the pasid given an aux-domain -* @sva_bind: Bind process address space to device -* @sva_unbind: Unbind process address space from device +* @sva_bind: Bind the current process address space to device +* @sva_unbind: Unbind the current process address space from device
These don't need changing since we're still passing the mm down to the drivers
Thanks,
Jean
Quoted 23 lines
include/linux/iommu.h +1
-2* @sva_get_pasid: Get PASID associated to a SVA handle * @page_response: handle page request response * @cache_invalidate: invalidate translation caches @@ -652,7 +652,6 @@ void iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev);int iommu_aux_get_pasid (struct iommu_domain *domain,struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev, -struct mm_struct *mm,unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);@@ -1028,7 +1027,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) +iommu_sva_bind_device (struct device *dev,unsigned int flags) {return NULL ; }Signature · 1 line
2.7.4
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jean-Philippe,
Quoted 41 lines · Jean-Philippe Brucker
Quoted 40 lines · Jacob Pan
(quoted diff) +0
-0
b/drivers/iommu/iommu-sva-lib.cindex bd41405..bd99f6b 100644drivers/iommu/iommu-sva-lib.c +0
-2@@ -12,27 +12,33 @@ static DECLARE_IOASID_SET(iommu_sva_pasid);/** * iommu_sva_alloc_pasid - Allocate a PASID for the mm -* @mm: the mm * @min: minimum PASID value (inclusive) * @max: maximum PASID value (inclusive) * -* Try to allocate a PASID for this mm, or take a reference to the existing one
- * provided it fits within the [@min, @max] range. On success the PASID is
- * available inmm->pasid, and must be released withiommu_sva_free_pasid().
+ * Try to allocate a PASID for the current mm, or take a reference to the
+ * existing one provided it fits within the [@min, @max] range. On success
+ * the PASID is available in the currentmm->pasid, and must be released with
+ *iommu_sva_free_pasid().
* @min must be greater than 0, because 0 indicates an unusedmm->pasid. *
* Returns 0 on success and < 0 on error.
*/
-intiommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max)+intiommu_sva_alloc_pasid(ioasid_t min, ioasid_t max)
{drivers/iommu/iommu-sva-lib.c +1
-0int ret =0 ;ioasid_t pasid; +struct mm_struct *mm;if (min ==INVALID_IOASID || max ==INVALID_IOASID || min ==0 || max < min)return -EINVAL ;
Quoted 10 lines
drivers/iommu/iommu-sva-lib.c static DECLARE_IOASID_SET(iommu_sva_pasid); · line 41
Quoted 6 lines
drivers/iommu/iommu-sva-lib.c +5
-0mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current); +if (!mm) { + ret = -EINVAL ; + goto out_unlock; + }I still think it would be more elegant to keep the choice of context in
iommu_sva_bind_device()and pass it down to leaf functions such asiommu_sva_alloc_pasid(). The patch is trying to solve two separate
I agree if iommu_sva_alloc_pasid() is a leaf function, but it is a public function, e.g. called by smmu code:
/* Allocate a PASID for this mm if necessary */ ret = iommu_sva_alloc_pasid(1, (1U << master->ssid_bits) - 1);
If we give mm as parameter, it will give callers the illusion that this mm doesn't have to be current->mm.
Should we make it into a leaf function by splitting iommu_sva_alloc_pasid() into two parts?
1. iommu_sva_assign_pasid() //a new leaf helper function does mm->pasid assignment
2. ioasid_alloc()
in iommu_sva_bind_device(), we do:
1. handle = driver ops->sva_bind(dev, mm, flags);
2. pasid = sva_get_pasid(handle);
3. iommu_sva_assign_pasid(mm, pasid)
In vendor driver sva_bind(), it just use ioasid_alloc directly with custom range. e.g. arm-smmu-v3-sva.c
- ret = iommu_sva_alloc_pasid(1, (1U << master->ssid_bits) - 1);
+ ret = ioasid_alloc(&iommu_sva_pasid, 1, (1U << master->ssid_bits);
Quoted 10 lines
problems:
* We don't have a use-case for binding the mm of a remote process (and it's supposedly difficult for device drivers to do it securely). So OK, we remove the mm argument from
iommu_sva_bind_device()and use the current mm. But the IOMMU driver isn't going to doget_task_mm(current)every time it needs the mm being bound, it will take it fromiommu_sva_bind_device(). Likewiseiommu_sva_alloc_pasid()shouldn't need to bother withget_task_mm().
Quoted 8 lines
* cgroup accounting for IOASIDs needs to be on the current task. Removing the mm parameter from
iommu_sva_alloc_pasid()doesn't help with that. Sure it indicates thatiommu_sva_alloc_pasid()needs a specific task context but that's only for cgroup purpose, and I'd rather pass the cgroup down fromiommu_sva_bind_device()anyway (but am fine with keeping it withinioasid_alloc()for now). Plus it's an internal helper, easy for us to check that the callers are doing the right thing.
With the above split, we really just have one allocation function:ioasid_alloc(), so it can manage current cgroup accounting within. Would this work?
Quoted 32 lines
Quoted 21 lines
drivers/iommu/iommu-sva-lib.c +0
-0if (mm->pasid) {if (mm->pasid >= min && mm->pasid <= max)ioasid_get (mm->pasid);@@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm,
ioasid_tmin,ioasid_tmax) elsedrivers/iommu/iommu-sva-lib.c +3
-1mm->pasid = pasid; } +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock);return ret; }EXPORT_SYMBOL_GPL (iommu_sva_alloc_pasid);/** -* iommu_sva_free_pasid - Release the mm's PASID +* iommu_sva_free_pasid - Release the current mm's PASID * @mm: the mm * * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid() */ drivers/iommu/iommu-sva-lib.c int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) · line 75
Quoted 10 lines
drivers/iommu/iommu-sva-lib.c +7
-1-void iommu_sva_free_pasid (struct mm_struct *mm) +void iommu_sva_free_pasid (void ) { +struct mm_struct *mm; +mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current); +if (!mm) + goto out_unlock; +
Quoted 8 lines
More importantly, could we at least dissociate
free_pasid()from the current process? Otherwise drivers can't clean up from a workqueue (as amdkfd does) or from an rcu callback. Given thatiommu_sva_unbind_device()takes the SVA handle owned by whomever didbind(), there shouldn't be any security issue. For the cgroup problem,ioasid.ccould internally keep track of the cgroup used during allocation rather than assuming the context ofioasid_put()is the same asioasid_get()
Good point, you are right cgroup uncharge does not have to be on the current. I will keep the mm parameter here.
Quoted 37 lines
Quoted 37 lines
drivers/iommu/iommu-sva-lib.c +2
-0if (ioasid_put (mm->pasid)) mm->pasid =0 ; +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock); }EXPORT_SYMBOL_GPL (iommu_sva_free_pasid);(quoted diff) +0
-0
b/drivers/iommu/iommu-sva-lib.hindex b40990a..278b8b4 100644drivers/iommu/iommu-sva-lib.h +2
-1@@ -8,8 +8,8 @@#include <linux/ioasid.h> #include <linux/mm_types.h> -int iommu_sva_alloc_pasid (struct mm_struct *mm,ioasid_t min,ioasid_t max); -void iommu_sva_free_pasid(struct mm_struct *mm); +int iommu_sva_alloc_pasid (ioasid_t min,ioasid_t max); +void iommu_sva_free_pasid (void );struct mm_struct *iommu_sva_find (ioasid_t pasid);#endif /* _IOMMU_SVA_LIB_H */ drivers/iommu/iommu.c +1
-0@@ -23,6 +23,7 @@#include <linux/property.h> #include <linux/fsl/mc.h> #include <linux/module.h> +#include <linux/sched/mm.h> #include <trace/events/iommu.h> static struct kset *iommu_group_kset;@@ -2959,9 +2960,8 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);
Quoted 13 lines
Quoted 10 lines
drivers/iommu/iommu.c +1
-1/** -* iommu_sva_bind_device() - Bind a process address space to a device +* iommu_sva_bind_device() - Bind the current process address space to a device
* @dev: the device
- * @mm: the mm to bind, caller must hold a reference to it
* @flags: options for the bind operation
*
* Create a bond between device and address space, allowing the device
to accessThere is another reference to @mm to remove in the function description
will do
Quoted 48 lines
Quoted 48 lines
drivers/iommu/iommu.c +0
-1@@ -2975,9 +2975,10 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* On error, returns an ERR_PTR value. */ struct iommu_sva * -iommu_sva_bind_device(struct device *dev, struct mm_struct *mm,unsigned int flags) +iommu_sva_bind_device(struct device *dev, unsigned int flags) {
drivers/iommu/iommu.c +8
-2struct iommu_group *group; +struct mm_struct *mm =NULL ;struct iommu_sva *handle =ERR_PTR (-EINVAL );const struct iommu_ops *ops = dev->bus->iommu_ops;@@ -2989,8 +2990,11 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, unsigned int fla return ERR_PTR(-ENODEV);/* Supervisor SVA does not need the current mm */ -if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) -return ERR_PTR (-EINVAL ); +if (!(flags &IOMMU_SVA_BIND_SUPERVISOR )) { + mm =get_task_mm (current); +if (!mm) +return ERR_PTR (-EINVAL ); + }/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);@@ -3004,6 +3008,8 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, unsigned int fla goto out_unlock; handle = ops->sva_bind (dev, mm, flags); +if (mm) +mmput (mm); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);drivers/misc/uacce/uacce.c +1
-1@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q) if (!(uacce->flags & UACCE_DEV_SVA))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm,0 ); + handle =iommu_sva_bind_device (uacce->parent,0 );if (IS_ERR (handle))return PTR_ERR (handle);
Quoted 16 lines
include/linux/iommu.h struct iommu_iotlb_gather { · line 235
Quoted 12 lines
include/linux/iommu.h +2
-2@@ -231,8 +231,8 @@ struct iommu_iotlb_gather {* @dev_feat_enabled: check enabled feature * @aux_attach/detach_dev: aux-domain specific attach/detach entries. * @aux_get_pasid: get the pasid given an aux-domain -* @sva_bind: Bind process address space to device -* @sva_unbind: Unbind process address space from device +* @sva_bind: Bind the current process address space to device +* @sva_unbind: Unbind the current process address space from device These don't need changing since we're still passing the mm down to the drivers
Right, I struggled between two options :)
Quoted 17 lines
Thanks,
JeanQuoted 14 lines
include/linux/iommu.h +0
-1* @sva_get_pasid: Get PASID associated to a SVA handle * @page_response: handle page request response * @cache_invalidate: invalidate translation caches @@ -652,7 +652,6 @@ void iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev); int iommu_aux_get_pasid(structiommu_domain *domain,struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev, -struct mm_struct *mm,unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);@@ -1028,7 +1027,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }
Quoted 9 lines
Quoted 9 lines
include/linux/iommu.h +0
-1static inline struct iommu_sva * -iommu_sva_bind_device(struct device *dev, struct mm_struct *mm,unsigned int flags) +iommu_sva_bind_device(struct device *dev, unsigned int flags) {
return NULL;
}Signature · 1 line
2.7.4
Thanks,
Jacob
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jean,
Quoted 18 lines · Jacob Pan
Quoted 10 lines
problems:
* We don't have a use-case for binding the mm of a remote process (and it's supposedly difficult for device drivers to do it securely). So
OK, we remove the mm argument fromiommu_sva_bind_device()and use the
current mm. But the IOMMU driver isn't going to doget_task_mm(current)every time it needs the mm being bound, it will take it fromiommu_sva_bind_device(). Likewiseiommu_sva_alloc_pasid()shouldn't need to bother withget_task_mm().Quoted 8 lines
* cgroup accounting for IOASIDs needs to be on the current task. Removing the mm parameter from
iommu_sva_alloc_pasid()doesn't help with that. Sure it indicates thatiommu_sva_alloc_pasid()needs a specific task context but that's only for cgroup purpose, and I'd rather pass the cgroup down fromiommu_sva_bind_device()anyway (but am fine with keeping it withinioasid_alloc()for now). Plus it's an internal helper, easy for us to check that the callers are doing the right thing.
Quoted 3 lines
With the above split, we really just have one allocation function:
ioasid_alloc(), so it can manage current cgroup accounting within. Would this work?
After a few attempts, I don't think the split can work better. I will restore the mm parameter and add a warning if mm != current->mm.
Thanks,
Jacob
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerRe: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jacob,
Quoted 23 lines · Jacob Pan
Hi Jean,
Quoted 18 lines · Jacob Pan
Quoted 18 lines
problems:
* We don't have a use-case for binding the mm of a remote process (and it's supposedly difficult for device drivers to do it securely). So
OK, we remove the mm argument fromiommu_sva_bind_device()and use the
current mm. But the IOMMU driver isn't going to doget_task_mm(current)every time it needs the mm being bound, it will take it fromiommu_sva_bind_device(). Likewiseiommu_sva_alloc_pasid()shouldn't need to bother withget_task_mm().* cgroup accounting for IOASIDs needs to be on the current task. Removing the mm parameter from
iommu_sva_alloc_pasid()doesn't help with that. Sure it indicates thatiommu_sva_alloc_pasid()needs a specific task context but that's only for cgroup purpose, and I'd rather pass the cgroup down fromiommu_sva_bind_device()anyway (but am fine with keeping it withinioasid_alloc()for now). Plus it's an internal helper, easy for us to check that the callers are doing the right thing.
Quoted 5 lines
Quoted 3 lines
With the above split, we really just have one allocation function:
ioasid_alloc(), so it can manage current cgroup accounting within. Would this work?After a few attempts, I don't think the split can work better. I will restore the mm parameter and add a warning if mm !=
current->mm.
I still worry about supervisor pasid allocation.
If we use iommu_sva_alloc_pasid() to allocate a supervisor pasid, which mm should the pasid be set? I've ever thought about passing &init_mm to iommu_sva_alloc_pasid(). But if you add "mm != current->mm", this seems not to work. Or do you prefer a separated interface for supervisor pasid allocation/free?
Best regards,
baolu
Quoted 5 lines
Thanks,
Jacob
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Quoted 7 lines · Lu Baolu
I still worry about supervisor pasid allocation.
If we use
iommu_sva_alloc_pasid()to allocate a supervisor pasid, which mm should the pasid be set? I've ever thought about passing&init_mmtoiommu_sva_alloc_pasid(). But if you add "mm !=current->mm", this seems not to work. Or do you prefer a separated interface for supervisor pasid allocation/free?
Without a mm_struct it is not SVA, so don't use SVA APIs for whatever a 'supervisor pasid' is
Jason
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Lu Baolu
maintainerRe: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Jason,
Quoted 4 lines · Jason Gunthorpe
Quoted 2 lines · Lu Baolu
I still worry about supervisor pasid allocation.
Quoted 8 lines
Quoted 5 lines
If we use
iommu_sva_alloc_pasid()to allocate a supervisor pasid, which mm should the pasid be set? I've ever thought about passing&init_mmtoiommu_sva_alloc_pasid(). But if you add "mm !=current->mm", this seems not to work. Or do you prefer a separated interface for supervisor pasid allocation/free?Without a
mm_structit is not SVA, so don't use SVA APIs for whatever a 'supervisor pasid' is
The supervisor PASID has its mm_struct. The only difference is that the device will set priv=1 in its DMA transactions with the PASID.
Best regards,
baolu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Quoted 13 lines · Lu Baolu
Hi Jason,
Quoted 10 lines · Jason Gunthorpe
Quoted 7 lines · Lu Baolu
I still worry about supervisor pasid allocation.
If we use
iommu_sva_alloc_pasid()to allocate a supervisor pasid, which mm should the pasid be set? I've ever thought about passing&init_mmtoiommu_sva_alloc_pasid(). But if you add "mm !=current->mm", this seems not to work. Or do you prefer a separated interface for supervisor pasid allocation/free?
Quoted 5 lines
Quoted 2 lines
Without a
mm_structit is not SVA, so don't use SVA APIs for whatever a 'supervisor pasid' isThe supervisor PASID has its
mm_struct. The only difference is that the device will set priv=1 in its DMA transactions with the PASID.
Soemthing like init_mm should not be used with 'SVA'
Jason
Lu Baolu
maintainerRe: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
In reply to Jacob PanHi,
Quoted 20 lines · Jacob Pan
/**
*iommu_sva_alloc_pasid- Allocate a PASID for the mm
- * @mm: the mm
* @min: minimum PASID value (inclusive)
* @max: maximum PASID value (inclusive)
*
- * Try to allocate a PASID for this mm, or take a reference to the existing one
- * provided it fits within the [@min, @max] range. On success the PASID is
- * available inmm->pasid, and must be released withiommu_sva_free_pasid().
+ * Try to allocate a PASID for the current mm, or take a reference to the
+ * existing one provided it fits within the [@min, @max] range. On success
+ * the PASID is available in the currentmm->pasid, and must be released with
+ *iommu_sva_free_pasid().
* @min must be greater than 0, because 0 indicates an unusedmm->pasid. *
* Returns 0 on success and < 0 on error.
*/drivers/iommu/iommu-sva-lib.c +1
-1-int iommu_sva_alloc_pasid (struct mm_struct *mm,ioasid_t min,ioasid_t max) +int iommu_sva_alloc_pasid (ioasid_t min,ioasid_t max) {
drivers/iommu/iommu-sva-lib.c static DECLARE_IOASID_SET(iommu_sva_pasid); · line 37
Quoted 10 lines
drivers/iommu/iommu-sva-lib.c +2
-0int ret =0 ;ioasid_t pasid; +struct mm_struct *mm;if (min ==INVALID_IOASID || max ==INVALID_IOASID || min ==0 || max < min)return -EINVAL ;mutex_lock (&iommu_sva_lock); + mm =get_task_mm (current);
How could we allocate a supervisor PASID through iommu_sva_alloc_pasid() if we always use current->mm here?
Quoted 8 lines
drivers/iommu/iommu-sva-lib.c +4
-0+if (!mm) { + ret = -EINVAL ; + goto out_unlock; + }if (mm->pasid) {if (mm->pasid >= min && mm->pasid <= max)ioasid_get (mm->pasid);
drivers/iommu/iommu-sva-lib.c int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) · line 59
Quoted 9 lines
drivers/iommu/iommu-sva-lib.c +2
-0@@ -45,22 +51,32 @@ int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max)else mm->pasid = pasid; } +mmput (mm); +out_unlock:mutex_unlock (&iommu_sva_lock);return ret; }EXPORT_SYMBOL_GPL (iommu_sva_alloc_pasid);
Best regards,
baolu
Re: [PATCH 2/2] iommu/sva: Remove mm parameter from SVA bind API
Hi Lu,
Quoted 11 lines · Lu Baolu
Quoted 11 lines
-int
iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max)+intiommu_sva_alloc_pasid(ioasid_t min, ioasid_t max)
{
int ret = 0;
ioasid_tpasid;drivers/iommu/iommu-sva-lib.c +1
-0+struct mm_struct *mm;if (min ==INVALID_IOASID || max ==INVALID_IOASID || min ==0 || max < min)return -EINVAL ;
Quoted 5 lines
Review
Quoted 2 lines
mutex_lock(&iommu_sva_lock);(quoted diff) +1
-0+ mm = get_task_mm(current);How could we allocate a supervisor PASID through
iommu_sva_alloc_pasid()if we always usecurrent->mmhere?
I don't think you can. But I guess the current callers of this function do not need supervisor PASID.
In reply to Jean, I suggest we split this function into mm->pasid assignment and keep using ioasid_alloc() directly, then supervisor PASID is caller's bind choice.
Thanks,
Jacob
Quoted 2 lines · Jacob Pan
The void* drvdata parameter isn't really used in iommu_sva_bind_device() API,
Right, it used to be a cookie passed to the device driver in the exit_mm() callback, but that went away with edcc40d2ab5f ("iommu: Remove iommu_sva_ops::mm_exit()")
Quoted 8 lines
the current IDXD code "borrows" the drvdata for a VT-d private flag for supervisor SVA usage.
Supervisor/Privileged mode request is a generic feature. It should be promoted from the VT-d vendor driver to the generic code.
This patch replaces void* drvdata with a unsigned int flags parameter and adjusts callers accordingly.
Thanks for cleaning this up. Making flags unsigned long seems more common (I suggested int without thinking). But it doesn't matter much, we won't get to 32 flags.
Quoted 57 lines
Suggested-by Jean-Philippe Brucker <[email protected]>Signed-off-by Jacob Pan <[email protected]>--- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 6 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 ++-- drivers/iommu/intel/Kconfig | 1 + drivers/iommu/intel/svm.c | 18 ++++++------------ drivers/iommu/iommu.c | 9 ++++++--- drivers/misc/uacce/uacce.c | 2 +- include/linux/intel-iommu.h | 2 +- include/linux/intel-svm.h | 17 ++--------------- include/linux/iommu.h | 19 ++++++++++++++++--- 11 files changed, 40 insertions(+), 42 deletions(-)drivers/dma/idxd/cdev.c +1
-1@@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx;if (device_pasid_enabled (idxd)) { - sva =iommu_sva_bind_device (dev, current->mm,NULL ); + sva =iommu_sva_bind_device (dev, current->mm,0 );if (IS_ERR (sva)) { rc =PTR_ERR (sva);dev_err (dev,"pasid allocation failed: %d\n" , rc);drivers/dma/idxd/init.c +3
-3@@ -300,13 +300,13 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev)static int idxd_enable_system_pasid (struct idxd_device *idxd) { -int flags; +unsigned int flags;unsigned int pasid;struct iommu_sva *sva; - flags =SVM_FLAG_SUPERVISOR_MODE ; + flags =IOMMU_SVA_BIND_SUPERVISOR ; - sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , &flags); + sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , flags);if (IS_ERR (sva)) {dev_warn (&idxd->pdev->dev,"iommu sva bind failed: %ld\n" ,PTR_ERR (sva));drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +0
-0
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) · line 357
Quoted 5 lines
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +1
-1@@ -354,7 +354,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) }struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags)
Could you add a check on flags:
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +4 -1
@@ -354,12 +354,15 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) }struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_sva *handle;struct iommu_domain *domain =iommu_get_domain_for_dev (dev);struct arm_smmu_domain *smmu_domain =to_smmu_domain (domain); +if (flags) +return ERR_PTR (-EINVAL ); +if (smmu_domain->stage !=ARM_SMMU_DOMAIN_S1 )return ERR_PTR (-EINVAL );
Quoted 30 lines
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +0
-0{struct iommu_sva *handle;struct iommu_domain *domain =iommu_get_domain_for_dev (dev);drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +2
-2@@ -711,7 +711,7 @@ bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);int arm_smmu_master_enable_sva (struct arm_smmu_master *master);int arm_smmu_master_disable_sva (struct arm_smmu_master *master);struct iommu_sva *arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void arm_smmu_sva_unbind (struct iommu_sva *handle);u32 arm_smmu_sva_get_pasid (struct iommu_sva *handle);void arm_smmu_sva_notifier_synchronize (void );@@ -742,7 +742,7 @@ static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) }static inline struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {return ERR_PTR (-ENODEV ); }drivers/iommu/intel/Kconfig +0
-0
drivers/iommu/intel/Kconfig config INTEL_IOMMU_SVM · line 44
Quoted 4 lines
drivers/iommu/intel/Kconfig +1
-0@@ -41,6 +41,7 @@ config INTEL_IOMMU_SVM select PCI_PRI select MMU_NOTIFIER select IOASID + select IOMMU_SVA_LIB
Not needed here?
Quoted 68 lines
drivers/iommu/intel/Kconfig +0
-0help Shared Virtual Memory (SVM) provides a facility for devices to access DMA resources through process address space bydrivers/iommu/intel/svm.c +6
-12@@ -486,12 +486,9 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, }else pasid_max =1 <<20 ; -/* Bind supervisor PASID shuld have mm = NULL */ -if (flags &SVM_FLAG_SUPERVISOR_MODE ) { -if (!ecap_srs (iommu->ecap) || mm) { -pr_err ("Supervisor PASID with user provided mm.\n" ); -return -EINVAL ; - } +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && !ecap_srs (iommu->ecap)) { +pr_err ("Supervisor PASID not supported.\n" ); +return -EINVAL ; }if (!(flags &SVM_FLAG_PRIVATE_PASID )) {@@ -593,7 +590,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret =intel_pasid_setup_first_level (iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid,FLPT_DEFAULT_DID , - (mm ?0 :PASID_FLAG_SUPERVISOR_MODE ) | + (mm ?0 :IOMMU_SVA_BIND_SUPERVISOR ) | (cpu_feature_enabled (X86_FEATURE_LA57 ) ?PASID_FLAG_FL5LP :0 ));spin_unlock_irqrestore (&iommu->lock, iflags);@@ -620,7 +617,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret =intel_pasid_setup_first_level (iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid,FLPT_DEFAULT_DID , - (mm ?0 :PASID_FLAG_SUPERVISOR_MODE ) | + (mm ?0 :IOMMU_SVA_BIND_SUPERVISOR ) | (cpu_feature_enabled (X86_FEATURE_LA57 ) ?PASID_FLAG_FL5LP :0 ));spin_unlock_irqrestore (&iommu->lock, iflags);@@ -1059,11 +1056,10 @@ static irqreturn_t prq_event_thread(int irq, void *d)#define to_intel_svm_dev (handle) container_of(handle, struct intel_svm_dev, sva)struct iommu_sva * -intel_svm_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +intel_svm_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_sva *sva =ERR_PTR (-EINVAL );struct intel_svm_dev *sdev =NULL ; -unsigned int flags =0 ;int ret;/* @@ -1071,8 +1067,6 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata)* It will require shared SVM data structures, i.e. combine io_mm * and intel_svm etc. */ -if (drvdata) - flags = *(unsigned int *)drvdata;mutex_lock (&pasid_mutex); ret =intel_svm_bind_mm (dev, flags,NULL , mm, &sdev);if (ret)drivers/iommu/iommu.c +0
-0
drivers/iommu/iommu.c EXPORT_SYMBOL_GPL(iommu_aux_get_pasid); · line 2965
Quoted 4 lines
drivers/iommu/iommu.c +1
-0@@ -2962,6 +2962,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* iommu_sva_bind_device() - Bind a process address space to a device * @dev: the device * @mm: the mm to bind, caller must hold a reference to it +* @flags: options for the bind operation
Could also specify valid flags "IOMMU_SVA_BIND_*"
Quoted 106 lines
drivers/iommu/iommu.c +5
-3* * Create a bond between device and address space, allowing the device to access * the mm using the returned PASID. If a bond already exists between @device and @@ -2974,7 +2975,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* On error, returns an ERR_PTR value. */ struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_group *group;struct iommu_sva *handle =ERR_PTR (-EINVAL );@@ -2987,6 +2988,9 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)if (!group)return ERR_PTR (-ENODEV ); +/* Supervisor SVA does not need the current mm */ +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) +return ERR_PTR (-EINVAL );/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);@@ -2999,8 +3003,7 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)if (iommu_group_device_count (group) !=1 ) goto out_unlock; - handle = ops->sva_bind (dev, mm, drvdata); - + handle = ops->sva_bind (dev, mm, flags); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);drivers/misc/uacce/uacce.c +1
-1@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)if (!(uacce->flags &UACCE_DEV_SVA ))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm,NULL ); + handle =iommu_sva_bind_device (uacce->parent, current->mm,0 );if (IS_ERR (handle))return PTR_ERR (handle);include/linux/intel-iommu.h +1
-1@@ -757,7 +757,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, struct iommu_gpasid_bind_data *data);int intel_svm_unbind_gpasid (struct device *dev,u32 pasid);struct iommu_sva *intel_svm_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void intel_svm_unbind (struct iommu_sva *handle);u32 intel_svm_get_pasid (struct iommu_sva *handle); int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt,include/linux/intel-svm.h +2
-15@@ -30,30 +30,17 @@ struct svm_dev_ops {* if there is no other way to do so. It should be used sparingly, if at all. */ #define SVM_FLAG_PRIVATE_PASID (1<<0) - -/* -* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only -* for access to kernel addresses. No IOTLB flushes are automatically done -* for kernel mappings; it is valid only for access to the kernel's static -* 1:1 mapping of physical memory — not to vmalloc or even module mappings. -* A future API addition may permit the use of such ranges, by means of an -* explicit IOTLB flush call (akin to the DMA API's unmap method). -* -* It is unlikely that we will ever hook into flush_tlb_kernel_range() to -* do such IOTLB flushes automatically. -*/ -#define SVM_FLAG_SUPERVISOR_MODE (1<<1)/* * The SVM_FLAG_GUEST_MODE flag is used when a PASID bind is for guest * processes. Compared to the host bind, the primary differences are: * 1. mm life cycle management * 2. fault reporting */ -#define SVM_FLAG_GUEST_MODE (1<<2) +#define SVM_FLAG_GUEST_MODE (1<<1)/* * The SVM_FLAG_GUEST_PASID flag is used when a guest has its own PASID space, * which requires guest and host PASID translation at both directions. */ -#define SVM_FLAG_GUEST_PASID (1<<3) +#define SVM_FLAG_GUEST_PASID (1<<2)#endif /* __INTEL_SVM_H__ */ include/linux/iommu.h +3
-0@@ -166,6 +166,19 @@ enum iommu_dev_features {#ifdef CONFIG_IOMMU_API +/* +* The IOMMU_SVA_BIND_SUPERVISOR flag requests a PASID which can be used only +* for access to kernel addresses. No IOTLB flushes are automatically done
include/linux/iommu.h enum iommu_dev_features { · line 181
Quoted 10 lines
include/linux/iommu.h +10
-0+* for kernel mappings; it is valid only for access to the kernel's static +* 1:1 mapping of physical memory — not to vmalloc or even module mappings. +* A future API addition may permit the use of such ranges, by means of an +* explicit IOTLB flush call (akin to the DMA API's unmap method). +* +* It is unlikely that we will ever hook into flush_tlb_kernel_range() to +* do such IOTLB flushes automatically. +*/ +#define IOMMU_SVA_BIND_SUPERVISOR BIT(0) +
It needs to be defined before the #ifdef CONFIG_IOMMU_API, otherwise drivers using it won't build with !CONFIG_IOMMU_API
Thanks,
Jean
Quoted 33 lines
include/linux/iommu.h +3
-3/** * struct iommu_iotlb_gather - Range information for a pending IOTLB flush * @@ -287,7 +300,7 @@ struct iommu_ops {int (*aux_get_pasid)(struct iommu_domain *domain,struct device *dev);struct iommu_sva *(*sva_bind)(struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void (*sva_unbind)(struct iommu_sva *handle);u32 (*sva_get_pasid)(struct iommu_sva *handle);@@ -640,7 +653,7 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);@@ -1015,7 +1028,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) {return NULL ; }Signature · 1 line
2.7.4
Hi Jean-Philippe,
Quoted 14 lines · Jean-Philippe Brucker
Quoted 2 lines · Jacob Pan
The void* drvdata parameter isn't really used in iommu_sva_bind_device() API,
Right, it used to be a cookie passed to the device driver in the
exit_mm()callback, but that went away withedcc40d2ab5f("iommu: Removeiommu_sva_ops::mm_exit()")Quoted 6 lines
the current IDXD code "borrows" the drvdata for a VT-d private flag for supervisor SVA usage.
Supervisor/Privileged mode request is a generic feature. It should be promoted from the VT-d vendor driver to the generic code.
Quoted 7 lines
Quoted 2 lines
This patch replaces void* drvdata with a unsigned int flags parameter and adjusts callers accordingly.
Thanks for cleaning this up. Making flags unsigned long seems more common (I suggested int without thinking). But it doesn't matter much, we won't get to 32 flags.
I was just thinking unsigned int is 32 bit for both 32 and 64 bit machine.
Quoted 77 lines
Quoted 59 lines
Suggested-by Jean-Philippe Brucker <[email protected]>Signed-off-by Jacob Pan <[email protected]>--- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 6 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 ++-- drivers/iommu/intel/Kconfig | 1 + drivers/iommu/intel/svm.c | 18 ++++++------------ drivers/iommu/iommu.c | 9 ++++++--- drivers/misc/uacce/uacce.c | 2 +- include/linux/intel-iommu.h | 2 +- include/linux/intel-svm.h | 17 ++--------------- include/linux/iommu.h | 19++++++++++++++++--- 11 files changed, 40 insertions(+), 42 deletions(-)
drivers/dma/idxd/cdev.c +1
-1@@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx;if (device_pasid_enabled (idxd)) { - sva =iommu_sva_bind_device (dev, current->mm,NULL ); + sva =iommu_sva_bind_device (dev, current->mm,0 );if (IS_ERR (sva)) { rc =PTR_ERR (sva); dev_err(dev, "pasid allocation failed: %d\n",rc); diff --git
a/drivers/dma/idxd/init.cb/drivers/dma/idxd/init.cindex 085a0c3..cdc85f1 100644drivers/dma/idxd/init.c +3
-3@@ -300,13 +300,13 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev)static int idxd_enable_system_pasid (struct idxd_device *idxd) { -int flags; +unsigned int flags;unsigned int pasid;struct iommu_sva *sva; - flags =SVM_FLAG_SUPERVISOR_MODE ; + flags =IOMMU_SVA_BIND_SUPERVISOR ; - sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , &flags); + sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , flags);if (IS_ERR (sva)) {dev_warn (&idxd->pdev->dev,"iommu sva bind failed: %ld\n" ,PTR_ERR (sva));(quoted diff) +0
-0
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.cindex bb251ca..23e287e 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@@ -354,7 +354,7 @@__arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)}Quoted 4 lines
struct
iommu_sva*
-arm_smmu_sva_bind(struct device *dev, structmm_struct*mm, void *drvdata) +arm_smmu_sva_bind(struct device *dev, structmm_struct*mm, unsigned int flags)Could you add a check on flags:
(quoted diff) +0
-0
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.cindexbb251cab61f3..145ceb2fc5da100644 ---a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c+++b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c@@ -354,12 +354,15 @@__arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)}struct
iommu_sva*
-arm_smmu_sva_bind(struct device *dev, structmm_struct*mm, void *drvdata) +arm_smmu_sva_bind(struct device *dev, structmm_struct*mm, unsigned int flags) {
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) · line 365
Quoted 7 lines
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +3
-0struct iommu_sva *handle;struct iommu_domain *domain =iommu_get_domain_for_dev (dev);struct arm_smmu_domain *smmu_domain =to_smmu_domain (domain); +if (flags) +return ERR_PTR (-EINVAL ); +
yes, will do.
Quoted 34 lines
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +0
-0if (smmu_domain->stage !=ARM_SMMU_DOMAIN_S1 )return ERR_PTR (-EINVAL );Quoted 32 lines
{
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +0
-0struct iommu_sva *handle;struct iommu_domain *domain =iommu_get_domain_for_dev (dev);(quoted diff) +0
-0
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.hindex f985817..b971d4d 100644 ---a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h+++b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h(quoted diff) +0
-0@@ -711,7 +711,7 @@ bool arm_smmu_master_sva_enabled(struct
arm_smmu_master*master); intarm_smmu_master_enable_sva(struct arm_smmu_master *master); intarm_smmu_master_disable_sva(struct arm_smmu_master *master); structiommu_sva*arm_smmu_sva_bind(struct device *dev, structmm_struct*mm,(quoted diff) +1
-2- void *drvdata); + unsigned int flags); void arm_smmu_sva_unbind(struct iommu_sva *handle); u32 arm_smmu_sva_get_pasid(struct iommu_sva *handle); void arm_smmu_sva_notifier_synchronize(void);@@ -742,7 +742,7 @@ static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) } static inline struct iommu_sva * -arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, void *drvdata) +arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, unsigned int flags) { return ERR_PTR(-ENODEV); }drivers/iommu/intel/Kconfig +0
-1--- a/drivers/iommu/intel/Kconfig
Quoted 8 lines
drivers/iommu/intel/Kconfig config INTEL_IOMMU_SVM · line 44
Quoted 6 lines
+++ b/drivers/iommu/intel/Kconfig
drivers/iommu/intel/Kconfig +1
-0@@ -41,6 +41,7 @@ config INTEL_IOMMU_SVM select PCI_PRI select MMU_NOTIFIER select IOASID + select IOMMU_SVA_LIBNot needed here?
intel/svm.c is registered to sva-lib and use the IOMMU_SVA_BIND_SUPERVISOR flag.
Quoted 72 lines
Quoted 72 lines
drivers/iommu/intel/Kconfig +0
-0help Shared Virtual Memory (SVM) provides a facility for devices to access DMA resources through process address space bydrivers/iommu/intel/svm.c +0
-0@@ -486,12 +486,9 @@ intel_svm_bind_mm(struct device *dev, unsigned intflags, } else
drivers/iommu/intel/svm.c +0
-4pasid_max =1 <<20 ; -/* Bind supervisor PASID shuld have mm = NULL */ -if (flags &SVM_FLAG_SUPERVISOR_MODE ) { -if (!ecap_srs (iommu->ecap) || mm) { - pr_err("Supervisor PASID with user providedmm.\n");
drivers/iommu/intel/svm.c +1
-2-return -EINVAL ; - } + if ((flags & IOMMU_SVA_BIND_SUPERVISOR) &&!ecap_srs(iommu->ecap)) {
drivers/iommu/intel/svm.c +3
-2+pr_err ("Supervisor PASID not supported.\n" ); +return -EINVAL ; }if (!(flags &SVM_FLAG_PRIVATE_PASID )) {@@ -593,7 +590,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret =intel_pasid_setup_first_level (iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid,FLPT_DEFAULT_DID , - (mm ?0 :PASID_FLAG_SUPERVISOR_MODE ) | + (mm ?0 :IOMMU_SVA_BIND_SUPERVISOR ) | (cpu_feature_enabled (X86_FEATURE_LA57 ) ?PASID_FLAG_FL5LP :0 ));spin_unlock_irqrestore (&iommu->lock, iflags);@@ -620,7 +617,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret = intel_pasid_setup_first_level(iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid, FLPT_DEFAULT_DID, - (mm ? 0 :
PASID_FLAG_SUPERVISOR_MODE) |drivers/iommu/intel/svm.c +1
-0+ (mm ? 0 :
IOMMU_SVA_BIND_SUPERVISOR) | (cpu_feature_enabled(X86_FEATURE_LA57)?drivers/iommu/intel/svm.c +0
-0PASID_FLAG_FL5LP : 0));spin_unlock_irqrestore (&iommu->lock, iflags);@@ -1059,11 +1056,10 @@ static irqreturn_t prq_event_thread(int irq, void *d)#define to_intel_svm_dev (handle) container_of(handle, struct
intel_svm_dev, sva) structiommu_sva*drivers/iommu/intel/svm.c +1
-1-intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata) +intel_svm_bind(struct device *dev, struct mm_struct *mm, unsigned intflags) {
drivers/iommu/intel/svm.c +0
-1struct iommu_sva *sva =ERR_PTR (-EINVAL );struct intel_svm_dev *sdev =NULL ; -unsigned int flags =0 ;int ret;/* @@ -1071,8 +1067,6 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata) * It will require shared SVM data structures, i.e. combine
io_mmdrivers/iommu/intel/svm.c +0
-2* and intel_svm etc. */ -if (drvdata) - flags = *(unsigned int *)drvdata;mutex_lock (&pasid_mutex); ret =intel_svm_bind_mm (dev, flags,NULL , mm, &sdev);if (ret)drivers/iommu/iommu.c +0
-1--- a/drivers/iommu/iommu.c
Quoted 9 lines
drivers/iommu/iommu.c EXPORT_SYMBOL_GPL(iommu_aux_get_pasid); · line 2965
Quoted 6 lines
+++
b/drivers/iommu/iommu.cdrivers/iommu/iommu.c +1
-0@@ -2962,6 +2962,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* iommu_sva_bind_device() - Bind a process address space to a device * @dev: the device * @mm: the mm to bind, caller must hold a reference to it +* @flags: options for the bind operation Could also specify valid flags "IOMMU_SVA_BIND_*"
Good point! will do.
Quoted 128 lines
Quoted 128 lines
drivers/iommu/iommu.c +0
-0* * Create a bond between device and address space, allowing the device to access
* the mm using the returned PASID. If a bond already exists between
@device and @@ -2974,7 +2975,7 @@EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);
* On error, returns anERR_PTRvalue.
*/
structiommu_sva*
-iommu_sva_bind_device(struct device *dev, structmm_struct*mm, void *drvdata) +iommu_sva_bind_device(struct device *dev, structmm_struct*mm, unsigned int flags) {drivers/iommu/iommu.c +4
-2struct iommu_group *group;struct iommu_sva *handle =ERR_PTR (-EINVAL );@@ -2987,6 +2988,9 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata) if (!group)return ERR_PTR (-ENODEV ); +/* Supervisor SVA does not need the current mm */ +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) +return ERR_PTR (-EINVAL );/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);@@ -2999,8 +3003,7 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata) if (iommu_group_device_count(group) != 1) goto out_unlock; - handle = ops->sva_bind (dev, mm, drvdata); - + handle = ops->sva_bind (dev, mm, flags); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);drivers/misc/uacce/uacce.c +1
-1@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q) if (!(uacce->flags & UACCE_DEV_SVA))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm, NULL); + handle =iommu_sva_bind_device (uacce->parent, current->mm,0 );if (IS_ERR (handle))return PTR_ERR (handle);include/linux/intel-iommu.h +1
-1@@ -757,7 +757,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, struct iommu_gpasid_bind_data *data);int intel_svm_unbind_gpasid (struct device *dev,u32 pasid);struct iommu_sva *intel_svm_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void intel_svm_unbind (struct iommu_sva *handle);u32 intel_svm_get_pasid (struct iommu_sva *handle);int intel_svm_page_response(struct device *dev, struct
iommu_fault_event*evt, diff --gita/include/linux/intel-svm.hb/include/linux/intel-svm.hindex 39d368a..ef6b753 100644include/linux/intel-svm.h +0
-0@@ -30,30 +30,17 @@ struct svm_dev_ops {* if there is no other way to do so. It should be used sparingly, if at all. */
#defineSVM_FLAG_PRIVATE_PASID(1<<0)include/linux/intel-svm.h +0
-3- -/* -* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only
- * for access to kernel addresses. No IOTLB flushes are automatically done
- * for kernel mappings; it is valid only for access to the kernel's static
- * 1:1 mapping of physical memory — not to vmalloc or even module mappings.
- * A future API addition may permit the use of such ranges, by means of an
- * explicit IOTLB flush call (akin to the DMA API's unmap method).
- *
- * It is unlikely that we will ever hook intoflush_tlb_kernel_range()to
- * do such IOTLB flushes automatically.
- */include/linux/intel-svm.h +1
-2-#define SVM_FLAG_SUPERVISOR_MODE (1<<1)/* * The SVM_FLAG_GUEST_MODE flag is used when a PASID bind is for guest * processes. Compared to the host bind, the primary differences are: * 1. mm life cycle management * 2. fault reporting */ -#define SVM_FLAG_GUEST_MODE (1<<2) +#define SVM_FLAG_GUEST_MODE (1<<1)/* * The SVM_FLAG_GUEST_PASID flag is used when a guest has its own PASID space,
* which requires guest and host PASID translation at both directions. */include/linux/intel-svm.h +1
-1-#define SVM_FLAG_GUEST_PASID (1<<3) +#define SVM_FLAG_GUEST_PASID (1<<2)#endif /* __INTEL_SVM_H__ */ include/linux/iommu.h +2
-0@@ -166,6 +166,19 @@ enum iommu_dev_features {#ifdef CONFIG_IOMMU_API +/* +* The IOMMU_SVA_BIND_SUPERVISOR flag requests a PASID which can be used only
+ * for access to kernel addresses. No IOTLB flushes are automatically done
+ * for kernel mappings; it is valid only for access to the kernel's static
+ * 1:1 mapping of physical memory — not to vmalloc or even module mappings.
+ * A future API addition may permit the use of such ranges, by means of an
+ * explicit IOTLB flush call (akin to the DMA API's unmap method).
+ *
+ * It is unlikely that we will ever hook intoflush_tlb_kernel_range()
Quoted 9 lines
include/linux/iommu.h
Quoted 5 lines
to
+ * do such IOTLB flushes automatically.
+ */include/linux/iommu.h +2
-0+#define IOMMU_SVA_BIND_SUPERVISOR BIT(0) +It needs to be defined before the #ifdef
CONFIG_IOMMU_API, otherwise drivers using it won't build with !CONFIG_IOMMU_API
Good point, I was counting on driver that uses SVA must depend on CONFIG_IOMMU_API. But SVA could be an option of the driver itself.
Quoted 28 lines
Thanks,
JeanQuoted 25 lines
/**
* structiommu_iotlb_gather- Range information for a pending IOTLB
flush *include/linux/iommu.h +2
-2@@ -287,7 +300,7 @@ struct iommu_ops {int (*aux_get_pasid)(struct iommu_domain *domain,struct device *dev);struct iommu_sva *(*sva_bind)(struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void (*sva_unbind)(struct iommu_sva *handle);u32 (*sva_get_pasid)(struct iommu_sva *handle);@@ -640,7 +653,7 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);@@ -1015,7 +1028,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }
Quoted 9 lines
Quoted 9 lines
include/linux/iommu.h +0
-1static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device(struct device *dev, struct mm_struct *mm,unsigned int flags) {return NULL ; }Signature · 1 line
2.7.4
Thanks,
Jacob
Lu Baolu
maintainerHi Jacob,
Quoted 45 lines · Jacob Pan
The void* drvdata parameter isn't really used in iommu_sva_bind_device() API, the current IDXD code "borrows" the drvdata for a VT-d private flag for supervisor SVA usage.
Supervisor/Privileged mode request is a generic feature. It should be promoted from the VT-d vendor driver to the generic code.
This patch replaces void* drvdata with a unsigned int flags parameter and adjusts callers accordingly.
Suggested-by Jean-Philippe Brucker <[email protected]>Signed-off-by Jacob Pan <[email protected]>--- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 6 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 ++-- drivers/iommu/intel/Kconfig | 1 + drivers/iommu/intel/svm.c | 18 ++++++------------ drivers/iommu/iommu.c | 9 ++++++--- drivers/misc/uacce/uacce.c | 2 +- include/linux/intel-iommu.h | 2 +- include/linux/intel-svm.h | 17 ++--------------- include/linux/iommu.h | 19 ++++++++++++++++--- 11 files changed, 40 insertions(+), 42 deletions(-)drivers/dma/idxd/cdev.c +1
-1@@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx;if (device_pasid_enabled (idxd)) { - sva =iommu_sva_bind_device (dev, current->mm,NULL ); + sva =iommu_sva_bind_device (dev, current->mm,0 );if (IS_ERR (sva)) { rc =PTR_ERR (sva);dev_err (dev,"pasid allocation failed: %d\n" , rc);drivers/dma/idxd/init.c +0
-0
drivers/dma/idxd/init.c static struct idxd_device *idxd_alloc(struct pci_dev *pdev) · line 307
Quoted 10 lines
drivers/dma/idxd/init.c +2
-2@@ -300,13 +300,13 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev)static int idxd_enable_system_pasid (struct idxd_device *idxd) { -int flags; +unsigned int flags;unsigned int pasid;struct iommu_sva *sva; - flags =SVM_FLAG_SUPERVISOR_MODE ; + flags =IOMMU_SVA_BIND_SUPERVISOR ;
With SVM_FLAG_SUPERVISOR_MODE removed, I guess
#include <linux/intel-svm.h>
in this file could be removed as well.
Quoted 46 lines
drivers/dma/idxd/init.c +1
-1- sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , &flags); + sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , flags);if (IS_ERR (sva)) {dev_warn (&idxd->pdev->dev,"iommu sva bind failed: %ld\n" ,PTR_ERR (sva));drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +1
-1@@ -354,7 +354,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm) }struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_sva *handle;struct iommu_domain *domain =iommu_get_domain_for_dev (dev);drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +2
-2@@ -711,7 +711,7 @@ bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);int arm_smmu_master_enable_sva (struct arm_smmu_master *master);int arm_smmu_master_disable_sva (struct arm_smmu_master *master);struct iommu_sva *arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void arm_smmu_sva_unbind (struct iommu_sva *handle);u32 arm_smmu_sva_get_pasid (struct iommu_sva *handle);void arm_smmu_sva_notifier_synchronize (void );@@ -742,7 +742,7 @@ static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) }static inline struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {return ERR_PTR (-ENODEV ); }drivers/iommu/intel/Kconfig +0
-0
drivers/iommu/intel/Kconfig config INTEL_IOMMU_SVM · line 44
Quoted 4 lines
drivers/iommu/intel/Kconfig +1
-0@@ -41,6 +41,7 @@ config INTEL_IOMMU_SVM select PCI_PRI select MMU_NOTIFIER select IOASID + select IOMMU_SVA_LIB
Why?
Quoted 24 lines
drivers/iommu/intel/Kconfig +0
-0help Shared Virtual Memory (SVM) provides a facility for devices to access DMA resources through process address space bydrivers/iommu/intel/svm.c +3
-6@@ -486,12 +486,9 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, }else pasid_max =1 <<20 ; -/* Bind supervisor PASID shuld have mm = NULL */ -if (flags &SVM_FLAG_SUPERVISOR_MODE ) { -if (!ecap_srs (iommu->ecap) || mm) { -pr_err ("Supervisor PASID with user provided mm.\n" ); -return -EINVAL ; - } +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && !ecap_srs (iommu->ecap)) { +pr_err ("Supervisor PASID not supported.\n" ); +return -EINVAL ; }if (!(flags &SVM_FLAG_PRIVATE_PASID )) {
drivers/iommu/intel/svm.c intel_svm_bind_mm(struct device *dev, unsigned int flags, · line 593
Quoted 5 lines
drivers/iommu/intel/svm.c +1
-1@@ -593,7 +590,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret = intel_pasid_setup_first_level(iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid, FLPT_DEFAULT_DID, - (mm ? 0 : PASID_FLAG_SUPERVISOR_MODE) | + (mm ? 0 : IOMMU_SVA_BIND_SUPERVISOR) |
NO. PASID_FLAG_SUPERVISOR_MODE is an internal flag to tell the helper whether the SRE bit should be set in the PASID entry.
drivers/iommu/intel/svm.c intel_svm_bind_mm(struct device *dev, unsigned int flags, · line 620
Quoted 9 lines
drivers/iommu/intel/svm.c +1
-1(cpu_feature_enabled (X86_FEATURE_LA57 ) ? PASID_FLAG_FL5LP : 0));spin_unlock_irqrestore (&iommu->lock, iflags);@@ -620,7 +617,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret = intel_pasid_setup_first_level(iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid, FLPT_DEFAULT_DID, - (mm ? 0 : PASID_FLAG_SUPERVISOR_MODE) | + (mm ? 0 : IOMMU_SVA_BIND_SUPERVISOR) |
The same as above.
Quoted 173 lines
drivers/iommu/intel/svm.c +1
-4(cpu_feature_enabled (X86_FEATURE_LA57 ) ? PASID_FLAG_FL5LP : 0));spin_unlock_irqrestore (&iommu->lock, iflags);@@ -1059,11 +1056,10 @@ static irqreturn_t prq_event_thread(int irq, void *d)#define to_intel_svm_dev (handle) container_of(handle, struct intel_svm_dev, sva)struct iommu_sva * -intel_svm_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +intel_svm_bind (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_sva *sva =ERR_PTR (-EINVAL );struct intel_svm_dev *sdev =NULL ; -unsigned int flags =0 ;int ret;/* @@ -1071,8 +1067,6 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata)* It will require shared SVM data structures, i.e. combine io_mm * and intel_svm etc. */ -if (drvdata) - flags = *(unsigned int *)drvdata;mutex_lock (&pasid_mutex); ret =intel_svm_bind_mm (dev, flags,NULL , mm, &sdev);if (ret)drivers/iommu/iommu.c +6
-3@@ -2962,6 +2962,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* iommu_sva_bind_device() - Bind a process address space to a device * @dev: the device * @mm: the mm to bind, caller must hold a reference to it +* @flags: options for the bind operation * * Create a bond between device and address space, allowing the device to access * the mm using the returned PASID. If a bond already exists between @device and @@ -2974,7 +2975,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* On error, returns an ERR_PTR value. */ struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) {struct iommu_group *group;struct iommu_sva *handle =ERR_PTR (-EINVAL );@@ -2987,6 +2988,9 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)if (!group)return ERR_PTR (-ENODEV ); +/* Supervisor SVA does not need the current mm */ +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) +return ERR_PTR (-EINVAL );/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);@@ -2999,8 +3003,7 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)if (iommu_group_device_count (group) !=1 ) goto out_unlock; - handle = ops->sva_bind (dev, mm, drvdata); - + handle = ops->sva_bind (dev, mm, flags); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);drivers/misc/uacce/uacce.c +1
-1@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)if (!(uacce->flags &UACCE_DEV_SVA ))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm,NULL ); + handle =iommu_sva_bind_device (uacce->parent, current->mm,0 );if (IS_ERR (handle))return PTR_ERR (handle);include/linux/intel-iommu.h +1
-1@@ -757,7 +757,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, struct iommu_gpasid_bind_data *data);int intel_svm_unbind_gpasid (struct device *dev,u32 pasid);struct iommu_sva *intel_svm_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void intel_svm_unbind (struct iommu_sva *handle);u32 intel_svm_get_pasid (struct iommu_sva *handle); int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt,include/linux/intel-svm.h +2
-15@@ -30,30 +30,17 @@ struct svm_dev_ops {* if there is no other way to do so. It should be used sparingly, if at all. */ #define SVM_FLAG_PRIVATE_PASID (1<<0) - -/* -* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only -* for access to kernel addresses. No IOTLB flushes are automatically done -* for kernel mappings; it is valid only for access to the kernel's static -* 1:1 mapping of physical memory — not to vmalloc or even module mappings. -* A future API addition may permit the use of such ranges, by means of an -* explicit IOTLB flush call (akin to the DMA API's unmap method). -* -* It is unlikely that we will ever hook into flush_tlb_kernel_range() to -* do such IOTLB flushes automatically. -*/ -#define SVM_FLAG_SUPERVISOR_MODE (1<<1)/* * The SVM_FLAG_GUEST_MODE flag is used when a PASID bind is for guest * processes. Compared to the host bind, the primary differences are: * 1. mm life cycle management * 2. fault reporting */ -#define SVM_FLAG_GUEST_MODE (1<<2) +#define SVM_FLAG_GUEST_MODE (1<<1)/* * The SVM_FLAG_GUEST_PASID flag is used when a guest has its own PASID space, * which requires guest and host PASID translation at both directions. */ -#define SVM_FLAG_GUEST_PASID (1<<3) +#define SVM_FLAG_GUEST_PASID (1<<2)#endif /* __INTEL_SVM_H__ */ include/linux/iommu.h +15
-2@@ -166,6 +166,19 @@ enum iommu_dev_features {#ifdef CONFIG_IOMMU_API +/* +* The IOMMU_SVA_BIND_SUPERVISOR flag requests a PASID which can be used only +* for access to kernel addresses. No IOTLB flushes are automatically done +* for kernel mappings; it is valid only for access to the kernel's static +* 1:1 mapping of physical memory — not to vmalloc or even module mappings. +* A future API addition may permit the use of such ranges, by means of an +* explicit IOTLB flush call (akin to the DMA API's unmap method). +* +* It is unlikely that we will ever hook into flush_tlb_kernel_range() to +* do such IOTLB flushes automatically. +*/ +#define IOMMU_SVA_BIND_SUPERVISOR BIT(0) +/** * struct iommu_iotlb_gather - Range information for a pending IOTLB flush * @@ -287,7 +300,7 @@ struct iommu_ops {int (*aux_get_pasid)(struct iommu_domain *domain,struct device *dev);struct iommu_sva *(*sva_bind)(struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void (*sva_unbind)(struct iommu_sva *handle);u32 (*sva_get_pasid)(struct iommu_sva *handle);@@ -640,7 +653,7 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);
include/linux/iommu.h iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) · line 1034
Quoted 8 lines
include/linux/iommu.h +1
-1@@ -1015,7 +1028,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,unsigned int flags) {return NULL ; }
Best regards,
baolu
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Hi Baolu,
Thanks for the view.
Quoted 56 lines · Lu Baolu
Hi Jacob,
Quoted 53 lines · Jacob Pan
The void* drvdata parameter isn't really used in iommu_sva_bind_device() API, the current IDXD code "borrows" the drvdata for a VT-d private flag for supervisor SVA usage.
Supervisor/Privileged mode request is a generic feature. It should be promoted from the VT-d vendor driver to the generic code.
This patch replaces void* drvdata with a unsigned int flags parameter and adjusts callers accordingly.
Suggested-by Jean-Philippe Brucker <[email protected]>Signed-off-by Jacob Pan <[email protected]>--- drivers/dma/idxd/cdev.c | 2 +- drivers/dma/idxd/init.c | 6 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 ++-- drivers/iommu/intel/Kconfig | 1 + drivers/iommu/intel/svm.c | 18 ++++++------------ drivers/iommu/iommu.c | 9 ++++++--- drivers/misc/uacce/uacce.c | 2 +- include/linux/intel-iommu.h | 2 +- include/linux/intel-svm.h | 17 ++--------------- include/linux/iommu.h | 19++++++++++++++++--- 11 files changed, 40 insertions(+), 42 deletions(-)
drivers/dma/idxd/cdev.c +1
-1@@ -103,7 +103,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) filp->private_data = ctx;if (device_pasid_enabled (idxd)) { - sva =iommu_sva_bind_device (dev, current->mm,NULL ); + sva =iommu_sva_bind_device (dev, current->mm,0 );if (IS_ERR (sva)) { rc =PTR_ERR (sva); dev_err(dev, "pasid allocation failed: %d\n",rc); diff --git
a/drivers/dma/idxd/init.cb/drivers/dma/idxd/init.cindex 085a0c3..cdc85f1 100644drivers/dma/idxd/init.c +1
-1@@ -300,13 +300,13 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev)static int idxd_enable_system_pasid (struct idxd_device *idxd) { -int flags; +unsigned int flags;unsigned int pasid;struct iommu_sva *sva;
Quoted 8 lines
drivers/dma/idxd/init.c static struct idxd_device *idxd_alloc(struct pci_dev *pdev) · line 307
Quoted 2 lines
drivers/dma/idxd/init.c +1
-1- flags =SVM_FLAG_SUPERVISOR_MODE ; + flags =IOMMU_SVA_BIND_SUPERVISOR ;With
SVM_FLAG_SUPERVISOR_MODEremoved, I guess#include <
linux/intel-svm.h>in this file could be removed as well.
yes, good point.
Quoted 46 lines
Quoted 46 lines
drivers/dma/idxd/init.c +1
-1- sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , &flags); + sva =iommu_sva_bind_device (&idxd->pdev->dev,NULL , flags);if (IS_ERR (sva)) { dev_warn(&idxd->pdev->dev, "iommu sva bind failed: %ld\n",
PTR_ERR(sva)); diff --gita/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.cb/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.cindex bb251ca..23e287e 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@@ -354,7 +354,7 @@__arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)}
structiommu_sva*
-arm_smmu_sva_bind(struct device *dev, structmm_struct*mm, void *drvdata) +arm_smmu_sva_bind(struct device *dev, structmm_struct*mm, unsigned int flags) {
structiommu_sva*handle;
structiommu_domain*domain =iommu_get_domain_for_dev(dev);(quoted diff) +0
-0
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.hindex f985817..b971d4d 100644 ---a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h+++b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.hdrivers/dma/idxd/init.c +0
-0@@ -711,7 +711,7 @@ bool arm_smmu_master_sva_enabled(struct
arm_smmu_master*master); intarm_smmu_master_enable_sva(struct arm_smmu_master *master); intarm_smmu_master_disable_sva(struct arm_smmu_master *master); structiommu_sva*arm_smmu_sva_bind(struct device *dev, structmm_struct*mm,drivers/dma/idxd/init.c +1
-2- void *drvdata); + unsigned int flags);void arm_smmu_sva_unbind (struct iommu_sva *handle);u32 arm_smmu_sva_get_pasid (struct iommu_sva *handle);void arm_smmu_sva_notifier_synchronize (void );@@ -742,7 +742,7 @@ static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master) } static inline struct iommu_sva * -arm_smmu_sva_bind (struct device *dev,struct mm_struct *mm,void *drvdata) +arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm,unsigned int flags) {return ERR_PTR (-ENODEV ); }drivers/iommu/intel/Kconfig +0
-1--- a/drivers/iommu/intel/Kconfig
Quoted 8 lines
drivers/iommu/intel/Kconfig config INTEL_IOMMU_SVM · line 44
Quoted 6 lines
+++ b/drivers/iommu/intel/Kconfig
drivers/iommu/intel/Kconfig +1
-0@@ -41,6 +41,7 @@ config INTEL_IOMMU_SVM select PCI_PRI select MMU_NOTIFIER select IOASID + select IOMMU_SVA_LIBWhy?
Right, not needed. VT-d is not using iommu_sva_alloc/free_pasid() yet. I was under the wrong impression that iommu_sva_bind_device is part of the sva-lib.
Quoted 25 lines
Quoted 25 lines
drivers/iommu/intel/Kconfig +0
-0help Shared Virtual Memory (SVM) provides a facility for devices to access DMA resources through process address space bydrivers/iommu/intel/svm.c +0
-0@@ -486,12 +486,9 @@ intel_svm_bind_mm(struct device *dev, unsigned intflags, } else
pasid_max= 1 << 20;drivers/iommu/intel/svm.c +0
-4-/* Bind supervisor PASID shuld have mm = NULL */ -if (flags &SVM_FLAG_SUPERVISOR_MODE ) { -if (!ecap_srs (iommu->ecap) || mm) { - pr_err("Supervisor PASID with user providedmm.\n");
drivers/iommu/intel/svm.c +1
-2-return -EINVAL ; - } + if ((flags & IOMMU_SVA_BIND_SUPERVISOR) &&!ecap_srs(iommu->ecap)) {
drivers/iommu/intel/svm.c +2
-0+pr_err ("Supervisor PASID not supported.\n" ); +return -EINVAL ; }
Quoted 12 lines
drivers/iommu/intel/svm.c intel_svm_bind_mm(struct device *dev, unsigned int · line 594
Quoted 8 lines
if (!(flags & SVM_FLAG_PRIVATE_PASID)) {drivers/iommu/intel/svm.c +1
-1@@ -593,7 +590,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret = intel_pasid_setup_first_level(iommu, dev, mm ? mm->pgd : init_mm.pgd, svm->pasid, FLPT_DEFAULT_DID, - (mm ? 0 : PASID_FLAG_SUPERVISOR_MODE) | + (mm ? 0 : IOMMU_SVA_BIND_SUPERVISOR) |NO.
PASID_FLAG_SUPERVISOR_MODEis an internal flag to tell the helper whether the SRE bit should be set in the PASID entry.
OK, will keep them separate.
Quoted 5 lines
Quoted 5 lines
drivers/iommu/intel/svm.c +0
-0(cpu_feature_enabled (X86_FEATURE_LA57 ) ? PASID_FLAG_FL5LP : 0));spin_unlock_irqrestore(&iommu->lock, iflags);drivers/iommu/intel/svm.c +0
-0@@ -620,7 +617,7 @@ intel_svm_bind_mm(struct device *dev, unsigned int flags, ret = intel_pasid_setup_first_level(iommu, dev,
Quoted 9 lines
Quoted 6 lines
drivers/iommu/intel/svm.c +0
-1mm ? mm->pgd : init_mm.pgd, svm->pasid, FLPT_DEFAULT_DID, - (mm ? 0 :
PASID_FLAG_SUPERVISOR_MODE) |drivers/iommu/intel/svm.c +1
-0+ (mm ? 0 :
IOMMU_SVA_BIND_SUPERVISOR) |The same as above.
got it.
Quoted 194 lines
Quoted 194 lines
(
cpu_feature_enabled(X86_FEATURE_LA57)
?PASID_FLAG_FL5LP: 0));
spin_unlock_irqrestore(&iommu->lock, iflags);drivers/iommu/intel/svm.c +0
-0@@ -1059,11 +1056,10 @@ static irqreturn_t prq_event_thread(int irq, void *d)#define to_intel_svm_dev (handle) container_of(handle, struct
intel_svm_dev, sva) structiommu_sva*drivers/iommu/intel/svm.c +1
-1-intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata) +intel_svm_bind(struct device *dev, struct mm_struct *mm, unsigned intflags) {
structiommu_sva*sva =ERR_PTR(-EINVAL);
structintel_svm_dev*sdev = NULL;drivers/iommu/intel/svm.c +0
-1-unsigned int flags =0 ;int ret;/* @@ -1071,8 +1067,6 @@ intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata) * It will require shared SVM data structures, i.e. combine
io_mm
* andintel_svmetc.
*/drivers/iommu/intel/svm.c +0
-2-if (drvdata) - flags = *(unsigned int *)drvdata;mutex_lock (&pasid_mutex); ret =intel_svm_bind_mm (dev, flags,NULL , mm, &sdev);if (ret)drivers/iommu/iommu.c +1
-0@@ -2962,6 +2962,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);* iommu_sva_bind_device() - Bind a process address space to a device * @dev: the device * @mm: the mm to bind, caller must hold a reference to it +* @flags: options for the bind operation * * Create a bond between device and address space, allowing the device to access
* the mm using the returned PASID. If a bond already exists between
@device and @@ -2974,7 +2975,7 @@EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);
* On error, returns anERR_PTRvalue.
*/
structiommu_sva*
-iommu_sva_bind_device(struct device *dev, structmm_struct*mm, void *drvdata) +iommu_sva_bind_device(struct device *dev, structmm_struct*mm, unsigned int flags) {
structiommu_group*group;
structiommu_sva*handle =ERR_PTR(-EINVAL);drivers/iommu/iommu.c +4
-2@@ -2987,6 +2988,9 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata) if (!group)return ERR_PTR (-ENODEV ); +/* Supervisor SVA does not need the current mm */ +if ((flags &IOMMU_SVA_BIND_SUPERVISOR ) && mm) +return ERR_PTR (-EINVAL );/* Ensure device count and domain don't change while we're binding */ mutex_lock (&group->mutex);@@ -2999,8 +3003,7 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata) if (iommu_group_device_count(group) != 1) goto out_unlock; - handle = ops->sva_bind (dev, mm, drvdata); - + handle = ops->sva_bind (dev, mm, flags); out_unlock:mutex_unlock (&group->mutex);iommu_group_put (group);drivers/misc/uacce/uacce.c +1
-1@@ -99,7 +99,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q) if (!(uacce->flags & UACCE_DEV_SVA))return 0 ; - handle =iommu_sva_bind_device (uacce->parent, current->mm, NULL); + handle =iommu_sva_bind_device (uacce->parent, current->mm,0 );if (IS_ERR (handle))return PTR_ERR (handle);include/linux/intel-iommu.h +1
-1@@ -757,7 +757,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, struct iommu_gpasid_bind_data *data);int intel_svm_unbind_gpasid (struct device *dev,u32 pasid);struct iommu_sva *intel_svm_bind (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void intel_svm_unbind (struct iommu_sva *handle);u32 intel_svm_get_pasid (struct iommu_sva *handle);int intel_svm_page_response(struct device *dev, struct
iommu_fault_event*evt, diff --gita/include/linux/intel-svm.hb/include/linux/intel-svm.hindex 39d368a..ef6b753 100644include/linux/intel-svm.h +0
-0@@ -30,30 +30,17 @@ struct svm_dev_ops {* if there is no other way to do so. It should be used sparingly, if at all. */
#defineSVM_FLAG_PRIVATE_PASID(1<<0)include/linux/intel-svm.h +0
-3- -/* -* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only
- * for access to kernel addresses. No IOTLB flushes are automatically done
- * for kernel mappings; it is valid only for access to the kernel's static
- * 1:1 mapping of physical memory — not to vmalloc or even module mappings.
- * A future API addition may permit the use of such ranges, by means of an
- * explicit IOTLB flush call (akin to the DMA API's unmap method).
- *
- * It is unlikely that we will ever hook intoflush_tlb_kernel_range()to
- * do such IOTLB flushes automatically.
- */include/linux/intel-svm.h +1
-2-#define SVM_FLAG_SUPERVISOR_MODE (1<<1)/* * The SVM_FLAG_GUEST_MODE flag is used when a PASID bind is for guest * processes. Compared to the host bind, the primary differences are: * 1. mm life cycle management * 2. fault reporting */ -#define SVM_FLAG_GUEST_MODE (1<<2) +#define SVM_FLAG_GUEST_MODE (1<<1)/* * The SVM_FLAG_GUEST_PASID flag is used when a guest has its own PASID space,
* which requires guest and host PASID translation at both directions. */include/linux/intel-svm.h +1
-1-#define SVM_FLAG_GUEST_PASID (1<<3) +#define SVM_FLAG_GUEST_PASID (1<<2)#endif /* __INTEL_SVM_H__ */ include/linux/iommu.h +2
-0@@ -166,6 +166,19 @@ enum iommu_dev_features {#ifdef CONFIG_IOMMU_API +/* +* The IOMMU_SVA_BIND_SUPERVISOR flag requests a PASID which can be used only
+ * for access to kernel addresses. No IOTLB flushes are automatically done
+ * for kernel mappings; it is valid only for access to the kernel's static
+ * 1:1 mapping of physical memory — not to vmalloc or even module mappings.
+ * A future API addition may permit the use of such ranges, by means of an
+ * explicit IOTLB flush call (akin to the DMA API's unmap method).
+ *
+ * It is unlikely that we will ever hook intoflush_tlb_kernel_range()to
+ * do such IOTLB flushes automatically.
+ */include/linux/iommu.h +2
-0+#define IOMMU_SVA_BIND_SUPERVISOR BIT(0) +/** * struct iommu_iotlb_gather - Range information for a pending IOTLB flush *
include/linux/iommu.h +2
-2@@ -287,7 +300,7 @@ struct iommu_ops {int (*aux_get_pasid)(struct iommu_domain *domain,struct device *dev);struct iommu_sva *(*sva_bind)(struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void (*sva_unbind)(struct iommu_sva *handle);u32 (*sva_get_pasid)(struct iommu_sva *handle);@@ -640,7 +653,7 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev);struct iommu_sva *iommu_sva_bind_device (struct device *dev,struct mm_struct *mm, -void *drvdata); +unsigned int flags);void iommu_sva_unbind_device (struct iommu_sva *handle);u32 iommu_sva_get_pasid (struct iommu_sva *handle);@@ -1015,7 +1028,7 @@ iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) }
Quoted 10 lines
include/linux/iommu.h iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) · line 1034
Quoted 7 lines
include/linux/iommu.h +0
-1static inline struct iommu_sva * -iommu_sva_bind_device (struct device *dev,struct mm_struct *mm,void *drvdata) +iommu_sva_bind_device(struct device *dev, struct mm_struct *mm,unsigned int flags) {return NULL ; }Best regards,
baolu
Thanks,
Jacob
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
kernel test robot
build botI love your patch! Yet something to improve:
Hi Jacob,
I love your patch! Yet something to improve:
[auto build test ERROR on vkoul-dmaengine/next]
[also build test ERROR on char-misc/char-misc-testing v5.12-rc7] [cannot apply to iommu/next next-20210413]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Jacob-Pan/iommu-sva-Tighten-SVA-bind-API-with-explicit-flags/20210409-094521 base: https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next config: x86_64-randconfig-a016-20200531 (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/3b009446e2f451c401cff7a6d4766424acbcc890 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jacob-Pan/iommu-sva-Tighten-SVA-bind-API-with-explicit-flags/20210409-094521 git checkout 3b009446e2f451c401cff7a6d4766424acbcc890 # save the attached .config to linux build tree make W=1 ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>):
drivers/dma/idxd/init.c: In function 'idxd_enable_system_pasid':
>> drivers/dma/idxd/init.c:307:10: error: 'IOMMU_SVA_BIND_SUPERVISOR' undeclared (first use in this function)
307 | flags = IOMMU_SVA_BIND_SUPERVISOR;
| ^~~~~~~~~~~~~~~~~~~~~~~~~ drivers/dma/idxd/init.c:307:10: note: each undeclared identifier is reported only once for each function it appears in
vim +/IOMMU_SVA_BIND_SUPERVISOR +307 drivers/dma/idxd/init.c
300
301 static int idxd_enable_system_pasid(struct idxd_device *idxd)
302 {
303 unsigned int flags;
304 unsigned int pasid;
305 struct iommu_sva *sva;
306
> 307 flags = IOMMU_SVA_BIND_SUPERVISOR;
308
309 sva = iommu_sva_bind_device(&idxd->pdev->dev, NULL, flags);
310 if (IS_ERR(sva)) {
311 dev_warn(&idxd->pdev->dev,
312 "iommu sva bind failed: %ld\n", PTR_ERR(sva));
313 return PTR_ERR(sva);
314 }
315
316 pasid = iommu_sva_get_pasid(sva);
317 if (pasid == IOMMU_PASID_INVALID) {
318 iommu_sva_unbind_device(sva);
319 return -ENODEV;
320 }
321
322 idxd->sva = sva;
323 idxd->pasid = pasid;
324 dev_dbg(&idxd->pdev->dev, "system pasid: %u\n", pasid);
325 return 0;
326 }
327
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
kernel test robot
build botI love your patch! Yet something to improve:
Hi Jacob,
I love your patch! Yet something to improve:
[auto build test ERROR on vkoul-dmaengine/next]
[also build test ERROR on char-misc/char-misc-testing v5.12-rc7] [cannot apply to iommu/next next-20210413]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Jacob-Pan/iommu-sva-Tighten-SVA-bind-API-with-explicit-flags/20210409-094521 base: https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next config: x86_64-randconfig-a016-20210413 (attached as .config) compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 9829f5e6b1bca9b61efc629770d28bb9014dec45)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install x86_64 cross compiling tool for clang build
# apt-get install binutils-x86-64-linux-gnu
# https://github.com/0day-ci/linux/commit/3b009446e2f451c401cff7a6d4766424acbcc890
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Jacob-Pan/iommu-sva-Tighten-SVA-bind-API-with-explicit-flags/20210409-094521 git checkout 3b009446e2f451c401cff7a6d4766424acbcc890
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>):
>> drivers/dma/idxd/init.c:307:10: error: use of undeclared identifier 'IOMMU_SVA_BIND_SUPERVISOR'
flags = IOMMU_SVA_BIND_SUPERVISOR;
^
drivers/dma/idxd/init.c:422:30: warning: shift count >= width of type [-Wshift-count-overflow]
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
^~~~~~~~~~~~~~~~
include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
^ ~~~
drivers/dma/idxd/init.c:428:41: warning: shift count >= width of type [-Wshift-count-overflow]
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
^~~~~~~~~~~~~~~~
include/linux/dma-mapping.h:76:54: note: expanded from macro 'DMA_BIT_MASK'
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
^ ~~~2 warnings and 1 error generated.
vim +/IOMMU_SVA_BIND_SUPERVISOR +307 drivers/dma/idxd/init.c
300
301 static int idxd_enable_system_pasid(struct idxd_device *idxd)
302 {
303 unsigned int flags;
304 unsigned int pasid;
305 struct iommu_sva *sva;
306
> 307 flags = IOMMU_SVA_BIND_SUPERVISOR;
308
309 sva = iommu_sva_bind_device(&idxd->pdev->dev, NULL, flags);
310 if (IS_ERR(sva)) {
311 dev_warn(&idxd->pdev->dev,
312 "iommu sva bind failed: %ld\n", PTR_ERR(sva));
313 return PTR_ERR(sva);
314 }
315
316 pasid = iommu_sva_get_pasid(sva);
317 if (pasid == IOMMU_PASID_INVALID) {
318 iommu_sva_unbind_device(sva);
319 return -ENODEV;
320 }
321
322 idxd->sva = sva;
323 idxd->pasid = pasid;
324 dev_dbg(&idxd->pdev->dev, "system pasid: %u\n", pasid);
325 return 0;
326 }
327
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org