target/arm/ptw.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
When a PMSAv7 (ARMv7-M) MPU region's DRBAR base is not aligned to its
DRSR region size, get_phys_addr_pmsav7() logged a guest-error and
skipped the region entirely (continue). The architecture calls a
misaligned base UNPREDICTABLE, but real Cortex-M hardware does not
disable the region: RBAR.ADDR is only bits [31:log2(size)], so the
sub-size low bits are simply ignored and the region matches against the
aligned-down base.
NXP's i.MX95 Cortex-M7 firmware (and the MCUXpresso SDK demos) rely on
this. The M7 sets up a deny-all background region (region 0, whole
address space, AP=000) and then grants the peripheral space with a
512 MiB region programmed as DRBAR=0x4c800000 - misaligned, intended as
0x40000000. QEMU dropped that region, so a privileged access to e.g.
LPUART3 at 0x42570000 fell through to the deny-all region and took a
MemManage fault (CFSR.DACCVIOL), trapping the firmware in its default
fault handler before it could print anything.
Align the base down to the region size (base &= ~rmask) to match
silicon, and keep a (now-accurate) guest-error note. This only changes
the previously-UNPREDICTABLE misaligned case; correctly-aligned regions
are unaffected.
Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
Found while bringing up the i.MX95 Cortex-M7 in an out-of-tree machine
model: the M7's MCUXpresso-SDK firmware programs the misaligned 512 MiB
peripheral region described above. With this change the firmware reaches
its FreeRTOS/UART banner; without it the region was dropped and the first
peripheral access took a MemManage DACCVIOL.
The new branch only executes in the previously-UNPREDICTABLE misaligned
case (base & rmask != 0), so correctly-aligned MPU regions are unchanged.
Tested on master: qemu-system-arm builds clean, and the ARMv7-M / MPS2
qtests pass with no regression -- boot-serial (incl. stm32vldiscovery,
Cortex-M3), the stm32l4x5 suite (Cortex-M4: exti/gpio/rcc/syscfg/usart),
microbit, sse-timer and cmsdk-apb-watchdog.
target/arm/ptw.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 0a5201763a..3914d05449 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2665,11 +2665,24 @@ static bool get_phys_addr_pmsav7(CPUARMState *env,
rmask = (1ull << rsize) - 1;
if (base & rmask) {
+ /*
+ * The region base is not aligned to the region size. The
+ * architecture calls this UNPREDICTABLE, but real Cortex-M
+ * hardware ignores the sub-size low bits of RBAR.ADDR (the
+ * field is only [31:log2(size)]) and matches against the
+ * aligned-down base rather than disabling the region. NXP's
+ * i.MX95 M7 firmware relies on this for its peripheral
+ * region (e.g. DRBAR 0x4c800000 with a 512MB size, intended
+ * as 0x40000000), so align down to match silicon instead of
+ * dropping the region (which would leave the access to fall
+ * through to a lower-priority deny-all background region).
+ */
qemu_log_mask(LOG_GUEST_ERROR,
- "DRBAR[%d]: 0x%" PRIx32 " misaligned "
- "to DRSR region size, mask = 0x%" PRIx32 "\n",
- n, base, rmask);
- continue;
+ "DRBAR[%d]: 0x%" PRIx32 " not aligned to DRSR "
+ "region size (mask 0x%" PRIx32 "); aligning down "
+ "to 0x%" PRIx32 " to match Cortex-M behaviour\n",
+ n, base, rmask, base & ~rmask);
+ base &= ~rmask;
}
if (address < base || address > base + rmask) {
--
2.34.1
© 2016 - 2026 Red Hat, Inc.