U-Boot relocates itself and its heap to the top of RAM. On the QEMU
virt machine that is fine with -m 3072 and below, where RAM ends at or
under the 4 GiB boundary, but with more memory (e.g. -m 6144) U-Boot
ends up around 7 GiB. Every buffer it then hands to a DMA engine that
is limited to 32-bit addresses is unreachable by the device.

The generic SDHCI driver is such a consumer: it transfers via 32-bit
SDMA or 32-bit ADMA2 descriptors. With an emulated sdhci-pci eMMC on
the virt machine and 6 GiB of RAM, card initialization data transfers
fail silently, the MMC block device never probes, and bootstd finds no
bootflow on the eMMC: autoboot drops to the prompt with an empty 'pci'
listing as the only visible symptom (enumeration not yet run), while
'dm tree' after a manual 'pci enum' shows the controller bound but the
blk child never probed.

Clamp the usable RAM top to 4 GiB like other boards with 32-bit DMA
constraints do, so U-Boot and its buffers stay DMA-addressable however
much memory the VM is given. The OS still sees and uses all of it.

Fixes: f37770c7707b ("ARM: qemu-arm: Bump RAM size in AArch64 MMU table")
Signed-off-by: Igor Opaniuk <[email protected]>
---
A single fix for running U-Boot on the QEMU virt machine with more
than 3 GiB of RAM: relocation then places U-Boot (and its DMA
buffers) above the 32-bit boundary, which the generic SDHCI driver
cannot address with SDMA or 32-bit ADMA2 descriptors, so an emulated
sdhci-pci eMMC silently loses its block device and bootstd finds no
bootflow on it. Clamp the usable RAM top to 4 GiB, as other boards
with 32-bit DMA constraints do.

Found while bringing up an Android boot chain (TF-A + OP-TEE +
U-Boot AVB + eMMC/RPMB) on qemu_arm64 and raising the VM memory
from 3 GiB to 6 GiB.
---
 board/emulation/qemu-arm/qemu-arm.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/board/emulation/qemu-arm/qemu-arm.c 
b/board/emulation/qemu-arm/qemu-arm.c
index 38f0ec5f2fb..18daca4a16f 100644
--- a/board/emulation/qemu-arm/qemu-arm.c
+++ b/board/emulation/qemu-arm/qemu-arm.c
@@ -144,6 +144,20 @@ int dram_init_banksize(void)
        return 0;
 }
 
+phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
+{
+       /*
+        * Keep U-Boot below 4 GiB when QEMU is given more RAM: the
+        * generic SDHCI driver transfers via 32-bit SDMA or 32-bit
+        * ADMA2 descriptors, so buffers (and U-Boot itself, after
+        * relocation to the top of RAM) must stay DMA-addressable.
+        */
+       if (gd->ram_base + gd->ram_size > SZ_4G)
+               return SZ_4G;
+
+       return gd->ram_base + gd->ram_size;
+}
+
 int board_fdt_blob_setup(void **fdtp)
 {
        /* QEMU loads a generated DTB for us at the start of RAM. */

---
base-commit: 8649a54d301a4d0ac526324c7a7ad2574939ff27
change-id: 20261026-upstream-u-boot_qemu_arm_b4-a5fc6e8b22b0

Best regards,
-- 
Igor Opaniuk <[email protected]>

Reply via email to