When U-Boot/SPL is built using the Thumb instruction set the toolchain has a potential issue with weakly linked symbols. If a function has a weakly linked default implementation in C and a real implementation in assembly GCC is confused about the instruction set of the assembly implementation. As a result the assembly function that is built in ARM is executed as if it is Thumb. This results in a crash.
We need to investigate further to see if this is a toolchain issue or an issue with our usage of it. In the meanwhile, we can workaround the issue by having both the weakly linked alias and the real implementation in C. Signed-off-by: Aneesh V <ane...@ti.com> --- arch/arm/cpu/armv7/cpu.c | 4 ++- arch/arm/cpu/armv7/omap-common/hwinit-common.c | 25 ++++++++++++++++++++++++ arch/arm/cpu/armv7/omap-common/lowlevel_init.S | 4 +- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c index 662c496..3844556 100644 --- a/arch/arm/cpu/armv7/cpu.c +++ b/arch/arm/cpu/armv7/cpu.c @@ -37,8 +37,10 @@ #include <asm/cache.h> #include <asm/armv7.h> -void save_boot_params_default(u32 r0, u32 r1, u32 r2, u32 r3) +void __attribute__((naked)) save_boot_params_default(u32 r0, u32 r1, + u32 r2, u32 r3) { + asm volatile ("blx lr"); } void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index ab46bff..16dfbed 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -237,3 +237,28 @@ void enable_caches(void) dcache_enable(); } #endif + +/* + * This function is a wrapper to do_save_boot_params that does the + * real implementation of the functionality. 'do_save_boot_params()' is + * implemented in assembly because this is called very early in the boot + * when stack is not available. We had to wrap it around in this 'naked' + * C function because of a potential issue with the tool-chain. + * + * When U-Boot/SPL is built using the Thumb instruction set compiler + * potential issue with weakly linked symbols. If a function has a weakly + * linked default implementation in C and a real implementation in assembly + * GCC is confused about the instruction set of the assembly implementation + * As a result the assembly function that is built in ARM is executed as + * if it is Thumb. This results in a crash. The solution (or workaround) + * is to have both the weakly linked alias and the real implementation + * in C. + * + * This function runs without a valid stack. So, never try to use a stack + * or any other fancy stuff. + */ +void __attribute__((naked)) save_boot_params(u32 r0, u32 r1, u32 r2, u32 r4) +{ + asm volatile ("ldr r12, =do_save_boot_params"); + asm volatile ("bx r12"); +} diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S index 35f38ac..38ca054 100644 --- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S @@ -28,8 +28,8 @@ #include <asm/arch/omap.h> -.global save_boot_params -save_boot_params: +.global do_save_boot_params +do_save_boot_params: /* * See if the rom code passed pointer is valid: * It is not valid if it is not in non-secure SRAM -- 1.7.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot