@samitouri / QOSamiQemu / commits / ad693ac92b

hw/arm/smmuv3: Fix off-by-one bug in alignment strtab mask

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 <eric.auger@redhat.com> Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260707085028.165557-2-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Eric Auger committed Jul 13, 2026 at 12:34 UTC ad693ac92b95e09cb68a75791d7879ac218e0cc1
2 files changed +8 -5
hw/arm/smmuv3-internal.h
+3
@@ -359,6 +359,9 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
359 void smmuv3_propagate_event(SMMUv3State *s, Evt *evt);
360 int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event);
361
362 +#define STE_SIZE 6
363 +#define L1STD_SIZE 3
364 +
365 static inline int oas2bits(int oas_field)
366 {
367 switch (oas_field) {
hw/arm/smmuv3.c
+5 -5
@@ -664,7 +664,7 @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event)
664 {
665 dma_addr_t addr, strtab_base;
666 uint32_t log2size;
667 - int strtab_size_shift;
667 + int strtab_size;
668 int ret;
669
670 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)
685 * Align strtab base address to table size. For this purpose, assume it
686 * is not bounded by SMMU_IDR1_SIDSIZE.
687 */
688 - strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3);
688 + strtab_size = MAX(6, (int)log2size - s->sid_split + L1STD_SIZE);
689 strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
690 - ~MAKE_64BIT_MASK(0, strtab_size_shift);
690 + ~MAKE_64BIT_MASK(0, strtab_size);
691 l1_ste_offset = sid >> s->sid_split;
692 l2_ste_offset = sid & ((1 << s->sid_split) - 1);
693 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)
729 }
730 addr = l2ptr + l2_ste_offset * sizeof(*ste);
731 } else {
732 - strtab_size_shift = log2size + 5;
732 + strtab_size = log2size + STE_SIZE;
733 strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
734 - ~MAKE_64BIT_MASK(0, strtab_size_shift);
734 + ~MAKE_64BIT_MASK(0, strtab_size);
735 addr = strtab_base + sid * sizeof(*ste);
736 }
737