Skip to content

Commit 942fd54

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Remove SVM_FLAG_SUPERVISOR_MODE support
The current kernel DMA with PASID support is based on the SVA with a flag SVM_FLAG_SUPERVISOR_MODE. The IOMMU driver binds the kernel memory address space to a PASID of the device. The device driver programs the device with kernel virtual address (KVA) for DMA access. There have been security and functional issues with this approach: - The lack of IOTLB synchronization upon kernel page table updates. (vmalloc, module/BPF loading, CONFIG_DEBUG_PAGEALLOC etc.) - Other than slight more protection, using kernel virtual address (KVA) has little advantage over physical address. There are also no use cases yet where DMA engines need kernel virtual addresses for in-kernel DMA. This removes SVM_FLAG_SUPERVISOR_MODE support from the IOMMU interface. The device drivers are suggested to handle kernel DMA with PASID through the kernel DMA APIs. The drvdata parameter in iommu_sva_bind_device() and all callbacks is not needed anymore. Cleanup them as well. Link: https://lore.kernel.org/linux-iommu/[email protected]/ Signed-off-by: Jacob Pan <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Jean-Philippe Brucker <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Fenghua Yu <[email protected]> Tested-by: Zhangfei Gao <[email protected]> Tested-by: Tony Zhu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 22d2c7a commit 942fd54

File tree

10 files changed

+25
-97
lines changed

10 files changed

+25
-97
lines changed

drivers/dma/idxd/cdev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <linux/pci.h>
77
#include <linux/device.h>
88
#include <linux/sched/task.h>
9-
#include <linux/intel-svm.h>
109
#include <linux/io-64-nonatomic-lo-hi.h>
1110
#include <linux/cdev.h>
1211
#include <linux/fs.h>
@@ -100,7 +99,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
10099
filp->private_data = ctx;
101100

102101
if (device_user_pasid_enabled(idxd)) {
103-
sva = iommu_sva_bind_device(dev, current->mm, NULL);
102+
sva = iommu_sva_bind_device(dev, current->mm);
104103
if (IS_ERR(sva)) {
105104
rc = PTR_ERR(sva);
106105
dev_err(dev, "pasid allocation failed: %d\n", rc);

drivers/dma/idxd/init.c

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/io-64-nonatomic-lo-hi.h>
1515
#include <linux/device.h>
1616
#include <linux/idr.h>
17-
#include <linux/intel-svm.h>
1817
#include <linux/iommu.h>
1918
#include <uapi/linux/idxd.h>
2019
#include <linux/dmaengine.h>
@@ -502,29 +501,7 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d
502501

503502
static int idxd_enable_system_pasid(struct idxd_device *idxd)
504503
{
505-
int flags;
506-
unsigned int pasid;
507-
struct iommu_sva *sva;
508-
509-
flags = SVM_FLAG_SUPERVISOR_MODE;
510-
511-
sva = iommu_sva_bind_device(&idxd->pdev->dev, NULL, &flags);
512-
if (IS_ERR(sva)) {
513-
dev_warn(&idxd->pdev->dev,
514-
"iommu sva bind failed: %ld\n", PTR_ERR(sva));
515-
return PTR_ERR(sva);
516-
}
517-
518-
pasid = iommu_sva_get_pasid(sva);
519-
if (pasid == IOMMU_PASID_INVALID) {
520-
iommu_sva_unbind_device(sva);
521-
return -ENODEV;
522-
}
523-
524-
idxd->sva = sva;
525-
idxd->pasid = pasid;
526-
dev_dbg(&idxd->pdev->dev, "system pasid: %u\n", pasid);
527-
return 0;
504+
return -EOPNOTSUPP;
528505
}
529506

530507
static void idxd_disable_system_pasid(struct idxd_device *idxd)

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,7 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
367367
return ERR_PTR(ret);
368368
}
369369

370-
struct iommu_sva *
371-
arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, void *drvdata)
370+
struct iommu_sva *arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
372371
{
373372
struct iommu_sva *handle;
374373
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,7 @@ bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);
754754
int arm_smmu_master_enable_sva(struct arm_smmu_master *master);
755755
int arm_smmu_master_disable_sva(struct arm_smmu_master *master);
756756
bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master);
757-
struct iommu_sva *arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm,
758-
void *drvdata);
757+
struct iommu_sva *arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm);
759758
void arm_smmu_sva_unbind(struct iommu_sva *handle);
760759
u32 arm_smmu_sva_get_pasid(struct iommu_sva *handle);
761760
void arm_smmu_sva_notifier_synchronize(void);
@@ -791,7 +790,7 @@ static inline bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master
791790
}
792791

793792
static inline struct iommu_sva *
794-
arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, void *drvdata)
793+
arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
795794
{
796795
return ERR_PTR(-ENODEV);
797796
}

