[U-Boot] [PATCH] arm: support Thumb-1 with CONFIG_SYS_THUMB_BUILD

When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD, some files fail to build, most of the time because they include mcr instructions, which only exist for Thumb-2.
Thos patch introduces a Kconfig option CONFIG_THUMB2 and uses it to select between Thumb-2 and ARM mode for the aforementioned files.
This code has been build-tested and run-tested on ED Mini V2, both with U-Boot and SPL.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net --- arch/arm/Kconfig | 4 ++++ arch/arm/cpu/arm926ejs/Makefile | 11 +++++++++++ arch/arm/cpu/arm926ejs/orion5x/Makefile | 10 ++++++++++ arch/arm/lib/Makefile | 11 +++++++++++ examples/standalone/Makefile | 10 ++++++++++ include/configs/edminiv2.h | 2 ++ 6 files changed, 48 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5eb1d03..264af8b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -10,6 +10,9 @@ config ARM64 config HAS_VBAR bool
+config HAS_THUMB2 + bool + config CPU_ARM720T bool
@@ -32,6 +35,7 @@ config CPU_ARM1176 config CPU_V7 bool select HAS_VBAR + select HAS_THUMB2
config CPU_PXA bool diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile index adcea9f..721b478 100644 --- a/arch/arm/cpu/arm926ejs/Makefile +++ b/arch/arm/cpu/arm926ejs/Makefile @@ -28,3 +28,14 @@ obj-$(CONFIG_ORION5X) += orion5x/ obj-$(CONFIG_PANTHEON) += pantheon/ obj-$(if $(filter spear,$(SOC)),y) += spear/ obj-$(CONFIG_ARCH_VERSATILE) += versatile/ + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cpu.o := -marm +CFLAGS_cache.o := -marm + +endif +endif diff --git a/arch/arm/cpu/arm926ejs/orion5x/Makefile b/arch/arm/cpu/arm926ejs/orion5x/Makefile index 546ebcb..33dcad4 100644 --- a/arch/arm/cpu/arm926ejs/orion5x/Makefile +++ b/arch/arm/cpu/arm926ejs/orion5x/Makefile @@ -16,3 +16,13 @@ obj-y += timer.o ifndef CONFIG_SKIP_LOWLEVEL_INIT obj-y += lowlevel_init.o endif + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cpu.o := -marm + +endif +endif diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index d74e4b8..4916f30 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -54,3 +54,14 @@ obj-$(CONFIG_DEBUG_LL) += debug.o ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS))) extra-y += eabi_compat.o endif + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cache.o := -marm +CFLAGS_cache-cp15.o := -marm + +endif +endif diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index 0863a8c..5a6ae00 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -73,3 +73,13 @@ $(obj)/%.srec: $(obj)/% FORCE $(obj)/%.bin: OBJCOPYFLAGS := -O binary $(obj)/%.bin: $(obj)/% FORCE $(call if_changed,objcopy) + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_stubs.o := -marm + +endif +endif diff --git a/include/configs/edminiv2.h b/include/configs/edminiv2.h index 70a698a..f07b0d9 100644 --- a/include/configs/edminiv2.h +++ b/include/configs/edminiv2.h @@ -12,6 +12,8 @@ #ifndef _CONFIG_EDMINIV2_H #define _CONFIG_EDMINIV2_H
+#define CONFIG_SYS_THUMB_BUILD + /* * Version number information */

Hi Albert,
On 01.02.2015 03:55, Albert ARIBAUD wrote:
When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD, some files fail to build, most of the time because they include mcr instructions, which only exist for Thumb-2.
Thos patch introduces a Kconfig option CONFIG_THUMB2 and uses it to select between Thumb-2 and ARM mode for the aforementioned files.
This code has been build-tested and run-tested on ED Mini V2, both with U-Boot and SPL.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net
Thanks. This helped me to get Thumb-1 working on the x600 (SPEAr600 with ARM926EJS). Where I some size constraints. So for this patch:
Tested-by: Stefan Roese sr@denx.de
But I have another Thumb-1 related problem. I'm also including UBIFS in my board. And this results in these errors:
{standard input}: Assembler messages: {standard input}:695: Error: selected processor does not support Thumb mode `mrs r2,cpsr' {standard input}:696: Error: unshifted register required -- `orr r1,r2,#128' {standard input}:697: Error: selected processor does not support Thumb mode `msr cpsr_c,r1' {standard input}:711: Error: selected processor does not support Thumb mode `msr cpsr_c,r2' {standard input}:766: Error: selected processor does not support Thumb mode `mrs r2,cpsr' {standard input}:767: Error: unshifted register required -- `orr r4,r2,#128' {standard input}:768: Error: selected processor does not support Thumb mode `msr cpsr_c,r4' {standard input}:782: Error: selected processor does not support Thumb mode `msr cpsr_c,r2' make[2]: *** [fs/ubifs/super.o] Error 1 ...
This is because the UBIFS code uses the atomic_foo() functions and the bitops functions. Which call the local_irq_foo() functions. And these include the "msr/mrs" instructions, which seem to be unsupported in Thumb-1, similar to the "mcr" instruction.
I've "solved" this problem by adding these lines to the UBIFS Makefile:
+# some files can only build in ARM or THUMB2, not THUMB1 +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 +CFLAGS_lpt.o := -marm +CFLAGS_lpt_commit.o := -marm +CFLAGS_super.o := -marm +CFLAGS_tnc.o := -marm +CFLAGS_tnc_misc.o := -marm +endif +endif
But I'm not really happy with this "solution".
Another option would be to remove all the irq_off/_on stuff from the atomic_foo() and the bitops functions. We are running in a single-threaded environment after all in U-Boot. So there should be no need for such synch mechanisms. But these files are copied from Linux. And I really don't like to make changes to these files.
And ideas / comments welcome.
BTW: You can easily test this on your ED Mini board as well by enabling UBI & UBIFS support. Then you also should see those errors.
Thanks, Stefan

