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];