aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2015-09-03 08:24:40 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-09-07 08:24:05 -0400
commita077224fd35b2f7fbc93f14cf67074fc792fbac2 (patch)
treed54776f130253f4b0e8f2afdb4233a8c453ace63
parent3939f3345050b1ace675675c47d99fd7b606d9e3 (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/Makefile8
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
54LD += -EL 54LD += -EL
55endif 55endif
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#
63KBUILD_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