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


Reply via email to