Skip to content

Commit 208fae5

Browse files
Nicolas PitreRussell King
authored andcommitted
ARM: 8550/1: protect idiv patching against undefined gcc behavior
It was reported that a kernel with CONFIG_ARM_PATCH_IDIV=y stopped booting when compiled with the upcoming gcc 6. Turns out that turning a function address into a writable array is undefined and gcc 6 decided it was OK to omit the store to the first word of the function while still preserving the store to the second word. Even though gcc 6 is now fixed to behave more coherently, it is a mystery that gcc 4 and gcc 5 actually produce wanted code in the kernel. And in fact the reduced test case to illustrate the issue does indeed break with gcc < 6 as well. In any case, let's guard the kernel against undefined compiler behavior by hiding the nature of the array location as suggested by gcc developers. Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70128 Signed-off-by: Nicolas Pitre <nico@linaro.org> Reported-by: Marcin Juszkiewicz <mjuszkiewicz@redhat.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: stable@vger.kernel.org # v4.5 Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
1 parent f2335a2 commit 208fae5

File tree

1 file changed

+2
-0
lines changed

1 file changed

+2
-0
lines changed

arch/arm/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,13 @@ static void __init patch_aeabi_idiv(void)
430430
pr_info("CPU: div instructions available: patching division code\n");
431431

432432
fn_addr = ((uintptr_t)&__aeabi_uidiv) & ~1;
433+
asm ("" : "+g" (fn_addr));
433434
((u32 *)fn_addr)[0] = udiv_instruction();
434435
((u32 *)fn_addr)[1] = bx_lr_instruction();
435436
flush_icache_range(fn_addr, fn_addr + 8);
436437

437438
fn_addr = ((uintptr_t)&__aeabi_idiv) & ~1;
439+
asm ("" : "+g" (fn_addr));
438440
((u32 *)fn_addr)[0] = sdiv_instruction();
439441
((u32 *)fn_addr)[1] = bx_lr_instruction();
440442
flush_icache_range(fn_addr, fn_addr + 8);

0 commit comments

Comments
 (0)