diff options
| author | Tom Rini <[email protected]> | 2026-06-24 15:39:29 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-06-24 18:13:25 -0600 |
| commit | 19eafbadf20f56c1a24abe6b5e8774e776894261 (patch) | |
| tree | 1ece0528f796fb129f2a7d6b18cf14db130b1150 /common | |
| parent | 47e9c542ee032e89f556adc73c2aeff3acb0e5a9 (diff) | |
| parent | fb537c85bca0e3d29a62fe119181bf1744b8c91a (diff) | |
Merge patch series "Relocate U-Boot in the last bank"
Ilias Apalodimas <[email protected]> says:
There was a discussion recently on the mailing lists regarding our
management of memory above ram_top [0]. The tl;dr is that we have two problems.
The first one is that U-Boot always relocates to the top of the first available
bank unless there's special board code to sidestep that. The second is we don't
successfully deal with devices that can only do 32-bit DMA.
This patch series deals with the first problem by adding a Kconfig option
allowing platforms to relocate to the top of the last discovered bank.
It's worth noting that this is easily testable with QEMU
qemu-system-aarch64 -m 8192 -smp 2 -nographic -cpu cortex-a57 \
-machine virt,secure=off \
-bios u-boot.bin \
-device virtio-rng-pci \
-drive id=os,if=none,file="$image" \
-device virtio-blk-device,drive=os \
-object memory-backend-ram,id=ram0,size=4G \
-object memory-backend-ram,id=ram1,size=4G \
-numa node,memdev=ram0 \
-numa node,memdev=ram1
# RELOC_ADDR_TOP not set
Hit any key to stop autoboot: 0
=> bdinfo
[...]
relocaddr = 0x000000013f66c000
reloc off = 0x000000013f66c000
[...]
lmb_dump_all:
memory.count = 0x1
memory[0] [0x40000000-0x23fffffff], 0x200000000 bytes, flags: none
reserved.count = 0x2
reserved[0] [0x13d507000-0x13d509fff], 0x3000 bytes, flags: no-notify, no-overwrite
reserved[1] [0x13d50aff0-0x23fffffff], 0x102af5010 bytes, flags: no-overwrite
devicetree = board
[...]
TLB addr = 0x000000013ffe0000
irq_sp = 0x000000013e50aff0
sp start = 0x000000013e50aff0
Early malloc usage: e88 / 2000
=>
# RELOC_ADDR_TOP enabled
=> bdinfo
[...]
relocaddr = 0x000000023f66c000
reloc off = 0x000000023f66c000
[...]
lmb_dump_all:
memory.count = 0x1
memory[0] [0x40000000-0x23fffffff], 0x200000000 bytes, flags: none
reserved.count = 0x2
reserved[0] [0x23d507000-0x23d509fff], 0x3000 bytes, flags: no-notify, no-overwrite
reserved[1] [0x23d50aff0-0x23fffffff], 0x2af5010 bytes, flags: no-overwrite
devicetree = board
[...]
TLB addr = 0x000000023ffe0000
irq_sp = 0x000000023e50aff0
sp start = 0x000000023e50aff0
Early malloc usage: e88 / 2000
=>
[0] https://lore.kernel.org/u-boot/CAC_iWjKFAzpj3B_MEW7-dnOrcAV-rfkhXXo8Bv0KgLNP2VJxRA@mail.gmail.com/
Link: https://lore.kernel.org/r/[email protected]
Diffstat (limited to 'common')
| -rw-r--r-- | common/board_f.c | 71 | ||||
| -rw-r--r-- | common/init/handoff.c | 10 |
2 files changed, 56 insertions, 25 deletions
diff --git a/common/board_f.c b/common/board_f.c index fdb3577fec0..85b888d4bb8 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -31,6 +31,7 @@ #include <log.h> #include <malloc.h> #include <mapmem.h> +#include <memtop.h> #include <os.h> #include <post.h> #include <relocate.h> @@ -50,6 +51,7 @@ #include <dm/root.h> #include <linux/errno.h> #include <linux/log2.h> +#include <linux/sizes.h> DECLARE_GLOBAL_DATA_PTR; @@ -222,11 +224,11 @@ static int show_dram_config(void) debug("\nRAM Configuration:\n"); for (i = size = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - size += gd->bd->bi_dram[i].size; + size += gd->dram[i].size; debug("Bank #%d: %llx ", i, - (unsigned long long)(gd->bd->bi_dram[i].start)); + (unsigned long long)(gd->dram[i].start)); #ifdef DEBUG - print_size(gd->bd->bi_dram[i].size, "\n"); + print_size(gd->dram[i].size, "\n"); #endif } debug("\nDRAM: "); @@ -244,8 +246,8 @@ static int show_dram_config(void) __weak int dram_init_banksize(void) { - gd->bd->bi_dram[0].start = gd->ram_base; - gd->bd->bi_dram[0].size = get_effective_memsize(); + gd->dram[0].start = gd->ram_base; + gd->dram[0].size = get_effective_memsize(); return 0; } @@ -308,6 +310,9 @@ __weak int mach_cpu_init(void) /* Get the top of usable RAM */ __weak phys_addr_t board_get_usable_ram_top(phys_size_t total_size) { + if (CONFIG_IS_ENABLED(RELOC_ADDR_TOP)) + return gd->ram_top; + #if defined(CFG_SYS_SDRAM_BASE) && CFG_SYS_SDRAM_BASE > 0 /* * Detect whether we have so much RAM that it goes past the end of our @@ -328,16 +333,34 @@ __weak int arch_setup_dest_addr(void) return 0; } -static int setup_dest_addr(void) +static int setup_ram_base(void) { - int ret; +#ifdef CFG_SYS_SDRAM_BASE + gd->ram_base = CFG_SYS_SDRAM_BASE; +#endif + return 0; +} +static int setup_ram_config(void) +{ debug("Monitor len: %08x\n", gd->mon_len); - /* - * Ram is setup, size stored in gd !! - */ - debug("Ram size: %08llX\n", (unsigned long long)gd->ram_size); -#if CONFIG_VAL(SYS_MEM_TOP_HIDE) + + if (CONFIG_IS_ENABLED(RELOC_ADDR_TOP)) { + int i; + phys_addr_t top; + + gd->ram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + top = get_mem_top(gd->dram[i].start, gd->dram[i].size, + ALIGN(gd->mon_len, SZ_1M), + (void *)gd->fdt_blob); + gd->ram_top = max(top, gd->ram_top); + gd->ram_size += gd->dram[i].size; + } + } else { + gd->ram_top = gd->ram_base + get_effective_memsize(); + } + gd->ram_top = board_get_usable_ram_top(gd->mon_len); /* * Subtract specified amount of memory to hide so that it won't * get "touched" at all by U-Boot. By fixing up gd->ram_size @@ -348,15 +371,23 @@ static int setup_dest_addr(void) * memory size from the SDRAM controller setup will have to * get fixed. */ +#if CONFIG_VAL(SYS_MEM_TOP_HIDE) + gd->ram_top -= CONFIG_SYS_MEM_TOP_HIDE; gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE; #endif -#ifdef CFG_SYS_SDRAM_BASE - gd->ram_base = CFG_SYS_SDRAM_BASE; -#endif - gd->ram_top = gd->ram_base + get_effective_memsize(); - gd->ram_top = board_get_usable_ram_top(gd->mon_len); + + debug("Ram top: %08llx\n", (unsigned long long)gd->ram_top); + debug("Ram size: %08llx\n", (unsigned long long)gd->ram_size); + + return 0; +} + +static int setup_dest_addr(void) +{ + int ret; + gd->relocaddr = gd->ram_top; - debug("Ram top: %08llX\n", (unsigned long long)gd->ram_top); + debug("Reloc addr: %08llX\n", (unsigned long long)gd->relocaddr); ret = arch_setup_dest_addr(); if (ret) @@ -977,6 +1008,9 @@ static void initcall_run_f(void) * - monitor code * - board info struct */ + INITCALL(setup_ram_base); + INITCALL(dram_init_banksize); + INITCALL(setup_ram_config); INITCALL(setup_dest_addr); #if CONFIG_IS_ENABLED(OF_BOARD_FIXUP) && \ !CONFIG_IS_ENABLED(OF_INITIAL_DTB_READONLY) @@ -1004,7 +1038,6 @@ static void initcall_run_f(void) INITCALL(reserve_bloblist); INITCALL(reserve_arch); INITCALL(reserve_stacks); - INITCALL(dram_init_banksize); INITCALL(show_dram_config); WATCHDOG_RESET(); INITCALL(setup_bdinfo); diff --git a/common/init/handoff.c b/common/init/handoff.c index a7cd065fb38..a4d9d14393b 100644 --- a/common/init/handoff.c +++ b/common/init/handoff.c @@ -12,14 +12,13 @@ DECLARE_GLOBAL_DATA_PTR; void handoff_save_dram(struct spl_handoff *ho) { - struct bd_info *bd = gd->bd; int i; ho->ram_size = gd->ram_size; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - ho->ram_bank[i].start = bd->bi_dram[i].start; - ho->ram_bank[i].size = bd->bi_dram[i].size; + ho->ram_bank[i].start = gd->dram[i].start; + ho->ram_bank[i].size = gd->dram[i].size; } } @@ -30,11 +29,10 @@ void handoff_load_dram_size(struct spl_handoff *ho) void handoff_load_dram_banks(struct spl_handoff *ho) { - struct bd_info *bd = gd->bd; int i; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - bd->bi_dram[i].start = ho->ram_bank[i].start; - bd->bi_dram[i].size = ho->ram_bank[i].size; + gd->dram[i].start = ho->ram_bank[i].start; + gd->dram[i].size = ho->ram_bank[i].size; } } |
