summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2019-01-04 12:10:20 +0300
committerStefano Babic <sbabic@denx.de>2019-01-28 22:35:47 +0300
commit528915c71762cb46fdad4f355931d04bb06f21b7 (patch)
tree062f6245ceb50e95a9332fd05dd96727e2a48728 /arch
parent11a1c27eb454ece04ca4e61f0ea1ab4ebaafa5b5 (diff)
downloadu-boot-528915c71762cb46fdad4f355931d04bb06f21b7.tar.xz
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.c32
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;
+ }
+}