#include <asm/asm-offsets.h>
 #include <asm/processor-flags.h>
 #include <asm/ptrace-abi.h>
+#include <asm/msr.h>
+#include <asm/nospec-branch.h>
 
 /*
 
 
 #endif
 
+/*
+ * IBRS kernel mitigation for Spectre_v2.
+ *
+ * Assumes full context is established (PUSH_REGS, CR3 and GS) and it clobbers
+ * the regs it uses (AX, CX, DX). Must be called before the first RET
+ * instruction (NOTE! UNTRAIN_RET includes a RET instruction)
+ *
+ * The optional argument is used to save/restore the current value,
+ * which is used on the paranoid paths.
+ *
+ * Assumes x86_spec_ctrl_{base,current} to have SPEC_CTRL_IBRS set.
+ */
+.macro IBRS_ENTER save_reg
+       ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS
+       movl    $MSR_IA32_SPEC_CTRL, %ecx
+
+.ifnb \save_reg
+       rdmsr
+       shl     $32, %rdx
+       or      %rdx, %rax
+       mov     %rax, \save_reg
+       test    $SPEC_CTRL_IBRS, %eax
+       jz      .Ldo_wrmsr_\@
+       lfence
+       jmp     .Lend_\@
+.Ldo_wrmsr_\@:
+.endif
+
+       movq    PER_CPU_VAR(x86_spec_ctrl_current), %rdx
+       movl    %edx, %eax
+       shr     $32, %rdx
+       wrmsr
+.Lend_\@:
+.endm
+
+/*
+ * Similar to IBRS_ENTER, requires KERNEL GS,CR3 and clobbers (AX, CX, DX)
+ * regs. Must be called after the last RET.
+ */
+.macro IBRS_EXIT save_reg
+       ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS
+       movl    $MSR_IA32_SPEC_CTRL, %ecx
+
+.ifnb \save_reg
+       mov     \save_reg, %rdx
+.else
+       movq    PER_CPU_VAR(x86_spec_ctrl_current), %rdx
+       andl    $(~SPEC_CTRL_IBRS), %edx
+.endif
+
+       movl    %edx, %eax
+       shr     $32, %rdx
+       wrmsr
+.Lend_\@:
+.endm
+
 /*
  * Mitigate Spectre v1 for conditional swapgs code paths.
  *
 
 
 SYM_INNER_LABEL(entry_SYSCALL_64_safe_stack, SYM_L_GLOBAL)
        ANNOTATE_NOENDBR
-       UNTRAIN_RET
 
        /* Construct struct pt_regs on stack */
        pushq   $__USER_DS                              /* pt_regs->ss */
        movq    %rsp, %rdi
        /* Sign extend the lower 32bit as syscall numbers are treated as int */
        movslq  %eax, %rsi
+
+       /* clobbers %rax, make sure it is after saving the syscall nr */
+       IBRS_ENTER
+       UNTRAIN_RET
+
        call    do_syscall_64           /* returns with IRQs disabled */
 
        /*
         * perf profiles. Nothing jumps here.
         */
 syscall_return_via_sysret:
+       IBRS_EXIT
        POP_REGS pop_rdi=0
 
        /*
 
 SYM_CODE_START_LOCAL(common_interrupt_return)
 SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
+       IBRS_EXIT
 #ifdef CONFIG_DEBUG_ENTRY
        /* Assert that pt_regs indicates user mode. */
        testb   $3, CS(%rsp)
  *              1 -> no SWAPGS on exit
  *
  *     Y        GSBASE value at entry, must be restored in paranoid_exit
+ *
+ * R14 - old CR3
+ * R15 - old SPEC_CTRL
  */
 SYM_CODE_START_LOCAL(paranoid_entry)
        UNWIND_HINT_FUNC
         * be retrieved from a kernel internal table.
         */
        SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
-       UNTRAIN_RET
 
        /*
         * Handling GSBASE depends on the availability of FSGSBASE.
         * is needed here.
         */
        SAVE_AND_SET_GSBASE scratch_reg=%rax save_reg=%rbx
-       RET
+       jmp .Lparanoid_gsbase_done
 
 .Lparanoid_entry_checkgs:
        /* EBX = 1 -> kernel GSBASE active, no restore required */
        xorl    %ebx, %ebx
        swapgs
 .Lparanoid_kernel_gsbase:
-
        FENCE_SWAPGS_KERNEL_ENTRY
+.Lparanoid_gsbase_done:
+
+       /*
+        * Once we have CR3 and %GS setup save and set SPEC_CTRL. Just like
+        * CR3 above, keep the old value in a callee saved register.
+        */
+       IBRS_ENTER save_reg=%r15
+       UNTRAIN_RET
+
        RET
 SYM_CODE_END(paranoid_entry)
 
  *              1 -> no SWAPGS on exit
  *
  *     Y        User space GSBASE, must be restored unconditionally
+ *
+ * R14 - old CR3
+ * R15 - old SPEC_CTRL
  */
 SYM_CODE_START_LOCAL(paranoid_exit)
        UNWIND_HINT_REGS
