Commit 09a3b025b1 for qemu.org
commit 09a3b025b1f0c903802de793a0fd07b677a11060
Author: Gilles Grimaud <gilles.grimaud@univ-lille.fr>
Date: Mon Sep 14 21:23:19 2026 +0200
target/arm: MPU - limit regs RBAR/RASR A1-A3 to Main Extension
The alias registers MPU_RBAR_A1-A3 and MPU_RASR_A1-A3 (v7M) or
MPU_RLAR_A1-A3 (v8M) exist only when the Main Extension is implemented
(ARM_FEATURE_M_MAIN). The current NVIC decoder groups the principal
register and its aliases in the same case fall-through, so once the
PMSAv7 path is enabled for v6-M (or the PMSAv8 path for v8-M Baseline)
the aliases become incorrectly accessible.
The fix reorders the case statements for the four locations (read and
write of RBAR and RASR/RLAR) in hw/intc/armv7m_nvic.c. Alias cases are
placed before the principal register case with a fall-through and are
guarded by a test of ARM_FEATURE_M_MAIN. If the Main Extension is absent
the code jumps to bad_offset, causing a read to log "NVIC: Bad read
offset" and return zero, and a write to log "NVIC: Bad write offset" and
be ignored. The principal MPU_RBAR and MPU_RASR/RLAR registers remain
functional for CPUs that implement the corresponding MPU.
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gilles Grimaud <gilles.grimaud@univ-lille.fr>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index b1d27dfb32..51d3dba852 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1382,10 +1382,15 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
return cpu->env.v7m.mpu_ctrl[attrs.secure];
case 0xd98: /* MPU_RNR */
return cpu->env.pmsav7.rnr[attrs.secure];
- case 0xd9c: /* MPU_RBAR */
case 0xda4: /* MPU_RBAR_A1 */
case 0xdac: /* MPU_RBAR_A2 */
case 0xdb4: /* MPU_RBAR_A3 */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
+ /* These aliases are not present for v6M or v8M without Main */
+ goto bad_offset;
+ }
+ /* fall through */
+ case 0xd9c: /* MPU_RBAR */
{
int region = cpu->env.pmsav7.rnr[attrs.secure];
@@ -1410,10 +1415,16 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
}
return (cpu->env.pmsav7.drbar[region] & ~0x1f) | (region & 0xf);
}
- case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */
+
case 0xda8: /* MPU_RASR_A1 (v7M), MPU_RLAR_A1 (v8M) */
case 0xdb0: /* MPU_RASR_A2 (v7M), MPU_RLAR_A2 (v8M) */
case 0xdb8: /* MPU_RASR_A3 (v7M), MPU_RLAR_A3 (v8M) */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
+ /* These aliases are not present for v6M or v8M without Main */
+ goto bad_offset;
+ }
+ /* fall through */
+ case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */
{
int region = cpu->env.pmsav7.rnr[attrs.secure];
@@ -1892,10 +1903,15 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
cpu->env.pmsav7.rnr[attrs.secure] = value;
}
break;
- case 0xd9c: /* MPU_RBAR */
case 0xda4: /* MPU_RBAR_A1 */
case 0xdac: /* MPU_RBAR_A2 */
case 0xdb4: /* MPU_RBAR_A3 */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
+ /* These aliases are not present for v6M or v8M without Main */
+ goto bad_offset;
+ }
+ /* fall through */
+ case 0xd9c: /* MPU_RBAR */
{
int region;
@@ -1943,10 +1959,16 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
tlb_flush(CPU(cpu));
break;
}
- case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */
+
case 0xda8: /* MPU_RASR_A1 (v7M), MPU_RLAR_A1 (v8M) */
case 0xdb0: /* MPU_RASR_A2 (v7M), MPU_RLAR_A2 (v8M) */
case 0xdb8: /* MPU_RASR_A3 (v7M), MPU_RLAR_A3 (v8M) */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
+ /* These aliases are not present for v6M or v8M without Main */
+ goto bad_offset;
+ }
+ /* fall through */
+ case 0xda0: /* MPU_RASR (v7M), MPU_RLAR (v8M) */
{
int region = cpu->env.pmsav7.rnr[attrs.secure];