]> Git Repo - J-linux.git/commitdiff
iommu/amd/pgtbl_v2: Invalidate updated page ranges only
authorVasant Hegde <[email protected]>
Wed, 22 Nov 2023 09:02:15 +0000 (09:02 +0000)
committerJoerg Roedel <[email protected]>
Mon, 11 Dec 2023 14:25:38 +0000 (15:25 +0100)
Enhance __domain_flush_pages() to detect domain page table mode and use
that info to build invalidation commands. So that we can use
amd_iommu_domain_flush_pages() to invalidate v2 page table.

Also pass PASID, gn variable to device_flush_iotlb() so that it can build
IOTLB invalidation command for both v1 and v2 page table.

Signed-off-by: Vasant Hegde <[email protected]>
Reviewed-by: Jason Gunthorpe <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Joerg Roedel <[email protected]>
drivers/iommu/amd/io_pgtable_v2.c
drivers/iommu/amd/iommu.c

index f818a7e254d42627ebbd2d3154e290263af37421..6d69ba60744f063462ae8205284004de78d95ed2 100644 (file)
@@ -244,7 +244,6 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
        unsigned long mapped_size = 0;
        unsigned long o_iova = iova;
        size_t size = pgcount << __ffs(pgsize);
-       int count = 0;
        int ret = 0;
        bool updated = false;
 
@@ -265,19 +264,14 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
 
                *pte = set_pte_attr(paddr, map_size, prot);
 
-               count++;
                iova += map_size;
                paddr += map_size;
                mapped_size += map_size;
        }
 
 out:
-       if (updated) {
-               if (count > 1)
-                       amd_iommu_flush_tlb(&pdom->domain, 0);
-               else
-                       amd_iommu_flush_page(&pdom->domain, 0, o_iova);
-       }
+       if (updated)
+               amd_iommu_domain_flush_pages(pdom, o_iova, size);
 
        if (mapped)
                *mapped += mapped_size;
index 77cf1e3de053bb710606867f6f291d8ed0d71ce2..255ea754c0cdd5adda882c5b866f0c3468610021 100644 (file)
@@ -85,6 +85,11 @@ static void detach_device(struct device *dev);
  *
  ****************************************************************************/
 
+static inline bool pdom_is_v2_pgtbl_mode(struct protection_domain *pdom)
+{
+       return (pdom && (pdom->flags & PD_IOMMUV2_MASK));
+}
+
 static inline int get_acpihid_device_id(struct device *dev,
                                        struct acpihid_map_entry **entry)
 {
@@ -1382,8 +1387,8 @@ void amd_iommu_flush_all_caches(struct amd_iommu *iommu)
 /*
  * Command send function for flushing on-device TLB
  */
-static int device_flush_iotlb(struct iommu_dev_data *dev_data,
-                             u64 address, size_t size)
+static int device_flush_iotlb(struct iommu_dev_data *dev_data, u64 address,
+                             size_t size, ioasid_t pasid, bool gn)
 {
        struct amd_iommu *iommu;
        struct iommu_cmd cmd;
@@ -1395,7 +1400,7 @@ static int device_flush_iotlb(struct iommu_dev_data *dev_data,
                return -EINVAL;
 
        build_inv_iotlb_pages(&cmd, dev_data->devid, qdep, address,
-                             size, IOMMU_NO_PASID, false);
+                             size, pasid, gn);
 
        return iommu_queue_command(iommu, &cmd);
 }
@@ -1441,8 +1446,11 @@ static int device_flush_dte(struct iommu_dev_data *dev_data)
                        return ret;
        }
 
-       if (dev_data->ats_enabled)
-               ret = device_flush_iotlb(dev_data, 0, ~0UL);
+       if (dev_data->ats_enabled) {
+               /* Invalidate the entire contents of an IOTLB */
+               ret = device_flush_iotlb(dev_data, 0, ~0UL,
+                                        IOMMU_NO_PASID, false);
+       }
 
        return ret;
 }
@@ -1458,9 +1466,13 @@ static void __domain_flush_pages(struct protection_domain *domain,
        struct iommu_dev_data *dev_data;
        struct iommu_cmd cmd;
        int ret = 0, i;
+       ioasid_t pasid = IOMMU_NO_PASID;
+       bool gn = false;
+
+       if (pdom_is_v2_pgtbl_mode(domain))
+               gn = true;
 
-       build_inv_iommu_pages(&cmd, address, size, domain->id,
-                             IOMMU_NO_PASID, false);
+       build_inv_iommu_pages(&cmd, address, size, domain->id, pasid, gn);
 
        for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
                if (!domain->dev_iommu[i])
@@ -1478,7 +1490,7 @@ static void __domain_flush_pages(struct protection_domain *domain,
                if (!dev_data->ats_enabled)
                        continue;
 
-               ret |= device_flush_iotlb(dev_data, address, size);
+               ret |= device_flush_iotlb(dev_data, address, size, pasid, gn);
        }
 
        WARN_ON(ret);
This page took 0.059039 seconds and 4 git commands to generate.