From: Eric Auger <[email protected]>

The stream table base address needs to be aligned to its size.

With FMT == 0 (linear stream table), the table size is log2size *
STE_SIZE (2^6). So the spec says the base address
must have ADDR[LOG2SIZE + 5:0] = 0.

With FMT == 1 (2 level stream table), the table size is
(log2size - split) * L1STD_SIZE (2^3) So the spec days
the effective base address is aligned by the SMMU to the larger of
64 bytes or the first-level table size:
ADDR[MAX(5, (LOG2SIZE - SPLIT - 1 + 3)):0] = 0.

MAKE_64BIT_MASK() second argument is a size and not a shift, so
fix this off-by-one computation.

Subsequent patches will fix the risk of overflow in MAKE_64BIT_MASK()

Signed-off-by: Eric Auger <[email protected]>
Reviewed-by: Shameer Kolothum <[email protected]>
Message-id: [email protected]
Signed-off-by: Peter Maydell <[email protected]>
---
 hw/arm/smmuv3-internal.h |  3 +++
 hw/arm/smmuv3.c          | 10 +++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index eb482c7000f..0819a4b2e8d 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -359,6 +359,9 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo 
*event);
 void smmuv3_propagate_event(SMMUv3State *s, Evt *evt);
 int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo 
*event);
 
+#define STE_SIZE 6
+#define L1STD_SIZE 3
+
 static inline int oas2bits(int oas_field)
 {
     switch (oas_field) {
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 5e5a6a960c9..10c67645a57 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -664,7 +664,7 @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, 
SMMUEventInfo *event)
 {
     dma_addr_t addr, strtab_base;
     uint32_t log2size;
-    int strtab_size_shift;
+    int strtab_size;
     int ret;
 
     trace_smmuv3_find_ste(sid, s->features, s->sid_split);
@@ -685,9 +685,9 @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, 
SMMUEventInfo *event)
          * Align strtab base address to table size. For this purpose, assume it
          * is not bounded by SMMU_IDR1_SIDSIZE.
          */
-        strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3);
+        strtab_size = MAX(6, (int)log2size - s->sid_split + L1STD_SIZE);
         strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
-                      ~MAKE_64BIT_MASK(0, strtab_size_shift);
+                      ~MAKE_64BIT_MASK(0, strtab_size);
         l1_ste_offset = sid >> s->sid_split;
         l2_ste_offset = sid & ((1 << s->sid_split) - 1);
         l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std));
@@ -729,9 +729,9 @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, 
SMMUEventInfo *event)
         }
         addr = l2ptr + l2_ste_offset * sizeof(*ste);
     } else {
-        strtab_size_shift = log2size + 5;
+        strtab_size = log2size + STE_SIZE;
         strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
-                      ~MAKE_64BIT_MASK(0, strtab_size_shift);
+                      ~MAKE_64BIT_MASK(0, strtab_size);
         addr = strtab_base + sid * sizeof(*ste);
     }
 
-- 
2.43.0


Reply via email to