From 6808bca939b8722d98165319ba42366ca80de907 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:06 +0200 Subject: hw/arm/smmu-common: Add IOTLB helpers Add two helpers: one to lookup for a given IOTLB entry and one to insert a new entry. We also move the tracing there. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-3-eric.auger@redhat.com Signed-off-by: Peter Maydell --- include/hw/arm/smmu-common.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index ca4a4b1ad1..1dceec5cb1 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -153,6 +153,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); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova); -- cgit v1.2.3-55-g7522 From 60a61f1b31fc03080aadb63c9b1006f8b1972adb Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:07 +0200 Subject: hw/arm/smmu: Introduce smmu_get_iotlb_key() Introduce the smmu_get_iotlb_key() helper and the SMMU_IOTLB_ASID() macro. Also move smmu_get_iotlb_key and smmu_iotlb_key_hash in the IOTLB related code section. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-4-eric.auger@redhat.com Signed-off-by: Peter Maydell --- hw/arm/smmu-common.c | 66 ++++++++++++++++++++++++-------------------- hw/arm/smmu-internal.h | 1 + include/hw/arm/smmu-common.h | 1 + 3 files changed, 38 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index f3aa581f80..7dc8541e8b 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -32,10 +32,42 @@ /* IOTLB Management */ +static guint smmu_iotlb_key_hash(gconstpointer v) +{ + SMMUIOTLBKey *key = (SMMUIOTLBKey *)v; + uint32_t a, b, c; + + /* Jenkins hash */ + a = b = c = JHASH_INITVAL + sizeof(*key); + a += key->asid; + b += extract64(key->iova, 0, 32); + c += extract64(key->iova, 32, 32); + + __jhash_mix(a, b, c); + __jhash_final(a, b, c); + + return c; +} + +static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2) +{ + const SMMUIOTLBKey *k1 = v1; + const SMMUIOTLBKey *k2 = v2; + + return (k1->asid == k2->asid) && (k1->iova == k2->iova); +} + +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova) +{ + SMMUIOTLBKey key = {.asid = asid, .iova = iova}; + + return key; +} + IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova) { - SMMUIOTLBKey key = {.asid = cfg->asid, .iova = iova}; + SMMUIOTLBKey key = smmu_get_iotlb_key(cfg->asid, iova); IOMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key); if (entry) { @@ -62,8 +94,7 @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry) smmu_iotlb_inv_all(bs); } - key->asid = cfg->asid; - key->iova = entry->iova; + *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); } @@ -80,12 +111,12 @@ static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value, uint16_t asid = *(uint16_t *)user_data; SMMUIOTLBKey *iotlb_key = (SMMUIOTLBKey *)key; - return iotlb_key->asid == asid; + return SMMU_IOTLB_ASID(*iotlb_key) == asid; } inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova) { - SMMUIOTLBKey key = {.asid = asid, .iova = iova}; + SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova); trace_smmu_iotlb_inv_iova(asid, iova); g_hash_table_remove(s->iotlb, &key); @@ -383,31 +414,6 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid) return NULL; } -static guint smmu_iotlb_key_hash(gconstpointer v) -{ - SMMUIOTLBKey *key = (SMMUIOTLBKey *)v; - uint32_t a, b, c; - - /* Jenkins hash */ - a = b = c = JHASH_INITVAL + sizeof(*key); - a += key->asid; - b += extract64(key->iova, 0, 32); - c += extract64(key->iova, 32, 32); - - __jhash_mix(a, b, c); - __jhash_final(a, b, c); - - return c; -} - -static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2) -{ - const SMMUIOTLBKey *k1 = v1; - const SMMUIOTLBKey *k2 = v2; - - return (k1->asid == k2->asid) && (k1->iova == k2->iova); -} - /* Unmap the whole notifier's range */ static void smmu_unmap_notifier_range(IOMMUNotifier *n) { diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h index 7794d6d394..3104f768cd 100644 --- a/hw/arm/smmu-internal.h +++ b/hw/arm/smmu-internal.h @@ -96,4 +96,5 @@ uint64_t iova_level_offset(uint64_t iova, int inputsize, MAKE_64BIT_MASK(0, gsz - 3); } +#define SMMU_IOTLB_ASID(key) ((key).asid) #endif diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 1dceec5cb1..5f9f3535d2 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -155,6 +155,7 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid); IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova); void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *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); void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova); -- cgit v1.2.3-55-g7522 From a7550158556b7fc2f2baaecf9092499c6687b160 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:08 +0200 Subject: hw/arm/smmu: Introduce SMMUTLBEntry for PTW and IOTLB value 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 Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-5-eric.auger@redhat.com Signed-off-by: Peter Maydell --- 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(-) (limited to 'include') diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 7dc8541e8b..398e958bb4 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -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) @@ -216,7 +216,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 @@ -226,7 +226,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; @@ -246,8 +246,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); @@ -298,14 +298,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; } @@ -321,7 +323,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 cd2a2e7e14..db74d27add 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -626,7 +626,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 = { @@ -676,7 +676,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; @@ -689,7 +689,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); @@ -743,9 +743,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 5f9f3535d2..79c2c6486a 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -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); -- cgit v1.2.3-55-g7522 From 9e54dee71fcfaae69f87b8e1f51485a832266a39 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:09 +0200 Subject: hw/arm/smmu-common: Manage IOTLB block entries At the moment each entry in the IOTLB corresponds to a page sized mapping (4K, 16K or 64K), even if the page belongs to a mapped block. In case of block mapping this unefficiently consumes IOTLB entries. Change the value of the entry so that it reflects the actual mapping it belongs to (block or page start address and size). Also the level/tg of the entry is encoded in the key. In subsequent patches we will enable range invalidation. This latter is able to provide the level/tg of the entry. Encoding the level/tg directly in the key will allow to invalidate using g_hash_table_remove() when num_pages equals to 1. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-6-eric.auger@redhat.com Signed-off-by: Peter Maydell --- hw/arm/smmu-common.c | 67 ++++++++++++++++++++++++++++++++------------ hw/arm/smmu-internal.h | 7 +++++ hw/arm/smmuv3.c | 6 ++-- hw/arm/trace-events | 2 +- include/hw/arm/smmu-common.h | 10 +++++-- 5 files changed, 67 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 398e958bb4..2922deec6f 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -39,7 +39,7 @@ static guint smmu_iotlb_key_hash(gconstpointer v) /* Jenkins hash */ a = b = c = JHASH_INITVAL + sizeof(*key); - a += key->asid; + a += key->asid + key->level + key->tg; b += extract64(key->iova, 0, 32); c += extract64(key->iova, 32, 32); @@ -51,24 +51,41 @@ static guint smmu_iotlb_key_hash(gconstpointer v) static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2) { - const SMMUIOTLBKey *k1 = v1; - const SMMUIOTLBKey *k2 = v2; + SMMUIOTLBKey *k1 = (SMMUIOTLBKey *)v1, *k2 = (SMMUIOTLBKey *)v2; - return (k1->asid == k2->asid) && (k1->iova == k2->iova); + return (k1->asid == k2->asid) && (k1->iova == k2->iova) && + (k1->level == k2->level) && (k1->tg == k2->tg); } -SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova) +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, + uint8_t tg, uint8_t level) { - SMMUIOTLBKey key = {.asid = asid, .iova = iova}; + SMMUIOTLBKey key = {.asid = asid, .iova = iova, .tg = tg, .level = level}; return key; } SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, - hwaddr iova) + SMMUTransTableInfo *tt, hwaddr iova) { - SMMUIOTLBKey key = smmu_get_iotlb_key(cfg->asid, iova); - SMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key); + uint8_t tg = (tt->granule_sz - 10) / 2; + uint8_t inputsize = 64 - tt->tsz; + uint8_t stride = tt->granule_sz - 3; + uint8_t level = 4 - (inputsize - 4) / stride; + SMMUTLBEntry *entry = NULL; + + while (level <= 3) { + uint64_t subpage_size = 1ULL << level_shift(level, tt->granule_sz); + uint64_t mask = subpage_size - 1; + SMMUIOTLBKey key; + + key = smmu_get_iotlb_key(cfg->asid, iova & ~mask, tg, level); + entry = g_hash_table_lookup(bs->iotlb, &key); + if (entry) { + break; + } + level++; + } if (entry) { cfg->iotlb_hits++; @@ -89,13 +106,14 @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new) { SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1); + uint8_t tg = (new->granule - 10) / 2; if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) { smmu_iotlb_inv_all(bs); } - *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova); - trace_smmu_iotlb_insert(cfg->asid, new->entry.iova); + *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova, tg, new->level); + trace_smmu_iotlb_insert(cfg->asid, new->entry.iova, tg, new->level); g_hash_table_insert(bs->iotlb, key, new); } @@ -114,12 +132,26 @@ static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value, return SMMU_IOTLB_ASID(*iotlb_key) == asid; } -inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova) +static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value, + gpointer user_data) { - SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova); + SMMUTLBEntry *iter = (SMMUTLBEntry *)value; + IOMMUTLBEntry *entry = &iter->entry; + SMMUIOTLBPageInvInfo *info = (SMMUIOTLBPageInvInfo *)user_data; + SMMUIOTLBKey iotlb_key = *(SMMUIOTLBKey *)key; + + if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) { + return false; + } + return (info->iova & ~entry->addr_mask) == entry->iova; +} + +inline void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova) +{ + SMMUIOTLBPageInvInfo info = {.asid = asid, .iova = iova}; trace_smmu_iotlb_inv_iova(asid, iova); - g_hash_table_remove(s->iotlb, &key); + g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid_iova, &info); } inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid) @@ -246,9 +278,6 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, baseaddr = extract64(tt->ttb, 0, 48); baseaddr &= ~indexmask; - 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); uint64_t mask = subpage_size - 1; @@ -298,7 +327,9 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, goto error; } - tlbe->entry.translated_addr = gpa + (iova & mask); + tlbe->entry.translated_addr = gpa; + tlbe->entry.iova = iova & ~mask; + tlbe->entry.addr_mask = mask; tlbe->entry.perm = PTE_AP_TO_PERM(ap); tlbe->level = level; tlbe->granule = granule_sz; diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h index 3104f768cd..55147f29be 100644 --- a/hw/arm/smmu-internal.h +++ b/hw/arm/smmu-internal.h @@ -97,4 +97,11 @@ uint64_t iova_level_offset(uint64_t iova, int inputsize, } #define SMMU_IOTLB_ASID(key) ((key).asid) + +typedef struct SMMUIOTLBPageInvInfo { + int asid; + uint64_t iova; + uint64_t mask; +} SMMUIOTLBPageInvInfo; + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index db74d27add..b717bde832 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -674,7 +674,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, page_mask = (1ULL << (tt->granule_sz)) - 1; aligned_addr = addr & ~page_mask; - cached_entry = smmu_iotlb_lookup(bs, cfg, aligned_addr); + cached_entry = smmu_iotlb_lookup(bs, cfg, tt, aligned_addr); if (cached_entry) { if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) { status = SMMU_TRANS_ERROR; @@ -744,7 +744,7 @@ epilogue: case SMMU_TRANS_SUCCESS: entry.perm = flag; entry.translated_addr = cached_entry->entry.translated_addr + - (addr & page_mask); + (addr & cached_entry->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); @@ -972,7 +972,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr); smmuv3_inv_notifiers_iova(bs, -1, addr); - smmu_iotlb_inv_all(bs); + smmu_iotlb_inv_iova(bs, -1, addr); break; } case SMMU_CMD_TLBI_NH_VA: diff --git a/hw/arm/trace-events b/hw/arm/trace-events index b808a1bfc1..f74d3e920f 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -16,7 +16,7 @@ smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB invalidate asid=%d addr smmu_inv_notifiers_mr(const char *name) "iommu mr=%s" smmu_iotlb_lookup_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" smmu_iotlb_lookup_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" -smmu_iotlb_insert(uint16_t asid, uint64_t addr) "IOTLB ++ asid=%d addr=0x%"PRIx64 +smmu_iotlb_insert(uint16_t asid, uint64_t addr, uint8_t tg, uint8_t level) "IOTLB ++ asid=%d addr=0x%"PRIx64" tg=%d level=%d" # smmuv3.c smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)" diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 79c2c6486a..ece62c3652 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -97,6 +97,8 @@ typedef struct SMMUPciBus { typedef struct SMMUIOTLBKey { uint64_t iova; uint16_t asid; + uint8_t tg; + uint8_t level; } SMMUIOTLBKey; typedef struct SMMUState { @@ -159,12 +161,14 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid); #define SMMU_IOTLB_MAX_SIZE 256 -SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova); +SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, + SMMUTransTableInfo *tt, hwaddr iova); void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry); -SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova); +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, + uint8_t tg, uint8_t level); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); -void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova); +void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova); /* Unmap the range of all the notifiers registered to any IOMMU mr */ void smmu_inv_notifiers_all(SMMUState *s); -- cgit v1.2.3-55-g7522 From d52915616c059ed273caa2d496b58e5d215c5962 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:11 +0200 Subject: hw/arm/smmuv3: Get prepared for range invalidation Enhance the smmu_iotlb_inv_iova() helper with range invalidation. This uses the new fields passed in the NH_VA and NH_VAA commands: the size of the range, the level and the granule. As NH_VA and NH_VAA both use those fields, their decoding and handling is factorized in a new smmuv3_s1_range_inval() helper. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-8-eric.auger@redhat.com Signed-off-by: Peter Maydell --- hw/arm/smmu-common.c | 25 +++++++++++++---- hw/arm/smmuv3-internal.h | 4 +++ hw/arm/smmuv3.c | 64 ++++++++++++++++++++++++++++---------------- hw/arm/trace-events | 4 +-- include/hw/arm/smmu-common.h | 3 ++- 5 files changed, 69 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 2922deec6f..8d89a86699 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -143,15 +143,30 @@ static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value, if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) { return false; } - return (info->iova & ~entry->addr_mask) == entry->iova; + return ((info->iova & ~entry->addr_mask) == entry->iova) || + ((entry->iova & ~info->mask) == info->iova); } -inline void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova) +inline void +smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages, uint8_t ttl) { - SMMUIOTLBPageInvInfo info = {.asid = asid, .iova = iova}; + if (ttl && (num_pages == 1)) { + SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl); - trace_smmu_iotlb_inv_iova(asid, iova); - g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid_iova, &info); + g_hash_table_remove(s->iotlb, &key); + } else { + /* if tg is not set we use 4KB range invalidation */ + uint8_t granule = tg ? tg * 2 + 10 : 12; + + SMMUIOTLBPageInvInfo info = { + .asid = asid, .iova = iova, + .mask = (num_pages * 1 << granule) - 1}; + + g_hash_table_foreach_remove(s->iotlb, + smmu_hash_remove_by_asid_iova, + &info); + } } inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 4112394129..5babf72f7d 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -298,6 +298,8 @@ enum { /* Command completion notification */ }; #define CMD_TYPE(x) extract32((x)->word[0], 0 , 8) +#define CMD_NUM(x) extract32((x)->word[0], 12 , 5) +#define CMD_SCALE(x) extract32((x)->word[0], 20 , 5) #define CMD_SSEC(x) extract32((x)->word[0], 10, 1) #define CMD_SSV(x) extract32((x)->word[0], 11, 1) #define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1) @@ -310,6 +312,8 @@ enum { /* Command completion notification */ #define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16) #define CMD_RESP(x) extract32((x)->word[2], 11, 2) #define CMD_LEAF(x) extract32((x)->word[2], 0 , 1) +#define CMD_TTL(x) extract32((x)->word[2], 8 , 2) +#define CMD_TG(x) extract32((x)->word[2], 10, 2) #define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5) #define CMD_ADDR(x) ({ \ uint64_t high = (uint64_t)(x)->word[3]; \ diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index e4a2cea7ad..89ab11fc36 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -785,42 +785,49 @@ epilogue: * @n: notifier to be called * @asid: address space ID or negative value if we don't care * @iova: iova + * @tg: translation granule (if communicated through range invalidation) + * @num_pages: number of @granule sized pages (if tg != 0), otherwise 1 */ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, IOMMUNotifier *n, - int asid, - dma_addr_t iova) + int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages) { SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu); - SMMUEventInfo event = {.inval_ste_allowed = true}; - SMMUTransTableInfo *tt; - SMMUTransCfg *cfg; IOMMUTLBEntry entry; + uint8_t granule = tg; - cfg = smmuv3_get_config(sdev, &event); - if (!cfg) { - return; - } + if (!tg) { + SMMUEventInfo event = {.inval_ste_allowed = true}; + SMMUTransCfg *cfg = smmuv3_get_config(sdev, &event); + SMMUTransTableInfo *tt; - if (asid >= 0 && cfg->asid != asid) { - return; - } + if (!cfg) { + return; + } - tt = select_tt(cfg, iova); - if (!tt) { - return; + if (asid >= 0 && cfg->asid != asid) { + return; + } + + tt = select_tt(cfg, iova); + if (!tt) { + return; + } + granule = tt->granule_sz; } entry.target_as = &address_space_memory; entry.iova = iova; - entry.addr_mask = (1 << tt->granule_sz) - 1; + entry.addr_mask = num_pages * (1 << granule) - 1; entry.perm = IOMMU_NONE; memory_region_notify_one(n, &entry); } -/* invalidate an asid/iova tuple in all mr's */ -static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) +/* invalidate an asid/iova range tuple in all mr's */ +static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages) { SMMUDevice *sdev; @@ -828,28 +835,39 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) IOMMUMemoryRegion *mr = &sdev->iommu; IOMMUNotifier *n; - trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova); + trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova, + tg, num_pages); IOMMU_NOTIFIER_FOREACH(n, mr) { - smmuv3_notify_iova(mr, n, asid, iova); + smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages); } } } static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) { + uint8_t scale = 0, num = 0, ttl = 0; dma_addr_t addr = CMD_ADDR(cmd); uint8_t type = CMD_TYPE(cmd); uint16_t vmid = CMD_VMID(cmd); bool leaf = CMD_LEAF(cmd); + uint8_t tg = CMD_TG(cmd); + hwaddr num_pages = 1; int asid = -1; + if (tg) { + scale = CMD_SCALE(cmd); + num = CMD_NUM(cmd); + ttl = CMD_TTL(cmd); + num_pages = (num + 1) * (1 << (scale)); + } + if (type == SMMU_CMD_TLBI_NH_VA) { asid = CMD_ASID(cmd); } - trace_smmuv3_s1_range_inval(vmid, asid, addr, leaf); - smmuv3_inv_notifiers_iova(s, asid, addr); - smmu_iotlb_inv_iova(s, asid, addr); + trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf); + smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages); + smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl); } static int smmuv3_cmdq_consume(SMMUv3State *s) diff --git a/hw/arm/trace-events b/hw/arm/trace-events index c219fe9e82..3d905e0f7d 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -45,11 +45,11 @@ smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d" smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d" smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)" smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)" -smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d" +smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d" smmuv3_cmdq_tlbi_nh(void) "" smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d" smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d" smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s" smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s" -smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova) "iommu mr=%s asid=%d iova=0x%"PRIx64 +smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64 diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index ece62c3652..4f6acf634c 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -168,7 +168,8 @@ SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, uint8_t tg, uint8_t level); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); -void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova); +void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages, uint8_t ttl); /* Unmap the range of all the notifiers registered to any IOMMU mr */ void smmu_inv_notifiers_all(SMMUState *s); -- cgit v1.2.3-55-g7522 From 5888f0ad12e40c8b079365593900df80b5c261bf Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:13 +0200 Subject: hw/arm/smmuv3: Let AIDR advertise SMMUv3.0 support Add the support for AIDR register. It currently advertises SMMU V3.0 spec. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-10-eric.auger@redhat.com Signed-off-by: Peter Maydell --- hw/arm/smmuv3-internal.h | 1 + hw/arm/smmuv3.c | 3 +++ include/hw/arm/smmuv3.h | 1 + 3 files changed, 5 insertions(+) (limited to 'include') diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index ef093eaff5..bd34a4f330 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -64,6 +64,7 @@ REG32(IDR5, 0x14) #define SMMU_IDR5_OAS 4 REG32(IIDR, 0x18) +REG32(AIDR, 0x1c) REG32(CR0, 0x20) FIELD(CR0, SMMU_ENABLE, 0, 1) FIELD(CR0, EVENTQEN, 2, 1) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 89ab11fc36..718f28462e 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1251,6 +1251,9 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, case A_IIDR: *data = s->iidr; return MEMTX_OK; + case A_AIDR: + *data = s->aidr; + return MEMTX_OK; case A_CR0: *data = s->cr[0]; return MEMTX_OK; diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h index 36b2f45253..68d7a963e0 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -41,6 +41,7 @@ typedef struct SMMUv3State { uint32_t idr[6]; uint32_t iidr; + uint32_t aidr; uint32_t cr[3]; uint32_t cr0ack; uint32_t statusr; -- cgit v1.2.3-55-g7522 From e7c3b9d9a0ddee7daa9b08bd14bd3ebbcf5f5cd3 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Jul 2020 17:08:14 +0200 Subject: hw/arm/smmuv3: Support HAD and advertise SMMUv3.1 support HAD is a mandatory features with SMMUv3.1 if S1P is set, which is our case. Other 3.1 mandatory features come with S2P which we don't have. So let's support HAD and advertise SMMUv3.1 support in AIDR. HAD support allows the CD to disable hierarchical attributes, ie. if the HAD0/1 bit is set, the APTable field of table descriptors walked through TTB0/1 is ignored. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell Message-id: 20200728150815.11446-11-eric.auger@redhat.com Signed-off-by: Peter Maydell --- hw/arm/smmu-common.c | 2 +- hw/arm/smmuv3-internal.h | 2 ++ hw/arm/smmuv3.c | 6 +++++- hw/arm/trace-events | 2 +- include/hw/arm/smmu-common.h | 1 + 5 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 8d89a86699..3838db1395 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -316,7 +316,7 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, if (is_table_pte(pte, level)) { ap = PTE_APTABLE(pte); - if (is_permission_fault(ap, perm)) { + if (is_permission_fault(ap, perm) && !tt->had) { info->type = SMMU_PTW_ERR_PERMISSION; goto error; } diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index bd34a4f330..9ae7d97faf 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -54,6 +54,7 @@ REG32(IDR1, 0x4) REG32(IDR2, 0x8) REG32(IDR3, 0xc) + FIELD(IDR3, HAD, 2, 1); REG32(IDR4, 0x10) REG32(IDR5, 0x14) FIELD(IDR5, OAS, 0, 3); @@ -578,6 +579,7 @@ static inline int pa_range(STE *ste) lo = (x)->word[(sel) * 2 + 2] & ~0xfULL; \ hi | lo; \ }) +#define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1) #define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6) #define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 718f28462e..b262f0e4a7 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -254,6 +254,8 @@ static void smmuv3_init_regs(SMMUv3State *s) s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS); s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS); + s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1); + /* 4K and 64K granule support */ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1); s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1); @@ -270,6 +272,7 @@ static void smmuv3_init_regs(SMMUv3State *s) s->features = 0; s->sid_split = 0; + s->aidr = 0x1; } static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, @@ -506,7 +509,8 @@ static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event) if (tt->ttb & ~(MAKE_64BIT_MASK(0, cfg->oas))) { goto bad_cd; } - trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz); + tt->had = CD_HAD(cd, i); + trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz, tt->had); } event->record_trans_faults = CD_R(cd); diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 3d905e0f7d..c8a4d80f6b 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -39,7 +39,7 @@ smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x" smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64 smmuv3_decode_cd(uint32_t oas) "oas=%d" -smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d" +smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d" smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d" smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d" smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d" diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 4f6acf634c..880dccd7c0 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -50,6 +50,7 @@ typedef struct SMMUTransTableInfo { uint64_t ttb; /* TT base address */ uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ uint8_t granule_sz; /* granule page shift */ + bool had; /* hierarchical attribute disable */ } SMMUTransTableInfo; typedef struct SMMUTLBEntry { -- cgit v1.2.3-55-g7522