Commit 520a13c5 authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Ingo Molnar

x86/asm: Fix inline asm call constraints for GCC 4.4

The kernel test bot (run by Xiaolong Ye) reported that the following commit:

  f5caf621 ("x86/asm: Fix inline asm call constraints for Clang")

is causing double faults in a kernel compiled with GCC 4.4.

Linus subsequently diagnosed the crash pattern and the buggy commit and found that
the issue is with this code:

  register unsigned int __asm_call_sp asm("esp");
  #define ASM_CALL_CONSTRAINT "+r" (__asm_call_sp)

Even on a 64-bit kernel, it's using ESP instead of RSP.  That causes GCC
to produce the following bogus code:

  ffffffff8147461d:       89 e0                   mov    %esp,%eax
  ffffffff8147461f:       4c 89 f7                mov    %r14,%rdi
  ffffffff81474622:       4c 89 fe                mov    %r15,%rsi
  ffffffff81474625:       ba 20 00 00 00          mov    $0x20,%edx
  ffffffff8147462a:       89 c4                   mov    %eax,%esp
  ffffffff8147462c:       e8 bf 52 05 00          callq  ffffffff814c98f0 <copy_user_generic_unrolled>

Despite the absurdity of it backing up and restoring the stack pointer
for no reason, the bug is actually the fact that it's only backing up
and restoring the lower 32 bits of the stack pointer.  The upper 32 bits
are getting cleared out, corrupting the stack pointer.

So change the '__asm_call_sp' register variable to be associated with
the actual full-size stack pointer.

This also requires changing the __ASM_SEL() macro to be based on the
actual compiled arch size, rather than the CONFIG value, because
CONFIG_X86_64 compiles some files with '-m32' (e.g., realmode and vdso).
Otherwise Clang fails to build the kernel because it complains about the
use of a 64-bit register (RSP) in a 32-bit file.
Reported-and-Bisected-and-Tested-by: default avatarkernel test robot <xiaolong.ye@intel.com>
Diagnosed-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: LKP <lkp@01.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matthias Kaehlcke <mka@chromium.org>
Cc: Miguel Bernal Marin <miguel.bernal.marin@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: f5caf621 ("x86/asm: Fix inline asm call constraints for Clang")
Link: http://lkml.kernel.org/r/20170928215826.6sdpmwtkiydiytim@trebleSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 29b46dfb
...@@ -11,10 +11,12 @@ ...@@ -11,10 +11,12 @@
# define __ASM_FORM_COMMA(x) " " #x "," # define __ASM_FORM_COMMA(x) " " #x ","
#endif #endif
#ifdef CONFIG_X86_32 #ifndef __x86_64__
/* 32 bit */
# define __ASM_SEL(a,b) __ASM_FORM(a) # define __ASM_SEL(a,b) __ASM_FORM(a)
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a) # define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a)
#else #else
/* 64 bit */
# define __ASM_SEL(a,b) __ASM_FORM(b) # define __ASM_SEL(a,b) __ASM_FORM(b)
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b) # define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
#endif #endif
...@@ -139,7 +141,7 @@ ...@@ -139,7 +141,7 @@
* gets set up by the containing function. If you forget to do this, objtool * gets set up by the containing function. If you forget to do this, objtool
* may print a "call without frame pointer save/setup" warning. * may print a "call without frame pointer save/setup" warning.
*/ */
register unsigned int __asm_call_sp asm("esp"); register unsigned long __asm_call_sp asm(_ASM_SP);
#define ASM_CALL_CONSTRAINT "+r" (__asm_call_sp) #define ASM_CALL_CONSTRAINT "+r" (__asm_call_sp)
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment