From: Mostafa Saleh <smostafa@google.com>
To: Tao Tang <tangtao1634@phytium.com.cn>
Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org,
Eric Auger <eric.auger@redhat.com>,
Peter Maydell <peter.maydell@linaro.org>,
Chen Baozi <chenbaozi@phytium.com.cn>
Subject: Re: [RFC 06/11] hw/arm/smmuv3: Plumb security state through core functions
Date: Mon, 18 Aug 2025 21:28:16 +0000 [thread overview]
Message-ID: <aKOa8KwAcm6hhAXq@google.com> (raw)
In-Reply-To: <20250806151134.365755-7-tangtao1634@phytium.com.cn>
On Wed, Aug 06, 2025 at 11:11:29PM +0800, Tao Tang wrote:
> To support parallel processing of secure and non-secure streams, the
> SMMUv3 model needs to differentiate between the two contexts throughout
> its core logic. This commit is the foundational step to make the code
> security-state aware.
>
> An is_secure flag, which will be used in subsequent patches to represent
> the transaction's security state, is now plumbed through the main
> processing paths.
>
> This change is purely preparatory and introduces no functional changes
> for the existing non-secure path. All current call sites are updated
> to pass is_secure = false.
>
> This refactoring paves the way for upcoming patches that will introduce
> separate TLB entries for secure transactions and enable a fully
> parallel secure/non-secure SMMU model.
>
I think it’s easier to review if this patch was split (STE parsing,
page table handling and translation, TLB invalidation)
Also based on my comment on patch 2, stage-2 handling doesn’t seem correct to me.
Thanks,
Mostafa
> Signed-off-by: Tao Tang <tangtao1634@phytium.com.cn>
> ---
> hw/arm/smmu-common.c | 11 ++-
> hw/arm/smmuv3-internal.h | 16 +++-
> hw/arm/smmuv3.c | 160 ++++++++++++++++++++++++-----------
> hw/arm/trace-events | 2 +-
> include/hw/arm/smmu-common.h | 1 +
> include/hw/arm/smmuv3.h | 4 +
> 6 files changed, 138 insertions(+), 56 deletions(-)
>
> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
> index 0dcaf2f589..28d6d1bc7f 100644
> --- a/hw/arm/smmu-common.c
> +++ b/hw/arm/smmu-common.c
> @@ -332,13 +332,16 @@ void smmu_iotlb_inv_vmid_s1(SMMUState *s, int vmid)
> * @base_addr[@index]
> */
> static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte,
> - SMMUPTWEventInfo *info)
> + SMMUPTWEventInfo *info, bool is_secure)
> {
> int ret;
> dma_addr_t addr = baseaddr + index * sizeof(*pte);
> + MemTxAttrs attrs = is_secure ?
> + (MemTxAttrs) { .secure = 1 } :
> + (MemTxAttrs) { .unspecified = true };
>
> /* TODO: guarantee 64-bit single-copy atomicity */
> - ret = ldq_le_dma(&address_space_memory, addr, pte, MEMTXATTRS_UNSPECIFIED);
> + ret = ldq_le_dma(&address_space_memory, addr, pte, attrs);
>
> if (ret != MEMTX_OK) {
> info->type = SMMU_PTW_ERR_WALK_EABT;
> @@ -485,7 +488,7 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg *cfg,
> dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
> uint8_t ap;
>
> - if (get_pte(baseaddr, offset, &pte, info)) {
> + if (get_pte(baseaddr, offset, &pte, info, cfg->secure)) {
> goto error;
> }
> trace_smmu_ptw_level(stage, level, iova, subpage_size,
> @@ -621,7 +624,7 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
> dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
> uint8_t s2ap;
>
> - if (get_pte(baseaddr, offset, &pte, info)) {
> + if (get_pte(baseaddr, offset, &pte, info, cfg->secure)) {
> goto error;
> }
> trace_smmu_ptw_level(stage, level, ipa, subpage_size,
> diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
> index 720d21652c..852186cea4 100644
> --- a/hw/arm/smmuv3-internal.h
> +++ b/hw/arm/smmuv3-internal.h
> @@ -243,9 +243,13 @@ REG64(S_EVENTQ_IRQ_CFG0, 0x80b0)
> REG32(S_EVENTQ_IRQ_CFG1, 0x80b8)
> REG32(S_EVENTQ_IRQ_CFG2, 0x80bc)
>
> -static inline int smmu_enabled(SMMUv3State *s)
> +static inline int smmu_enabled(SMMUv3State *s, bool is_secure)
> {
> - return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE);
> + if (is_secure) {
> + return FIELD_EX32(s->secure_cr[0], S_CR0, SMMUEN);
> + } else {
> + return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE);
> + }
> }
>
> /* Command Queue Entry */
> @@ -661,6 +665,10 @@ typedef struct CD {
> #define STE_S2S(x) extract32((x)->word[5], 25, 1)
> #define STE_S2R(x) extract32((x)->word[5], 26, 1)
>
> +#define STE_S_S2T0SZ(x) extract32((x)->word[9], 0 , 6)
> +#define STE_S_S2SL0(x) extract32((x)->word[9], 6 , 2)
> +#define STE_S_S2TG(x) extract32((x)->word[9], 14, 2)
> +
> #define STE_CTXPTR(x) \
> ((extract64((x)->word[1], 0, 16) << 32) | \
> ((x)->word[0] & 0xffffffc0))
> @@ -669,6 +677,10 @@ typedef struct CD {
> ((extract64((x)->word[7], 0, 16) << 32) | \
> ((x)->word[6] & 0xfffffff0))
>
> +#define STE_S_S2TTB(x) \
> + ((extract64((x)->word[13], 0, 16) << 32) | \
> + ((x)->word[12] & 0xfffffff0))
> +
> static inline int oas2bits(int oas_field)
> {
> switch (oas_field) {
> diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> index 1f05cc983b..bcf06679e1 100644
> --- a/hw/arm/smmuv3.c
> +++ b/hw/arm/smmuv3.c
> @@ -354,14 +354,14 @@ static void smmuv3_init_regs(SMMUv3State *s)
> }
>
> static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
> - SMMUEventInfo *event)
> + SMMUEventInfo *event, MemTxAttrs attrs)
> {
> int ret, i;
>
> trace_smmuv3_get_ste(addr);
> /* TODO: guarantee 64-bit single-copy atomicity */
> ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf),
> - MEMTXATTRS_UNSPECIFIED);
> + attrs);
> if (ret != MEMTX_OK) {
> qemu_log_mask(LOG_GUEST_ERROR,
> "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
> @@ -390,6 +390,9 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
> int ret, i;
> SMMUTranslationStatus status;
> SMMUTLBEntry *entry;
> + MemTxAttrs attrs = cfg->secure ?
> + (MemTxAttrs) { .secure = 1 } :
> + (MemTxAttrs) { .unspecified = true };
>
> trace_smmuv3_get_cd(addr);
>
> @@ -407,7 +410,7 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
>
> /* TODO: guarantee 64-bit single-copy atomicity */
> ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf),
> - MEMTXATTRS_UNSPECIFIED);
> + attrs);
> if (ret != MEMTX_OK) {
> qemu_log_mask(LOG_GUEST_ERROR,
> "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
> @@ -472,7 +475,8 @@ static int decode_ste_s2_cfg(SMMUv3State *s, SMMUTransCfg *cfg,
> g_assert_not_reached();
> }
>
> - switch (STE_S2TG(ste)) {
> + uint32_t s2tg = cfg->secure ? STE_S_S2TG(ste) : STE_S2TG(ste);
> + switch (s2tg) {
> case 0x0: /* 4KB */
> cfg->s2cfg.granule_sz = 12;
> break;
> @@ -484,13 +488,13 @@ static int decode_ste_s2_cfg(SMMUv3State *s, SMMUTransCfg *cfg,
> break;
> default:
> qemu_log_mask(LOG_GUEST_ERROR,
> - "SMMUv3 bad STE S2TG: %x\n", STE_S2TG(ste));
> + "SMMUv3 bad STE S2TG: %x\n", s2tg);
> goto bad_ste;
> }
>
> - cfg->s2cfg.vttb = STE_S2TTB(ste);
> + cfg->s2cfg.vttb = cfg->secure ? STE_S_S2TTB(ste) : STE_S2TTB(ste);
>
> - cfg->s2cfg.sl0 = STE_S2SL0(ste);
> + cfg->s2cfg.sl0 = cfg->secure ? STE_S_S2SL0(ste) : STE_S2SL0(ste);
> /* FEAT_TTST not supported. */
> if (cfg->s2cfg.sl0 == 0x3) {
> qemu_log_mask(LOG_UNIMP, "SMMUv3 S2SL0 = 0x3 has no meaning!\n");
> @@ -519,7 +523,7 @@ static int decode_ste_s2_cfg(SMMUv3State *s, SMMUTransCfg *cfg,
> goto bad_ste;
> }
>
> - cfg->s2cfg.tsz = STE_S2T0SZ(ste);
> + cfg->s2cfg.tsz = cfg->secure ? STE_S_S2T0SZ(ste) : STE_S2T0SZ(ste);
>
> if (!s2t0sz_valid(cfg)) {
> qemu_log_mask(LOG_GUEST_ERROR, "SMMUv3 bad STE S2T0SZ = %d\n",
> @@ -599,21 +603,52 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
> if (cfg->aborted || cfg->bypassed) {
> return 0;
> }
> + bool is_secure = cfg->secure;
>
> /*
> * If a stage is enabled in SW while not advertised, throw bad ste
> * according to user manual(IHI0070E) "5.2 Stream Table Entry".
> */
> - if (!STAGE1_SUPPORTED(s) && STE_CFG_S1_ENABLED(config)) {
> - qemu_log_mask(LOG_GUEST_ERROR, "SMMUv3 S1 used but not supported.\n");
> - goto bad_ste;
> - }
> - if (!STAGE2_SUPPORTED(s) && STE_CFG_S2_ENABLED(config)) {
> - qemu_log_mask(LOG_GUEST_ERROR, "SMMUv3 S2 used but not supported.\n");
> - goto bad_ste;
> + if (!is_secure) {
> + if (!STAGE1_SUPPORTED(s) && STE_CFG_S1_ENABLED(config)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "SMMUv3 S1 used but not supported.\n");
> + goto bad_ste;
> + }
> + if (!STAGE2_SUPPORTED(s) && STE_CFG_S2_ENABLED(config)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "SMMUv3 S2 used but not supported.\n");
> + goto bad_ste;
> + }
> + } else {
> + /*
> + * As described in user manual(IHI0070G.b) "3.10.2 Support for Secure
> + * state" , the SMMU supports stage 1 translation and might support
> + * stage 2 translation.
> + */
> + if (!SECURE_IMPLEMENTED(s) && STE_CFG_S1_ENABLED(config)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "SMMUv3 S1 used but not supported in secure state.\n");
> + goto bad_ste;
> + }
> +
> + /*
> + * IHI0070G.b "6.3.53 SMMU_S_IDR1": SEL2 == 0 if SMMU_IDR0.S1P == 0 or
> + * if SMMU_IDR0.S2P == 0.
> + */
> + if (STE_CFG_S2_ENABLED(config)) {
> + if (!SECURE_S2_SUPPORTED(s) ||
> + (SECURE_S2_SUPPORTED(s) &&
> + (!STAGE1_SUPPORTED(s) || !STAGE2_SUPPORTED(s)))) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "SMMUv3 S2 used but not supported in secure state.\n");
> + goto bad_ste;
> + }
> + }
> }
>
> - if (STAGE2_SUPPORTED(s)) {
> + if ((!is_secure && STAGE2_SUPPORTED(s)) ||
> + (is_secure && SECURE_S2_SUPPORTED(s))) {
> /* VMID is considered even if s2 is disabled. */
> cfg->s2cfg.vmid = STE_S2VMID(ste);
> } else {
> @@ -659,20 +694,29 @@ bad_ste:
> * @sid: stream ID
> * @ste: returned stream table entry
> * @event: handle to an event info
> + * @is_secure: true if the translation is for a secure domain
> *
> * Supports linear and 2-level stream table
> * Return 0 on success, -EINVAL otherwise
> */
> static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
> - SMMUEventInfo *event)
> + SMMUEventInfo *event, bool is_secure)
> {
> - dma_addr_t addr, strtab_base;
> + dma_addr_t addr;
> uint32_t log2size;
> int strtab_size_shift;
> int ret;
> + uint32_t features = is_secure ? s->secure_features : s->features;
> + dma_addr_t strtab_base = is_secure ? s->secure_strtab_base : s->strtab_base;
> + uint8_t sid_split = is_secure ? s->secure_sid_split : s->sid_split;
> + MemTxAttrs attrs = is_secure ?
> + (MemTxAttrs) { .secure = 1 } :
> + (MemTxAttrs) { .unspecified = true };
>
> - trace_smmuv3_find_ste(sid, s->features, s->sid_split);
> - log2size = FIELD_EX32(s->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE);
> + trace_smmuv3_find_ste(sid, features, sid_split, is_secure);
> + log2size = is_secure
> + ? FIELD_EX32(s->secure_strtab_base_cfg, S_STRTAB_BASE_CFG, LOG2SIZE)
> + : FIELD_EX32(s->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE);
> /*
> * Check SID range against both guest-configured and implementation limits
> */
> @@ -680,7 +724,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
> event->type = SMMU_EVT_C_BAD_STREAMID;
> return -EINVAL;
> }
> - if (s->features & SMMU_FEATURE_2LVL_STE) {
> + if (features & SMMU_FEATURE_2LVL_STE) {
> int l1_ste_offset, l2_ste_offset, max_l2_ste, span, i;
> dma_addr_t l1ptr, l2ptr;
> STEDesc l1std;
> @@ -689,15 +733,15 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
> * Align strtab base address to table size. For this purpose, assume it
> * is not bounded by SMMU_IDR1_SIDSIZE.
> */
> - strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3);
> - strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
> + strtab_size_shift = MAX(5, (int)log2size - sid_split - 1 + 3);
> + strtab_base = strtab_base & SMMU_BASE_ADDR_MASK &
> ~MAKE_64BIT_MASK(0, strtab_size_shift);
> - l1_ste_offset = sid >> s->sid_split;
> - l2_ste_offset = sid & ((1 << s->sid_split) - 1);
> + l1_ste_offset = sid >> sid_split;
> + l2_ste_offset = sid & ((1 << sid_split) - 1);
> l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std));
> /* TODO: guarantee 64-bit single-copy atomicity */
> ret = dma_memory_read(&address_space_memory, l1ptr, &l1std,
> - sizeof(l1std), MEMTXATTRS_UNSPECIFIED);
> + sizeof(l1std), attrs);
> if (ret != MEMTX_OK) {
> qemu_log_mask(LOG_GUEST_ERROR,
> "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr);
> @@ -722,7 +766,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
> }
> max_l2_ste = (1 << span) - 1;
> l2ptr = l1std_l2ptr(&l1std);
> - trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset,
> + trace_smmuv3_find_ste_2lvl(strtab_base, l1ptr, l1_ste_offset,
> l2ptr, l2_ste_offset, max_l2_ste);
> if (l2_ste_offset > max_l2_ste) {
> qemu_log_mask(LOG_GUEST_ERROR,
> @@ -734,12 +778,12 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
> addr = l2ptr + l2_ste_offset * sizeof(*ste);
> } else {
> strtab_size_shift = log2size + 5;
> - strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
> + strtab_base = strtab_base & SMMU_BASE_ADDR_MASK &
> ~MAKE_64BIT_MASK(0, strtab_size_shift);
> addr = strtab_base + sid * sizeof(*ste);
> }
>
> - if (smmu_get_ste(s, addr, ste, event)) {
> + if (smmu_get_ste(s, addr, ste, event, attrs)) {
> return -EINVAL;
> }
>
> @@ -868,7 +912,7 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
> /* ASID defaults to -1 (if s1 is not supported). */
> cfg->asid = -1;
>
> - ret = smmu_find_ste(s, sid, &ste, event);
> + ret = smmu_find_ste(s, sid, &ste, event, cfg->secure);
> if (ret) {
> return ret;
> }
> @@ -897,12 +941,14 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
> *
> * @sdev: SMMUDevice handle
> * @event: output event info
> + * @is_secure: true if the translation is for a secure domain
> *
> * The configuration cache contains data resulting from both STE and CD
> * decoding under the form of an SMMUTransCfg struct. The hash table is indexed
> * by the SMMUDevice handle.
> */
> -static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *event)
> +static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *event,
> + bool is_secure)
> {
> SMMUv3State *s = sdev->smmu;
> SMMUState *bc = &s->smmu_state;
> @@ -922,6 +968,7 @@ static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *event)
> 100 * sdev->cfg_cache_hits /
> (sdev->cfg_cache_hits + sdev->cfg_cache_misses));
> cfg = g_new0(SMMUTransCfg, 1);
> + cfg->secure = is_secure;
>
> if (!smmuv3_decode_config(&sdev->iommu, cfg, event)) {
> g_hash_table_insert(bc->configs, sdev, cfg);
> @@ -1103,19 +1150,25 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
> .perm = IOMMU_NONE,
> };
> SMMUTLBEntry *cached_entry = NULL;
> + /* We don't support secure translation for now */
> + bool is_secure = false;
>
> qemu_mutex_lock(&s->mutex);
>
> - if (!smmu_enabled(s)) {
> - if (FIELD_EX32(s->gbpa, GBPA, ABORT)) {
> - status = SMMU_TRANS_ABORT;
> + if (!smmu_enabled(s, is_secure)) {
> + bool abort_flag;
> +
> + if (is_secure) {
> + abort_flag = FIELD_EX32(s->secure_gbpa, S_GBPA, ABORT);
> } else {
> - status = SMMU_TRANS_DISABLE;
> + abort_flag = FIELD_EX32(s->gbpa, GBPA, ABORT);
> }
> +
> + status = abort_flag ? SMMU_TRANS_ABORT : SMMU_TRANS_DISABLE;
> goto epilogue;
> }
>
> - cfg = smmuv3_get_config(sdev, &event);
> + cfg = smmuv3_get_config(sdev, &event, is_secure);
> if (!cfg) {
> status = SMMU_TRANS_ERROR;
> goto epilogue;
> @@ -1167,7 +1220,7 @@ epilogue:
> qemu_log_mask(LOG_GUEST_ERROR,
> "%s translation failed for iova=0x%"PRIx64" (%s)\n",
> mr->parent_obj.name, addr, smmu_event_string(event.type));
> - smmuv3_record_event(s, &event, false);
> + smmuv3_record_event(s, &event, cfg->secure);
> break;
> }
>
> @@ -1186,16 +1239,18 @@ epilogue:
> * @tg: translation granule (if communicated through range invalidation)
> * @num_pages: number of @granule sized pages (if tg != 0), otherwise 1
> * @stage: Which stage(1 or 2) is used
> + * @is_secure: true if the translation is for a secure domain
> */
> static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
> IOMMUNotifier *n,
> int asid, int vmid,
> dma_addr_t iova, uint8_t tg,
> - uint64_t num_pages, int stage)
> + uint64_t num_pages, int stage,
> + bool is_secure)
> {
> SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
> SMMUEventInfo eventinfo = {.inval_ste_allowed = true};
> - SMMUTransCfg *cfg = smmuv3_get_config(sdev, &eventinfo);
> + SMMUTransCfg *cfg = smmuv3_get_config(sdev, &eventinfo, is_secure);
> IOMMUTLBEvent event;
> uint8_t granule;
>
> @@ -1251,7 +1306,8 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
> /* invalidate an asid/vmid/iova range tuple in all mr's */
> static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, int vmid,
> dma_addr_t iova, uint8_t tg,
> - uint64_t num_pages, int stage)
> + uint64_t num_pages, int stage,
> + bool is_secure)
> {
> SMMUDevice *sdev;
>
> @@ -1263,12 +1319,14 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, int vmid,
> iova, tg, num_pages, stage);
>
> IOMMU_NOTIFIER_FOREACH(n, mr) {
> - smmuv3_notify_iova(mr, n, asid, vmid, iova, tg, num_pages, stage);
> + smmuv3_notify_iova(mr, n, asid, vmid, iova, tg,
> + num_pages, stage, is_secure);
> }
> }
> }
>
> -static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
> +static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage,
> + bool is_secure)
> {
> dma_addr_t end, addr = CMD_ADDR(cmd);
> uint8_t type = CMD_TYPE(cmd);
> @@ -1284,7 +1342,8 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
> SMMUv3State *smmuv3 = ARM_SMMUV3(s);
>
> /* Only consider VMID if stage-2 is supported. */
> - if (STAGE2_SUPPORTED(smmuv3)) {
> + if (STAGE2_SUPPORTED(smmuv3) ||
> + (SECURE_IMPLEMENTED(smmuv3) && SECURE_S2_SUPPORTED(smmuv3))) {
> vmid = CMD_VMID(cmd);
> }
>
> @@ -1294,7 +1353,7 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
>
> if (!tg) {
> trace_smmuv3_range_inval(vmid, asid, addr, tg, 1, ttl, leaf, stage);
> - smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, 1, stage);
> + smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, 1, stage, is_secure);
> if (stage == SMMU_STAGE_1) {
> smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, 1, ttl);
> } else {
> @@ -1317,7 +1376,8 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
> num_pages = (mask + 1) >> granule;
> trace_smmuv3_range_inval(vmid, asid, addr, tg, num_pages,
> ttl, leaf, stage);
> - smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg, num_pages, stage);
> + smmuv3_inv_notifiers_iova(s, asid, vmid, addr, tg,
> + num_pages, stage, is_secure);
> if (stage == SMMU_STAGE_1) {
> smmu_iotlb_inv_iova(s, asid, vmid, addr, tg, num_pages, ttl);
> } else {
> @@ -1461,7 +1521,8 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, bool is_secure)
> * VMID is only matched when stage 2 is supported, otherwise set it
> * to -1 as the value used for stage-1 only VMIDs.
> */
> - if (STAGE2_SUPPORTED(s)) {
> + if (STAGE2_SUPPORTED(s) ||
> + (SECURE_IMPLEMENTED(s) && SECURE_S2_SUPPORTED(s))) {
> vmid = CMD_VMID(&cmd);
> }
>
> @@ -1483,7 +1544,8 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, bool is_secure)
> * If stage-2 is supported, invalidate for this VMID only, otherwise
> * invalidate the whole thing.
> */
> - if (STAGE2_SUPPORTED(s)) {
> + if (STAGE2_SUPPORTED(s) ||
> + (SECURE_IMPLEMENTED(s) && SECURE_S2_SUPPORTED(s))) {
> vmid = CMD_VMID(&cmd);
> trace_smmuv3_cmdq_tlbi_nh(vmid);
> smmu_iotlb_inv_vmid_s1(bs, vmid);
> @@ -1502,7 +1564,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, bool is_secure)
> cmd_error = SMMU_CERROR_ILL;
> break;
> }
> - smmuv3_range_inval(bs, &cmd, SMMU_STAGE_1);
> + smmuv3_range_inval(bs, &cmd, SMMU_STAGE_1, false);
> break;
> case SMMU_CMD_TLBI_S12_VMALL:
> {
> @@ -1527,7 +1589,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, bool is_secure)
> * As currently only either s1 or s2 are supported
> * we can reuse same function for s2.
> */
> - smmuv3_range_inval(bs, &cmd, SMMU_STAGE_2);
> + smmuv3_range_inval(bs, &cmd, SMMU_STAGE_2, false);
> break;
> case SMMU_CMD_TLBI_EL3_ALL:
> case SMMU_CMD_TLBI_EL3_VA:
> diff --git a/hw/arm/trace-events b/hw/arm/trace-events
> index 7bb0bd0cc5..92c87f0b9e 100644
> --- a/hw/arm/trace-events
> +++ b/hw/arm/trace-events
> @@ -41,7 +41,7 @@ smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t
> smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
> smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
> smmuv3_record_event(const char *type, uint32_t sid, bool is_secure) "%s sid=0x%x is_secure=%d"
> -smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid=0x%x features:0x%x, sid_split:0x%x"
> +smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split, bool is_secure) "sid=0x%x features:0x%x, sid_split:0x%x is_secure=%d"
> smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRIx64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
> smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
> smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
> diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
> index e5e2d09294..5d15a1212b 100644
> --- a/include/hw/arm/smmu-common.h
> +++ b/include/hw/arm/smmu-common.h
> @@ -116,6 +116,7 @@ typedef struct SMMUTransCfg {
> SMMUTransTableInfo tt[2];
> /* Used by stage-2 only. */
> struct SMMUS2Cfg s2cfg;
> + bool secure;
> } SMMUTransCfg;
>
> typedef struct SMMUDevice {
> diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
> index 72ad042514..43c7289a43 100644
> --- a/include/hw/arm/smmuv3.h
> +++ b/include/hw/arm/smmuv3.h
> @@ -110,4 +110,8 @@ OBJECT_DECLARE_TYPE(SMMUv3State, SMMUv3Class, ARM_SMMUV3)
> #define STAGE1_SUPPORTED(s) FIELD_EX32(s->idr[0], IDR0, S1P)
> #define STAGE2_SUPPORTED(s) FIELD_EX32(s->idr[0], IDR0, S2P)
>
> +#define SECURE_IMPLEMENTED(s) \
> + FIELD_DP32(s->secure_idr[1], S_IDR1, SECURE_IMPL, 1)
> +#define SECURE_S2_SUPPORTED(s) \
> + FIELD_DP32(s->secure_idr[1], S_IDR1, SEL2, 1)
> #endif
> --
> 2.34.1
>
>
next prev parent reply other threads:[~2025-08-18 21:29 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-06 15:11 [RFC 00/11] hw/arm/smmuv3: Add initial support for Secure State Tao Tang
2025-08-06 15:11 ` [RFC 01/11] hw/arm/smmuv3: Introduce secure registers and commands Tao Tang
2025-08-11 10:22 ` Philippe Mathieu-Daudé
2025-08-11 10:43 ` Philippe Mathieu-Daudé
2025-08-18 21:21 ` Mostafa Saleh
2025-08-06 15:11 ` [RFC 02/11] hw/arm/smmuv3: Implement read/write logic for secure registers Tao Tang
2025-08-06 21:53 ` Pierrick Bouvier
2025-08-10 16:54 ` Tao Tang
2025-08-12 17:12 ` Pierrick Bouvier
2025-08-18 21:24 ` Mostafa Saleh
2025-08-20 15:21 ` Tao Tang
2025-08-23 10:41 ` Mostafa Saleh
2025-09-11 15:27 ` Tao Tang
2025-09-15 9:14 ` Mostafa Saleh
2025-09-15 9:34 ` Eric Auger
2025-08-06 15:11 ` [RFC 03/11] hw/arm/smmuv3: Implement S_INIT for secure initialization Tao Tang
2025-08-18 21:26 ` Mostafa Saleh
2025-08-20 16:01 ` Tao Tang
2025-08-06 15:11 ` [RFC 04/11] hw/arm/smmuv3: Enable command processing for the Secure state Tao Tang
2025-08-06 21:55 ` Pierrick Bouvier
2025-08-10 16:59 ` Tao Tang
2025-08-11 10:34 ` Philippe Mathieu-Daudé
2025-08-12 17:27 ` Pierrick Bouvier
2025-08-12 17:39 ` Philippe Mathieu-Daudé
2025-08-12 18:42 ` Peter Maydell
2025-08-15 6:02 ` Tao Tang
2025-08-15 14:53 ` Peter Maydell
2025-08-17 3:46 ` Tao Tang
2025-08-06 15:11 ` [RFC 05/11] hw/arm/smmuv3: Support secure event queue and error handling Tao Tang
2025-08-11 10:41 ` Philippe Mathieu-Daudé
2025-08-06 15:11 ` [RFC 06/11] hw/arm/smmuv3: Plumb security state through core functions Tao Tang
2025-08-18 21:28 ` Mostafa Saleh [this message]
2025-08-20 16:25 ` Tao Tang
2025-08-23 10:43 ` Mostafa Saleh
2025-08-06 15:11 ` [RFC 07/11] hw/arm/smmuv3: Add separate address space for secure SMMU accesses Tao Tang
2025-08-06 15:11 ` [RFC 08/11] hw/arm/smmuv3: Enable secure-side stage 2 TLB invalidations Tao Tang
2025-08-06 15:11 ` [RFC 09/11] hw/arm/smmuv3: Make the configuration cache security-state aware Tao Tang
2025-08-06 15:11 ` [RFC 10/11] hw/arm/smmuv3: Differentiate secure TLB entries via keying Tao Tang
2025-08-06 21:11 ` [RFC 00/11] hw/arm/smmuv3: Add initial support for Secure State Pierrick Bouvier
2025-08-06 21:28 ` Pierrick Bouvier
2025-08-10 16:11 ` Tao Tang
2025-08-11 10:26 ` Philippe Mathieu-Daudé
2025-08-12 17:50 ` Pierrick Bouvier
2025-08-12 18:04 ` Pierrick Bouvier
2025-08-15 5:49 ` Tao Tang
2025-09-30 4:04 ` Tao Tang
2025-08-18 21:52 ` Mostafa Saleh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aKOa8KwAcm6hhAXq@google.com \
--to=smostafa@google.com \
--cc=chenbaozi@phytium.com.cn \
--cc=eric.auger@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=tangtao1634@phytium.com.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.