diff mbox

libgcc erroneously built as armv5 for arm920t(armv4t)

Message ID 20131102163906.0b558177@skate
State Accepted
Headers show

Commit Message

Thomas Petazzoni Nov. 2, 2013, 3:39 p.m. UTC
Dear adam hussein\(!\),

On Thu, 26 Sep 2013 08:34:53 -0700 (PDT), adam hussein\(!\) wrote:

> I've been building the at91rm9200ek configuration of buildroot to get a toolchain I can use to build u-boot with some board specific configuration.
> 
> This is an ARM920T core chip with ARMv4T architecture  - later ARM9 series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)
> 
> When gcc is built, or perhaps specifically libgcc only, it seems the selection of 920t/v4 architecture gets lost and v5 is used instead.
> This means that when I use it to build u-boot, I find it has the __udivsi3 function using the illegal (to v4) instruction CLZ (count leading zeros).
> 
> The easiest workaround for me is to specify arm7tdmi and be done with it, but I'd like to try contributing a proper fix if possible.

Can you try the attached patch? Ideally, it would be nice if you could
try it with two configurations:

 * With the internal toolchain backend
 * With the Sourcery CodeBench 2013.05 external toolchain

and run it on real hardware.

Thanks a lot for your testing!

Thomas

Comments

Thomas Petazzoni Nov. 7, 2013, 7:31 p.m. UTC | #1
Adam,

Did you had the opportunity to test the proposed patch?

On Sat, 2 Nov 2013 16:39:06 +0100, Thomas Petazzoni wrote:
> Dear adam hussein\(!\),
> 
> On Thu, 26 Sep 2013 08:34:53 -0700 (PDT), adam hussein\(!\) wrote:
> 
> > I've been building the at91rm9200ek configuration of buildroot to get a toolchain I can use to build u-boot with some board specific configuration.
> > 
> > This is an ARM920T core chip with ARMv4T architecture  - later ARM9 series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)
> > 
> > When gcc is built, or perhaps specifically libgcc only, it seems the selection of 920t/v4 architecture gets lost and v5 is used instead.
> > This means that when I use it to build u-boot, I find it has the __udivsi3 function using the illegal (to v4) instruction CLZ (count leading zeros).
> > 
> > The easiest workaround for me is to specify arm7tdmi and be done with it, but I'd like to try contributing a proper fix if possible.
> 
> Can you try the attached patch? Ideally, it would be nice if you could
> try it with two configurations:
> 
>  * With the internal toolchain backend
>  * With the Sourcery CodeBench 2013.05 external toolchain
> 
> and run it on real hardware.
> 
> Thanks a lot for your testing!
> 
> Thomas
adam hussein\(!\) Nov. 21, 2013, 2:56 p.m. UTC | #2
Hi Thomas,

Sorry for going quiet for so long; a lot of change going on here.

Thanks for the patch; much tidier!

I'm
 not in a position to work on this board now, the project taking a 
different direction altogether; however, I have found time for a sneaky 
test of the patch using the internal toolchain, and it seems fine.

The objdump showing that udivsi3 no longer has CLZ instructions.

arm-buildroot-linux-uclibcgnueabi-objdump -d u-boot | grep "20126c1c:" -A 10
20126c1c:    e2512001     subs    r2, r1, #1
20126c20:    012fff1e     bxeq    lr
20126c24:    3a000036     bcc    20126d04 <__udivsi3+0xe8>
20126c28:    e1500001     cmp    r0, r1
20126c2c:    9a000022     bls    20126cbc <__udivsi3+0xa0>
20126c30:    e1110002     tst    r1, r2
20126c34:    0a000023     beq    20126cc8 <__udivsi3+0xac>
20126c38:    e311020e     tst    r1, #-536870912    ; 0xe0000000
20126c3c:    01a01181     lsleq    r1, r1, #3
20126c40:    03a03008     moveq    r3, #8
20126c44:    13a03001     movne    r3, #1

