Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 <smostafa@google.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Message-id: 20230516203327.2051088-7-smostafa@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
misaleh authored and pm215 committed May 30, 2023
1 parent ed1a07a commit 0154688
Showing 1 changed file with 33 additions and 11 deletions.
44 changes: 33 additions & 11 deletions hw/arm/smmuv3.c
Expand Up @@ -720,6 +720,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;
Expand Down Expand Up @@ -817,6 +820,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);

Expand Down Expand Up @@ -845,21 +853,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;
Expand Down

0 comments on commit 0154688

Please sign in to comment.