Blame SOURCES/kvm-hw-arm-smmu-Introduce-SMMUTLBEntry-for-PTW-and-IOTLB.patch

8fced6
From 602f17920e422e2b8d3ce485e56066a97b74e723 Mon Sep 17 00:00:00 2001
8fced6
From: eperezma <eperezma@redhat.com>
8fced6
Date: Tue, 12 Jan 2021 14:36:29 -0500
8fced6
Subject: [PATCH 05/17] hw/arm/smmu: Introduce SMMUTLBEntry for PTW and IOTLB
8fced6
 value
8fced6
MIME-Version: 1.0
8fced6
Content-Type: text/plain; charset=UTF-8
8fced6
Content-Transfer-Encoding: 8bit
8fced6
8fced6
RH-Author: eperezma <eperezma@redhat.com>
8fced6
Message-id: <20210112143638.374060-5-eperezma@redhat.com>
8fced6
Patchwork-id: 100597
8fced6
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 04/13] hw/arm/smmu: Introduce SMMUTLBEntry for PTW and IOTLB value
8fced6
Bugzilla: 1843852
8fced6
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
8fced6
RH-Acked-by: Peter Xu <peterx@redhat.com>
8fced6
RH-Acked-by: Auger Eric <eric.auger@redhat.com>
8fced6
8fced6
From: Eric Auger <eric.auger@redhat.com>
8fced6
8fced6
Introduce a specialized SMMUTLBEntry to store the result of
8fced6
the PTW and cache in the IOTLB. This structure extends the
8fced6
generic IOMMUTLBEntry struct with the level of the entry and
8fced6
the granule size.
8fced6
8fced6
Those latter will be useful when implementing range invalidation.
8fced6
8fced6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8fced6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8fced6
Message-id: 20200728150815.11446-5-eric.auger@redhat.com
8fced6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8fced6
(cherry picked from commit a7550158556b7fc2f2baaecf9092499c6687b160)
8fced6
Signed-off-by: Eugenio PĂ©rez <eperezma@redhat.com>
8fced6
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
8fced6
---
8fced6
 hw/arm/smmu-common.c         | 32 +++++++++++++++++---------------
8fced6
 hw/arm/smmuv3.c              | 10 +++++-----
8fced6
 include/hw/arm/smmu-common.h | 12 +++++++++---
8fced6
 3 files changed, 31 insertions(+), 23 deletions(-)
8fced6
8fced6
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
8fced6
index 0b89c9fbbbc..06e9e38b007 100644
8fced6
--- a/hw/arm/smmu-common.c
8fced6
+++ b/hw/arm/smmu-common.c
8fced6
@@ -64,11 +64,11 @@ SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova)
8fced6
     return key;
8fced6
 }
8fced6
 
8fced6
-IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
8fced6
-                                 hwaddr iova)
8fced6
+SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
8fced6
+                                hwaddr iova)
8fced6
 {
8fced6
     SMMUIOTLBKey key = smmu_get_iotlb_key(cfg->asid, iova);
8fced6
-    IOMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
8fced6
+    SMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
8fced6
 
8fced6
     if (entry) {
8fced6
         cfg->iotlb_hits++;
8fced6
@@ -86,7 +86,7 @@ IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
8fced6
     return entry;
8fced6
 }
8fced6
 
8fced6
-void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry)
8fced6
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new)
8fced6
 {
8fced6
     SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1);
8fced6
 
8fced6
@@ -94,9 +94,9 @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry)
8fced6
         smmu_iotlb_inv_all(bs);
8fced6
     }
8fced6
 
8fced6
-    *key = smmu_get_iotlb_key(cfg->asid, entry->iova);
8fced6
-    trace_smmu_iotlb_insert(cfg->asid, entry->iova);
8fced6
-    g_hash_table_insert(bs->iotlb, key, entry);
8fced6
+    *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova);
8fced6
+    trace_smmu_iotlb_insert(cfg->asid, new->entry.iova);
8fced6
+    g_hash_table_insert(bs->iotlb, key, new);
8fced6
 }
8fced6
 
8fced6
 inline void smmu_iotlb_inv_all(SMMUState *s)
8fced6
@@ -217,7 +217,7 @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
8fced6
  * @cfg: translation config
8fced6
  * @iova: iova to translate
8fced6
  * @perm: access type
8fced6
- * @tlbe: IOMMUTLBEntry (out)
8fced6
+ * @tlbe: SMMUTLBEntry (out)
8fced6
  * @info: handle to an error info
8fced6
  *
8fced6
  * Return 0 on success, < 0 on error. In case of error, @info is filled
8fced6
@@ -227,7 +227,7 @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
8fced6
  */
