|
40 | 40 | #include <asm/debugreg.h>
|
41 | 41 | #include <asm/set_memory.h>
|
42 | 42 | #include <asm/sections.h>
|
| 43 | +#include <asm/nospec-branch.h> |
43 | 44 |
|
44 | 45 | #include "common.h"
|
45 | 46 |
|
@@ -203,7 +204,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real)
|
203 | 204 | }
|
204 | 205 |
|
205 | 206 | /* Check whether insn is indirect jump */
|
206 |
| -static int insn_is_indirect_jump(struct insn *insn) |
| 207 | +static int __insn_is_indirect_jump(struct insn *insn) |
207 | 208 | {
|
208 | 209 | return ((insn->opcode.bytes[0] == 0xff &&
|
209 | 210 | (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
|
@@ -237,6 +238,26 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
|
237 | 238 | return (start <= target && target <= start + len);
|
238 | 239 | }
|
239 | 240 |
|
| 241 | +static int insn_is_indirect_jump(struct insn *insn) |
| 242 | +{ |
| 243 | + int ret = __insn_is_indirect_jump(insn); |
| 244 | + |
| 245 | +#ifdef CONFIG_RETPOLINE |
| 246 | + /* |
| 247 | + * Jump to x86_indirect_thunk_* is treated as an indirect jump. |
| 248 | + * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with |
| 249 | + * older gcc may use indirect jump. So we add this check instead of |
| 250 | + * replace indirect-jump check. |
| 251 | + */ |
| 252 | + if (!ret) |
| 253 | + ret = insn_jump_into_range(insn, |
| 254 | + (unsigned long)__indirect_thunk_start, |
| 255 | + (unsigned long)__indirect_thunk_end - |
| 256 | + (unsigned long)__indirect_thunk_start); |
| 257 | +#endif |
| 258 | + return ret; |
| 259 | +} |
| 260 | + |
240 | 261 | /* Decode whole function to ensure any instructions don't jump into target */
|
241 | 262 | static int can_optimize(unsigned long paddr)
|
242 | 263 | {
|
|
0 commit comments