fix(raspi): the Pi 5's native path turns the MMU and caches on before any C; bounded mailbox; framebuffer address from dma-ranges

boards/BRINGUP.md R2/R3, FABRIC-3 SXXXIX.  The entry stub cleans the cache
over the image, builds an identity map (the image's GiB Normal, the rest
Device) and enables MMU and caches at EL2 (or EL1); rpi5_mmu.c makes the
devicetree's RAM Normal and the framebuffer uncached.  Mailbox waits give
up after one second; the buffer is cleaned around the exchange; the
framebuffer address goes through dma-ranges, not a Pi 4 mask.

New rpi5-rehearsal target runs the native image on QEMU virt at EL2.  It
found three more that would each have stopped the board: the PL011 shift
(mine, c9519173; the host test asserted it), the GIC address not carried
through /soc's ranges (new fdt_reg_address(), checked against the real
Pi 5 DTB), and no timer IRQ at EL2 (HCR_EL2.IMO/FMO/AMO).

Rehearsal: POST 1052 passed, same parity hash as UEFI.  Standard acceptance
on three ISAs: POST 1052, hash 0x82f4ae7cb2e2d424.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-14 12:58:35 -04:00
co-authored by Claude Opus 5.5
parent 4da370f492
commit 0e2c60dac3
23 changed files with 36835 additions and 85 deletions
+60
View File
@@ -5676,3 +5676,63 @@ ERROR probe, sent by itself at once, under source `00` (`-114847`); the lost-rec
(`-120526`) and riscv64 (`-120746`). Standard acceptance, all three ISAs: `zuse@Hera`, POST 1052
passed, no unknown word, **new baseline `word_count=526 ... hash=0x82f4ae7cb2e2d424`**
(deliberate: Hera's new words) (`logs/20261014-120027`, `-120148`, `-120356`).
## XXXIX. The Pi 5's native path: MMU and caches on before any C, bounded mailbox, framebuffer address from the devicetree -- and a rehearsal on QEMU that found three more (2026-10-14)
Captain Bob, 2026-10-14: "fix the pi 5 problems" -- the three from the Friday review (`boards/BRINGUP.md`
R2, R3).
**1. MMU and caches off (R2).** The firmware enters at EL2 with the MMU off: every access is
Device memory, where an unaligned access or an exclusive faults and nothing is cached. The
aarch64 kernel had never needed to turn the MMU on -- under UEFI it runs on the firmware's map
(`arch_mmu_init()` is a stub; `vmm.c` builds x86-shaped tables it never loads on aarch64).
`native_rpi5_entry.S` now: cleans and invalidates the data cache over the whole image first
(so nothing the firmware left there lands on top of what follows); builds an identity map, the
image's GiB Normal write-back in 2 MiB blocks, every other GiB Device-nGnRE and never executable;
sets MAIR, TCR and TTBR0 and turns on M, C and I at whichever EL it was entered at (EL2 on the
Pi 5, EL1 handled too), with WXN and alignment checking off. In C, `rpi5_mmu.c` then makes every
further GiB the devicetree's `/memory` covers entirely Normal, and makes the framebuffer Normal
non-cacheable (the display reads it straight from RAM), each change break-before-make.
**2. Unbounded mailbox waits (R3).** Every wait now gives up after one second by the
architectural counter (`-5`); before any console exists a silent VideoCore must cost a missing
framebuffer, not a hang. With the caches on, the request buffer is cleaned to RAM before it is
sent and invalidated before the answer is read: the VideoCore does not see the ARM's caches.
**3. The framebuffer address (R3).** `& 0x3FFFFFFF` was the Pi 4's rule. The address the firmware
returns is now carried through the devicetree's `dma-ranges` from the firmware node up: on the
Pi 5 (the real `bcm2712-rpi-5-b.dtb`) the firmware node's is empty and `/soc` has none, so it is
already physical; on a Pi 4 `/soc` maps bus `0xC0000000` onto 0, and that is handled too. An
address no entry holds is refused (`-6`). Still unverified: the allocate tag's size field.
**The rehearsal.** There is no QEMU model of the Pi 5, but QEMU's virt machine with
`virtualization=on` enters a raw image exactly as the Pi 5's firmware does: at EL2, MMU off,
devicetree in x0. New `make -f kernel/Makefile ARCH=aarch64 RPI5_NATIVE_BASE=0x40080000
rpi5-rehearsal` links the same native image at virt's address (the linker script's base is now
`RPI5_NATIVE_BASE`, 0x80000 by default) and boots it, Cortex-A76, one QEMU, foreground. It found
three more, each of which would have stopped the Pi 5:
- **The PL011's register shift**, mine (`c9519173`): `fdt_uart.c` gave a devicetree PL011 a shift
of 0, but `console.c` numbers its registers by word -- the flag register was read at +6, not
+0x18: an alignment fault on Device memory at the first character. The UEFI path never met it
(it uses a built-in default with the right shift), and the host test asserted the wrong value.
Shift 2 now; the test expects it.
- **The GIC's address**: `apic.c` read the GIC's `reg` as two 64-bit cells with no translation --
right only where the GIC is a child of the root. On the Pi 5 it is on `/soc` (one cell,
`0x7fff9000`), `0x107fff9000` to the CPU. New `fdt_reg_address()` (`fdt.c`) reads a node's `reg`
entry in its parent's cells and carries it up through every bus's `ranges`; the GIC lookup uses
it, and accepts virt's `arm,cortex-a15-gic` too. Checked against the real Pi 5 devicetree:
`tools/fdt_uart_test.c <dtb> pl011 0x107d001000 2 4 arm,gic-400 0x107fff9000 0x107fffa000`.
- **No timer interrupt at EL2**: with `HCR_EL2.IMO/FMO/AMO` clear an IRQ targets EL1 and is never
taken while the CPU runs at EL2 -- "Heartbeat: 0 ticks". The entry stub sets them at EL2. The
UEFI path runs at EL1 and never met it.
**Verified.** Rehearsal, final: POST 1052 passed, `PARITY:M7.1a word_count=526 ...
hash=0x82f4ae7cb2e2d424` -- the same as the UEFI build -- the Tripod born, the heartbeat ticking,
no exception (`logs/20261014-124530/aarch64-rpi5/`). Earlier rehearsal and the hand-run QEMU
sessions that found the three are not logged (`-d int` to a scratch file); `logs/20261014-123129`
is the first, silent, run. Not rehearsed: the mailbox and framebuffer (virt has neither), the Pi
5's own UART and GIC addresses (the host test checks them against its devicetree), PCI (virt's
needs ACPI; the Pi 5's is R4). The board image (`make boot_image TARGET=RASPI`) links at 0x80000
and ends at 0x834000. Standard acceptance, all three ISAs: POST 1052 passed, same hash
(`logs/20261014-125305`, `-125427`, `-125635`).