8fced6
 static int smmu_ptw_64(SMMUTransCfg *cfg,
8fced6
                        dma_addr_t iova, IOMMUAccessFlags perm,
8fced6
-                       IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
8fced6
+                       SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
8fced6
 {
8fced6
     dma_addr_t baseaddr, indexmask;
8fced6
     int stage = cfg->stage;
8fced6
@@ -247,8 +247,8 @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
8fced6
     baseaddr = extract64(tt->ttb, 0, 48);
8fced6
     baseaddr &= ~indexmask;
8fced6
 
8fced6
-    tlbe->iova = iova;
8fced6
-    tlbe->addr_mask = (1 << granule_sz) - 1;
8fced6
+    tlbe->entry.iova = iova;
8fced6
+    tlbe->entry.addr_mask = (1 << granule_sz) - 1;
8fced6
 
8fced6
     while (level <= 3) {
8fced6
         uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
8fced6
@@ -299,14 +299,16 @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
8fced6
             goto error;
8fced6
         }
8fced6
 
8fced6
-        tlbe->translated_addr = gpa + (iova & mask);
8fced6
-        tlbe->perm = PTE_AP_TO_PERM(ap);
8fced6
+        tlbe->entry.translated_addr = gpa + (iova & mask);
8fced6
+        tlbe->entry.perm = PTE_AP_TO_PERM(ap);
8fced6
+        tlbe->level = level;
8fced6
+        tlbe->granule = granule_sz;
8fced6
         return 0;
8fced6
     }
8fced6
     info->type = SMMU_PTW_ERR_TRANSLATION;
8fced6
 
8fced6
 error:
8fced6
-    tlbe->perm = IOMMU_NONE;
8fced6
+    tlbe->entry.perm = IOMMU_NONE;
8fced6
     return -EINVAL;
8fced6
 }
8fced6
 
8fced6
@@ -322,7 +324,7 @@ error:
8fced6
  * return 0 on success
8fced6
  */
8fced6
 inline int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
8fced6
-             IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
8fced6
+                    SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
8fced6
 {
8fced6
     if (!cfg->aa64) {
8fced6
         /*
8fced6
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
8fced6
index 34dea4df4da..ad8212779d3 100644
8fced6
--- a/hw/arm/smmuv3.c
8fced6
+++ b/hw/arm/smmuv3.c
8fced6
@@ -614,7 +614,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
8fced6
     SMMUTranslationStatus status;
8fced6
     SMMUState *bs = ARM_SMMU(s);
8fced6
     uint64_t page_mask, aligned_addr;
8fced6
-    IOMMUTLBEntry *cached_entry = NULL;
8fced6
+    SMMUTLBEntry *cached_entry = NULL;
8fced6
     SMMUTransTableInfo *tt;
8fced6
     SMMUTransCfg *cfg = NULL;
8fced6
     IOMMUTLBEntry entry = {
8fced6
@@ -664,7 +664,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
8fced6
 
8fced6
     cached_entry = smmu_iotlb_lookup(bs, cfg, aligned_addr);
8fced6
     if (cached_entry) {
8fced6
-        if ((flag & IOMMU_WO) && !(cached_entry->perm & IOMMU_WO)) {
8fced6
+        if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) {
8fced6
             status = SMMU_TRANS_ERROR;
8fced6
             if (event.record_trans_faults) {
8fced6
                 event.type = SMMU_EVT_F_PERMISSION;
8fced6
@@ -677,7 +677,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
8fced6
         goto epilogue;
8fced6
     }
8fced6
 
8fced6
-    cached_entry = g_new0(IOMMUTLBEntry, 1);
8fced6
+    cached_entry = g_new0(SMMUTLBEntry, 1);
8fced6
 
8fced6
     if (smmu_ptw(cfg, aligned_addr, flag, cached_entry, &ptw_info)) {
8fced6
         g_free(cached_entry);
8fced6
@@ -731,9 +731,9 @@ epilogue:
8fced6
     switch (status) {
8fced6
     case SMMU_TRANS_SUCCESS:
8fced6
         entry.perm = flag;
8fced6
-        entry.translated_addr = cached_entry->translated_addr +
8fced6
+        entry.translated_addr = cached_entry->entry.translated_addr +
8fced6
                                     (addr & page_mask);
8fced6
-        entry.addr_mask = cached_entry->addr_mask;
8fced6
+        entry.addr_mask = cached_entry->entry.addr_mask;
8fced6
         trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr,
8fced6
                                        entry.translated_addr, entry.perm);
8fced6
         break;
8fced6
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
8fced6
index bceba40885c..277923bdc0a 100644
8fced6
--- a/include/hw/arm/smmu-common.h
8fced6
+++ b/include/hw/arm/smmu-common.h
8fced6
@@ -52,6 +52,12 @@ typedef struct SMMUTransTableInfo {
8fced6
     uint8_t granule_sz;        /* granule page shift */
8fced6
 } SMMUTransTableInfo;
8fced6
 
8fced6
+typedef struct SMMUTLBEntry {
8fced6
+    IOMMUTLBEntry entry;
8fced6
+    uint8_t level;
8fced6
+    uint8_t granule;
8fced6
+} SMMUTLBEntry;
8fced6
+
8fced6
 /*
8fced6
  * Generic structure populated by derived SMMU devices
8fced6
  * after decoding the configuration information and used as
8fced6
@@ -140,7 +146,7 @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
8fced6
  * pair, according to @cfg translation config
8fced6
  */
8fced6
 int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
8fced6
-             IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
8fced6
+             SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
8fced6
 
8fced6
 /**
8fced6
  * select_tt - compute which translation table shall be used according to
8fced6
@@ -153,8 +159,8 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
8fced6
 
8fced6
 #define SMMU_IOTLB_MAX_SIZE 256
8fced6
 
8fced6
-IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
8fced6
-void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry);
8fced6
+SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
8fced6
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry);
8fced6
 SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova);
8fced6
 void smmu_iotlb_inv_all(SMMUState *s);
8fced6
 void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
8fced6
-- 
8fced6
2.27.0
8fced6