Hi Simon, On 12/16/19 4:15 PM, Simon Veith wrote: > Per the specification, and as observed in hardware, the SMMUv3 aligns > the SMMU_STRTAB_BASE address to the size of the table by masking out the > respective least significant bits in the ADDR field. > > Apply this masking logic to our smmu_find_ste() lookup function per the > specification. > > ref. ARM IHI 0070C, section 6.3.23. > > Signed-off-by: Simon Veith <sve...@amazon.de> > Cc: Eric Auger <eric.au...@redhat.com> > Cc: qemu-devel@nongnu.org > Cc: qemu-...@nongnu.org Looks good to me.
Acked-by: Eric Auger <eric.au...@redhat.com> Thanks Eric > --- > Changed in v2: > > * Now using MAKE_64BIT_MASK() > * Eliminated unnecessary branches by using MAX() > * Removed unnecessary range check against DMA_ADDR_BITS > > hw/arm/smmuv3.c | 18 ++++++++++++++---- > 1 file changed, 14 insertions(+), 4 deletions(-) > > diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c > index 727558b..31ac3ca 100644 > --- a/hw/arm/smmuv3.c > +++ b/hw/arm/smmuv3.c > @@ -376,8 +376,9 @@ bad_ste: > static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, > SMMUEventInfo *event) > { > - dma_addr_t addr; > + dma_addr_t addr, strtab_base; > uint32_t log2size; > + int strtab_size_shift; > int ret; > > trace_smmuv3_find_ste(sid, s->features, s->sid_split); > @@ -391,10 +392,16 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, > STE *ste, > } > if (s->features & SMMU_FEATURE_2LVL_STE) { > int l1_ste_offset, l2_ste_offset, max_l2_ste, span; > - dma_addr_t strtab_base, l1ptr, l2ptr; > + dma_addr_t l1ptr, l2ptr; > STEDesc l1std; > > - strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK; > + /* > + * 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_base = s->strtab_base & SMMU_BASE_ADDR_MASK & > + ~MAKE_64BIT_MASK(0, strtab_size_shift); > 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)); > @@ -433,7 +440,10 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, > STE *ste, > } > addr = l2ptr + l2_ste_offset * sizeof(*ste); > } else { > - addr = (s->strtab_base & SMMU_BASE_ADDR_MASK) + sid * sizeof(*ste); > + strtab_size_shift = log2size + 5; > + strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK & > + ~MAKE_64BIT_MASK(0, strtab_size_shift); > + addr = strtab_base + sid * sizeof(*ste); > } > > if (smmu_get_ste(s, addr, ste, event)) { >