README.arm-unaligned-accesses 5.6 KB

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