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