drivers/iommu/intel/iommu.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,8 +748,7 @@ struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn);
748748
extern void intel_svm_check(struct intel_iommu *iommu);
749749
extern int intel_svm_enable_prq(struct intel_iommu *iommu);
750750
extern int intel_svm_finish_prq(struct intel_iommu *iommu);
751-
struct iommu_sva *intel_svm_bind(struct device *dev, struct mm_struct *mm,
752-
void *drvdata);
751+
struct iommu_sva *intel_svm_bind(struct device *dev, struct mm_struct *mm);
753752
void intel_svm_unbind(struct iommu_sva *handle);
754753
u32 intel_svm_get_pasid(struct iommu_sva *handle);
755754
int intel_svm_page_response(struct device *dev, struct iommu_fault_event *evt,

drivers/iommu/intel/svm.c

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,7 @@ static int pasid_to_svm_sdev(struct device *dev, unsigned int pasid,
296296
return 0;
297297
}
298298

299-
static int intel_svm_alloc_pasid(struct device *dev, struct mm_struct *mm,
300-
unsigned int flags)
299+
static int intel_svm_alloc_pasid(struct device *dev, struct mm_struct *mm)
301300
{
302301
ioasid_t max_pasid = dev_is_pci(dev) ?
303302
pci_max_pasids(to_pci_dev(dev)) : intel_pasid_max_id;
@@ -307,8 +306,7 @@ static int intel_svm_alloc_pasid(struct device *dev, struct mm_struct *mm,
307306

308307
static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu,
309308
struct device *dev,
310-
struct mm_struct *mm,
311-
unsigned int flags)
309+
struct mm_struct *mm)
312310
{
313311
struct device_domain_info *info = dev_iommu_priv_get(dev);
314312
struct intel_svm_dev *sdev;
@@ -324,22 +322,18 @@ static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu,
324322

325323
svm->pasid = mm->pasid;
326324
svm->mm = mm;
327-
svm->flags = flags;
328325
INIT_LIST_HEAD_RCU(&svm->devs);
329326

330-
if (!(flags & SVM_FLAG_SUPERVISOR_MODE)) {
331-
svm->notifier.ops = &intel_mmuops;
332-
ret = mmu_notifier_register(&svm->notifier, mm);
333-
if (ret) {
334-
kfree(svm);
335-
return ERR_PTR(ret);
336-
}
327+
svm->notifier.ops = &intel_mmuops;
328+
ret = mmu_notifier_register(&svm->notifier, mm);
329+
if (ret) {
330+
kfree(svm);
331+
return ERR_PTR(ret);
337332
}
338333

339334
ret = pasid_private_add(svm->pasid, svm);
340335
if (ret) {
341-
if (svm->notifier.ops)
342-
mmu_notifier_unregister(&svm->notifier, mm);
336+
mmu_notifier_unregister(&svm->notifier, mm);
343337
kfree(svm);
344338
return ERR_PTR(ret);
345339
}
@@ -374,9 +368,7 @@ static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu,
374368
}
375369

376370
/* Setup the pasid table: */
377-
sflags = (flags & SVM_FLAG_SUPERVISOR_MODE) ?
378-
PASID_FLAG_SUPERVISOR_MODE : 0;
379-
sflags |= cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
371+
sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
380372
ret = intel_pasid_setup_first_level(iommu, dev, mm->pgd, mm->pasid,
381373
FLPT_DEFAULT_DID, sflags);
382374
if (ret)
@@ -390,8 +382,7 @@ static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu,
390382
kfree(sdev);
391383
free_svm:
392384
if (list_empty(&svm->devs)) {
393-
if (svm->notifier.ops)
394-
mmu_notifier_unregister(&svm->notifier, mm);
385+
mmu_notifier_unregister(&svm->notifier, mm);
395386
pasid_private_remove(mm->pasid);
396387
kfree(svm);
397388
}
@@ -780,40 +771,20 @@ static irqreturn_t prq_event_thread(int irq, void *d)
780771
return IRQ_RETVAL(handled);
781772
}
782773

783-
struct iommu_sva *intel_svm_bind(struct device *dev, struct mm_struct *mm, void *drvdata)
774+
struct iommu_sva *intel_svm_bind(struct device *dev, struct mm_struct *mm)
784775
{
785776
struct intel_iommu *iommu = device_to_iommu(dev, NULL, NULL);
786-
unsigned int flags = 0;
787777
struct iommu_sva *sva;
788778
int ret;
789779

790-
if (drvdata)
791-
flags = *(unsigned int *)drvdata;
792-
793-
if (flags & SVM_FLAG_SUPERVISOR_MODE) {
794-
if (!ecap_srs(iommu->ecap)) {
795-
dev_err(dev, "%s: Supervisor PASID not supported\n",
796-
iommu->name);
797-
return ERR_PTR(-EOPNOTSUPP);
798-
}
799-
800-
if (mm) {
801-
dev_err(dev, "%s: Supervisor PASID with user provided mm\n",
802-
iommu->name);
803-
return ERR_PTR(-EINVAL);
804-
}
805-
806-
mm = &init_mm;
807-
}
808-
809780
mutex_lock(&pasid_mutex);
810-
ret = intel_svm_alloc_pasid(dev, mm, flags);
781+
ret = intel_svm_alloc_pasid(dev, mm);
811782
if (ret) {
812783
mutex_unlock(&pasid_mutex);
813784
return ERR_PTR(ret);
814785
}
815786

816-
sva = intel_svm_bind_mm(iommu, dev, mm, flags);
787+
sva = intel_svm_bind_mm(iommu, dev, mm);
817788
mutex_unlock(&pasid_mutex);
818789

819790
return sva;

drivers/iommu/iommu.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2750,7 +2750,6 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature);
27502750
* iommu_sva_bind_device() - Bind a process address space to a device
27512751
* @dev: the device
27522752
* @mm: the mm to bind, caller must hold a reference to it
2753-
* @drvdata: opaque data pointer to pass to bind callback
27542753
*
27552754
* Create a bond between device and address space, allowing the device to access
27562755
* the mm using the returned PASID. If a bond already exists between @device and
@@ -2763,7 +2762,7 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature);
27632762
* On error, returns an ERR_PTR value.
27642763
*/
27652764
struct iommu_sva *
2766-
iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)
2765+
iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
27672766
{
27682767
struct iommu_group *group;
27692768
struct iommu_sva *handle = ERR_PTR(-EINVAL);
@@ -2788,7 +2787,7 @@ iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)
27882787
if (iommu_group_device_count(group) != 1)
27892788
goto out_unlock;
27902789

