On Wed, Aug 06, 2025 at 11:11:26PM +0800, Tao Tang wrote:
> 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);

Do we need to check that the SMMU is enabled as the spec says?

> +        }
> +        /* initialization is completed and set to 0 to terminate the polling 
> */
> +        s->secure_init = 0;

All access to SMMU registers are serialised, so it’s safe to drop this and
just return zero on reads.

Thanks,
Mostafa

> +        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