branches. Requires a compiler with -mindirect-branch=thunk-extern
          support for full protection. The kernel may run slower.
 
+config CC_HAS_SLS
+       def_bool $(cc-option,-mharden-sls=all)
+
+config SLS
+       bool "Mitigate Straight-Line-Speculation"
+       depends on CC_HAS_SLS && X86_64
+       default n
+       help
+         Compile the kernel with straight-line-speculation options to guard
+         against straight line speculation. The kernel image might be slightly
+         larger.
+
 config X86_CPU_RESCTRL
        bool "x86 CPU resource control support"
        depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
 
   endif
 endif
 
+ifdef CONFIG_SLS
+  KBUILD_CFLAGS += -mharden-sls=all
+endif
+
 KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)
 
 ifdef CONFIG_LTO_CLANG
 
 #define __ALIGN_STR    __stringify(__ALIGN)
 #endif
 
+#ifdef CONFIG_SLS
+#define RET    ret; int3
+#else
+#define RET    ret
+#endif
+
 #else /* __ASSEMBLY__ */
 
+#ifdef CONFIG_SLS
+#define ASM_RET        "ret; int3\n\t"
+#else
 #define ASM_RET        "ret\n\t"
+#endif
 
 #endif /* __ASSEMBLY__ */
 
 
        __ARCH_DEFINE_STATIC_CALL_TRAMP(name, ".byte 0xe9; .long " #func " - (. + 4)")
 
 #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name)                       \
-       __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; nop; nop; nop; nop")
+       __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; int3; nop; nop; nop")
 
 
 #define ARCH_ADD_TRAMP_KEY(name)                                       \
 
        } __attribute__((packed));
 };
 
-#define RET_SIZE               1
+#define RET_SIZE               1 + IS_ENABLED(CONFIG_SLS)
 
 static unsigned long
 create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
  */
 static const u8 xor5rax[] = { 0x66, 0x66, 0x48, 0x31, 0xc0 };
 
+static const u8 retinsn[] = { RET_INSN_OPCODE, 0xcc, 0xcc, 0xcc, 0xcc };
+
 static void __ref __static_call_transform(void *insn, enum insn_type type, void *func)
 {
        const void *emulate = NULL;
                break;
 
        case RET:
-               code = text_gen_insn(RET_INSN_OPCODE, insn, func);
-               size = RET_INSN_SIZE;
+               code = &retinsn;
                break;
        }
 
 
        /* FSRM implies ERMS => no length checks, do the copy directly */
 .Lmemmove_begin_forward:
        ALTERNATIVE "cmp $0x20, %rdx; jb 1f", "", X86_FEATURE_FSRM
-       ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; RET", X86_FEATURE_ERMS
+       ALTERNATIVE "", __stringify(movq %rdx, %rcx; rep movsb; RET), X86_FEATURE_ERMS
 
        /*
         * movsq instruction have many startup latency
 
 
        ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \
                      __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \
-                     __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_AMD
+                     __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg; int3), X86_FEATURE_RETPOLINE_AMD
 
 .endm
 
 
        $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
        $(if $(CONFIG_RETPOLINE), --retpoline)                          \
        $(if $(CONFIG_X86_SMAP), --uaccess)                             \
-       $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)
+       $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)             \
+       $(if $(CONFIG_SLS), --sls)
 
 cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@)
 cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
 
                if [ -n "${CONFIG_X86_SMAP}" ]; then
                        objtoolopt="${objtoolopt} --uaccess"
                fi
+               if [ -n "${CONFIG_SLS}" ]; then
+                       objtoolopt="${objtoolopt} --sls"
+               fi
                info OBJTOOL ${1}
                tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1}
        fi