This patch implements the S_INIT register, a secure-only register with no non-secure counterpart. It provides a simple mechanism for secure software to perform a global invalidation of all SMMU configuration and translation caches.
This is typically the final step in a SMMU's probe sequence, marking the end of initialization for the SMMU's secure interface. With this and the previous change, a guest that is aware of the SMMUv3 secure extensions can probe the device's capabilities and perform basic configuration of the secure interface, as is done by secure partition managers like Hafnium in its smmuv3_driver_init function. Signed-off-by: Tao Tang <tangtao1...@phytium.com.cn> --- hw/arm/smmuv3.c | 29 +++++++++++++++++++++++++++++ hw/arm/trace-events | 1 + 2 files changed, 30 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 619180d204..0ea9d897af 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -920,6 +920,21 @@ static void smmuv3_flush_config(SMMUDevice *sdev) g_hash_table_remove(bc->configs, sdev); } +static void smmuv3_invalidate_all_caches(SMMUv3State *s) +{ + trace_smmuv3_invalidate_all_caches(); + SMMUState *bs = &s->smmu_state; + + /* Clear all cached configs including STE and CD*/ + if (bs->configs) { + g_hash_table_remove_all(bs->configs); + } + + /* Invalidate all SMMU IOTLB entries */ + smmu_inv_notifiers_all(&s->smmu_state); + smmu_iotlb_inv_all(bs); +} + /* Do translation with TLB lookup. */ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr, SMMUTransCfg *cfg, @@ -1921,6 +1936,16 @@ static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset, SMMU_CHECK_ATTRS_SECURE("S_EVENTQ_IRQ_CFG2"); s->secure_eventq_irq_cfg2 = data; return MEMTX_OK; + case A_S_INIT: + SMMU_CHECK_SECURE_WRITE("S_INIT"); + if (data & R_S_INIT_INV_ALL_MASK) { + /* write S_INIT and poll*/ + s->secure_init = data & R_S_INIT_INV_ALL_MASK; + smmuv3_invalidate_all_caches(s); + } + /* initialization is completed and set to 0 to terminate the polling */ + s->secure_init = 0; + return MEMTX_OK; default: qemu_log_mask(LOG_UNIMP, "%s Unexpected 32-bit access to 0x%"PRIx64" (WI)\n", @@ -2249,6 +2274,10 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, } *data = s->secure_eventq.cons; return MEMTX_OK; + case A_S_INIT: + SMMU_CHECK_SECURE_READ("S_INIT"); + *data = s->secure_init; + return MEMTX_OK; default: *data = 0; qemu_log_mask(LOG_UNIMP, diff --git a/hw/arm/trace-events b/hw/arm/trace-events index f3386bd7ae..019129ea43 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -64,6 +64,7 @@ smmuv3_cmdq_tlbi_s12_vmid(int vmid) "vmid=%d" smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s" smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s" smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t iova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" stage=%d" +smmuv3_invalidate_all_caches(void) "Invalidate all SMMU caches and TLBs" smmu_reset_exit(void) "" # strongarm.c -- 2.34.1