[RFC v5 19/28] hw/arm/smmuv3: Determine register bank from MMIO offset
Tao Tang <[email protected]>
| Newsgroups | org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Modify the main MMIO handlers to select the target register bank from the memory-mapped offset. Offsets in the Secure register window select SMMU_SEC_SID_S and are normalized by subtracting SMMU_SECURE_REG_START. Other offsets select the Non-secure bank. Pass the selected SEC_SID to the register access helpers, where the normalized bank-local offset identifies the register. Keep bank-specific differences explicit, such as S_IDR5 being unimplemented. This patch implements Non-secure and Secure bank dispatch and prepares for later access checks; Realm and Root programming interfaces are not modeled. Signed-off-by: Tao Tang <[email protected]> Reviewed-by: Pierrick Bouvier <[email protected]> --- hw/arm/smmuv3.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index efa78869251..b36bc4a54e0 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1889,9 +1889,9 @@ static int smmuv3_cmdq_consume(SMMUv3State *s, Error **errp, SMMUSecSID sec_sid) } static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset, - uint64_t data, MemTxAttrs attrs) + uint64_t data, MemTxAttrs attrs, + SMMUSecSID reg_sec_sid) { - SMMUSecSID reg_sec_sid = SMMU_SEC_SID_NS; SMMUv3RegBank *bank = smmuv3_bank(s, reg_sec_sid); switch (offset) { @@ -1959,10 +1959,10 @@ static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset, } static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset, - uint64_t data, MemTxAttrs attrs) + uint64_t data, MemTxAttrs attrs, + SMMUSecSID reg_sec_sid) { Error *local_err = NULL; - SMMUSecSID reg_sec_sid = SMMU_SEC_SID_NS; SMMUv3RegBank *bank = smmuv3_bank(s, reg_sec_sid); switch (offset) { @@ -2223,16 +2223,26 @@ static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data, SMMUState *sys = opaque; SMMUv3State *s = ARM_SMMUV3(sys); MemTxResult r; + SMMUSecSID reg_sec_sid = SMMU_SEC_SID_NS; /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ offset &= ~0x10000; + /* + * Dispatch the Non-secure window directly. After access validation, + * translate the Secure window to its bank-local register offsets. + */ + if (offset >= SMMU_SECURE_REG_START) { + reg_sec_sid = SMMU_SEC_SID_S; + offset -= SMMU_SECURE_REG_START; + } + switch (size) { case 8: - r = smmu_writell(s, offset, data, attrs); + r = smmu_writell(s, offset, data, attrs, reg_sec_sid); break; case 4: - r = smmu_writel(s, offset, data, attrs); + r = smmu_writel(s, offset, data, attrs, reg_sec_sid); break; default: r = MEMTX_ERROR; @@ -2244,9 +2254,9 @@ static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data, } static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) + uint64_t *data, MemTxAttrs attrs, + SMMUSecSID reg_sec_sid) { - SMMUSecSID reg_sec_sid = SMMU_SEC_SID_NS; SMMUv3RegBank *bank = smmuv3_bank(s, reg_sec_sid); switch (offset) { @@ -2285,9 +2295,9 @@ static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset, } static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) + uint64_t *data, MemTxAttrs attrs, + SMMUSecSID reg_sec_sid) { - SMMUSecSID reg_sec_sid = SMMU_SEC_SID_NS; SMMUv3RegBank *bank = smmuv3_bank(s, reg_sec_sid); switch (offset) { @@ -2295,6 +2305,10 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, *data = smmuv3_idreg(offset - A_IDREGS); return MEMTX_OK; case A_IDR0 ... A_IDR5: + /* IDR5 does not support Secure or Realm state. */ + if ((reg_sec_sid != SMMU_SEC_SID_NS) && (offset == A_IDR5)) { + goto unhandled; + } *data = bank->idr[(offset - A_IDR0) / 4]; return MEMTX_OK; case A_IIDR: @@ -2429,6 +2443,7 @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset, *data = bank->eventq_irq_cfg2; return MEMTX_OK; default: + unhandled: *data = 0; qemu_log_mask(LOG_UNIMP, "%s unhandled 32-bit access at 0x%"PRIx64" (RAZ)\n", @@ -2443,16 +2458,21 @@ static MemTxResult smmu_read_mmio(void *opaque, hwaddr offset, uint64_t *data, SMMUState *sys = opaque; SMMUv3State *s = ARM_SMMUV3(sys); MemTxResult r; + SMMUSecSID reg_sec_sid = SMMU_SEC_SID_NS; /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ offset &= ~0x10000; + if (offset >= SMMU_SECURE_REG_START) { + reg_sec_sid = SMMU_SEC_SID_S; + offset -= SMMU_SECURE_REG_START; + } switch (size) { case 8: - r = smmu_readll(s, offset, data, attrs); + r = smmu_readll(s, offset, data, attrs, reg_sec_sid); break; case 4: - r = smmu_readl(s, offset, data, attrs); + r = smmu_readl(s, offset, data, attrs, reg_sec_sid); break; default: r = MEMTX_ERROR; -- 2.34.1