From 7210e457d5d166b4409bde402fd95a99e87cdfc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:38 +0200 Subject: [PATCH 01/12] common/memsize.c: Fix get_effective_memsize() to always check for CONFIG_MAX_MEM_MAPPED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONFIG_MAX_MEM_MAPPED when defined specifies upper memory mapped limit. So check for it always, and not only when CONFIG_VERY_BIG_RAM is defined. Signed-off-by: Pali Rohár --- common/memsize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/memsize.c b/common/memsize.c index d5d13d51bf..31884acca0 100644 --- a/common/memsize.c +++ b/common/memsize.c @@ -94,7 +94,7 @@ long get_ram_size(long *base, long maxsize) phys_size_t __weak get_effective_memsize(void) { -#ifndef CONFIG_VERY_BIG_RAM +#ifndef CONFIG_MAX_MEM_MAPPED return gd->ram_size; #else /* limit stack to what we can reasonable map */ From 777aaaa706bcfe08c284aed06886db7d482af3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:39 +0200 Subject: [PATCH 02/12] common/memsize.c: Fix get_effective_memsize() to check for overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure that top of RAM can be represented by phys_size_t type. If RAM is too large or RAM base address is too upper then limit RAM size to prevent address space overflow. Signed-off-by: Pali Rohár --- common/memsize.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/common/memsize.c b/common/memsize.c index 31884acca0..3c80ad2c83 100644 --- a/common/memsize.c +++ b/common/memsize.c @@ -94,11 +94,23 @@ long get_ram_size(long *base, long maxsize) phys_size_t __weak get_effective_memsize(void) { + phys_size_t ram_size = gd->ram_size; + + /* + * Check for overflow and limit ram size to some representable value. + * It is required that ram_base + ram_size must be representable by + * phys_size_t type and must be aligned by direct access, therefore + * calculate it from last 4kB sector which should work as alignment + * on any platform. + */ + if (gd->ram_base + ram_size < gd->ram_base) + ram_size = ((phys_size_t)~0xfffULL) - gd->ram_base; + #ifndef CONFIG_MAX_MEM_MAPPED - return gd->ram_size; + return ram_size; #else /* limit stack to what we can reasonable map */ - return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ? - CONFIG_MAX_MEM_MAPPED : gd->ram_size); + return ((ram_size > CONFIG_MAX_MEM_MAPPED) ? + CONFIG_MAX_MEM_MAPPED : ram_size); #endif } From 049704f808d5e643668a33a76e55f925d4c1b36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:40 +0200 Subject: [PATCH 03/12] board_f: Fix types for board_get_usable_ram_top() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 37dc958947ed ("global_data.h: Change ram_top type to phys_addr_t") changed type of ram_top member from ulong to phys_addr_t but did not changed types in board_get_usable_ram_top() function which returns value for ram_top. So change ulong to phys_addr_t type also in board_get_usable_ram_top() signature and implementations. Fixes: 37dc958947ed ("global_data.h: Change ram_top type to phys_addr_t") Signed-off-by: Pali Rohár Reviewed-by: Simon Glass --- arch/arm/mach-imx/imx8m/soc.c | 2 +- arch/arm/mach-mvebu/arm64-common.c | 2 +- arch/arm/mach-rockchip/sdram.c | 2 +- arch/arm/mach-stm32mp/dram_init.c | 2 +- arch/arm/mach-sunxi/board.c | 2 +- arch/arm/mach-tegra/board2.c | 2 +- arch/mips/mach-jz47xx/jz4780/jz4780.c | 2 +- arch/mips/mach-octeon/dram.c | 2 +- arch/riscv/cpu/fu540/dram.c | 2 +- arch/riscv/cpu/fu740/dram.c | 2 +- arch/riscv/cpu/generic/dram.c | 2 +- arch/x86/cpu/broadwell/sdram.c | 2 +- arch/x86/cpu/coreboot/sdram.c | 2 +- arch/x86/cpu/efi/payload.c | 2 +- arch/x86/cpu/efi/sdram.c | 2 +- arch/x86/cpu/intel_common/mrc.c | 4 ++-- arch/x86/cpu/ivybridge/sdram.c | 2 +- arch/x86/cpu/qemu/dram.c | 2 +- arch/x86/cpu/quark/dram.c | 2 +- arch/x86/cpu/slimbootloader/sdram.c | 2 +- arch/x86/cpu/tangier/sdram.c | 2 +- arch/x86/include/asm/mrc_common.h | 2 +- arch/x86/include/asm/u-boot-x86.h | 2 +- arch/x86/lib/fsp1/fsp_dram.c | 2 +- arch/x86/lib/fsp2/fsp_dram.c | 2 +- board/broadcom/bcmns3/ns3.c | 2 +- board/imgtec/boston/ddr.c | 2 +- board/menlo/m53menlo/m53menlo.c | 2 +- board/raspberrypi/rpi/rpi.c | 2 +- board/ti/am65x/evm.c | 2 +- board/ti/j721e/evm.c | 2 +- board/ti/j721s2/evm.c | 2 +- board/xilinx/common/board.c | 2 +- common/board_f.c | 2 +- include/init.h | 2 +- 35 files changed, 36 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index d115b25a5b..47c0a4f5c4 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -327,7 +327,7 @@ phys_size_t get_effective_memsize(void) } } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { ulong top_addr; diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c index 238edbe6ba..63f6af5fe8 100644 --- a/arch/arm/mach-mvebu/arm64-common.c +++ b/arch/arm/mach-mvebu/arm64-common.c @@ -30,7 +30,7 @@ DECLARE_GLOBAL_DATA_PTR; */ #define USABLE_RAM_SIZE 0x80000000ULL -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { unsigned long top = CONFIG_SYS_SDRAM_BASE + min(gd->ram_size, USABLE_RAM_SIZE); diff --git a/arch/arm/mach-rockchip/sdram.c b/arch/arm/mach-rockchip/sdram.c index 705ec7ba64..12f1d7ee56 100644 --- a/arch/arm/mach-rockchip/sdram.c +++ b/arch/arm/mach-rockchip/sdram.c @@ -205,7 +205,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { unsigned long top = CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE; diff --git a/arch/arm/mach-stm32mp/dram_init.c b/arch/arm/mach-stm32mp/dram_init.c index 920b99bb68..9346fa8546 100644 --- a/arch/arm/mach-stm32mp/dram_init.c +++ b/arch/arm/mach-stm32mp/dram_init.c @@ -40,7 +40,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { phys_size_t size; phys_addr_t reg; diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 8f7c894286..62bb40b8c8 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -65,7 +65,7 @@ static struct mm_region sunxi_mem_map[] = { }; struct mm_region *mem_map = sunxi_mem_map; -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { /* Some devices (like the EMAC) have a 32-bit DMA limit. */ if (gd->ram_top > (1ULL << 32)) diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 8950e678a6..1994db0e15 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -401,7 +401,7 @@ int dram_init_banksize(void) * This function is called before dram_init_banksize(), so we can't simply * return gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { ulong ram_top; diff --git a/arch/mips/mach-jz47xx/jz4780/jz4780.c b/arch/mips/mach-jz47xx/jz4780/jz4780.c index fefba12873..a57ec7802b 100644 --- a/arch/mips/mach-jz47xx/jz4780/jz4780.c +++ b/arch/mips/mach-jz47xx/jz4780/jz4780.c @@ -76,7 +76,7 @@ void board_init_f(ulong dummy) } #endif /* CONFIG_SPL_BUILD */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return CONFIG_SYS_SDRAM_BASE + (256 * 1024 * 1024); } diff --git a/arch/mips/mach-octeon/dram.c b/arch/mips/mach-octeon/dram.c index 4679260f17..9c5789b1c8 100644 --- a/arch/mips/mach-octeon/dram.c +++ b/arch/mips/mach-octeon/dram.c @@ -77,7 +77,7 @@ phys_size_t get_effective_memsize(void) return UBOOT_RAM_SIZE_MAX; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { if (IS_ENABLED(CONFIG_RAM_OCTEON)) { /* Map a maximum of 256MiB - return not size but address */ diff --git a/arch/riscv/cpu/fu540/dram.c b/arch/riscv/cpu/fu540/dram.c index 1fdc7837b8..44e11bd56c 100644 --- a/arch/riscv/cpu/fu540/dram.c +++ b/arch/riscv/cpu/fu540/dram.c @@ -21,7 +21,7 @@ int dram_init_banksize(void) return fdtdec_setup_memory_banksize(); } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { /* * Ensure that we run from first 4GB so that all diff --git a/arch/riscv/cpu/fu740/dram.c b/arch/riscv/cpu/fu740/dram.c index 1dc77efeca..d6d4a41d25 100644 --- a/arch/riscv/cpu/fu740/dram.c +++ b/arch/riscv/cpu/fu740/dram.c @@ -20,7 +20,7 @@ int dram_init_banksize(void) return fdtdec_setup_memory_banksize(); } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { #ifdef CONFIG_64BIT /* diff --git a/arch/riscv/cpu/generic/dram.c b/arch/riscv/cpu/generic/dram.c index 1fdc7837b8..44e11bd56c 100644 --- a/arch/riscv/cpu/generic/dram.c +++ b/arch/riscv/cpu/generic/dram.c @@ -21,7 +21,7 @@ int dram_init_banksize(void) return fdtdec_setup_memory_banksize(); } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { /* * Ensure that we run from first 4GB so that all diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c index c104a849a5..1295121ae5 100644 --- a/arch/x86/cpu/broadwell/sdram.c +++ b/arch/x86/cpu/broadwell/sdram.c @@ -25,7 +25,7 @@ #include #include -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return mrc_common_board_get_usable_ram_top(total_size); } diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index 4a256bad44..f4ee4cdf5d 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -27,7 +27,7 @@ unsigned int install_e820_map(unsigned int max_entries, * address, and how far U-Boot is moved by relocation are set in the global * data structure. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { uintptr_t dest_addr = 0; int i; diff --git a/arch/x86/cpu/efi/payload.c b/arch/x86/cpu/efi/payload.c index b7778565b1..1c28a43778 100644 --- a/arch/x86/cpu/efi/payload.c +++ b/arch/x86/cpu/efi/payload.c @@ -27,7 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; * the relocation address, and how far U-Boot is moved by relocation are * set in the global data structure. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { struct efi_mem_desc *desc, *end; struct efi_entry_memmap *map; diff --git a/arch/x86/cpu/efi/sdram.c b/arch/x86/cpu/efi/sdram.c index af65982fd0..f3086db42c 100644 --- a/arch/x86/cpu/efi/sdram.c +++ b/arch/x86/cpu/efi/sdram.c @@ -11,7 +11,7 @@ DECLARE_GLOBAL_DATA_PTR; -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return (ulong)efi_get_ram_base() + gd->ram_size; } diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c index a97b0b7ceb..a4918fbad6 100644 --- a/arch/x86/cpu/intel_common/mrc.c +++ b/arch/x86/cpu/intel_common/mrc.c @@ -25,7 +25,7 @@ static const char *const ecc_decoder[] = { "active" }; -ulong mrc_common_board_get_usable_ram_top(ulong total_size) +phys_size_t mrc_common_board_get_usable_ram_top(phys_size_t total_size) { struct memory_info *info = &gd->arch.meminfo; uintptr_t dest_addr = 0; @@ -50,7 +50,7 @@ ulong mrc_common_board_get_usable_ram_top(ulong total_size) dest_addr = largest->start + largest->size; - return (ulong)dest_addr; + return (phys_size_t)dest_addr; } void mrc_common_dram_init_banksize(void) diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index dd6b8753de..1a0ec433e6 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -44,7 +44,7 @@ DECLARE_GLOBAL_DATA_PTR; #define CMOS_OFFSET_MRC_SEED_S3 156 #define CMOS_OFFSET_MRC_SEED_CHK 160 -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return mrc_common_board_get_usable_ram_top(total_size); } diff --git a/arch/x86/cpu/qemu/dram.c b/arch/x86/cpu/qemu/dram.c index c174550129..595c397d4a 100644 --- a/arch/x86/cpu/qemu/dram.c +++ b/arch/x86/cpu/qemu/dram.c @@ -71,7 +71,7 @@ int dram_init_banksize(void) * the relocation address, and how far U-Boot is moved by relocation are * set in the global data structure. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return qemu_get_low_memory_size(); } diff --git a/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c index 2287dce12b..8b1ee2d5ae 100644 --- a/arch/x86/cpu/quark/dram.c +++ b/arch/x86/cpu/quark/dram.c @@ -184,7 +184,7 @@ int dram_init_banksize(void) * the relocation address, and how far U-Boot is moved by relocation are * set in the global data structure. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return gd->ram_size; } diff --git a/arch/x86/cpu/slimbootloader/sdram.c b/arch/x86/cpu/slimbootloader/sdram.c index c6f10e22e3..d748d5c7d4 100644 --- a/arch/x86/cpu/slimbootloader/sdram.c +++ b/arch/x86/cpu/slimbootloader/sdram.c @@ -48,7 +48,7 @@ static struct sbl_memory_map_info *get_memory_map_info(void) * @total_size: The memory size that u-boot occupies * Return: : The top available memory address lower than 4GB */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { struct sbl_memory_map_info *data; int i; diff --git a/arch/x86/cpu/tangier/sdram.c b/arch/x86/cpu/tangier/sdram.c index afb08476ed..8a4b1c5d2d 100644 --- a/arch/x86/cpu/tangier/sdram.c +++ b/arch/x86/cpu/tangier/sdram.c @@ -204,7 +204,7 @@ unsigned int install_e820_map(unsigned int max_entries, * address, and how far U-Boot is moved by relocation are set in the global * data structure. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { struct sfi_table_simple *sb; struct sfi_mem_entry *mentry; diff --git a/arch/x86/include/asm/mrc_common.h b/arch/x86/include/asm/mrc_common.h index 3d7f00c9f9..a7f260a707 100644 --- a/arch/x86/include/asm/mrc_common.h +++ b/arch/x86/include/asm/mrc_common.h @@ -47,7 +47,7 @@ int mrc_add_memory_area(struct memory_info *info, uint64_t start, * the relocation address, and how far U-Boot is moved by relocation are * set in the global data structure. */ -ulong mrc_common_board_get_usable_ram_top(ulong total_size); +phys_size_t mrc_common_board_get_usable_ram_top(phys_size_t total_size); void mrc_common_dram_init_banksize(void); diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index a1655e1cea..4cf41e9354 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -77,7 +77,7 @@ int x86_cleanup_before_linux(void); void x86_enable_caches(void); void x86_disable_caches(void); int x86_init_cache(void); -ulong board_get_usable_ram_top(ulong total_size); +phys_size_t board_get_usable_ram_top(phys_size_t total_size); int default_print_cpuinfo(void); /* Set up a UART which can be used with printch(), printhex8(), etc. */ diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index cfd9b9f48c..5825221d1e 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -34,7 +34,7 @@ int dram_init(void) * the relocation address, and how far U-Boot is moved by relocation are * set in the global data structure. */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return fsp_get_usable_lowmem_top(gd->arch.hob_list); } diff --git a/arch/x86/lib/fsp2/fsp_dram.c b/arch/x86/lib/fsp2/fsp_dram.c index 42d3892b76..f9ea1ab3ba 100644 --- a/arch/x86/lib/fsp2/fsp_dram.c +++ b/arch/x86/lib/fsp2/fsp_dram.c @@ -77,7 +77,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { if (!ll_boot_init()) return gd->ram_size; diff --git a/board/broadcom/bcmns3/ns3.c b/board/broadcom/bcmns3/ns3.c index 88036c16c9..26652e8f77 100644 --- a/board/broadcom/bcmns3/ns3.c +++ b/board/broadcom/bcmns3/ns3.c @@ -183,7 +183,7 @@ int dram_init_banksize(void) } /* Limit RAM used by U-Boot to the DDR first bank End region */ -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { return BCM_NS3_MEM_END; } diff --git a/board/imgtec/boston/ddr.c b/board/imgtec/boston/ddr.c index 182f79b918..5b245cb447 100644 --- a/board/imgtec/boston/ddr.c +++ b/board/imgtec/boston/ddr.c @@ -23,7 +23,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { DECLARE_GLOBAL_DATA_PTR; diff --git a/board/menlo/m53menlo/m53menlo.c b/board/menlo/m53menlo/m53menlo.c index 61ab3844b8..4afc5aaa43 100644 --- a/board/menlo/m53menlo/m53menlo.c +++ b/board/menlo/m53menlo/m53menlo.c @@ -42,7 +42,7 @@ DECLARE_GLOBAL_DATA_PTR; static u32 mx53_dram_size[2]; -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { /* * WARNING: We must override get_effective_memsize() function here diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 17b8108cc8..00afb352bd 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -335,7 +335,7 @@ static void set_fdt_addr(void) /* * Prevent relocation from stomping on a firmware provided FDT blob. */ -unsigned long board_get_usable_ram_top(unsigned long total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { if ((gd->ram_top - fw_dtb_pointer) > SZ_64M) return gd->ram_top; diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index 8a0a506a3e..34ec3915f3 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -61,7 +61,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { #ifdef CONFIG_PHYS_64BIT /* Limit RAM used by U-Boot to the DDR low region */ diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c index 5d090048ce..d6e431ead0 100644 --- a/board/ti/j721e/evm.c +++ b/board/ti/j721e/evm.c @@ -57,7 +57,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { #ifdef CONFIG_PHYS_64BIT /* Limit RAM used by U-Boot to the DDR low region */ diff --git a/board/ti/j721s2/evm.c b/board/ti/j721s2/evm.c index 3c75ecfc0f..e09adc8ad3 100644 --- a/board/ti/j721s2/evm.c +++ b/board/ti/j721s2/evm.c @@ -46,7 +46,7 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { #ifdef CONFIG_PHYS_64BIT /* Limit RAM used by U-Boot to the DDR low region */ diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index e1f7104960..391ce4dbd7 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -631,7 +631,7 @@ int embedded_dtb_select(void) #endif #if defined(CONFIG_LMB) -ulong board_get_usable_ram_top(ulong total_size) +phys_size_t board_get_usable_ram_top(phys_size_t total_size) { phys_size_t size; phys_addr_t reg; diff --git a/common/board_f.c b/common/board_f.c index f92d7b9faf..aee3f56d67 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -305,7 +305,7 @@ __weak int mach_cpu_init(void) } /* Get the top of usable RAM */ -__weak ulong board_get_usable_ram_top(ulong total_size) +__weak phys_size_t board_get_usable_ram_top(phys_size_t total_size) { #if defined(CONFIG_SYS_SDRAM_BASE) && CONFIG_SYS_SDRAM_BASE > 0 /* diff --git a/include/init.h b/include/init.h index 02bb4ce13e..50a8302dc5 100644 --- a/include/init.h +++ b/include/init.h @@ -291,7 +291,7 @@ int show_board_info(void); * * @param total_size Size of U-Boot (unused?) */ -ulong board_get_usable_ram_top(ulong total_size); +phys_size_t board_get_usable_ram_top(phys_size_t total_size); int board_early_init_f(void); From d92aee57eca089e6732a5c3c79c3a319819e1bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:41 +0200 Subject: [PATCH 04/12] board_f: Fix printing gd->ram_size and gd->ram_top MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Members gd->ram_size and gd->ram_top are of type phys_addr_t which does not have to fit into ulong type. So cast them into unsigned long long. Fixes: 37dc958947ed ("global_data.h: Change ram_top type to phys_addr_t") Signed-off-by: Pali Rohár Reviewed-by: Simon Glass --- common/board_f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/board_f.c b/common/board_f.c index aee3f56d67..970c8ff67f 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -328,7 +328,7 @@ static int setup_dest_addr(void) /* * Ram is setup, size stored in gd !! */ - debug("Ram size: %08lX\n", (ulong)gd->ram_size); + debug("Ram size: %08llX\n", (unsigned long long)gd->ram_size); #if CONFIG_VAL(SYS_MEM_TOP_HIDE) /* * Subtract specified amount of memory to hide so that it won't @@ -348,7 +348,7 @@ static int setup_dest_addr(void) gd->ram_top = gd->ram_base + get_effective_memsize(); gd->ram_top = board_get_usable_ram_top(gd->mon_len); gd->relocaddr = gd->ram_top; - debug("Ram top: %08lX\n", (ulong)gd->ram_top); + debug("Ram top: %08llX\n", (unsigned long long)gd->ram_top); #if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) /* * We need to make sure the location we intend to put secondary core From cf4eba4eb66dbf6102200af6ba6f1ee05fabfe3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:42 +0200 Subject: [PATCH 05/12] ddr: fsl: Fix checking for maximal mappable memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check needs to be done against CONFIG_MAX_MEM_MAPPED macro and not fixed size 4GB (as CONFIG_MAX_MEM_MAPPED can be lower and for example for e500 cores it is just 2GB). Also fix printf re-align, which should be applied only for non-SPL builds, during init_dram() call. Signed-off-by: Pali Rohár --- drivers/ddr/fsl/main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index 1903562ac4..020adb0abb 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -857,13 +857,22 @@ phys_size_t __fsl_ddr_sdram(fsl_ddr_info_t *pinfo) debug("total_memory by %s = %llu\n", __func__, total_memory); #if !defined(CONFIG_PHYS_64BIT) - /* Check for 4G or more. Bad. */ - if ((first_ctrl == 0) && (total_memory >= (1ull << 32))) { + /* Check for more than max memory. Bad. */ + if ((first_ctrl == 0) && (total_memory > CONFIG_MAX_MEM_MAPPED)) { puts("Detected "); print_size(total_memory, " of memory\n"); - printf(" This U-Boot only supports < 4G of DDR\n"); - printf(" You could rebuild it with CONFIG_PHYS_64BIT\n"); - printf(" "); /* re-align to match init_dram print */ +#ifndef CONFIG_SPL_BUILD + puts(" "); /* re-align to match init_dram print */ +#endif + puts("This U-Boot only supports <= "); + print_size(CONFIG_MAX_MEM_MAPPED, " of DDR\n"); +#ifndef CONFIG_SPL_BUILD + puts(" "); /* re-align to match init_dram print */ +#endif + puts("You could rebuild it with CONFIG_PHYS_64BIT\n"); +#ifndef CONFIG_SPL_BUILD + puts(" "); /* re-align to match init_dram print */ +#endif total_memory = CONFIG_MAX_MEM_MAPPED; } #endif From 922460be0b72b40cae52f5e870d38c90b609b64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:43 +0200 Subject: [PATCH 06/12] ddr: fsl: Fix fsl_ddr_sdram_size() for 4GB modules with 32-bit phys_size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function fsl_ddr_compute() always return size in unsigned long long type, but function fsl_ddr_sdram_size() returns size in phys_size_t type. When 36-bit addressing mode is not enabled then phys_size_t type is only 32-bit and thus it cannot store value 4GB (0x100000000). Function fsl_ddr_sdram_size() in this case returns truncated value 0x0. Fix this issue by returning the highest representable value, which is 0xffffffff (4GB - 1 byte). This change fixes crashing of proper U-Boot because it detected 4 GB module as RAM with zero size. Signed-off-by: Pali Rohár --- drivers/ddr/fsl/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index 020adb0abb..d44f16cdba 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -950,5 +950,9 @@ fsl_ddr_sdram_size(void) /* Compute it once normally. */ total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); + /* Ensure that total_memory does not overflow on return */ + if (total_memory > (phys_size_t)~0ULL) + total_memory = (phys_size_t)~0ULL; + return total_memory; } From 272199765412182f82ff789eaeffb2d93d70a01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:44 +0200 Subject: [PATCH 07/12] ddr: fsl: Allow to detect 4 GB DDR modules in 32-bit mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U-Boot core code already handles the case when RAM size is bigger than CONFIG_MAX_MEM_MAPPED. So there is no need to do duplicate check in fsl ddr driver for CONFIG_MAX_MEM_MAPPED. Instead simplify code to just check if RAM size can be representable in phys_size_t type. And avoid printing warning if phys_size_t is just 1 byte smaller than RAM size, which is the typical situation with 4 GB DDR module. Signed-off-by: Pali Rohár --- drivers/ddr/fsl/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index d44f16cdba..ed3313a531 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -857,15 +857,18 @@ phys_size_t __fsl_ddr_sdram(fsl_ddr_info_t *pinfo) debug("total_memory by %s = %llu\n", __func__, total_memory); #if !defined(CONFIG_PHYS_64BIT) - /* Check for more than max memory. Bad. */ - if ((first_ctrl == 0) && (total_memory > CONFIG_MAX_MEM_MAPPED)) { + /* + * Show warning about big DDR moodules. But avoid warning for 4 GB DDR + * modules when U-Boot supports RAM of maximal size 4 GB - 1 byte. + */ + if ((first_ctrl == 0) && (total_memory - 1 > (phys_size_t)~0ULL)) { puts("Detected "); print_size(total_memory, " of memory\n"); #ifndef CONFIG_SPL_BUILD puts(" "); /* re-align to match init_dram print */ #endif puts("This U-Boot only supports <= "); - print_size(CONFIG_MAX_MEM_MAPPED, " of DDR\n"); + print_size((unsigned long long)((phys_size_t)~0ULL)+1, " of DDR\n"); #ifndef CONFIG_SPL_BUILD puts(" "); /* re-align to match init_dram print */ #endif @@ -873,10 +876,13 @@ phys_size_t __fsl_ddr_sdram(fsl_ddr_info_t *pinfo) #ifndef CONFIG_SPL_BUILD puts(" "); /* re-align to match init_dram print */ #endif - total_memory = CONFIG_MAX_MEM_MAPPED; } #endif + /* Ensure that total_memory does not overflow on return */ + if (total_memory > (phys_size_t)~0ULL) + total_memory = (phys_size_t)~0ULL; + return total_memory; } From a86e294f9f072dd08410ef83af44258503dca1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:45 +0200 Subject: [PATCH 08/12] ddr: fsl: Fix re-align of verbose DRAM information for non-SPL builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During init_dram() is called also compute_lowest_common_dimm_parameters() function which prints multi-line detailed output. So print also re-aligning filler after "Detected ?DIMM" line to have "DRAM: " output aligned. Signed-off-by: Pali Rohár --- drivers/ddr/fsl/lc_common_dimm_params.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c index d738ae3a7c..5e4ad56f07 100644 --- a/drivers/ddr/fsl/lc_common_dimm_params.c +++ b/drivers/ddr/fsl/lc_common_dimm_params.c @@ -422,6 +422,9 @@ compute_lowest_common_dimm_parameters(const unsigned int ctrl_num, dimm_params[i].mpart); #endif } +#ifndef CONFIG_SPL_BUILD + puts(" "); +#endif } } From eec715e30f4e4c6afe1bc441f9c7682e9e5bac62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 9 Sep 2022 17:32:46 +0200 Subject: [PATCH 09/12] powerpc/mpc85xx: Explain TLB unmapped memory message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently U-Boot SPL prints just generic message "2 GiB left unmapped". Change it to more detailed "2 GiB of DDR memory left unmapped in U-Boot". This is just U-Boot configuration and operating system may map more (or also less) memory. Signed-off-by: Pali Rohár --- arch/powerpc/cpu/mpc85xx/tlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/cpu/mpc85xx/tlb.c b/arch/powerpc/cpu/mpc85xx/tlb.c index ab616497fa..4e4ecb4d7f 100644 --- a/arch/powerpc/cpu/mpc85xx/tlb.c +++ b/arch/powerpc/cpu/mpc85xx/tlb.c @@ -312,7 +312,7 @@ unsigned int setup_ddr_tlbs_phys(phys_addr_t p_addr, if (size || memsize > CONFIG_MAX_MEM_MAPPED) { print_size(memsize > CONFIG_MAX_MEM_MAPPED ? memsize - CONFIG_MAX_MEM_MAPPED + size : size, - " left unmapped\n"); + " of DDR memory left unmapped in U-Boot\n"); } return memsize_in_meg; From 6f915a5d24b1c8cf30a29d7edff01eb5951bef0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Sun, 11 Sep 2022 11:29:16 +0200 Subject: [PATCH 10/12] powerpc/mpc85xx: Fix re-align of unmapped DDR memory message for non-SPL builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During init_dram() is called also setup_ddr_tlbs_phys() function which may print message about unmapped DDR memory. So in this case print also re-aligning filler after unmapped DDR memory message. Signed-off-by: Pali Rohár --- arch/powerpc/cpu/mpc85xx/tlb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/cpu/mpc85xx/tlb.c b/arch/powerpc/cpu/mpc85xx/tlb.c index 4e4ecb4d7f..e39fe14382 100644 --- a/arch/powerpc/cpu/mpc85xx/tlb.c +++ b/arch/powerpc/cpu/mpc85xx/tlb.c @@ -313,6 +313,9 @@ unsigned int setup_ddr_tlbs_phys(phys_addr_t p_addr, print_size(memsize > CONFIG_MAX_MEM_MAPPED ? memsize - CONFIG_MAX_MEM_MAPPED + size : size, " of DDR memory left unmapped in U-Boot\n"); +#ifndef CONFIG_SPL_BUILD + puts(" "); +#endif } return memsize_in_meg; From d179018e4c9561afac5ca5c8878852f1171b836b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 12 Sep 2022 21:02:27 +0200 Subject: [PATCH 11/12] display_options: print_size: Fix order overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function print_size() round size to the nearst value with one decimal fraction number. But in special cases also unit order may overflow. For example value 1073689396 is printed as "1024 MiB" and value 1073741824 as "1 GiB". Fix this issue by detecting order overflow and increasing unit order. With this change also value 1073689396 is printed as "1 GiB". Signed-off-by: Pali Rohár Reviewed-by: Simon Glass --- lib/display_options.c | 6 ++++++ test/lib/test_print.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/lib/display_options.c b/lib/display_options.c index 7feb446a55..80def5201f 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -127,6 +127,12 @@ void print_size(uint64_t size, const char *s) if (m >= 10) { m -= 10; n += 1; + + if (n == 1024 && i > 0) { + n = 1; + m = 0; + c = names[i - 1]; + } } } diff --git a/test/lib/test_print.c b/test/lib/test_print.c index a60a5a51f1..79b67c7793 100644 --- a/test/lib/test_print.c +++ b/test/lib/test_print.c @@ -68,6 +68,9 @@ static int lib_test_print_size(struct unit_test_state *uts) ut_assertok(test_print_size(uts, 7654321, "7.3 MiB;")); ut_assertok(test_print_size(uts, 87654321, "83.6 MiB;")); ut_assertok(test_print_size(uts, 987654321, "941.9 MiB;")); + ut_assertok(test_print_size(uts, 1073689395, "1023.9 MiB;")); + ut_assertok(test_print_size(uts, 1073689396, "1 GiB;")); + ut_assertok(test_print_size(uts, 1073741824, "1 GiB;")); ut_assertok(test_print_size(uts, 1987654321, "1.9 GiB;")); ut_assertok(test_print_size(uts, 54321987654321, "49.4 TiB;")); return 0; From 236f73962718511e801f4ec9562075e86f737ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Sun, 18 Sep 2022 13:23:27 +0200 Subject: [PATCH 12/12] board_f: show_dram_config: Print also real DRAM size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 32-bit U-Boot builds cannot use more than around 2 GB of DDR memory. But on some platforms/boards it is possible to connect also 4 GB SODIMM DDR memory. U-Boot currently prints only effective size of RAM which can use, which may be misleading as somebody would expect that this line prints total size of connected DDR modules. So change show_dram_config code to prints both real and effective DRAM size if they are different. If they are same then print just one number like before. It is possible that effective size is just few bytes smaller than the real size, so print both numbers only in case function print_size() prints formats them differently. Signed-off-by: Pali Rohár --- common/board_f.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/common/board_f.c b/common/board_f.c index 970c8ff67f..3df4efeeff 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -57,6 +57,7 @@ #include #include #include +#include /* * Pointer to initial global data area @@ -216,6 +217,36 @@ static int announce_dram_init(void) return 0; } +/* + * From input size calculate its nearest rounded unit scale (multiply of 2^10) + * and value in calculated unit scale multiplied by 10 (as fractional fixed + * point number with one decimal digit), which is human natural format, + * same what uses print_size() function for displaying. Mathematically it is: + * round_nearest(val * 2^scale) = size * 10; where: 10 <= val < 10240. + * + * For example for size=87654321 we calculate scale=20 and val=836 which means + * that input has natural human format 83.6 M (mega = 2^20). + */ +#define compute_size_scale_val(size, scale, val) do { \ + scale = ilog2(size) / 10 * 10; \ + val = (10 * size + ((1ULL << scale) >> 1)) >> scale; \ + if (val == 10240) { val = 10; scale += 10; } \ +} while (0) + +/* + * Check if the sizes in their natural units written in decimal format with + * one fraction number are same. + */ +static int sizes_near(unsigned long long size1, unsigned long long size2) +{ + unsigned int size1_scale, size1_val, size2_scale, size2_val; + + compute_size_scale_val(size1, size1_scale, size1_val); + compute_size_scale_val(size2, size2_scale, size2_val); + + return size1_scale == size2_scale && size1_val == size2_val; +} + static int show_dram_config(void) { unsigned long long size; @@ -232,7 +263,11 @@ static int show_dram_config(void) } debug("\nDRAM: "); - print_size(size, ""); + print_size(gd->ram_size, ""); + if (!sizes_near(gd->ram_size, size)) { + printf(" (effective "); + print_size(size, ")"); + } board_add_ram_info(0); putc('\n');