Merge branch '2022-09-23-4gb-ddr-in-32bit-ppc' into next

To quote the author, for the first 9 patches:
This patch series fixes U-Boot code to correctly handle RAM size larger
than 2 GB and then fixes fsl ddr driver to do not crash U-Boot when 4 GB
DDR module is detected when U-Boot operates in 32-bit mode (as opposite
of the 36-bit mode).

With this patch series it is possible to boot 32-bit U-Boot with 4 GB
SODIMM DDR3 module without crashes. U-Boot will still use just
CONFIG_MAX_MEM_MAPPED amount of RAM, but it is better than crashing due
to the truncating of 4GB value to 32-bit number (which is zero).

I tested this patch series on powerpc P2020 based board but only with
U-Boot v2022.04 because U-Boot master branch is still broken on P2020.

And then the final two patches here are (in my mind at least) related
clean-ups.
This commit is contained in:
Tom Rini 2022-09-23 18:42:53 -04:00
commit 694e900867
41 changed files with 131 additions and 50 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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))

View file

@ -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;

View file

@ -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);
}

View file

@ -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 */

View file

@ -312,7 +312,10 @@ 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");
#ifndef CONFIG_SPL_BUILD
puts(" ");
#endif
}
return memsize_in_meg;

View file

@ -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

View file

@ -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
/*

View file

@ -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

View file

@ -25,7 +25,7 @@
#include <asm/arch/pei_data.h>
#include <asm/arch/pm.h>
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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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. */

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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;

View file

@ -57,6 +57,7 @@
#include <asm/sections.h>
#include <dm/root.h>
#include <linux/errno.h>
#include <linux/log2.h>
/*
* 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');
@ -305,7 +340,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
/*
@ -328,7 +363,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 +383,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

View file

@ -94,11 +94,23 @@ long get_ram_size(long *base, long maxsize)
phys_size_t __weak get_effective_memsize(void)
{
#ifndef CONFIG_VERY_BIG_RAM
return gd->ram_size;
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 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
}

View file

@ -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
}
}

View file

@ -857,17 +857,32 @@ 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))) {
/*
* 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");
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 */
total_memory = CONFIG_MAX_MEM_MAPPED;
#ifndef CONFIG_SPL_BUILD
puts(" "); /* re-align to match init_dram print */
#endif
puts("This U-Boot only supports <= ");
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
puts("You could rebuild it with CONFIG_PHYS_64BIT\n");
#ifndef CONFIG_SPL_BUILD
puts(" "); /* re-align to match init_dram print */
#endif
}
#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;
}
@ -941,5 +956,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;
}

View file

@ -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);

View file

@ -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];
}
}
}

View file

@ -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;