On 2024/7/2 13:52, CLEMENT MATHIEU--DRIF wrote:
From: Clément Mathieu--Drif <clement.mathieu--d...@eviden.com>

IOMMU have to implement iommu_ats_request_translation to support ATS.

Devices can use IOMMU_TLB_ENTRY_TRANSLATION_ERROR to check the tlb
entries returned by a translation request.

Signed-off-by: Clément Mathieu--Drif <clement.mathieu--d...@eviden.com>
---
  include/exec/memory.h | 26 ++++++++++++++++++++++++++
  system/memory.c       | 20 ++++++++++++++++++++
  2 files changed, 46 insertions(+)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 003ee06610..48555c87c6 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -148,6 +148,10 @@ struct IOMMUTLBEntry {
      uint32_t         pasid;
  };
+/* Check if an IOMMU TLB entry indicates a translation error */
+#define IOMMU_TLB_ENTRY_TRANSLATION_ERROR(entry) ((((entry)->perm) & IOMMU_RW) 
\
+                                                    == IOMMU_NONE)
+
  /*
   * Bitmap for different IOMMUNotifier capabilities. Each notifier can
   * register with one or multiple IOMMU Notifier capability bit(s).
@@ -571,6 +575,20 @@ struct IOMMUMemoryRegionClass {
       int (*iommu_set_iova_ranges)(IOMMUMemoryRegion *iommu,
                                    GList *iova_ranges,
                                    Error **errp);
+
+    /**
+     * @iommu_ats_request_translation:
+     * This method must be implemented if the IOMMU has ATS enabled
+     *
+     * @see pci_ats_request_translation_pasid
+     */
+    ssize_t (*iommu_ats_request_translation)(IOMMUMemoryRegion *iommu,
+                                             bool priv_req, bool exec_req,
+                                             hwaddr addr, size_t length,
+                                             bool no_write,
+                                             IOMMUTLBEntry *result,
+                                             size_t result_length,
+                                             uint32_t *err_count);
  };

I'm not quite understanding why the existing translate() does not work.
Could you elaborate?

  typedef struct RamDiscardListener RamDiscardListener;
@@ -1926,6 +1944,14 @@ void memory_region_iommu_replay(IOMMUMemoryRegion 
*iommu_mr, IOMMUNotifier *n);
  void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
                                               IOMMUNotifier *n);
+ssize_t memory_region_iommu_ats_request_translation(IOMMUMemoryRegion *iommu_mr,
+                                                bool priv_req, bool exec_req,
+                                                hwaddr addr, size_t length,
+                                                bool no_write,
+                                                IOMMUTLBEntry *result,
+                                                size_t result_length,
+                                                uint32_t *err_count);
+
  /**
   * memory_region_iommu_get_attr: return an IOMMU attr if get_attr() is
   * defined on the IOMMU.
diff --git a/system/memory.c b/system/memory.c
index 74cd73ebc7..8268df7bf5 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -2005,6 +2005,26 @@ void 
memory_region_unregister_iommu_notifier(MemoryRegion *mr,
      memory_region_update_iommu_notify_flags(iommu_mr, NULL);
  }
+ssize_t memory_region_iommu_ats_request_translation(IOMMUMemoryRegion *iommu_mr,
+                                                    bool priv_req,
+                                                    bool exec_req,
+                                                    hwaddr addr, size_t length,
+                                                    bool no_write,
+                                                    IOMMUTLBEntry *result,
+                                                    size_t result_length,
+                                                    uint32_t *err_count)
+{
+    IOMMUMemoryRegionClass *imrc = 
memory_region_get_iommu_class_nocheck(iommu_mr);
+
+    if (!imrc->iommu_ats_request_translation) {
+        return -ENODEV;
+    }
+
+    return imrc->iommu_ats_request_translation(iommu_mr, priv_req, exec_req,
+                                               addr, length, no_write, result,
+                                               result_length, err_count);
+}
+
  void memory_region_notify_iommu_one(IOMMUNotifier *notifier,
                                      IOMMUTLBEvent *event)
  {

--
Regards,
Yi Liu

Reply via email to