[U-Boot] [PATCH v4 2/4] arm: support Thumb-1 with CONFIG_SYS_THUMB_BUILD

Albert ARIBAUD albert.u.boot at aribaud.net
Mon Jul 6 13:48:25 CEST 2015


On Sun,  5 Jul 2015 17:13:45 +0200, Albert ARIBAUD <albert.u.boot at 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 at 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 v4: None
> Changes in v3:
> - added arch/arm/lib/mem{set,cpy}.S to the list of modules
>   which should always be built in ARM state.
> - Selected HAS_THUMB2 for CPU_V7M.
> - Fixed invalidate_l2_cache() when building for Thumb-1.
> 
> 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                               |  5 ++
>  arch/arm/cpu/arm926ejs/Makefile                | 11 ++++
>  arch/arm/cpu/arm926ejs/cache.c                 |  5 ++
>  arch/arm/include/asm/cache.h                   |  4 ++
>  arch/arm/lib/Makefile                          | 24 +++++++++
>  arch/arm/lib/cache.c                           | 11 ++++
>  arch/arm/lib/memcpy.S                          |  4 +-
>  arch/arm/lib/memset.S                          |  2 +-
>  arch/arm/mach-orion5x/Makefile                 | 10 ++++
>  arch/arm/thumb1/include/asm/proc-armv/system.h | 69 ++++++++++++++++++++++++++
>  examples/standalone/Makefile                   | 10 ++++
>  scripts/Makefile.lib                           |  3 +-
>  13 files changed, 156 insertions(+), 4 deletions(-)
>  create mode 100644 arch/arm/thumb1/include/asm/proc-armv/system.h
> 
> diff --git a/Makefile b/Makefile
> index 37cc4c3..dc881fa 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -606,6 +606,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 0829235..906afd0 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,9 +35,11 @@ config CPU_ARM1176
>  config CPU_V7
>          bool
>          select HAS_VBAR
> +        select HAS_THUMB2
>  
>  config CPU_V7M
>  	bool
> +        select HAS_THUMB2
>  
>  config CPU_PXA
>          bool
> diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
> index 63fa159..fe78922 100644
> --- a/arch/arm/cpu/arm926ejs/Makefile
> +++ b/arch/arm/cpu/arm926ejs/Makefile
> @@ -20,3 +20,14 @@ obj-$(CONFIG_MX25) += mx25/
>  obj-$(CONFIG_MX27) += mx27/
>  obj-$(if $(filter mxs,$(SOC)),y) += mxs/
>  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/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c
> index 8d7873c..f12e365 100644
> --- a/arch/arm/cpu/arm926ejs/cache.c
> +++ b/arch/arm/cpu/arm926ejs/cache.c
> @@ -99,4 +99,9 @@ void flush_cache(unsigned long start, unsigned long size)
>  /*
>   * Stub implementations for l2 cache operations
>   */
> +
>  __weak void l2_cache_disable(void) {}
> +
> +#if defined CONFIG_SYS_THUMB_BUILD
> +__weak void invalidate_l2_cache(void) {}
> +#endif
> diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
> index a836e9f..1f63127 100644
> --- a/arch/arm/include/asm/cache.h
> +++ b/arch/arm/include/asm/cache.h
> @@ -16,6 +16,9 @@
>  /*
>   * Invalidate L2 Cache using co-proc instruction
>   */
> +#ifdef CONFIG_SYS_THUMB_BUILD
> +void invalidate_l2_cache(void);
> +#else
>  static inline void invalidate_l2_cache(void)
>  {
>  	unsigned int val=0;
> @@ -24,6 +27,7 @@ static inline void invalidate_l2_cache(void)
>  		: : "r" (val) : "cc");
>  	isb();
>  }
> +#endif
>  
>  void l2_cache_enable(void);
>  void l2_cache_disable(void);
> diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
> index 9a631d1..4272d2f 100644
> --- a/arch/arm/lib/Makefile
> +++ b/arch/arm/lib/Makefile
> @@ -60,3 +60,27 @@ 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
> +
> +# for C files, just apend -marm, which will override previous -mthumb*
> +
> +CFLAGS_cache.o := -marm
> +CFLAGS_cache-cp15.o := -marm
> +
> +# For .S, drop -mthumb* and other thumb-related options.
> +# CFLAGS_REMOVE_* would not have an effet, so AFLAGS_REMOVE_*
> +# was implemented and is used here.
> +# Also, define ${target}_NO_THUMB_BUILD for these two targets
> +# so that the code knows it should not use Thumb.
> +
> +AFLAGS_REMOVE_memset.o := -mthumb -mthumb-interwork
> +AFLAGS_REMOVE_memcpy.o := -mthumb -mthumb-interwork
> +AFLAGS_memset.o := -DMEMSET_NO_THUMB_BUILD
> +AFLAGS_memcpy.o := -DMEMCPY_NO_THUMB_BUILD
> +
> +endif
> +endif
> diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
> index 74cfde6..7c8878d 100644
> --- a/arch/arm/lib/cache.c
> +++ b/arch/arm/lib/cache.c
> @@ -95,3 +95,14 @@ phys_addr_t noncached_alloc(size_t size, size_t align)
>  	return next;
>  }
>  #endif /* CONFIG_SYS_NONCACHED_MEMORY */
> +
> +#if defined(CONFIG_SYS_THUMB_BUILD)
> +void invalidate_l2_cache(void)
> +{
> +	unsigned int val = 0;
> +
> +	asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache"
> +		: : "r" (val) : "cc");
> +	isb();
> +}
> +#endif
> diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
> index ffaee74..409d5f7 100644
> --- a/arch/arm/lib/memcpy.S
> +++ b/arch/arm/lib/memcpy.S
> @@ -13,7 +13,7 @@
>  #include <linux/linkage.h>
>  #include <asm/assembler.h>
>  
> -#ifdef CONFIG_SYS_THUMB_BUILD
> +#if defined(CONFIG_SYS_THUMB_BUILD) && !defined(MEMCPY_NO_THUMB_BUILD)
>  #define W(instr)	instr.w
>  #else
>  #define W(instr)	instr
> @@ -62,7 +62,7 @@
>  
>  /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
>  	.syntax unified
> -#ifdef CONFIG_SYS_THUMB_BUILD
> +#if defined(CONFIG_SYS_THUMB_BUILD) && !defined(MEMCPY_NO_THUMB_BUILD)
>  	.thumb
>  	.thumb_func
>  #endif
> diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
> index 49bdff7..b586055 100644
> --- a/arch/arm/lib/memset.S
> +++ b/arch/arm/lib/memset.S
> @@ -16,7 +16,7 @@
>  	.align	5
>  
>  	.syntax unified
> -#ifdef CONFIG_SYS_THUMB_BUILD
> +#if defined(CONFIG_SYS_THUMB_BUILD) && !defined(MEMSET_NO_THUMB_BUILD)
>  	.thumb
>  	.thumb_func
>  #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 at 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/scripts/Makefile.lib b/scripts/Makefile.lib
> index 8731fc6..3d5c872 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -104,8 +104,9 @@ modname_flags  = $(if $(filter 1,$(words $(modname))),\
>  orig_c_flags   = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
>                   $(ccflags-y) $(CFLAGS_$(basetarget).o)
>  _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
> -_a_flags       = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
> +orig_a_flags   = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
>                   $(asflags-y) $(AFLAGS_$(basetarget).o)
> +_a_flags       = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags))
>  _cpp_flags     = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
>  
>  #
> -- 
> 2.1.0
> 

Applied to u-boot-arm/master.

Amicalement,
-- 
Albert.


More information about the U-Boot mailing list