[PATCH] ARM: disable GCC SRA optimization

Ard Biesheuvel ard.biesheuvel at linaro.org
Wed Sep 2 09:28:10 PDT 2015


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.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
---

Needs to go to stable perhaps?
The emitted asm is at the end of this patch.

 arch/arm/Makefile | 8 ++++++++
 1 file changed, 8 insertions(+)

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
 LD		+= -EL
 endif
 
+#
+# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and
+# later may result in code being generated that handles signed short and signed
+# char struct members incorrectly. So disable it.
+# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932)
+#
+KBUILD_CFLAGS	+= $(call cc-option,-fno-ipa-sra)
+
 # This selects which instruction set is used.
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
-- 
1.9.1


000014d0 <string.isra.5>:
    14d0:       e3520a01        cmp     r2, #4096       ; 0x1000
    14d4:       e92d41f0        push    {r4, r5, r6, r7, r8, lr}
    14d8:       e3007000        movw    r7, #0
    14dc:       e3407000        movt    r7, #0
    14e0:       21a07002        movcs   r7, r2
    14e4:       e1a05000        mov     r5, r0
    14e8:       e1a06001        mov     r6, r1
    14ec:       e1a00007        mov     r0, r7
    14f0:       e1dd11fc        ldrsh   r1, [sp, #28]
    14f4:       e1a08003        mov     r8, r3
    14f8:       e1dd41f8        ldrsh   r4, [sp, #24]
    14fc:       ebfffffe        bl      0 <strnlen>
    1500:       e3180002        tst     r8, #2
    1504:       1a00000d        bne     1540 <string.isra.5+0x70>
    1508:       e1500004        cmp     r0, r4
    150c:       e2443001        sub     r3, r4, #1
    1510:       e6bf4073        sxth    r4, r3
    1514:       aa000009        bge     1540 <string.isra.5+0x70>
    1518:       e3a02020        mov     r2, #32
    151c:       e2443001        sub     r3, r4, #1
    1520:       e1560005        cmp     r6, r5
    1524:       85c52000        strbhi  r2, [r5]
    1528:       e1500004        cmp     r0, r4
    152c:       e6ff3073        uxth    r3, r3
    1530:       e2855001        add     r5, r5, #1
    1534:       e6bf4073        sxth    r4, r3
    1538:       bafffff7        blt     151c <string.isra.5+0x4c>
    153c:       e1a04003        mov     r4, r3
    1540:       e3500000        cmp     r0, #0
    1544:       da000016        ble     15a4 <string.isra.5+0xd4>
    1548:       e085c000        add     ip, r5, r0
    154c:       e1560005        cmp     r6, r5
    1550:       e2855001        add     r5, r5, #1
    1554:       e2877001        add     r7, r7, #1
    1558:       85573001        ldrbhi  r3, [r7, #-1]
    155c:       85453001        strbhi  r3, [r5, #-1]
    1560:       e155000c        cmp     r5, ip
    1564:       1afffff8        bne     154c <string.isra.5+0x7c>
    1568:       e2443001        sub     r3, r4, #1
    156c:       e1500004        cmp     r0, r4
    1570:       e6bf3073        sxth    r3, r3
    1574:       aa000008        bge     159c <string.isra.5+0xcc>
    1578:       e3a01020        mov     r1, #32
    157c:       e156000c        cmp     r6, ip
    1580:       e1a02003        mov     r2, r3
    1584:       85cc1000        strbhi  r1, [ip]
    1588:       e2433001        sub     r3, r3, #1
    158c:       e1500002        cmp     r0, r2
    1590:       e28cc001        add     ip, ip, #1
    1594:       e6bf3073        sxth    r3, r3
    1598:       bafffff7        blt     157c <string.isra.5+0xac>
    159c:       e1a0000c        mov     r0, ip
    15a0:       e8bd81f0        pop     {r4, r5, r6, r7, r8, pc}
    15a4:       e1a0c005        mov     ip, r5
    15a8:       eaffffee        b       1568 <string.isra.5+0x98>




More information about the linux-arm-kernel mailing list