Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/paravirt: Add stack frame dependency to PVOP inline asm calls

If a PVOP call macro is inlined at the beginning of a function, gcc can
insert the call instruction before setting up a stack frame, which
breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and
can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by
listing the stack pointer as an output operand for the PVOP inline asm
statements.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Alok Kataria <akataria@vmware.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Bernd Petrovitsch <bernd@petrovitsch.priv.at>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chris J Arges <chris.j.arges@canonical.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michal Marek <mmarek@suse.cz>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Pedro Alves <palves@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: live-patching@vger.kernel.org
Link: http://lkml.kernel.org/r/6a13e48c5a8cf2de1aa112ae2d4c0ac194096282.1453405861.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Josh Poimboeuf and committed by
Ingo Molnar
bb93eb4c 8be0eb7e

+10 -8
+10 -8
arch/x86/include/asm/paravirt_types.h
··· 466 466 * makes sure the incoming and outgoing types are always correct. 467 467 */ 468 468 #ifdef CONFIG_X86_32 469 - #define PVOP_VCALL_ARGS \ 470 - unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx 469 + #define PVOP_VCALL_ARGS \ 470 + unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx; \ 471 + register void *__sp asm("esp") 471 472 #define PVOP_CALL_ARGS PVOP_VCALL_ARGS 472 473 473 474 #define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x)) ··· 486 485 #define VEXTRA_CLOBBERS 487 486 #else /* CONFIG_X86_64 */ 488 487 /* [re]ax isn't an arg, but the return val */ 489 - #define PVOP_VCALL_ARGS \ 490 - unsigned long __edi = __edi, __esi = __esi, \ 491 - __edx = __edx, __ecx = __ecx, __eax = __eax 488 + #define PVOP_VCALL_ARGS \ 489 + unsigned long __edi = __edi, __esi = __esi, \ 490 + __edx = __edx, __ecx = __ecx, __eax = __eax; \ 491 + register void *__sp asm("rsp") 492 492 #define PVOP_CALL_ARGS PVOP_VCALL_ARGS 493 493 494 494 #define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x)) ··· 528 526 asm volatile(pre \ 529 527 paravirt_alt(PARAVIRT_CALL) \ 530 528 post \ 531 - : call_clbr \ 529 + : call_clbr, "+r" (__sp) \ 532 530 : paravirt_type(op), \ 533 531 paravirt_clobber(clbr), \ 534 532 ##__VA_ARGS__ \ ··· 538 536 asm volatile(pre \ 539 537 paravirt_alt(PARAVIRT_CALL) \ 540 538 post \ 541 - : call_clbr \ 539 + : call_clbr, "+r" (__sp) \ 542 540 : paravirt_type(op), \ 543 541 paravirt_clobber(clbr), \ 544 542 ##__VA_ARGS__ \ ··· 565 563 asm volatile(pre \ 566 564 paravirt_alt(PARAVIRT_CALL) \ 567 565 post \ 568 - : call_clbr \ 566 + : call_clbr, "+r" (__sp) \ 569 567 : paravirt_type(op), \ 570 568 paravirt_clobber(clbr), \ 571 569 ##__VA_ARGS__ \