Selecting Sourcery CodeBench 2013.05 external toolchain had the buildroot make attempt end with:

  LD      vmlinux
  SYSMAP  System.map
  SYSMAP  .tmp_System.map
  OBJCOPY arch/arm/boot/Image
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head.o
arch/arm/boot/compressed/head.S: Assembler messages:
arch/arm/boot/compressed/head.S:936: Error: selected processor does not support ARM mode `clz r5,r4'

And using it for u-boot gave me:

arm-none-linux-gnueabi-objdump -d u-boot | grep "20126bc0:" -A 10
20126bc0:    e2512001     subs    r2, r1, #1
20126bc4:    012fff1e     bxeq    lr
20126bc8:    3a000074     bcc    20126da0 <__udivsi3+0x1e0>
20126bcc:    e1500001     cmp    r0, r1
20126bd0:    9a00006b     bls    20126d84 <__udivsi3+0x1c4>
20126bd4:    e1110002     tst    r1, r2
20126bd8:    0a00006c     beq    20126d90 <__udivsi3+0x1d0>
20126bdc:    e16f3f10     clz    r3, r0
20126be0:    e16f2f11     clz    r2, r1


I hope this tells you what you wanted to know, in spite of not being able to run on the hardware.


Adam





----- Original Message -----
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
To: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: adam hussein(!) <kryme76@yahoo.com>; "buildroot@busybox.net" <buildroot@busybox.net>
Sent: Thursday, November 7, 2013 7:31 PM
Subject: Re: [Buildroot] libgcc erroneously built as armv5 for arm920t(armv4t)

Adam,

Did you had the opportunity to test the proposed patch?


On Sat, 2 Nov 2013 16:39:06 +0100, Thomas Petazzoni wrote:
> Dear adam hussein\(!\),
> 
> On Thu, 26 Sep 2013 08:34:53 -0700 (PDT), adam hussein\(!\) wrote:
> 
> > I've been building the at91rm9200ek configuration of buildroot to get a toolchain I can use to build u-boot with some board specific configuration.
> > 
> > This is an ARM920T core chip with ARMv4T architecture  - later ARM9 series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)
> > 
> > When gcc is built, or perhaps specifically libgcc only, it seems the selection of 920t/v4 architecture gets lost and v5 is used instead.
> > This means that when I use it to build u-boot, I find it has the __udivsi3 function using the illegal (to v4) instruction CLZ (count leading zeros).
> > 
> > The easiest workaround for me is to specify arm7tdmi and be done with it, but I'd like to try contributing a proper fix if possible.
> 
> Can you try the attached patch? Ideally, it would be nice if you could
> try it with two configurations:
> 
>  * With the internal toolchain backend
>  * With the Sourcery CodeBench 2013.05 external toolchain
> 
> and run it on real hardware.
> 
> Thanks a lot for your testing!
> 
> Thomas
Thomas Petazzoni Nov. 21, 2013, 3:22 p.m. UTC | #3
Adam,

On Thu, 21 Nov 2013 06:56:10 -0800 (PST), adam hussein\(!\) wrote:

> Sorry for going quiet for so long; a lot of change going on here.

No problem.

> I'm
>  not in a position to work on this board now, the project taking a 
> different direction altogether; however, I have found time for a
> sneaky test of the patch using the internal toolchain, and it seems
> fine.
> 
> The objdump showing that udivsi3 no longer has CLZ instructions.
> 
> arm-buildroot-linux-uclibcgnueabi-objdump -d u-boot | grep
> "20126c1c:" -A 10 20126c1c:    e2512001     subs    r2, r1, #1
> 20126c20:    012fff1e     bxeq    lr
> 20126c24:    3a000036     bcc    20126d04 <__udivsi3+0xe8>
> 20126c28:    e1500001     cmp    r0, r1
> 20126c2c:    9a000022     bls    20126cbc <__udivsi3+0xa0>
> 20126c30:    e1110002     tst    r1, r2
> 20126c34:    0a000023     beq    20126cc8 <__udivsi3+0xac>
> 20126c38:    e311020e     tst    r1, #-536870912    ; 0xe0000000
> 20126c3c:    01a01181     lsleq    r1, r1, #3
> 20126c40:    03a03008     moveq    r3, #8
> 20126c44:    13a03001     movne    r3, #1

Ok, so that's with a Buildroot internal toolchain. Can you also try to
build the kernel with this toolchain to see if it's affected or not by
the below problem?

> Selecting Sourcery CodeBench 2013.05 external toolchain had the
> buildroot make attempt end with:
> 
>   LD      vmlinux
>   SYSMAP  System.map
>   SYSMAP  .tmp_System.map
>   OBJCOPY arch/arm/boot/Image
>   Kernel: arch/arm/boot/Image is ready
>   AS      arch/arm/boot/compressed/head.o
> arch/arm/boot/compressed/head.S: Assembler messages:
> arch/arm/boot/compressed/head.S:936: Error: selected processor does
> not support ARM mode `clz r5,r4'

Ok. I think this is a kernel bug actually. The head.S file is special
in that it contains instructions for ARMv5+, which an ARMv4t assembler
will not accept. But it should, because the code guarantees that the
ARMv5+ instructions will not be executed on ARMv4.

In order to ask the assembler to accept these instructions, the
following commit was made back in 2008:

  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/boot/compressed/Makefile?id=80cec14a83ad0ad109d822b3f3482a379bc481ba

However, it was reverted recently:

  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/boot/compressed/Makefile?id=da94a829305f1c217cfdf6771cb1faca0917e3b9

I am not sure how this last commit doesn't break your situation.

It would be interesting if you could confirm whether the kernel builds
or not with the Buildroot internal toolchain.

> And using it for u-boot gave me:
> 
> arm-none-linux-gnueabi-objdump -d u-boot | grep "20126bc0:" -A 10
> 20126bc0:    e2512001     subs    r2, r1, #1
> 20126bc4:    012fff1e     bxeq    lr
> 20126bc8:    3a000074     bcc    20126da0 <__udivsi3+0x1e0>
> 20126bcc:    e1500001     cmp    r0, r1
> 20126bd0:    9a00006b     bls    20126d84 <__udivsi3+0x1c4>
> 20126bd4:    e1110002     tst    r1, r2
> 20126bd8:    0a00006c     beq    20126d90 <__udivsi3+0x1d0>
> 20126bdc:    e16f3f10     clz    r3, r0
> 20126be0:    e16f2f11     clz    r2, r1

So in other words, you mean that this wouldn't work on the target
platform. Hum, weird. Is this a part of U-Boot implemented in assembly,
or something compiled from C ?

Can you give me the relevant informations to allow me to build the
kernel image and U-Boot image myself? Kernel version and configuration
file, U-Boot version and configuration, etc.

Thanks!

Thomas
adam hussein\(!\) Nov. 21, 2013, 4:07 p.m. UTC | #4
Hi Thomas,


>Ok, so that's with a Buildroot internal toolchain. Can you also try to
>build the kernel with this toolchain to see if it's affected or not by
>the below problem?

It was fine, just didn't think to mention it as was an exception of the Sourcery toolchain.

>Ok. I think this is a kernel bug actually. The head.S file is special
>in that it contains instructions for ARMv5+, which an ARMv4t assembler
>will not accept. But it should, because the code guarantees that the
>ARMv5+ instructions will not be executed on ARMv4.
>
>In order to ask the assembler to accept these instructions, the
>following commit was made back in 2008:
>
>  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/boot/compressed/Makefile?id=80cec14a83ad0ad109d822b3f3482a379bc481ba
>
>However, it was reverted recently:
>
>  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/boot/compressed/Makefile?id=da94a829305f1c217cfdf6771cb1faca0917e3b9
>
>I am not sure how this last commit doesn't break your situation.

Interesting stuff. It's building 2.6.38.6, which benefits only from the first commit.

>It would be interesting if you could confirm whether the kernel builds
>or not with the Buildroot internal toolchain.

As above, it built fine.

>> 20126bdc:    e16f3f10     clz    r3, r0
>> 20126be0:    e16f2f11     clz    r2, r1

>So in other words, you mean that this wouldn't work on the target
>platform. Hum, weird. Is this a part of U-Boot implemented in assembly,
>or something compiled from C ?

Yes indeed. My belief is that _udivsi3 was pulled in with CLZs intact from the libgcc built and distributed with the Sourcery toolchain, rather than rebuilding a 4T arch version for the occasion.
To be honest, I'm not sure if something like --sysroot can redirect this; I've never thought about it before.

>Can you give me the relevant informations to allow me to build the
>kernel image and U-Boot image myself? Kernel version and configuration
>file, U-Boot version and configuration, etc.

