From cd617556aded2528664a3673d66d5cd0864f5341 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Thu, 25 May 2023 10:37:50 +0100 Subject: [PATCH] hw/arm/smmuv3: Make TLB lookup work for stage-2 Right now, either stage-1 or stage-2 are supported, this simplifies how we can deal with TLBs. This patch makes TLB lookup work if stage-2 is enabled instead of stage-1. TLB lookup is done before a PTW, if a valid entry is found we won't do the PTW. To be able to do TLB lookup, we need the correct tagging info, as granularity and input size, so we get this based on the supported translation stage. The TLB entries are added correctly from each stage PTW. When nested translation is supported, this would need to change, for example if we go with a combined TLB implementation, we would need to use the min of the granularities in TLB. As stage-2 shouldn't be tagged by ASID, it will be set to -1 if S1P is not enabled. Signed-off-by: Mostafa Saleh Reviewed-by: Eric Auger Tested-by: Eric Auger Tested-by: Jean-Philippe Brucker Message-id: 20230516203327.2051088-7-smostafa@google.com Signed-off-by: Peter Maydell --- hw/arm/smmuv3.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 989afb1fda..3fb5ed512b 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -721,6 +721,9 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg, STE ste; CD cd; + /* ASID defaults to -1 (if s1 is not supported). */ + cfg->asid = -1; + ret = smmu_find_ste(s, sid, &ste, event); if (ret) { return ret; @@ -818,6 +821,11 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, .addr_mask = ~(hwaddr)0, .perm = IOMMU_NONE, }; + /* + * Combined attributes used for TLB lookup, as only one stage is supported, + * it will hold attributes based on the enabled stage. + */ + SMMUTransTableInfo tt_combined; qemu_mutex_lock(&s->mutex); @@ -846,21 +854,35 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, goto epilogue; } - tt = select_tt(cfg, addr); - if (!tt) { - if (cfg->record_faults) { - event.type = SMMU_EVT_F_TRANSLATION; - event.u.f_translation.addr = addr; - event.u.f_translation.rnw = flag & 0x1; + if (cfg->stage == 1) { + /* Select stage1 translation table. */ + tt = select_tt(cfg, addr); + if (!tt) { + if (cfg->record_faults) { + event.type = SMMU_EVT_F_TRANSLATION; + event.u.f_translation.addr = addr; + event.u.f_translation.rnw = flag & 0x1; + } + status = SMMU_TRANS_ERROR; + goto epilogue; } - status = SMMU_TRANS_ERROR; - goto epilogue; - } + tt_combined.granule_sz = tt->granule_sz; + tt_combined.tsz = tt->tsz; - page_mask = (1ULL << (tt->granule_sz)) - 1; + } else { + /* Stage2. */ + tt_combined.granule_sz = cfg->s2cfg.granule_sz; + tt_combined.tsz = cfg->s2cfg.tsz; + } + /* + * TLB lookup looks for granule and input size for a translation stage, + * as only one stage is supported right now, choose the right values + * from the configuration. + */ + page_mask = (1ULL << tt_combined.granule_sz) - 1; aligned_addr = addr & ~page_mask; - cached_entry = smmu_iotlb_lookup(bs, cfg, tt, aligned_addr); + cached_entry = smmu_iotlb_lookup(bs, cfg, &tt_combined, aligned_addr); if (cached_entry) { if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) { status = SMMU_TRANS_ERROR; -- 2.11.4.GIT