2791-
handle = ops->sva_bind(dev, mm, drvdata);
2790+
handle = ops->sva_bind(dev, mm);
27922791

27932792
out_unlock:
27942793
mutex_unlock(&group->mutex);

drivers/misc/uacce/uacce.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static int uacce_bind_queue(struct uacce_device *uacce, struct uacce_queue *q)
108108
if (!(uacce->flags & UACCE_DEV_SVA))
109109
return 0;
110110

111-
handle = iommu_sva_bind_device(uacce->parent, current->mm, NULL);
111+
handle = iommu_sva_bind_device(uacce->parent, current->mm);
112112
if (IS_ERR(handle))
113113
return PTR_ERR(handle);
114114

include/linux/intel-svm.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,4 @@
1313
#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x20)
1414
#define PRQ_DEPTH ((0x1000 << PRQ_ORDER) >> 5)
1515

16-
/*
17-
* The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only
18-
* for access to kernel addresses. No IOTLB flushes are automatically done
19-
* for kernel mappings; it is valid only for access to the kernel's static
20-
* 1:1 mapping of physical memory — not to vmalloc or even module mappings.
21-
* A future API addition may permit the use of such ranges, by means of an
22-
* explicit IOTLB flush call (akin to the DMA API's unmap method).
23-
*
24-
* It is unlikely that we will ever hook into flush_tlb_kernel_range() to
25-
* do such IOTLB flushes automatically.
26-
*/
27-
#define SVM_FLAG_SUPERVISOR_MODE BIT(0)
28-
2916
#endif /* __INTEL_SVM_H__ */

include/linux/iommu.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,7 @@ struct iommu_ops {
247247
int (*dev_enable_feat)(struct device *dev, enum iommu_dev_features f);
248248
int (*dev_disable_feat)(struct device *dev, enum iommu_dev_features f);
249249

250-
struct iommu_sva *(*sva_bind)(struct device *dev, struct mm_struct *mm,
251-
void *drvdata);
250+
struct iommu_sva *(*sva_bind)(struct device *dev, struct mm_struct *mm);
252251
void (*sva_unbind)(struct iommu_sva *handle);
253252
u32 (*sva_get_pasid)(struct iommu_sva *handle);
254253

@@ -668,8 +667,7 @@ int iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features f);
668667
int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features f);
669668

670669
struct iommu_sva *iommu_sva_bind_device(struct device *dev,
671-
struct mm_struct *mm,
672-
void *drvdata);
670+
struct mm_struct *mm);
673671
void iommu_sva_unbind_device(struct iommu_sva *handle);
674672
u32 iommu_sva_get_pasid(struct iommu_sva *handle);
675673

@@ -1000,7 +998,7 @@ iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features feat)
1000998
}
1001999

10021000
static inline struct iommu_sva *
1003-
iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)
1001+
iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
10041002
{
10051003
return NULL;
10061004
}

0 commit comments

Comments
 (0)