summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6528ff0)
raw | patch | inline | side by side (parent: 6528ff0)
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | |
Tue, 9 Oct 2012 09:28:15 +0000 (09:28 +0000) | ||
committer | Tom Rini <trini@ti.com> | |
Mon, 15 Oct 2012 18:53:07 +0000 (11:53 -0700) |
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@aribaud.net>
[trini: Switch to usign call cc-option for -mno-unaligned-access as
Albert had done previously as that's really correct]
Signed-off-by: Tom Rini <trini@ti.com>
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@aribaud.net>
[trini: Switch to usign call cc-option for -mno-unaligned-access as
Albert had done previously as that's really correct]
Signed-off-by: Tom Rini <trini@ti.com>
arch/arm/cpu/arm926ejs/orion5x/cpu.c | patch | blob | history | |
arch/arm/cpu/armv7/config.mk | patch | blob | history | |
arch/arm/lib/interrupts.c | patch | blob | history | |
board/ti/omap2420h4/sys_info.c | patch | blob | history | |
common/Makefile | patch | blob | history | |
common/cmd_dfu.c | patch | blob | history | |
doc/README.arm-unaligned-accesses | [new file with mode: 0644] | patch | blob |
fs/fat/Makefile | patch | blob | history | |
fs/ubifs/Makefile | patch | blob | history | |
lib/Makefile | patch | blob | history |
index c3948d38f081ecf4c5f62b8a53d157d4023c22e2..5a4775ab6ff8d651a9b63952e9737333bd14adbd 100644 (file)
*/
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;
index 560c084dc96b54bb5f3dade758d2513c4b030894..9c3e2f3ce421e3e24013f013dac85085d74286a1 100644 (file)
# supported by more tool-chains
PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5)
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7)
-PF_CPPFLAGS_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,)
-PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_NO_UNALIGNED)
# =========================================================================
#
# =========================================================================
PF_RELFLAGS_SLB_AT := $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
PLATFORM_RELFLAGS += $(PF_RELFLAGS_SLB_AT)
+
+# SEE README.arm-unaligned-accesses
+PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,)
+PLATFORM_NO_UNALIGNED := $(PF_NO_UNALIGNED)
+
ifneq ($(CONFIG_IMX_CONFIG),)
ALL-y += $(obj)u-boot.imx
endif
index 74ff5ce1c442564303ae09944f543517e5f3ce6e..02124a704112a318c01a15345adfb1f8c76c1039 100644 (file)
void do_data_abort (struct pt_regs *pt_regs)
{
- printf ("data abort\n");
+ printf ("data abort\n\n MAYBE you should read doc/README.arm-unaligned-accesses\n\n");
show_regs (pt_regs);
bad_mode ();
}
index a9f72412a790fd57ebfce665f09ebf30fedc925a..b12011e04ab630dfd34a0b8ea156b42399e12034 100644 (file)
@@ -237,20 +237,20 @@ 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_s, *db_s, *mem_s, *sec_s;
+ static const char cpu_2420 [] = "2420"; /* cpu type */
+ static const char cpu_2422 [] = "2422";
+ static const char cpu_2423 [] = "2423";
+ static const char db_men [] = "Menelaus"; /* board type */
+ static const char db_ip [] = "IP";
+ static const char mem_sdr [] = "mSDR"; /* memory type */
+ static const char mem_ddr [] = "mDDR";
+ static const char t_tst [] = "TST"; /* security level */
+ static const char t_emu [] = "EMU";
+ static const char t_hs [] = "HS";
+ static const char t_gp [] = "GP";
+ static const char unk [] = "?";
+
+ const char *cpu_s, *db_s, *mem_s, *sec_s;
u32 cpu, rev, sec;
rev = get_cpu_rev();
diff --git a/common/Makefile b/common/Makefile
index 973f05a99f5d76ff68a5ee9af56b6aa21e3a8f2e..33c606abb2305560879c007ab4c26e762b5ae027 100644 (file)
--- a/common/Makefile
+++ b/common/Makefile
$(obj)../tools/envcrc:
$(MAKE) -C ../tools
+# SEE README.arm-unaligned-accesses
+$(obj)hush.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
+$(obj)fdt_support.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
+
#########################################################################
# defines $(obj).depend target
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
index 62fb8904cfeba02b6e6dd200034622e847822f9c..01d6b3a2d66b6a4780f8a479ff41ffd2a5bd601b 100644 (file)
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
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
--- /dev/null
@@ -0,0 +1,122 @@
+If you are reading this because of a data abort: the following MIGHT
+be relevant to your abort, if it was caused by an alignment violation.
+In order to determine this, use the PC from the abort dump along with
+an objdump -s -S of the u-boot ELF binary to locate the function where
+the abort happened; then compare this function with the examples below.
+If they match, then you've been hit with a compiler generated unaligned
+access, and you should rewrite your code or add -mno-unaligned-access
+to the command line of the offending file.
+
+Note that the PC shown in the abort message is relocated. In order to
+be able to match it to an address in the ELF binary dump, you will need
+to know the relocation offset. If your target defines CONFIG_CMD_BDI
+and if you can get to the prompt and enter commands before the abort
+happens, then command "bdinfo" will give you the offset. Otherwise you
+will need to try a build with DEBUG set, which will display the offset,
+or use a debugger and set a breakpoint at relocate_code() to see the
+offset (passed as an argument).
+
+*
+
+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 starting at armv7 architectures, the default for
+performing unaligned accesses is to use unaligned native loads and
+stores (-munaligned-access), because the cost of unaligned accesses
+has dropped on armv7 and beyond. This should not affect U-Boot's
+policy of controlling unaligned accesses, however the compiler may
+generate uncontrolled unaligned accesses 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 a stricter target, possibly once the
+ bad code is already in mainline.
+
+c) Relax the -munaligned-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 -munaligned-access.
+
+d) Relax the -munaligned-access rule only for for files susceptible to
+ the local initialized array issue and for armv7 architectures and
+ beyond. This minimizes the quantity of code which can hide unwanted
+ misaligned accesses.
+
+The option retained is d).
+
+Considering that actual occurrences of the issue are rare (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*),
+contributors should not be required to systematically try and detect
+the issue in their patches.
+
+Detecting files susceptible to the issue can be automated through a
+filter installed as a hook in .git which recognizes local char array
+initializations. Automation 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 not prevent committing the patch, but
+shall pre-populate the commit message with a note to the effect that
+this patch contains an initialized local char or 16-bit array and thus
+should be protected from the gcc 4.7 issue.
+
+Upon a positive detection, either $(PLATFORM_NO_UNALIGNED) should be
+added to CFLAGS for the affected file(s), or if the array is a pseudo
+const char*, it should be replaced by an actual one.
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 9635d36fcf9caa4f2023c94b9a48bd08ec13517b..02e6881670fc0dc8adef38f2cacd7047c8dc56bb 100644 (file)
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
+# SEE README.arm-unaligned-accesses
+$(obj)file.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
#########################################################################
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index ccffe85ee1fc4edde080a8d577780446ae31865c..bfe687406fd1785b2722ef4c2702740a9417a8ce 100644 (file)
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
+# SEE README.arm-unaligned-accesses
+$(obj)super.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
+
#########################################################################
# defines $(obj).depend target
diff --git a/lib/Makefile b/lib/Makefile
index a099885f7b63b435f4f5ada5fa0d436ce89b139c..e44e04523313af357b039330409fb475aca09b65 100644 (file)
--- a/lib/Makefile
+++ b/lib/Makefile
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
+# SEE README.arm-unaligned-accesses
+$(obj)bzlib.o: CFLAGS += $(PLATFORM_NO_UNALIGNED)
+
#########################################################################
# defines $(obj).depend target