x86/entry/calling: Allow PUSH_AND_CLEAR_REGS being used beyond actual entry code
authorPeter Zijlstra (Intel) <peterz@infradead.org>
Tue, 5 Dec 2023 10:50:19 +0000 (02:50 -0800)
committerBorislav Petkov (AMD) <bp@alien8.de>
Wed, 31 Jan 2024 21:03:09 +0000 (22:03 +0100)
PUSH_AND_CLEAR_REGS could be used besides actual entry code; in that case
%rbp shouldn't be cleared (otherwise the frame pointer is destroyed) and
UNWIND_HINT shouldn't be added.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Xin Li <xin3.li@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Shan Kang <shan.kang@intel.com>
Link: https://lore.kernel.org/r/20231205105030.8698-31-xin3.li@intel.com
arch/x86/entry/calling.h

index 9f1d94790a54912cc431e9e39fc0a4a7e6069398..3ff925b17b7ed5684332b7a6166dd1d2e81a3ece 100644 (file)
@@ -65,7 +65,7 @@ For 32-bit we have the following conventions - kernel is built with
  * for assembly code:
  */
 
-.macro PUSH_REGS rdx=%rdx rcx=%rcx rax=%rax save_ret=0
+.macro PUSH_REGS rdx=%rdx rcx=%rcx rax=%rax save_ret=0 unwind_hint=1
        .if \save_ret
        pushq   %rsi            /* pt_regs->si */
        movq    8(%rsp), %rsi   /* temporarily store the return address in %rsi */
@@ -87,14 +87,17 @@ For 32-bit we have the following conventions - kernel is built with
        pushq   %r13            /* pt_regs->r13 */
        pushq   %r14            /* pt_regs->r14 */
        pushq   %r15            /* pt_regs->r15 */
+
+       .if \unwind_hint
        UNWIND_HINT_REGS
+       .endif
 
        .if \save_ret
        pushq   %rsi            /* return address on top of stack */
        .endif
 .endm
 
-.macro CLEAR_REGS
+.macro CLEAR_REGS clear_bp=1
        /*
         * Sanitize registers of values that a speculation attack might
         * otherwise want to exploit. The lower registers are likely clobbered
@@ -109,7 +112,9 @@ For 32-bit we have the following conventions - kernel is built with
        xorl    %r10d, %r10d    /* nospec r10 */
        xorl    %r11d, %r11d    /* nospec r11 */
        xorl    %ebx,  %ebx     /* nospec rbx */
+       .if \clear_bp
        xorl    %ebp,  %ebp     /* nospec rbp */
+       .endif
        xorl    %r12d, %r12d    /* nospec r12 */
        xorl    %r13d, %r13d    /* nospec r13 */
        xorl    %r14d, %r14d    /* nospec r14 */
@@ -117,9 +122,9 @@ For 32-bit we have the following conventions - kernel is built with
 
 .endm
 
-.macro PUSH_AND_CLEAR_REGS rdx=%rdx rcx=%rcx rax=%rax save_ret=0
-       PUSH_REGS rdx=\rdx, rcx=\rcx, rax=\rax, save_ret=\save_ret
-       CLEAR_REGS
+.macro PUSH_AND_CLEAR_REGS rdx=%rdx rcx=%rcx rax=%rax save_ret=0 clear_bp=1 unwind_hint=1
+       PUSH_REGS rdx=\rdx, rcx=\rcx, rax=\rax, save_ret=\save_ret unwind_hint=\unwind_hint
+       CLEAR_REGS clear_bp=\clear_bp
 .endm
 
 .macro POP_REGS pop_rdi=1