hw/arm/smmu: Split smmuv3_translate()

smmuv3_translate() does everything from STE/CD parsing to TLB lookup
and PTW.

Soon, when nesting is supported, stage-1 data (tt, CD) needs to be
translated using stage-2.

Split smmuv3_translate() to 3 functions:

- smmu_translate(): in smmu-common.c, which does the TLB lookup, PTW,
  TLB insertion, all the functions are already there, this just puts
  them together.
  This also simplifies the code as it consolidates event generation
  in case of TLB lookup permission failure or in TT selection.

- smmuv3_do_translate(): in smmuv3.c, Calls smmu_translate() and does
  the event population in case of errors.

- smmuv3_translate(), now calls smmuv3_do_translate() for
  translation while the rest is the same.

Also, add stage in trace_smmuv3_translate_success()

Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Mostafa Saleh <smostafa@google.com>
Reviewed-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20240715084519.1189624-6-smostafa@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Mostafa Saleh 2024-07-15 08:45:05 +00:00 committed by Peter Maydell
parent f6cc198050
commit a9e3f4c1eb
4 changed files with 142 additions and 121 deletions

View file

@ -566,6 +566,65 @@ int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
g_assert_not_reached();
}
SMMUTLBEntry *smmu_translate(SMMUState *bs, SMMUTransCfg *cfg, dma_addr_t addr,
IOMMUAccessFlags flag, SMMUPTWEventInfo *info)
{
uint64_t page_mask, aligned_addr;
SMMUTLBEntry *cached_entry = NULL;
SMMUTransTableInfo *tt;
int status;
/*
* Combined attributes used for TLB lookup, as only one stage is supported,
* it will hold attributes based on the enabled stage.
*/
SMMUTransTableInfo tt_combined;
if (cfg->stage == SMMU_STAGE_1) {
/* Select stage1 translation table. */
tt = select_tt(cfg, addr);
if (!tt) {
info->type = SMMU_PTW_ERR_TRANSLATION;
info->stage = SMMU_STAGE_1;
return NULL;
}
tt_combined.granule_sz = tt->granule_sz;
tt_combined.tsz = tt->tsz;
} 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_combined, aligned_addr);
if (cached_entry) {
if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) {
info->type = SMMU_PTW_ERR_PERMISSION;
info->stage = cfg->stage;
return NULL;
}
return cached_entry;
}
cached_entry = g_new0(SMMUTLBEntry, 1);
status = smmu_ptw(cfg, aligned_addr, flag, cached_entry, info);
if (status) {
g_free(cached_entry);
return NULL;
}
smmu_iotlb_insert(bs, cfg, cached_entry);
return cached_entry;
}
/**
* The bus number is used for lookup when SID based invalidation occurs.
* In that case we lazily populate the SMMUPciBus array from the bus hash