|
@@ -40,6 +40,7 @@
|
|
#include <asm/debugreg.h>
|
|
#include <asm/debugreg.h>
|
|
#include <asm/set_memory.h>
|
|
#include <asm/set_memory.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/sections.h>
|
|
|
|
+#include <asm/nospec-branch.h>
|
|
|
|
|
|
#include "common.h"
|
|
#include "common.h"
|
|
|
|
|
|
@@ -205,7 +206,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src)
|
|
}
|
|
}
|
|
|
|
|
|
/* Check whether insn is indirect jump */
|
|
/* Check whether insn is indirect jump */
|
|
-static int insn_is_indirect_jump(struct insn *insn)
|
|
|
|
|
|
+static int __insn_is_indirect_jump(struct insn *insn)
|
|
{
|
|
{
|
|
return ((insn->opcode.bytes[0] == 0xff &&
|
|
return ((insn->opcode.bytes[0] == 0xff &&
|
|
(X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
|
|
(X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
|
|
@@ -239,6 +240,26 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
|
|
return (start <= target && target <= start + len);
|
|
return (start <= target && target <= start + len);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int insn_is_indirect_jump(struct insn *insn)
|
|
|
|
+{
|
|
|
|
+ int ret = __insn_is_indirect_jump(insn);
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_RETPOLINE
|
|
|
|
+ /*
|
|
|
|
+ * Jump to x86_indirect_thunk_* is treated as an indirect jump.
|
|
|
|
+ * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with
|
|
|
|
+ * older gcc may use indirect jump. So we add this check instead of
|
|
|
|
+ * replace indirect-jump check.
|
|
|
|
+ */
|
|
|
|
+ if (!ret)
|
|
|
|
+ ret = insn_jump_into_range(insn,
|
|
|
|
+ (unsigned long)__indirect_thunk_start,
|
|
|
|
+ (unsigned long)__indirect_thunk_end -
|
|
|
|
+ (unsigned long)__indirect_thunk_start);
|
|
|
|
+#endif
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
/* Decode whole function to ensure any instructions don't jump into target */
|
|
/* Decode whole function to ensure any instructions don't jump into target */
|
|
static int can_optimize(unsigned long paddr)
|
|
static int can_optimize(unsigned long paddr)
|
|
{
|
|
{
|