diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2015-09-03 08:24:40 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-09-07 08:24:05 -0400 |
commit | a077224fd35b2f7fbc93f14cf67074fc792fbac2 (patch) | |
tree | d54776f130253f4b0e8f2afdb4233a8c453ace63 | |
parent | 3939f3345050b1ace675675c47d99fd7b606d9e3 (diff) |
ARM: 8429/1: disable GCC SRA optimization
While working on the 32-bit ARM port of UEFI, I noticed a strange
corruption in the kernel log. The following snprintf() statement
(in drivers/firmware/efi/efi.c:efi_md_typeattr_format())
snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
was producing the following output in the log:
| | | | | |WB|WT|WC|UC]
| | | | | |WB|WT|WC|UC]
| | | | | |WB|WT|WC|UC]
|RUN| | | | |WB|WT|WC|UC]*
|RUN| | | | |WB|WT|WC|UC]*
| | | | | |WB|WT|WC|UC]
|RUN| | | | |WB|WT|WC|UC]*
| | | | | |WB|WT|WC|UC]
|RUN| | | | | | | |UC]
|RUN| | | | | | | |UC]
As it turns out, this is caused by incorrect code being emitted for
the string() function in lib/vsprintf.c. The following code
if (!(spec.flags & LEFT)) {
while (len < spec.field_width--) {
if (buf < end)
*buf = ' ';
++buf;
}
}
for (i = 0; i < len; ++i) {
if (buf < end)
*buf = *s;
++buf; ++s;
}
while (len < spec.field_width--) {
if (buf < end)
*buf = ' ';
++buf;
}
when called with len == 0, triggers an issue in the GCC SRA optimization
pass (Scalar Replacement of Aggregates), which handles promotion of signed
struct members incorrectly. This is a known but as yet unresolved issue.
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932). In this particular
case, it is causing the second while loop to be executed erroneously a
single time, causing the additional space characters to be printed.
So disable the optimization by passing -fno-ipa-sra.
Cc: <stable@vger.kernel.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/Makefile | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 7451b447cc2d..2c2b28ee4811 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -54,6 +54,14 @@ AS += -EL | |||
54 | LD += -EL | 54 | LD += -EL |
55 | endif | 55 | endif |
56 | 56 | ||
57 | # | ||
58 | # The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and | ||
59 | # later may result in code being generated that handles signed short and signed | ||
60 | # char struct members incorrectly. So disable it. | ||
61 | # (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932) | ||
62 | # | ||
63 | KBUILD_CFLAGS += $(call cc-option,-fno-ipa-sra) | ||
64 | |||
57 | # This selects which instruction set is used. | 65 | # This selects which instruction set is used. |
58 | # Note that GCC does not numerically define an architecture version | 66 | # Note that GCC does not numerically define an architecture version |
59 | # macro, but instead defines a whole series of macros which makes | 67 | # macro, but instead defines a whole series of macros which makes |