[U-Boot] [RFC] ARM: prevent misaligned array inits

Lucas Stach dev at lynxeye.de
Thu Oct 4 21:10:54 CEST 2012


Hi Albert,

Am Dienstag, den 02.10.2012, 20:46 +0200 schrieb Albert ARIBAUD:
> Under option -munaligned-access, gcc can perform local char
> or 16-bit array initializations using misaligned native
> accesses which will throw a data abort exception. Fix files
> where these array initializations were unneeded, and for
> files known to contain such initializations, enforce gcc
> option -mno-unaligned-access.
> 
> Signed-off-by: Albert ARIBAUD <albert.u.boot at aribaud.net>
> ---
> Please test this patch with gcc 4.7 on boards which do data aborts
> or resets due to misaligned accesses and report result to me.
> 
Although, as you know, I don't like the general direction in which this
is heading you get a

Tested-by: Lucas Stach <dev at lynxeye.de>

As it at least allows for a booting machine in various configurations on
my Colibri T20.

>  arch/arm/cpu/arm926ejs/orion5x/cpu.c |    4 +-
>  board/ti/omap2420h4/sys_info.c       |   24 ++++-----
>  common/Makefile                      |    3 ++
>  common/cmd_dfu.c                     |    2 +-
>  doc/README.arm-unaligned-accesses    |   95 ++++++++++++++++++++++++++++++++++
>  fs/fat/Makefile                      |    2 +
>  fs/ubifs/Makefile                    |    3 ++
>  lib/Makefile                         |    3 ++
>  8 files changed, 121 insertions(+), 15 deletions(-)
>  create mode 100644 doc/README.arm-unaligned-accesses
> 
> diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c
> index c3948d3..5a4775a 100644
> --- a/arch/arm/cpu/arm926ejs/orion5x/cpu.c
> +++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c
> @@ -194,8 +194,8 @@ u32 orion5x_device_rev(void)
>   */
>  int print_cpuinfo(void)
>  {
> -	char dev_str[] = "0x0000";
> -	char rev_str[] = "0x00";
> +	char dev_str[7]; /* room enough for 0x0000 plus null byte */
> +	char rev_str[5]; /* room enough for 0x00 plus null byte */
>  	char *dev_name = NULL;
>  	char *rev_name = NULL;
>  
> diff --git a/board/ti/omap2420h4/sys_info.c b/board/ti/omap2420h4/sys_info.c
> index a9f7241..b462aa5 100644
> --- a/board/ti/omap2420h4/sys_info.c
> +++ b/board/ti/omap2420h4/sys_info.c
> @@ -237,18 +237,18 @@ u32 wait_on_value(u32 read_bit_mask, u32 match_value, u32 read_addr, u32 bound)
>   *********************************************************************/
>  void display_board_info(u32 btype)
>  {
> -	char cpu_2420[] = "2420";   /* cpu type */
> -	char cpu_2422[] = "2422";
> -	char cpu_2423[] = "2423";
> -	char db_men[] = "Menelaus"; /* board type */
> -	char db_ip[] = "IP";
> -	char mem_sdr[] = "mSDR";    /* memory type */
> -	char mem_ddr[] = "mDDR";
> -	char t_tst[] = "TST";	    /* security level */
> -	char t_emu[] = "EMU";
> -	char t_hs[] = "HS";
> -	char t_gp[] = "GP";
> -	char unk[] = "?";
> +	char *cpu_2420 = "2420";   /* cpu type */
> +	char *cpu_2422 = "2422";
> +	char *cpu_2423 = "2423";
> +	char *db_men = "Menelaus"; /* board type */
> +	char *db_ip = "IP";
> +	char *mem_sdr = "mSDR";    /* memory type */
> +	char *mem_ddr = "mDDR";
> +	char *t_tst = "TST";	    /* security level */
> +	char *t_emu = "EMU";
> +	char *t_hs = "HS";
> +	char *t_gp = "GP";
> +	char *unk = "?";
>  
>  	char *cpu_s, *db_s, *mem_s, *sec_s;
>  	u32 cpu, rev, sec;
> diff --git a/common/Makefile b/common/Makefile
> index 125b2be..19b2130 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -227,6 +227,9 @@ $(obj)env_embedded.o: $(src)env_embedded.c $(obj)../tools/envcrc
>  $(obj)../tools/envcrc:
>  	$(MAKE) -C ../tools
>  
> +$(obj)hush.o: CFLAGS += -mno-unaligned-access
> +$(obj)fdt_support.o: CFLAGS += -mno-unaligned-access
> +
>  #########################################################################
>  
>  # defines $(obj).depend target
> diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
> index 62fb890..01d6b3a 100644
> --- a/common/cmd_dfu.c
> +++ b/common/cmd_dfu.c
> @@ -30,7 +30,7 @@
>  static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  {
>  	const char *str_env;
> -	char s[] = "dfu";
> +	char *s = "dfu";
>  	char *env_bkp;
>  	int ret;
>  
> diff --git a/doc/README.arm-unaligned-accesses b/doc/README.arm-unaligned-accesses
> new file mode 100644
> index 0000000..00fb1c0
> --- /dev/null
> +++ b/doc/README.arm-unaligned-accesses
> @@ -0,0 +1,95 @@
> +Since U-Boot runs on a variety of hardware, some only able to perform
> +unaligned accesses with a strong penalty, some unable to perform them
> +at all, the policy regarding unaligned accesses is to not perform any,
> +unless absolutely necessary because of hardware or standards.
> +
> +Also, on hardware which permits it, the core is configured to throw
> +data abort exceptions on unaligned accesses  in order to catch these
> +unallowed accesses as early as possible.
> +
> +Until version 4.7, the gcc default for performing unaligned accesses
> +(-mno-unaligned-access) is to emulate unaligned accesses using aligned
> +loads and stores plus shifts and masks. Emulated unaligned accesses
> +will not be caught by hardware. These accesses may be costly and may
> +be  actually unnecessary. In order to catch these accesses and remove
> +or optimize them, option -munaligned-access is explicitly set for all
> +versions of gcc which support it.
> +
> +From gcc 4.7 onward, the default for performing unaligned accesses
> +is to use unaligned native loads and stores (-munaligned-access),
> +because the cost of unaligned accesses has dropped. This should not
> +affect U-Boot's policy of controlling unaligned accesses, however the
> +compiler may generate uncontrolled unaligned on its own in at least
> +one known case: when declaring a local initialized char array, e.g.
> +
> +function foo()
> +{
> +	char buffer[] = "initial value";
> +/* or */
> +	char buffer[] = { 'i', 'n', 'i', 't', 0 };
> +	...
> +}
> +
> +Under -munaligned-accesses with optimizations on, this declaration
> +causes the compiler to generate native loads from the literal string
> +and native stores to the buffer, and the literal string alignment
> +cannot be controlled. If it is misaligned, then the core will throw
> +a data abort exception.
> +
> +Quite probably the same might happen for 16-bit array initializations
> +where the constant is aligned on a boundary which is a multiple of 2
> +but not of 4:
> +
> +function foo()
> +{
> +	u16 buffer[] = { 1, 2, 3 };
> +	...
> +}
> +
> +The long term solution to this issue is to add an option to gcc to
> +allow controlling the general alignment of data, including constant
> +initialization values.
> +
> +However this will only apply to the version of gcc which will have such
> +an option. For other versions, there are four workarounds:
> +
> +a) Enforce as a rule that array initializations as described above
> +   are forbidden. This is generally not acceptable as they are valid,
> +   and usual, C constructs. The only case where they could be rejected
> +   is when they actually equate to a const char* declaration, i.e. the
> +   array is initialized and never modified in the function's scope.
> +
> +b) Drop the requirement on unaligned accesses at least for ARMv7,
> +   i.e. do not throw a data abort exception upon unaligned accesses.
> +   But that will allow adding badly aligned code to U-Boot, only for
> +   it to fail when re-used with another, more strict, target, possibly
> +   once the bad code is already in mainline.
> +
> +c) Relax the -munified-access rule globally. This will prevent native
> +   unaligned accesses of course, but that will also hide any bug caused
> +   by a bad unaligned access, making it much harder to diagnose it. It
> +   is actually what already happens when building ARM targets with a
> +   pre-4.7 gcc, and it may actually already hide some bugs yet unseen
> +   until the target gets compiled with m-unaligned-access.
> +
> +d) Relax the -munified-access rule only for for files susceptible to
> +   the local initialized array issue. This minimizes the quantity of
> +   code which can hide unwanted misaligned accesses.
> +
> +Considering the rarity of actual occurrences (as of this writing, 5
> +files out of 7840 in U-Boot, or .3%, contain an initialized local char
> +array which cannot actually be replaced with a const char*), detection
> +if the issue in patches should not be asked from contributors.
> +
> +Luckily, detecting files susceptible to the issue can be automated
> +through a filter/regexp/script which would recognize local char array
> +initializations. Automated should err on the false positive side, for
> +instance flagging non-local arrays as if they were local if they cannot
> +be told apart.
> +
> +In any case, detection shall be informative only and shall not prevent
> +applying the patch.
> +
> +Upon a positive detection, either option -mno-unaligned-access is
> +applied (if not already) to the affected file(s), or if the array is a
> +hidden const char*, it should be replaced by one.
> diff --git a/fs/fat/Makefile b/fs/fat/Makefile
> index 9635d36..5c4a2aa 100644
> --- a/fs/fat/Makefile
> +++ b/fs/fat/Makefile
> @@ -39,6 +39,8 @@ all:	$(LIB) $(AOBJS)
>  $(LIB):	$(obj).depend $(OBJS)
>  	$(call cmd_link_o_target, $(OBJS))
>  
> +# SEE README.arm-unaligned-accesses
> +$(obj)file.o: CFLAGS += -mno-unaligned-access
>  
>  #########################################################################
>  
> diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
> index ccffe85..71c40f2 100644
> --- a/fs/ubifs/Makefile
> +++ b/fs/ubifs/Makefile
> @@ -42,6 +42,9 @@ all:	$(LIB) $(AOBJS)
>  $(LIB):	$(obj).depend $(OBJS)
>  	$(call cmd_link_o_target, $(OBJS))
>  
> +# SEE README.arm-unaligned-accesses
> +$(obj)super.o: CFLAGS += -mno-unaligned-access
> +
>  #########################################################################
>  
>  # defines $(obj).depend target
> diff --git a/lib/Makefile b/lib/Makefile
> index 45798de..44393ed 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -78,6 +78,9 @@ OBJS	:= $(addprefix $(obj),$(COBJS))
>  $(LIB):	$(obj).depend $(OBJS)
>  	$(call cmd_link_o_target, $(OBJS))
>  
> +# SEE README.arm-unaligned-accesses
> +$(obj)bzlib.o: CFLAGS += -mno-unaligned-access
> +
>  #########################################################################
>  
>  # defines $(obj).depend target




More information about the U-Boot mailing list