
Update:
On Mon, 27 Feb 2017 07:52:10 +0100, Albert ARIBAUD albert.u.boot@aribaud.net wrote:
Hello Tom,
On Sun, 26 Feb 2017 20:04:28 -0500, Tom Rini trini@konsulko.com wrote:
On Sun, Feb 26, 2017 at 04:29:32PM +0100, Albert ARIBAUD wrote:
The switch to private LIBGCC causes 'undefined instruction' exception in at least the Open-RD Ultimate and Client, and quite probably the Open-RD Base as well.
While debugging this issue, it appeared the switch to architecture-optimized memset and memcpy also causes the same exceptions.
Until a fix to private libgcc and architecture-optimized memcpy and memset is mainlined, disable their use in all openrd configurations.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net
Implementation wise, there's two big problems here. First, all of the code we're talking about is a direct drop-in from the kernel. So whatever is wrong here is a problem that the kernel itself can trigger, so needs sorting out and fixing. Second, do you have more details on how to recreate (or not recreate) these problems?
Second answer first: the easy way to reproduce this is to build for any Thumb-1 board and wait for memset, memcpy or a libgcc function to be called, which eventually results in an 'undefined instruction' trap. Then add the three CONFIG...=n lines in the board's config file, build, and see that the issue is gone. This is 100% reproducible.
First answer:
I've looked into a 'slow general fix' in parallel to this 'fast fix', starting with the memset case (and assuming the issue is common to the memcpy and libgcc cases.
The cause seems to stem from this:
for Thumb-1 boards, the arch/arm/lib/memset.S et al. are built for ARM state, due AFAIR to incompatibilities with the Thumb-1 instruction set.
apparently the 'ret lr' in arch/arm/lib/memset.S gets translated into a 'mov pc, lr' which, at least for ATMv5TE, is a simple branch, not an interworking branch.
consequently, upon return from the memset call, the CPU remains in ARM state while trying to execute Thumb-1 instructions.
ISTR there are gnu as, gcc or ldoptions to be passed to cause the 'ret lr' to be turned into a 'bx lr', but I could not find them yesterday.
The 'slow and more correct' fix consists in building the Linux and U-Boot source code for the Open-RD board and looking into what code the memset.S produces in Linux and what compiler/assembler options were passed to it (or digging into the memset, memcpy and libgcc of the GCC C compiler, but that's a bit less simple).
I dropped the Linux trail because it builds Kirkwood (not Orion, as I wrongly stated previously) with ARM instruction set rather than the Thumb-1 set U-Boot uses, so the issue will never appear in the kernel (it might possibly happen in userland code if that code uses a custom libgcc, which I consider quite improbable).
So I dug into the 'ret' pseudo-opcode, which is in fact a macro, introduced to produce the most adequate opcode for the exact ARM architecture; it is defined in arch/arm/include/asm/assembler.h. Currently, defining __ARM_ARCH_5TE__ causes 'ret lr' to be encoded as 'mov pc, lr' rather than the 'bx lr' which should work.
I will have access again to my Open-RD board later today; I will test if making 'ret' use 'bx' for ARMv5TE works, and also if the current Linux version of arch/arm/include/asm/assembler.h can be used with current U-Boot, but that would be a wider change.
Amicalement,