Introduce helpers that derive MemTxAttrs and select an AddressSpace from
SEC_SID, then pass SEC_SID through the Stream Table and Context Descriptor
fetch paths. This makes reads of SMMU configuration structures use the
corresponding Non-secure or Secure memory context.

To support these helpers, include hw/arm/arm-security.h from smmu-common.h,
making the Arm security-space definitions available to the common SMMU code.

The accelerated path remains Non-secure-only and therefore passes
SMMU_SEC_SID_NS explicitly.

For now, the configuration cache lookup key remains based solely on the
SMMUDevice pointer. It is extended with SEC_SID in a later commit. Other
SEC_SID-sensitive memory accesses that still use the Non-secure address
space are converted in follow-up commits.

Signed-off-by: Tao Tang <[email protected]>
---
 hw/arm/smmu-common.c         | 30 +++++++++++++++++++++----
 hw/arm/smmuv3-accel.c        |  2 +-
 hw/arm/smmuv3-internal.h     |  3 ++-
 hw/arm/smmuv3.c              | 43 ++++++++++++++++++++++--------------
 include/hw/arm/smmu-common.h | 10 +++++++++
 5 files changed, 65 insertions(+), 23 deletions(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 54a6a9f4d62..89e1e2826d4 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -30,6 +30,27 @@
 #include "hw/arm/smmu-common.h"
 #include "smmu-internal.h"
 
+ARMSecuritySpace smmu_get_security_space(SMMUSecSID sec_sid)
+{
+    switch (sec_sid) {
+    case SMMU_SEC_SID_S:
+        return ARMSS_Secure;
+    case SMMU_SEC_SID_NS:
+        return ARMSS_NonSecure;
+    case SMMU_SEC_SID_NUM:
+        g_assert_not_reached();
+    }
+    g_assert_not_reached();
+}
+
+MemTxAttrs smmu_get_txattrs(SMMUSecSID sec_sid)
+{
+    return (MemTxAttrs) {
+        .secure = smmu_sec_sid_is_secure(sec_sid) ? 1 : 0,
+        .space = smmu_get_security_space(sec_sid),
+    };
+}
+
 AddressSpace *smmu_get_address_space(SMMUState *s, SMMUSecSID sec_sid)
 {
     switch (sec_sid) {
@@ -588,6 +609,7 @@ error:
 /**
  * smmu_ptw_64_s2 - VMSAv8-64 Walk of the page tables for a given ipa
  * for stage-2.
+ * @bs: smmu state which includes TLB instance
  * @cfg: translation config
  * @ipa: ipa to translate
  * @perm: access type
@@ -599,7 +621,7 @@ error:
  * 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)
 {
@@ -636,7 +658,6 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
         uint64_t pte, gpa;
         dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
         uint8_t s2ap;
-
         if (get_pte(baseaddr, offset, &pte, info)) {
                 goto error;
         }
@@ -690,6 +711,7 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
             goto error_ipa;
         }
 
+        tlbe->entry.target_as = &bs->memory_as;
         tlbe->entry.translated_addr = gpa;
         tlbe->entry.iova = ipa & ~mask;
         tlbe->entry.addr_mask = mask;
@@ -765,7 +787,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. */
@@ -775,7 +797,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-accel.c b/hw/arm/smmuv3-accel.c
index 2ce94786829..9d207acc8e3 100644
--- a/hw/arm/smmuv3-accel.c
+++ b/hw/arm/smmuv3-accel.c
@@ -310,7 +310,7 @@ bool smmuv3_accel_install_ste(SMMUv3State *s, SMMUDevice 
*sdev, int sid,
         return false;
     }
 
-    if (smmu_find_ste(sdev->smmu, sid, &ste, &event)) {
+    if (smmu_find_ste(sdev->smmu, sid, &ste, &event, sec_sid)) {
         /* No STE found, nothing to install */
         return true;
     }
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index 202cd533636..1f2f426da01 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -367,7 +367,8 @@ typedef struct SMMUEventInfo {
 
 void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
 void smmuv3_propagate_event(SMMUv3State *s, Evt *evt, SMMUSecSID sec_sid);
-int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo 
*event);
+int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event,
+                  SMMUSecSID sec_sid);
 
 #define STE_SIZE 6
 #define L1STD_SIZE 3
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 649050b9347..b5dc67dcb01 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -366,14 +366,15 @@ static void smmuv3_reset(SMMUv3State *s)
 }
 
 static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
-                        SMMUEventInfo *event)
+                        SMMUEventInfo *event, SMMUSecSID sec_sid)
 {
+    AddressSpace *as = smmu_get_address_space(ARM_SMMU(s), sec_sid);
+    MemTxAttrs txattrs = smmu_get_txattrs(sec_sid);
     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);
+    ret = dma_memory_read(as, addr, buf, sizeof(*buf), txattrs);
     if (ret != MEMTX_OK) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
@@ -396,12 +397,15 @@ static SMMUTranslationStatus 
smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
                                                  SMMUTranslationClass class);
 /* @ssid > 0 not supported yet */
 static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
-                       uint32_t ssid, CD *buf, SMMUEventInfo *event)
+                       uint32_t ssid, CD *buf, SMMUEventInfo *event,
+                       SMMUSecSID sec_sid)
 {
     dma_addr_t addr = STE_CTXPTR(ste);
     int ret, i;
     SMMUTranslationStatus status;
     SMMUTLBEntry *entry;
+    AddressSpace *as;
+    MemTxAttrs txattrs;
 
     trace_smmuv3_get_cd(addr);
 
@@ -417,9 +421,10 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, 
SMMUTransCfg *cfg,
         addr = CACHED_ENTRY_TO_ADDR(entry, addr);
     }
 
+    as = smmu_get_address_space(ARM_SMMU(s), sec_sid);
+    txattrs = smmu_get_txattrs(sec_sid);
     /* TODO: guarantee 64-bit single-copy atomicity */
-    ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf),
-                          MEMTXATTRS_UNSPECIFIED);
+    ret = dma_memory_read(as, addr, buf, sizeof(*buf), txattrs);
     if (ret != MEMTX_OK) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
@@ -680,18 +685,21 @@ bad_ste:
  * @sid: stream ID
  * @ste: returned stream table entry
  * @event: handle to an event info
+ * @sec_sid: StreamID Security state
  *
  * Supports linear and 2-level stream table
  * Return 0 on success, -EINVAL otherwise
  */
-int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event)
+int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event,
+                  SMMUSecSID sec_sid)
 {
     dma_addr_t addr, strtab_base;
     uint32_t log2size;
     int strtab_size;
     int ret;
-    SMMUSecSID sec_sid = SMMU_SEC_SID_NS;
     SMMUv3RegBank *bank = smmuv3_bank(s, sec_sid);
+    AddressSpace *as = smmu_get_address_space(ARM_SMMU(s), sec_sid);
+    MemTxAttrs txattrs = smmu_get_txattrs(sec_sid);
 
     trace_smmuv3_find_ste(sid, bank->features, bank->sid_split);
     log2size = FIELD_EX32(bank->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE);
@@ -718,8 +726,7 @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, 
SMMUEventInfo *event)
         l2_ste_offset = sid & ((1 << bank->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);
+        ret = dma_memory_read(as, l1ptr, &l1std, sizeof(l1std), txattrs);
         if (ret != MEMTX_OK) {
             qemu_log_mask(LOG_GUEST_ERROR,
                           "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr);
@@ -773,7 +780,7 @@ int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, 
SMMUEventInfo *event)
         addr = strtab_base + sid * sizeof(*ste);
     }
 
-    if (smmu_get_ste(s, addr, ste, event)) {
+    if (smmu_get_ste(s, addr, ste, event, sec_sid)) {
         return -EINVAL;
     }
 
@@ -904,7 +911,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, sec_sid);
     if (ret) {
         return ret;
     }
@@ -918,7 +925,7 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, 
SMMUTransCfg *cfg,
         return 0;
     }
 
-    ret = smmu_get_cd(s, &ste, cfg, 0 /* ssid */, &cd, event);
+    ret = smmu_get_cd(s, &ste, cfg, 0 /* ssid */, &cd, event, sec_sid);
     if (ret) {
         return ret;
     }
@@ -933,12 +940,14 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, 
SMMUTransCfg *cfg,
  *
  * @sdev: SMMUDevice handle
  * @event: output event info
+ * @sec_sid: StreamID Security state
  *
  * 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,
+                                       SMMUSecSID sec_sid)
 {
     SMMUv3State *s = sdev->smmu;
     SMMUState *bc = &s->smmu_state;
@@ -959,7 +968,7 @@ static SMMUTransCfg *smmuv3_get_config(SMMUDevice *sdev, 
SMMUEventInfo *event)
                             (sdev->cfg_cache_hits + sdev->cfg_cache_misses));
         cfg = g_new0(SMMUTransCfg, 1);
 
-        if (!smmuv3_decode_config(&sdev->iommu, cfg, event, SMMU_SEC_SID_NS)) {
+        if (!smmuv3_decode_config(&sdev->iommu, cfg, event, sec_sid)) {
             g_hash_table_insert(bc->configs, sdev, cfg);
         } else {
             g_free(cfg);
@@ -1139,7 +1148,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion 
*mr, hwaddr addr,
         goto epilogue;
     }
 
-    cfg = smmuv3_get_config(sdev, &event);
+    cfg = smmuv3_get_config(sdev, &event, sec_sid);
     if (!cfg) {
         status = SMMU_TRANS_ERROR;
         goto epilogue;
@@ -1221,7 +1230,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
     SMMUSecSID sec_sid = SMMU_SEC_SID_NS;
     SMMUEventInfo eventinfo = {.sec_sid = sec_sid,
                                .inval_ste_allowed = true};
-    SMMUTransCfg *cfg = smmuv3_get_config(sdev, &eventinfo);
+    SMMUTransCfg *cfg = smmuv3_get_config(sdev, &eventinfo, sec_sid);
     IOMMUTLBEvent event;
     uint8_t granule;
 
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index 9d6e2d3038f..a31ffcf6e71 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -22,6 +22,7 @@
 #include "hw/core/sysbus.h"
 #include "hw/pci/pci.h"
 #include "qom/object.h"
+#include "hw/arm/arm-security.h"
 
 #define SMMU_PCI_BUS_MAX                    256
 #define SMMU_PCI_DEVFN_MAX                  256
@@ -47,6 +48,9 @@ typedef enum SMMUSecSID {
     SMMU_SEC_SID_NUM,
 } SMMUSecSID;
 
+MemTxAttrs smmu_get_txattrs(SMMUSecSID sec_sid);
+ARMSecuritySpace smmu_get_security_space(SMMUSecSID sec_sid);
+
 /*
  * Page table walk error types
  */
@@ -200,6 +204,12 @@ SMMUPciBus *smmu_get_sbus(SMMUState *s, PCIBus *bus);
 /* Initialize SMMUDevice handle associated to a SMMUPciBus */
 void smmu_init_sdev(SMMUState *s, SMMUDevice *sdev, PCIBus *bus, int devfn);
 
+
+static inline bool smmu_sec_sid_is_secure(SMMUSecSID sec_sid)
+{
+    return sec_sid == SMMU_SEC_SID_S;
+}
+
 /* Return the stream ID of an SMMU device */
 static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
 {
-- 
2.34.1


Reply via email to