Sure. Didn't get far off making for the dev board it was based on, aside from memory tweaks to u-boot.
I'm building the buildroot-2013.08.1 archive with 'make at91rm9200df_defconfig'.
The u-boot clone is at commit 46ef4faed18196472eb95216b2f74c1397ecf024 from http://git.denx.de/u-boot.git.
Then:
    export PATH=$PATH:/data/at91rm9200/buildroot-2013.08.1/output/host/usr/bin/
    export CROSS_COMPILE=arm-buildroot-linux-uclibcgnueabi-
    make at91rm9200dvc_ram_config
    make
or:
    export PATH=$PATH:/data/at91rm9200/buildroot-2013.08.1-thomas2/output/host/opt/ext-toolchain/bin/
accordingly.

I used JTAG to pin-point that CLZ was the cause of failure, rather than myself!

Good luck,
Adam
Thomas Petazzoni Nov. 21, 2013, 4:12 p.m. UTC | #5
Adam,

On Thu, 21 Nov 2013 08:07:17 -0800 (PST), adam hussein\(!\) wrote:

> >Ok, so that's with a Buildroot internal toolchain. Can you also try to
> >build the kernel with this toolchain to see if it's affected or not by
> >the below problem?
> 
> It was fine, just didn't think to mention it as was an exception of the Sourcery toolchain.

Ok, thanks for the confirmation!

> >In order to ask the assembler to accept these instructions, the
> >following commit was made back in 2008:
> >
> >  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/boot/compressed/Makefile?id=80cec14a83ad0ad109d822b3f3482a379bc481ba
> >
> >However, it was reverted recently:
> >
> >  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/boot/compressed/Makefile?id=da94a829305f1c217cfdf6771cb1faca0917e3b9
> >
> >I am not sure how this last commit doesn't break your situation.
> 
> Interesting stuff. It's building 2.6.38.6, which benefits only from the first commit.

Ah, interesting.

> >So in other words, you mean that this wouldn't work on the target
> >platform. Hum, weird. Is this a part of U-Boot implemented in assembly,
> >or something compiled from C ?
> 
> Yes indeed. My belief is that _udivsi3 was pulled in with CLZs intact from the libgcc built and distributed with the Sourcery toolchain, rather than rebuilding a 4T arch version for the occasion.
> To be honest, I'm not sure if something like --sysroot can redirect this; I've never thought about it before.

The Sourcery toolchain has 3 sysroot: ARMv4, ARMv5, and ARMv7 Thumb2.
So if the proper -march=armv4t option is passed, it uses the ARMv4
sysroot.

> Sure. Didn't get far off making for the dev board it was based on, aside from memory tweaks to u-boot.
> I'm building the buildroot-2013.08.1 archive with 'make at91rm9200df_defconfig'.
> The u-boot clone is at commit 46ef4faed18196472eb95216b2f74c1397ecf024 from http://git.denx.de/u-boot.git.
> Then:
>     export PATH=$PATH:/data/at91rm9200/buildroot-2013.08.1/output/host/usr/bin/
>     export CROSS_COMPILE=arm-buildroot-linux-uclibcgnueabi-
>     make at91rm9200dvc_ram_config
>     make
> or:
>     export PATH=$PATH:/data/at91rm9200/buildroot-2013.08.1-thomas2/output/host/opt/ext-toolchain/bin/
> accordingly.

This is wrong. For external toolchains, you should *NOT* use the
compiler in host/opt/ext-toolchain/bin, but instead the compiler in
output/host/usr/bin. We create a toolchain wrapper which ensures that
the proper compiler flags are used. If you don't use this toolchain
wrapper, then it cannot work.

Have you been building both the kernel and u-boot outside of Buildroot?
Why not instruct Buildroot to build them instead?

Can you retry the external toolchain case, by using the compiler in
output/host/usr/bin instead?

Thanks!

