Hi Mostafa,
On 9/1/2026 10:26 PM, Mostafa Saleh wrote:
On Fri, Aug 14, 2026 at 12:25:57AM +0800, Tao Tang wrote:
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;
It's not that simple, both banks aren't identical.
Beyond the IDR5 handled here, AFAICT the following doesn't also exist
in the secure bank:
- 0x0018 SMMU_IIDR
- 0x001C SMMU_AIDR
- 0x0040 SMMU_STATUSR
You're right. I prepare to centralize these register-layout differences
in a helper:
```
static bool smmuv3_reg_is_raz_wi(hwaddr offset,
SMMUSecSID reg_sec_sid)
{
switch (offset) {
case A_IDR5:
case A_IIDR:
case A_STATUSR:
case A_IDREGS ... A_IDREGS + 0x2f:
return reg_sec_sid != SMMU_SEC_SID_NS;
case A_AIDR:
return reg_sec_sid == SMMU_SEC_SID_S;
default:
/* Leave other offsets to the register handlers */
return false;
}
}
static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
uint64_t *data, MemTxAttrs attrs,
SMMUSecSID reg_sec_sid)
{
SMMUv3RegBank *bank = smmuv3_bank(s, reg_sec_sid);
if (smmuv3_reg_is_raz_wi(offset, reg_sec_sid)) {
*data = 0;
qemu_log_mask(LOG_GUEST_ERROR,
"%s: read from undefined register: bank=%d "
"offset=0x%" PRIx64 " (RAZ)\n",
__func__, reg_sec_sid, offset);
return MEMTX_OK;
}
switch (offset) {
case A_AIDR:
if (reg_sec_sid == SMMU_SEC_SID_R) { // For the future Realm
support
/* RME architecture revision 0.0. */
*data = 0;
} else {
*data = s->aidr;
}
return MEMTX_OK;
......
default:
unhandled:
*data = 0;
qemu_log_mask(LOG_UNIMP,
"%s unhandled 32-bit access at 0x%"PRIx64" (RAZ)\n",
__func__, offset);
return MEMTX_OK;
}
}
```
The shared handlers will return zero or ignore writes when this helper
returns true. Also there is a code piece(` case A_AIDR `) to show how we
handle with same relative offset but with different meanings.
How do you think about this?
Also, A_GBPA seems to call smmuv3_accel_attach_gbpa_hwpt() irrelevant
of security state.
I'll add an if (reg_sec_sid == SMMU_SEC_SID_NS) guard before the
accelerator call.
Finally, the first patch introduced SMMU_S_CR0_RESERVED for the secure
register, but SMMU_CR0_RESERVED is still used here.
I'll fix it in V6.
Thanks,
Mostafa
Thanks,
Tao