Hello Stefan,
On Tue, 10 Feb 2015 14:36:35 +0100, Stefan Roese sr@denx.de wrote:
Hi Albert,
Another option would be to remove all the irq_off/_on stuff from the atomic_foo() and the bitops functions. We are running in a single-threaded environment after all in U-Boot. So there should be no need for such synch mechanisms. But these files are copied from Linux. And I really don't like to make changes to these files.
And ideas / comments welcome.
I have an idea, only moderately better, embodied in my V2 patch.
Basically, for Thumb-1 builds, I insert an include path which allows me to "intercept" includes of 'asm/proc-armv/system.h' and provide ad hoc definitions for local_* definitions.
Thanks, Stefan
Amicalement,

When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD, some files fail to build, most of the time because they include mcr instructions, which only exist for Thumb-2.
Thos patch introduces a Kconfig option CONFIG_THUMB2 and uses it to select between Thumb-2 and ARM mode for the aforementioned files.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net --- This patch has been build-tested and run-tested on ED Mini V2, above the "edmini: switch to SPL" patch, and found to reduce U-Boot size by 25% and SPL size by 14%... and to run fine. :)
This patch has also been tested against side effects on the non-Thumb wireless_space target. The binaries produced with and without ths patch were found to differ only by their version string.
Changes in v2: - fixed a typo in the commit message - added file arch/arm/thumb1/include/asm/proc-armv/system.h, which overrides arch/arm/include/asm/proc-armv/system.h when building for Thumb-1 and provides non-functional but Thumb-compilable IRQ and FIQ related macros and functions.
Makefile | 2 + arch/arm/Kconfig | 4 ++ arch/arm/cpu/arm926ejs/Makefile | 11 ++++ arch/arm/lib/Makefile | 11 ++++ arch/arm/mach-orion5x/Makefile | 10 ++++ arch/arm/thumb1/include/asm/proc-armv/system.h | 69 ++++++++++++++++++++++++++ examples/standalone/Makefile | 10 ++++ include/configs/edminiv2.h | 4 +- 8 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 arch/arm/thumb1/include/asm/proc-armv/system.h
diff --git a/Makefile b/Makefile index bd4abab..7dc9dc6 100644 --- a/Makefile +++ b/Makefile @@ -593,6 +593,8 @@ KBUILD_CFLAGS += $(KCFLAGS) UBOOTINCLUDE := \ -Iinclude \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ + $(if $(CONFIG_SYS_THUMB_BUILD), $(if $(CONFIG_HAS_THUMB2),, \ + -I$(srctree)/arch/$(ARCH)/thumb1/include),) \ -I$(srctree)/arch/$(ARCH)/include \ -include $(srctree)/include/linux/kconfig.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 820ba1c..35420ca 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -10,6 +10,9 @@ config ARM64 config HAS_VBAR bool
+config HAS_THUMB2 + bool + config CPU_ARM720T bool
@@ -32,6 +35,7 @@ config CPU_ARM1176 config CPU_V7 bool select HAS_VBAR + select HAS_THUMB2
config CPU_PXA bool diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile index f5944cc..090d64b 100644 --- a/arch/arm/cpu/arm926ejs/Makefile +++ b/arch/arm/cpu/arm926ejs/Makefile @@ -22,3 +22,14 @@ obj-$(CONFIG_MX27) += mx27/ obj-$(if $(filter mxs,$(SOC)),y) += mxs/ obj-$(CONFIG_PANTHEON) += pantheon/ obj-$(if $(filter spear,$(SOC)),y) += spear/ + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cpu.o := -marm +CFLAGS_cache.o := -marm + +endif +endif diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index da8ed72..a753bca 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -55,3 +55,14 @@ obj-$(CONFIG_DEBUG_LL) += debug.o ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS))) extra-y += eabi_compat.o endif + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cache.o := -marm +CFLAGS_cache-cp15.o := -marm + +endif +endif diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile index 546ebcb..33dcad4 100644 --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -16,3 +16,13 @@ obj-y += timer.o ifndef CONFIG_SKIP_LOWLEVEL_INIT obj-y += lowlevel_init.o endif + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cpu.o := -marm + +endif +endif diff --git a/arch/arm/thumb1/include/asm/proc-armv/system.h b/arch/arm/thumb1/include/asm/proc-armv/system.h new file mode 100644 index 0000000..7dfbf3d --- /dev/null +++ b/arch/arm/thumb1/include/asm/proc-armv/system.h @@ -0,0 +1,69 @@ +/* + * Thumb-1 drop-in for the linux/include/asm-arm/proc-armv/system.h + * + * (C) Copyright 2015 + * Albert ARIBAUD albert.u.boot@aribaud.net + * + * The original file does not build in Thumb mode. However, in U-Boot + * we don't use interrupt context, so we can redefine these as empty + * memory barriers, which makes Thumb-1 compiler happy. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Use the same macro name as linux/include/asm-arm/proc-armv/system.h + * here, so that if the original ever gets included after us, it won't + * try to re-redefine anything. + */ + +#ifndef __ASM_PROC_SYSTEM_H +#define __ASM_PROC_SYSTEM_H + +/* + * Redefine all original macros with static inline functions containing + * a simple memory barrier, so that they produce the same instruction + * ordering constraints as their original counterparts. + * We use static inline functions rather than macros so that we can tell + * the compiler to not complain about unused arguments. + */ + +static inline void local_irq_save( + unsigned long flags __attribute__((unused))) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +static inline void local_irq_enable(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +static inline void local_irq_disable(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +static inline void __stf(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +static inline void __clf(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +static inline void local_save_flags( + unsigned long flags __attribute__((unused))) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +static inline void local_irq_restore( + unsigned long flags __attribute__((unused))) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +#endif /* __ASM_PROC_SYSTEM_H */ diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index 0863a8c..5a6ae00 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -73,3 +73,13 @@ $(obj)/%.srec: $(obj)/% FORCE $(obj)/%.bin: OBJCOPYFLAGS := -O binary $(obj)/%.bin: $(obj)/% FORCE $(call if_changed,objcopy) + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_stubs.o := -marm + +endif +endif diff --git a/include/configs/edminiv2.h b/include/configs/edminiv2.h index 70a698a..112583b 100644 --- a/include/configs/edminiv2.h +++ b/include/configs/edminiv2.h @@ -12,6 +12,8 @@ #ifndef _CONFIG_EDMINIV2_H #define _CONFIG_EDMINIV2_H
+#define CONFIG_SYS_THUMB_BUILD + /* * Version number information */ @@ -203,7 +205,7 @@ /* * Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (1024 * 256) /* 256kB for malloc() */ +#define CONFIG_SYS_MALLOC_LEN (1024 * 1024) /* 1MB for malloc() */
/* * Other required minimal configurations

On Tue, 24 Feb 2015 14:53:36 +0100, Albert ARIBAUD albert.u.boot@aribaud.net wrote:
When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD,
- fixed a typo in the commit message
Drat. :/
If that version gets accepted, whoever commits it please s/THumb/Thumb/.
Amicalement,

Hello Albert,
On Tue, 24 Feb 2015 14:53:36 +0100, Albert ARIBAUD albert.u.boot@aribaud.net wrote:
When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD, some files fail to build, most of the time because they include mcr instructions, which only exist for Thumb-2.
Thos patch introduces a Kconfig option CONFIG_THUMB2 and uses it to select between Thumb-2 and ARM mode for the aforementioned files.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net
This patch has been build-tested and run-tested on ED Mini V2, above the "edmini: switch to SPL" patch, and found to reduce U-Boot size by 25% and SPL size by 14%... and to run fine. :)
This patch has also been tested against side effects on the non-Thumb wireless_space target. The binaries produced with and without ths patch were found to differ only by their version string.
Changes in v2:
- fixed a typo in the commit message
- added file arch/arm/thumb1/include/asm/proc-armv/system.h, which overrides arch/arm/include/asm/proc-armv/system.h when building for Thumb-1 and provides non-functional but Thumb-compilable IRQ and FIQ related macros and functions.
Ok, this does not fare as good as I have hoped, because there are also thumb1-unfrendly macros in arch/arm/include/asm/cache.h, this time with mcr and mrc instructions.
/me hates macros used as inline functions. :(
I cannot just replace the macros with empty inline functions as I did with arch/arm/include/asm/proc-armv/system.h, since this would cause cache to not work. :(
This leaves only one solution: when buildding for thumb1, replace the macros in cache.h with plain function prototypes, and provide simple ARM-state implementations for these. We'll lose a bit of performance as instead of a single mcr or mrc instruction, we'll have a call switching from Thumb to ARM state, the mcr/mrc instruction, and a return to Thumb state. Hopefully that won't hurt performance too much.
V3 in the works.
Amicalement,

Hi Albert,
On 25.02.2015 23:09, Albert ARIBAUD wrote:
On Tue, 24 Feb 2015 14:53:36 +0100, Albert ARIBAUD albert.u.boot@aribaud.net wrote:
When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD, some files fail to build, most of the time because they include mcr instructions, which only exist for Thumb-2.
Thos patch introduces a Kconfig option CONFIG_THUMB2 and uses it to select between Thumb-2 and ARM mode for the aforementioned files.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net
This patch has been build-tested and run-tested on ED Mini V2, above the "edmini: switch to SPL" patch, and found to reduce U-Boot size by 25% and SPL size by 14%... and to run fine. :)
This patch has also been tested against side effects on the non-Thumb wireless_space target. The binaries produced with and without ths patch were found to differ only by their version string.
Changes in v2:
- fixed a typo in the commit message
- added file arch/arm/thumb1/include/asm/proc-armv/system.h, which overrides arch/arm/include/asm/proc-armv/system.h when building for Thumb-1 and provides non-functional but Thumb-compilable IRQ and FIQ related macros and functions.
Ok, this does not fare as good as I have hoped, because there are also thumb1-unfrendly macros in arch/arm/include/asm/cache.h, this time with mcr and mrc instructions.
/me hates macros used as inline functions. :(
I cannot just replace the macros with empty inline functions as I did with arch/arm/include/asm/proc-armv/system.h, since this would cause cache to not work. :(
This leaves only one solution: when buildding for thumb1, replace the macros in cache.h with plain function prototypes, and provide simple ARM-state implementations for these. We'll lose a bit of performance as instead of a single mcr or mrc instruction, we'll have a call switching from Thumb to ARM state, the mcr/mrc instruction, and a return to Thumb state. Hopefully that won't hurt performance too much.
V3 in the works.
Any update on this?
Thanks, Stefan

Hello Stefan,
On Thu, 09 Apr 2015 11:22:27 +0200, Stefan Roese sr@denx.de wrote:
Hi Albert,
On 25.02.2015 23:09, Albert ARIBAUD wrote:
On Tue, 24 Feb 2015 14:53:36 +0100, Albert ARIBAUD albert.u.boot@aribaud.net wrote:
When building a THumb-1-only target with CONFIG_SYS_THUMB_BUILD, some files fail to build, most of the time because they include mcr instructions, which only exist for Thumb-2.
Thos patch introduces a Kconfig option CONFIG_THUMB2 and uses it to select between Thumb-2 and ARM mode for the aforementioned files.
Signed-off-by: Albert ARIBAUD albert.u.boot@aribaud.net
This patch has been build-tested and run-tested on ED Mini V2, above the "edmini: switch to SPL" patch, and found to reduce U-Boot size by 25% and SPL size by 14%... and to run fine. :)
This patch has also been tested against side effects on the non-Thumb wireless_space target. The binaries produced with and without ths patch were found to differ only by their version string.
Changes in v2:
- fixed a typo in the commit message
- added file arch/arm/thumb1/include/asm/proc-armv/system.h, which overrides arch/arm/include/asm/proc-armv/system.h when building for Thumb-1 and provides non-functional but Thumb-compilable IRQ and FIQ related macros and functions.
Ok, this does not fare as good as I have hoped, because there are also thumb1-unfrendly macros in arch/arm/include/asm/cache.h, this time with mcr and mrc instructions.
/me hates macros used as inline functions. :(
I cannot just replace the macros with empty inline functions as I did with arch/arm/include/asm/proc-armv/system.h, since this would cause cache to not work. :(
This leaves only one solution: when buildding for thumb1, replace the macros in cache.h with plain function prototypes, and provide simple ARM-state implementations for these. We'll lose a bit of performance as instead of a single mcr or mrc instruction, we'll have a call switching from Thumb to ARM state, the mcr/mrc instruction, and a return to Thumb state. Hopefully that won't hurt performance too much.
V3 in the works.
Any update on this?
I am just restarting on this right now.
Thanks, Stefan
Amicalement,
participants (2)
-
Albert ARIBAUD
-
Stefan Roese