Thomas
Yann E. MORIN Dec. 26, 2013, 9:57 p.m. UTC | #6
On 2013-11-02 16:39 +0100, Thomas Petazzoni spake thusly:
> Dear adam hussein\(!\),
> 
> On Thu, 26 Sep 2013 08:34:53 -0700 (PDT), adam hussein\(!\) wrote:
> 
> > I've been building the at91rm9200ek configuration of buildroot to get a toolchain I can use to build u-boot with some board specific configuration.
> > 
> > This is an ARM920T core chip with ARMv4T architecture  - later ARM9 series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)
> > 
> > When gcc is built, or perhaps specifically libgcc only, it seems the selection of 920t/v4 architecture gets lost and v5 is used instead.
> > This means that when I use it to build u-boot, I find it has the __udivsi3 function using the illegal (to v4) instruction CLZ (count leading zeros).
> > 
> > The easiest workaround for me is to specify arm7tdmi and be done with it, but I'd like to try contributing a proper fix if possible.
> 
> Can you try the attached patch? Ideally, it would be nice if you could
> try it with two configurations:
> 
>  * With the internal toolchain backend
>  * With the Sourcery CodeBench 2013.05 external toolchain
> 
> and run it on real hardware.
> 
> Thanks a lot for your testing!
> 
> Thomas
> -- 
> Thomas Petazzoni, CTO, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

> From d3dca38af037a96fe45f94a303775c4f29b022b4 Mon Sep 17 00:00:00 2001
> From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Date: Sat, 2 Nov 2013 16:32:48 +0100
> Subject: [PATCH] arch: use BR2_GCC_TARGET_CPU on ARM
> 
> Currently, the ARM Config.in logic specifies values for
> --with-arch/-march and --with-tune/-mtune, but not for
> --with-cpu/-mcpu. However, this causes problems on ARMv4, because
> specifying --with-arch=armv4t isn't enough to make gcc generate ARMv4
> code: one should also pass --with-cpu=<some ARMv4 CPU>.
> 
> Moreover, since Buildroot is generally designed to generate code
> specifically for the configured target, it makes sense to give our own
> --with-cpu/-mcpu value instead of relying on the default value used by
> gcc, and only do small optimizations with -mtune.
> 
> Reported-by: Adam Hussein <kryme76@yahoo.com>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>

Acked-by: "Yann E. MORIN" <yann.morin.1998@free.fr>

> ---
>  arch/Config.in.arm | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/Config.in.arm b/arch/Config.in.arm
> index c0fabb7..dd58744 100644
> --- a/arch/Config.in.arm
> +++ b/arch/Config.in.arm
> @@ -341,7 +341,7 @@ config BR2_ENDIAN
>  	default "LITTLE" if BR2_arm
>  	default "BIG"	 if BR2_armeb
>  
> -config BR2_GCC_TARGET_TUNE
> +config BR2_GCC_TARGET_CPU
>  	default "arm7tdmi"	if BR2_arm7tdmi
>  	default "arm7tdmi"	if BR2_arm720t
>  	default "arm7tdmi"	if BR2_arm740t
> -- 
> 1.8.1.2
> 

> _______________________________________________
> buildroot mailing list
> buildroot@busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
diff mbox

Patch

From d3dca38af037a96fe45f94a303775c4f29b022b4 Mon Sep 17 00:00:00 2001
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Date: Sat, 2 Nov 2013 16:32:48 +0100
Subject: [PATCH] arch: use BR2_GCC_TARGET_CPU on ARM

Currently, the ARM Config.in logic specifies values for
--with-arch/-march and --with-tune/-mtune, but not for
--with-cpu/-mcpu. However, this causes problems on ARMv4, because
specifying --with-arch=armv4t isn't enough to make gcc generate ARMv4
code: one should also pass --with-cpu=<some ARMv4 CPU>.

Moreover, since Buildroot is generally designed to generate code
specifically for the configured target, it makes sense to give our own
--with-cpu/-mcpu value instead of relying on the default value used by
gcc, and only do small optimizations with -mtune.

Reported-by: Adam Hussein <kryme76@yahoo.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 arch/Config.in.arm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/Config.in.arm b/arch/Config.in.arm
index c0fabb7..dd58744 100644
--- a/arch/Config.in.arm
+++ b/arch/Config.in.arm
@@ -341,7 +341,7 @@  config BR2_ENDIAN
 	default "LITTLE" if BR2_arm
 	default "BIG"	 if BR2_armeb
 
-config BR2_GCC_TARGET_TUNE
+config BR2_GCC_TARGET_CPU
 	default "arm7tdmi"	if BR2_arm7tdmi
 	default "arm7tdmi"	if BR2_arm720t
 	default "arm7tdmi"	if BR2_arm740t
-- 
1.8.1.2