diff options
author | Ye Li <ye.li@nxp.com> | 2019-01-04 09:10:20 +0000 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2019-01-28 20:35:47 +0100 |
commit | 528915c71762cb46fdad4f355931d04bb06f21b7 (patch) | |
tree | 062f6245ceb50e95a9332fd05dd96727e2a48728 /arch | |
parent | 11a1c27eb454ece04ca4e61f0ea1ab4ebaafa5b5 (diff) | |
download | u-boot-528915c71762cb46fdad4f355931d04bb06f21b7.tar.gz |
imx: Fix potential lmb memory overwritten by stack
At default, u-boot reserves the memory from SP - 4KB to DRAM end for
lmb in arch_lmb_reserve. So lmb won't allocate any memory from it.
But we found the 4K gap for SP is not enough now, because some FDT
updating operations are added in our u-boot before jumping to kernel,
which needs larger stack. This causes the lmb allocated memory is overwritten
by stack.
Fix the issue by implementing the board_lmb_reserve to reserve from
SP - 16KB to memory end for lmb.
Signed-off-by: Ye Li <ye.li@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/misc.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/misc.c b/arch/arm/mach-imx/misc.c index 1bb8c508de..31e95a9a28 100644 --- a/arch/arm/mach-imx/misc.c +++ b/arch/arm/mach-imx/misc.c @@ -9,6 +9,8 @@ #include <asm/io.h> #include <asm/mach-imx/regs-common.h> +DECLARE_GLOBAL_DATA_PTR; + /* 1 second delay should be plenty of time for block reset. */ #define RESET_MAX_TIMEOUT 1000000 @@ -71,3 +73,33 @@ int mxs_reset_block(struct mxs_register_32 *reg) return 0; } + +static ulong get_sp(void) +{ + ulong ret; + + asm("mov %0, sp" : "=r"(ret) : ); + return ret; +} + +void board_lmb_reserve(struct lmb *lmb) +{ + ulong sp, bank_end; + int bank; + + sp = get_sp(); + debug("## Current stack ends at 0x%08lx ", sp); + + /* adjust sp by 16K to be safe */ + sp -= 4096 << 2; + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (sp < gd->bd->bi_dram[bank].start) + continue; + bank_end = gd->bd->bi_dram[bank].start + + gd->bd->bi_dram[bank].size; + if (sp >= bank_end) + continue; + lmb_reserve(lmb, sp, bank_end - sp); + break; + } +} |