]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu/vt-d: Lift the __pa to domain_setup_first_level/intel_svm_set_dev_pasid()
authorJason Gunthorpe <jgg@nvidia.com>
Mon, 14 Jul 2025 04:50:20 +0000 (12:50 +0800)
committerWill Deacon <will@kernel.org>
Mon, 14 Jul 2025 10:18:03 +0000 (11:18 +0100)
Pass the phys_addr_t down through the call chain from the top instead of
passing a pgd_t * KVA. This moves the __pa() into
domain_setup_first_level() which is the first function to obtain the pgd
from the IOMMU page table in this call chain.

The SVA flow is also adjusted to get the pa of the mm->pgd.

iommput will move the __pa() into iommupt code, it never shares the KVA of
the page table with the driver.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/1-v3-dbbe6f7e7ae3+124ffe-vtd_prep_jgg@nvidia.com
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Link: https://lore.kernel.org/r/20250714045028.958850-4-baolu.lu@linux.intel.com
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/intel/iommu.c
drivers/iommu/intel/iommu.h
drivers/iommu/intel/pasid.c
drivers/iommu/intel/pasid.h
drivers/iommu/intel/svm.c

index f60201ee4be0fd66568611529c39ea99d7aca15e..bb29c4a635ea4d2fe31b6f7c96b5447ae8047642 100644 (file)
@@ -1736,15 +1736,14 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
        intel_context_flush_no_pasid(info, context, did);
 }
 