+
+       /*
+        * Must restore IBRS state before both CR3 and %GS since we need access
+        * to the per-CPU x86_spec_ctrl_shadow variable.
+        */
+       IBRS_EXIT save_reg=%r15
+
        /*
         * The order of operations is important. RESTORE_CR3 requires
         * kernel GSBASE.
        FENCE_SWAPGS_USER_ENTRY
        /* We have user CR3.  Change to kernel CR3. */
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
+       IBRS_ENTER
        UNTRAIN_RET
 
        leaq    8(%rsp), %rdi                   /* arg0 = pt_regs pointer */
 .Lerror_entry_from_usermode_after_swapgs:
+
        /* Put us onto the real thread stack. */
        call    sync_regs
        RET
        swapgs
        FENCE_SWAPGS_USER_ENTRY
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
+       IBRS_ENTER
        UNTRAIN_RET
 
        /*
        movq    %rsp, %rdx
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
        UNWIND_HINT_IRET_REGS base=%rdx offset=8
-       UNTRAIN_RET
        pushq   5*8(%rdx)       /* pt_regs->ss */
        pushq   4*8(%rdx)       /* pt_regs->rsp */
        pushq   3*8(%rdx)       /* pt_regs->flags */
        PUSH_AND_CLEAR_REGS rdx=(%rdx)
        ENCODE_FRAME_POINTER
 
+       IBRS_ENTER
+       UNTRAIN_RET
+
        /*
         * At this point we no longer need to worry about stack damage
         * due to nesting -- we're on the normal thread stack and we're
        movq    $-1, %rsi
        call    exc_nmi
 
+       /* Always restore stashed SPEC_CTRL value (see paranoid_entry) */
+       IBRS_EXIT save_reg=%r15
+
        /* Always restore stashed CR3 value (see paranoid_entry) */
        RESTORE_CR3 scratch_reg=%r15 save_reg=%r14
 
 
  *
  * Copyright 2000-2002 Andi Kleen, SuSE Labs.
  */
-#include "calling.h"
 #include <asm/asm-offsets.h>
 #include <asm/current.h>
 #include <asm/errno.h>
 #include <linux/linkage.h>
 #include <linux/err.h>
 
+#include "calling.h"
+
        .section .entry.text, "ax"
 
 /*
        pushq   $__USER32_CS            /* pt_regs->cs */
        pushq   $0                      /* pt_regs->ip = 0 (placeholder) */
 SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
-       UNTRAIN_RET
 
        /*
         * User tracing code (ptrace or signal handlers) might assume that
 
        cld
 
+       IBRS_ENTER
+       UNTRAIN_RET
+
        /*
         * SYSENTER doesn't filter flags, so we need to clear NT and AC
         * ourselves.  To save a few cycles, we can check whether
 
 SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL)
        ANNOTATE_NOENDBR
-       UNTRAIN_RET
 
        /* Construct struct pt_regs on stack */
        pushq   $__USER32_DS            /* pt_regs->ss */
        PUSH_AND_CLEAR_REGS rcx=%rbp rax=$-ENOSYS
        UNWIND_HINT_REGS
 
+       IBRS_ENTER
+       UNTRAIN_RET
+
        movq    %rsp, %rdi
        call    do_fast_syscall_32
        /* XEN PV guests always use IRET path */
         */
        STACKLEAK_ERASE
 
+       IBRS_EXIT
+
        movq    RBX(%rsp), %rbx         /* pt_regs->rbx */
        movq    RBP(%rsp), %rbp         /* pt_regs->rbp */
        movq    EFLAGS(%rsp), %r11      /* pt_regs->flags (in r11) */
        pushq   0*8(%rax)               /* regs->orig_ax */
 .Lint80_keep_stack:
 
-       UNTRAIN_RET
        PUSH_AND_CLEAR_REGS rax=$-ENOSYS
        UNWIND_HINT_REGS
 
        cld
 
+       IBRS_ENTER
+       UNTRAIN_RET
+
        movq    %rsp, %rdi
        call    do_int80_syscall_32
        jmp     swapgs_restore_regs_and_return_to_usermode
 
 #define X86_FEATURE_PROC_FEEDBACK      ( 7*32+ 9) /* AMD ProcFeedbackInterface */
 #define X86_FEATURE_XCOMPACTED         ( 7*32+10) /* "" Use compacted XSTATE (XSAVES or XSAVEC) */
 #define X86_FEATURE_PTI                        ( 7*32+11) /* Kernel Page Table Isolation enabled */
-/* FREE!                               ( 7*32+12) */
+#define X86_FEATURE_KERNEL_IBRS                ( 7*32+12) /* "" Set/clear IBRS on kernel entry/exit */
 /* FREE!                               ( 7*32+13) */
 #define X86_FEATURE_INTEL_PPIN         ( 7*32+14) /* Intel Processor Inventory Number */
 #define X86_FEATURE_CDP_L2             ( 7*32+15) /* Code and Data Prioritization L2 */