blob: c37d1358522a81be985c5f179d55ce70ca765a85 [file] [log] [blame]
Albert ARIBAUDb823fd92012-10-09 09:28:15 +00001If you are reading this because of a data abort: the following MIGHT
2be relevant to your abort, if it was caused by an alignment violation.
3In order to determine this, use the PC from the abort dump along with
4an objdump -s -S of the u-boot ELF binary to locate the function where
5the abort happened; then compare this function with the examples below.
6If they match, then you've been hit with a compiler generated unaligned
7access, and you should rewrite your code or add -mno-unaligned-access
8to the command line of the offending file.
9
10Note that the PC shown in the abort message is relocated. In order to
11be able to match it to an address in the ELF binary dump, you will need
12to know the relocation offset. If your target defines CONFIG_CMD_BDI
13and if you can get to the prompt and enter commands before the abort
14happens, then command "bdinfo" will give you the offset. Otherwise you
15will need to try a build with DEBUG set, which will display the offset,
16or use a debugger and set a breakpoint at relocate_code() to see the
17offset (passed as an argument).
18
19*
20
21Since U-Boot runs on a variety of hardware, some only able to perform
22unaligned accesses with a strong penalty, some unable to perform them
23at all, the policy regarding unaligned accesses is to not perform any,
24unless absolutely necessary because of hardware or standards.
25
26Also, on hardware which permits it, the core is configured to throw
27data abort exceptions on unaligned accesses in order to catch these
28unallowed accesses as early as possible.
29
30Until version 4.7, the gcc default for performing unaligned accesses
31(-mno-unaligned-access) is to emulate unaligned accesses using aligned
32loads and stores plus shifts and masks. Emulated unaligned accesses
33will not be caught by hardware. These accesses may be costly and may
34be actually unnecessary. In order to catch these accesses and remove
35or optimize them, option -munaligned-access is explicitly set for all
36versions of gcc which support it.
37
38From gcc 4.7 onward starting at armv7 architectures, the default for
39performing unaligned accesses is to use unaligned native loads and
40stores (-munaligned-access), because the cost of unaligned accesses
41has dropped on armv7 and beyond. This should not affect U-Boot's
42policy of controlling unaligned accesses, however the compiler may
43generate uncontrolled unaligned accesses on its own in at least one
44known case: when declaring a local initialized char array, e.g.
45
46function foo()
47{
48 char buffer[] = "initial value";
49/* or */
50 char buffer[] = { 'i', 'n', 'i', 't', 0 };
51 ...
52}
53
54Under -munaligned-accesses with optimizations on, this declaration
55causes the compiler to generate native loads from the literal string
56and native stores to the buffer, and the literal string alignment
57cannot be controlled. If it is misaligned, then the core will throw
58a data abort exception.
59
60Quite probably the same might happen for 16-bit array initializations
61where the constant is aligned on a boundary which is a multiple of 2
62but not of 4:
63
64function foo()
65{
66 u16 buffer[] = { 1, 2, 3 };
67 ...
68}
69
70The long term solution to this issue is to add an option to gcc to
71allow controlling the general alignment of data, including constant
72initialization values.
73
74However this will only apply to the version of gcc which will have such
75an option. For other versions, there are four workarounds:
76
77a) Enforce as a rule that array initializations as described above
78 are forbidden. This is generally not acceptable as they are valid,
79 and usual, C constructs. The only case where they could be rejected
80 is when they actually equate to a const char* declaration, i.e. the
81 array is initialized and never modified in the function's scope.
82
83b) Drop the requirement on unaligned accesses at least for ARMv7,
84 i.e. do not throw a data abort exception upon unaligned accesses.
85 But that will allow adding badly aligned code to U-Boot, only for
86 it to fail when re-used with a stricter target, possibly once the
87 bad code is already in mainline.
88
89c) Relax the -munaligned-access rule globally. This will prevent native
90 unaligned accesses of course, but that will also hide any bug caused
91 by a bad unaligned access, making it much harder to diagnose it. It
92 is actually what already happens when building ARM targets with a
93 pre-4.7 gcc, and it may actually already hide some bugs yet unseen
94 until the target gets compiled with -munaligned-access.
95
96d) Relax the -munaligned-access rule only for for files susceptible to
97 the local initialized array issue and for armv7 architectures and
98 beyond. This minimizes the quantity of code which can hide unwanted
99 misaligned accesses.
100
101The option retained is d).
102
103Considering that actual occurrences of the issue are rare (as of this
104writing, 5 files out of 7840 in U-Boot, or .3%, contain an initialized
105local char array which cannot actually be replaced with a const char*),
106contributors should not be required to systematically try and detect
107the issue in their patches.
108
109Detecting files susceptible to the issue can be automated through a
110filter installed as a hook in .git which recognizes local char array
111initializations. Automation should err on the false positive side, for
112instance flagging non-local arrays as if they were local if they cannot
113be told apart.
114
115In any case, detection shall not prevent committing the patch, but
116shall pre-populate the commit message with a note to the effect that
117this patch contains an initialized local char or 16-bit array and thus
118should be protected from the gcc 4.7 issue.
119
120Upon a positive detection, either $(PLATFORM_NO_UNALIGNED) should be
121added to CFLAGS for the affected file(s), or if the array is a pseudo
122const char*, it should be replaced by an actual one.