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