-int __domain_setup_first_level(struct intel_iommu *iommu,
-                              struct device *dev, ioasid_t pasid,
-                              u16 did, pgd_t *pgd, int flags,
-                              struct iommu_domain *old)
+int __domain_setup_first_level(struct intel_iommu *iommu, struct device *dev,
+                              ioasid_t pasid, u16 did, phys_addr_t fsptptr,
+                              int flags, struct iommu_domain *old)
 {
        if (!old)
-               return intel_pasid_setup_first_level(iommu, dev, pgd,
-                                                    pasid, did, flags);
-       return intel_pasid_replace_first_level(iommu, dev, pgd, pasid, did,
+               return intel_pasid_setup_first_level(iommu, dev, fsptptr, pasid,
+                                                    did, flags);
+       return intel_pasid_replace_first_level(iommu, dev, fsptptr, pasid, did,
                                               iommu_domain_did(old, iommu),
                                               flags);
 }
@@ -1793,7 +1792,7 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
 
        return __domain_setup_first_level(iommu, dev, pasid,
                                          domain_id_iommu(domain, iommu),
-                                         (pgd_t *)pgd, flags, old);
+                                         __pa(pgd), flags, old);
 }
 
 static bool domain_need_iotlb_sync_map(struct dmar_domain *domain,
index 7ab2c34a5ecc40d0d26c784aebe2ecb6ea082836..30baee6f6519f7412361c8c7260c7e14551c618b 100644 (file)
@@ -1255,10 +1255,9 @@ domain_add_dev_pasid(struct iommu_domain *domain,
 void domain_remove_dev_pasid(struct iommu_domain *domain,
                             struct device *dev, ioasid_t pasid);
 
-int __domain_setup_first_level(struct intel_iommu *iommu,
-                              struct device *dev, ioasid_t pasid,
-                              u16 did, pgd_t *pgd, int flags,
-                              struct iommu_domain *old);
+int __domain_setup_first_level(struct intel_iommu *iommu, struct device *dev,
+                              ioasid_t pasid, u16 did, phys_addr_t fsptptr,
+                              int flags, struct iommu_domain *old);
 
 int dmar_ir_support(void);
 
index ac67a056b6c868e16cca5c930e727038641e9018..52f678975da745ac1ba5168705b1f70c170755eb 100644 (file)
@@ -348,14 +348,15 @@ static void intel_pasid_flush_present(struct intel_iommu *iommu,
  */
 static void pasid_pte_config_first_level(struct intel_iommu *iommu,
                                         struct pasid_entry *pte,
-                                        pgd_t *pgd, u16 did, int flags)
+                                        phys_addr_t fsptptr, u16 did,
+                                        int flags)
 {
        lockdep_assert_held(&iommu->lock);
 
        pasid_clear_entry(pte);
 
        /* Setup the first level page table pointer: */
-       pasid_set_flptr(pte, (u64)__pa(pgd));
+       pasid_set_flptr(pte, fsptptr);
 
        if (flags & PASID_FLAG_FL5LP)
                pasid_set_flpm(pte, 1);
@@ -372,9 +373,9 @@ static void pasid_pte_config_first_level(struct intel_iommu *iommu,
        pasid_set_present(pte);
 }
 
-int intel_pasid_setup_first_level(struct intel_iommu *iommu,
-                                 struct device *dev, pgd_t *pgd,
-                                 u32 pasid, u16 did, int flags)
+int intel_pasid_setup_first_level(struct intel_iommu *iommu, struct device *dev,
+                                 phys_addr_t fsptptr, u32 pasid, u16 did,
+                                 int flags)
 {
        struct pasid_entry *pte;
 
@@ -402,7 +403,7 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
                return -EBUSY;
        }
 
-       pasid_pte_config_first_level(iommu, pte, pgd, did, flags);
+       pasid_pte_config_first_level(iommu, pte, fsptptr, did, flags);
 
        spin_unlock(&iommu->lock);
 
@@ -412,7 +413,7 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
 }
 
 int intel_pasid_replace_first_level(struct intel_iommu *iommu,
-                                   struct device *dev, pgd_t *pgd,
+                                   struct device *dev, phys_addr_t fsptptr,
                                    u32 pasid, u16 did, u16 old_did,
                                    int flags)
 {
@@ -430,7 +431,7 @@ int intel_pasid_replace_first_level(struct intel_iommu *iommu,
                return -EINVAL;
        }
 
-       pasid_pte_config_first_level(iommu, &new_pte, pgd, did, flags);
+       pasid_pte_config_first_level(iommu, &new_pte, fsptptr, did, flags);
 
        spin_lock(&iommu->lock);
        pte = intel_pasid_get_entry(dev, pasid);
index fd0fd1a0df84cc1327d4f5b040c820337ead6b5e..a771a77d4239c479a381d1979f33d9bc0baf64df 100644 (file)
@@ -288,9 +288,9 @@ extern unsigned int intel_pasid_max_id;
 int intel_pasid_alloc_table(struct device *dev);
 void intel_pasid_free_table(struct device *dev);
 struct pasid_table *intel_pasid_get_table(struct device *dev);
-int intel_pasid_setup_first_level(struct intel_iommu *iommu,
-                                 struct device *dev, pgd_t *pgd,
-                                 u32 pasid, u16 did, int flags);
+int intel_pasid_setup_first_level(struct intel_iommu *iommu, struct device *dev,
+                                 phys_addr_t fsptptr, u32 pasid, u16 did,
+                                 int flags);
 int intel_pasid_setup_second_level(struct intel_iommu *iommu,
                                   struct dmar_domain *domain,
                                   struct device *dev, u32 pasid);
@@ -302,9 +302,8 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
 int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
                             u32 pasid, struct dmar_domain *domain);
 int intel_pasid_replace_first_level(struct intel_iommu *iommu,
-                                   struct device *dev, pgd_t *pgd,
-                                   u32 pasid, u16 did, u16 old_did,
-                                   int flags);
+                                   struct device *dev, phys_addr_t fsptptr,
+                                   u32 pasid, u16 did, u16 old_did, int flags);
 int intel_pasid_replace_second_level(struct intel_iommu *iommu,
                                     struct dmar_domain *domain,
                                     struct device *dev, u16 old_did,
index f3da596410b5e55bcea31009a94f61921b1f9009..8c0bed36c58777a5bfa24536a0af4579a570a156 100644 (file)
@@ -171,7 +171,7 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
        /* Setup the pasid table: */
        sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
        ret = __domain_setup_first_level(iommu, dev, pasid,
-                                        FLPT_DEFAULT_DID, mm->pgd,
+                                        FLPT_DEFAULT_DID, __pa(mm->pgd),
                                         sflags, old);
        if (ret)
                goto out_unwind_iopf;