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

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