From f6d8e41c02caaf0b9af73dc54de48d7b97ae1354 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Thu, 11 Dec 2025 13:04:25 -0800 Subject: [PATCH 2/2] hw/arm/smmu: use SMMU address spaces to access memory Signed-off-by: Pierrick Bouvier --- include/hw/arm/smmu-common.h | 49 ++++++++++++++++++------------------ hw/arm/smmu-common.c | 21 ++++++++-------- hw/arm/smmuv3.c | 23 +++++++++-------- 3 files changed, 49 insertions(+), 44 deletions(-) diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 0f08ae080c9..3ee853ccdd9 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -69,30 +69,6 @@ extern AddressSpace __attribute__((weak)) arm_secure_address_space; extern bool arm_secure_as_available; void smmu_enable_secure_address_space(void); -/* - * Return the address space corresponding to the SEC_SID. - * If SEC_SID is Secure, but secure address space is not available, - * return NULL and print a warning message. - */ -static inline AddressSpace *smmu_get_address_space(SMMUSecSID sec_sid) -{ - switch (sec_sid) { - case SMMU_SEC_SID_NS: - return &address_space_memory; - case SMMU_SEC_SID_R: - return &address_space_memory; - case SMMU_SEC_SID_S: - if (!arm_secure_as_available || arm_secure_address_space.root == NULL) { - printf("Secure address space requested but not available\n"); - return NULL; - } - return &arm_secure_address_space; - default: - printf("Unknown SEC_SID value %d\n", sec_sid); - return NULL; - } -} - /* * Page table walk error types */ @@ -243,6 +219,31 @@ struct SMMUBaseClass { }; +/* + * Return the address space corresponding to the SEC_SID. + * If SEC_SID is Secure, but secure address space is not available, + * return NULL and print a warning message. + */ +static inline AddressSpace *smmu_get_address_space(struct SMMUState *bs, + SMMUSecSID sec_sid) +{ + switch (sec_sid) { + case SMMU_SEC_SID_NS: + return &bs->as_memory; + case SMMU_SEC_SID_R: + return &bs->as_memory; + case SMMU_SEC_SID_S: + if (!bs->secure_memory) { + printf("Secure address space requested but not available\n"); + return NULL; + } + return &bs->as_secure_memory; + default: + printf("Unknown SEC_SID value %d\n", sec_sid); + return NULL; + } +} + #define TYPE_ARM_SMMU "arm-smmu" OBJECT_DECLARE_TYPE(SMMUState, SMMUBaseClass, ARM_SMMU) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 5fbfe825fd0..d6aba95cfd9 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -405,13 +405,13 @@ void smmu_iotlb_inv_vmid_s1(SMMUState *s, int vmid) * get_pte - Get the content of a page table entry located at * @base_addr[@index] */ -static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte, - SMMUPTWEventInfo *info, SMMUSecSID sec_sid) +static int get_pte(SMMUState *bs, dma_addr_t baseaddr, uint32_t index, + uint64_t *pte, SMMUPTWEventInfo *info, SMMUSecSID sec_sid) { int ret; dma_addr_t addr = baseaddr + index * sizeof(*pte); MemTxAttrs attrs = smmu_get_txattrs(sec_sid); - AddressSpace *as = smmu_get_address_space(sec_sid); + AddressSpace *as = smmu_get_address_space(bs, sec_sid); if (!as) { info->type = SMMU_PTW_ERR_WALK_EABT; info->addr = addr; @@ -570,7 +570,7 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg *cfg, /* Use NS if forced by previous NSTable=1 or current nscfg */ int current_ns = forced_ns || nscfg; SMMUSecSID sec_sid = SMMU_SEC_SID_NS; - if (get_pte(baseaddr, offset, &pte, info, sec_sid)) { + if (get_pte(bs, baseaddr, offset, &pte, info, sec_sid)) { goto error; } trace_smmu_ptw_level(stage, level, iova, subpage_size, @@ -658,7 +658,7 @@ static int smmu_ptw_64_s1(SMMUState *bs, SMMUTransCfg *cfg, } tlbe->sec_sid = SMMU_SEC_SID_NS; - tlbe->entry.target_as = smmu_get_address_space(tlbe->sec_sid); + tlbe->entry.target_as = smmu_get_address_space(bs, tlbe->sec_sid); if (!tlbe->entry.target_as) { info->type = SMMU_PTW_ERR_WALK_EABT; info->addr = gpa; @@ -720,6 +720,7 @@ static int AArch64_S2StartLevel(int sl0 , int granule_sz) /** * smmu_ptw_64_s2 - VMSAv8-64 Walk of the page tables for a given ipa * for stage-2. + * @bs: SMMU base state * @cfg: translation config * @ipa: ipa to translate * @perm: access type @@ -731,7 +732,7 @@ static int AArch64_S2StartLevel(int sl0 , int granule_sz) * Upon success, @tlbe is filled with translated_addr and entry * permission rights. */ -static int smmu_ptw_64_s2(SMMUTransCfg *cfg, +static int smmu_ptw_64_s2(SMMUState *bs, SMMUTransCfg *cfg, dma_addr_t ipa, IOMMUAccessFlags perm, SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) { @@ -834,7 +835,7 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg, uint8_t s2ap; /* Use NS as Secure Stage 2 is not implemented (SMMU_S_IDR1.SEL2 == 0)*/ - if (get_pte(baseaddr, offset, &pte, info, SMMU_SEC_SID_NS)) { + if (get_pte(bs, baseaddr, offset, &pte, info, SMMU_SEC_SID_NS)) { goto error; } trace_smmu_ptw_level(stage, level, ipa, subpage_size, @@ -888,7 +889,7 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg, } tlbe->sec_sid = SMMU_SEC_SID_NS; - tlbe->entry.target_as = &address_space_memory; + tlbe->entry.target_as = &bs->as_memory; tlbe->entry.translated_addr = gpa; tlbe->entry.iova = ipa & ~mask; tlbe->entry.addr_mask = mask; @@ -964,7 +965,7 @@ int smmu_ptw(SMMUState *bs, SMMUTransCfg *cfg, dma_addr_t iova, return -EINVAL; } - return smmu_ptw_64_s2(cfg, iova, perm, tlbe, info); + return smmu_ptw_64_s2(bs, cfg, iova, perm, tlbe, info); } /* SMMU_NESTED. */ @@ -985,7 +986,7 @@ int smmu_ptw(SMMUState *bs, SMMUTransCfg *cfg, dma_addr_t iova, } ipa = CACHED_ENTRY_TO_ADDR(tlbe, iova); - ret = smmu_ptw_64_s2(cfg, ipa, perm, &tlbe_s2, info); + ret = smmu_ptw_64_s2(bs, cfg, ipa, perm, &tlbe_s2, info); if (ret) { return ret; } diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 885dae6f50e..a4a03c064d5 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -110,13 +110,14 @@ static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn, trace_smmuv3_write_gerrorn(toggled & pending, bank->gerrorn); } -static inline MemTxResult queue_read(SMMUQueue *q, Cmd *cmd, SMMUSecSID sec_sid) +static inline MemTxResult queue_read(SMMUState *bs, SMMUQueue *q, + Cmd *cmd, SMMUSecSID sec_sid) { dma_addr_t addr = Q_CONS_ENTRY(q); MemTxResult ret; int i; - ret = dma_memory_read(&address_space_memory, addr, cmd, sizeof(Cmd), + ret = dma_memory_read(&bs->as_memory, addr, cmd, sizeof(Cmd), MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { return ret; @@ -127,7 +128,7 @@ static inline MemTxResult queue_read(SMMUQueue *q, Cmd *cmd, SMMUSecSID sec_sid) return ret; } -static MemTxResult queue_write(SMMUQueue *q, Evt *evt_in) +static MemTxResult queue_write(SMMUState *bs, SMMUQueue *q, Evt *evt_in) { dma_addr_t addr = Q_PROD_ENTRY(q); MemTxResult ret; @@ -137,7 +138,7 @@ static MemTxResult queue_write(SMMUQueue *q, Evt *evt_in) for (i = 0; i < ARRAY_SIZE(evt.word); i++) { cpu_to_le32s(&evt.word[i]); } - ret = dma_memory_write(&address_space_memory, addr, &evt, sizeof(Evt), + ret = dma_memory_write(&bs->as_memory, addr, &evt, sizeof(Evt), MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { return ret; @@ -162,7 +163,7 @@ static MemTxResult smmuv3_write_eventq(SMMUv3State *s, SMMUSecSID sec_sid, return MEMTX_ERROR; } - r = queue_write(q, evt); + r = queue_write(&s->smmu_state, q, evt); if (r != MEMTX_OK) { return r; } @@ -993,7 +994,7 @@ static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, SMMUEventInfo *event, cfg = g_new0(SMMUTransCfg, 1); cfg->sec_sid = sec_sid; cfg->txattrs = smmu_get_txattrs(sec_sid); - cfg->as = smmu_get_address_space(sec_sid); + cfg->as = smmu_get_address_space(bc, sec_sid); if (!cfg->as) { /* Can't get AddressSpace, free cfg and return. */ g_free(cfg); @@ -1221,7 +1222,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, SMMUTranslationStatus status; SMMUTransCfg *cfg = NULL; IOMMUTLBEntry entry = { - .target_as = &address_space_memory, + .target_as = &s->smmu_state.as_memory, .iova = addr, .translated_addr = addr, .addr_mask = ~(hwaddr)0, @@ -1322,6 +1323,8 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, SMMUSecSID sec_sid) { SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu); + SMMUv3State *s3 = sdev->smmu; + SMMUState *bs = &(s3->smmu_state); SMMUEventInfo eventinfo = {.sec_sid = sec_sid, .inval_ste_allowed = true}; SMMUTransCfg *cfg = smmuv3_get_config(sdev, &eventinfo, sec_sid); @@ -1369,7 +1372,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, } event.type = IOMMU_NOTIFIER_UNMAP; - event.entry.target_as = smmu_get_address_space(sec_sid); + event.entry.target_as = smmu_get_address_space(bs, sec_sid); event.entry.iova = iova; event.entry.addr_mask = num_pages * (1 << granule) - 1; event.entry.perm = IOMMU_NONE; @@ -1618,7 +1621,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSecSID sec_sid) break; } - if (queue_read(q, &cmd, sec_sid) != MEMTX_OK) { + if (queue_read(&s->smmu_state, q, &cmd, sec_sid) != MEMTX_OK) { cmd_error = SMMU_CERROR_ABT; break; } @@ -1649,7 +1652,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, SMMUSecSID sec_sid) SMMUTransCfg *cfg = g_new0(SMMUTransCfg, 1); cfg->sec_sid = sec_sid; cfg->txattrs = smmu_get_txattrs(sec_sid); - cfg->as = smmu_get_address_space(sec_sid); + cfg->as = smmu_get_address_space(bs, sec_sid); if (!cfg->as) { g_free(cfg); qemu_log_mask(LOG_GUEST_ERROR, "SMMUv3 Can't get address space\n"); -- 2.47.3