nospec-branch.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __NOSPEC_BRANCH_H__
  3. #define __NOSPEC_BRANCH_H__
  4. #include <asm/alternative.h>
  5. #include <asm/alternative-asm.h>
  6. #include <asm/cpufeatures.h>
  7. #ifdef __ASSEMBLY__
  8. /*
  9. * This should be used immediately before a retpoline alternative. It tells
  10. * objtool where the retpolines are so that it can make sense of the control
  11. * flow by just reading the original instruction(s) and ignoring the
  12. * alternatives.
  13. */
  14. .macro ANNOTATE_NOSPEC_ALTERNATIVE
  15. .Lannotate_\@:
  16. .pushsection .discard.nospec
  17. .long .Lannotate_\@ - .
  18. .popsection
  19. .endm
  20. /*
  21. * These are the bare retpoline primitives for indirect jmp and call.
  22. * Do not use these directly; they only exist to make the ALTERNATIVE
  23. * invocation below less ugly.
  24. */
  25. .macro RETPOLINE_JMP reg:req
  26. call .Ldo_rop_\@
  27. .Lspec_trap_\@:
  28. pause
  29. jmp .Lspec_trap_\@
  30. .Ldo_rop_\@:
  31. mov \reg, (%_ASM_SP)
  32. ret
  33. .endm
  34. /*
  35. * This is a wrapper around RETPOLINE_JMP so the called function in reg
  36. * returns to the instruction after the macro.
  37. */
  38. .macro RETPOLINE_CALL reg:req
  39. jmp .Ldo_call_\@
  40. .Ldo_retpoline_jmp_\@:
  41. RETPOLINE_JMP \reg
  42. .Ldo_call_\@:
  43. call .Ldo_retpoline_jmp_\@
  44. .endm
  45. /*
  46. * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple
  47. * indirect jmp/call which may be susceptible to the Spectre variant 2
  48. * attack.
  49. */
  50. .macro JMP_NOSPEC reg:req
  51. #ifdef CONFIG_RETPOLINE
  52. ANNOTATE_NOSPEC_ALTERNATIVE
  53. ALTERNATIVE_2 __stringify(jmp *\reg), \
  54. __stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE, \
  55. __stringify(lfence; jmp *\reg), X86_FEATURE_RETPOLINE_AMD
  56. #else
  57. jmp *\reg
  58. #endif
  59. .endm
  60. .macro CALL_NOSPEC reg:req
  61. #ifdef CONFIG_RETPOLINE
  62. ANNOTATE_NOSPEC_ALTERNATIVE
  63. ALTERNATIVE_2 __stringify(call *\reg), \
  64. __stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\
  65. __stringify(lfence; call *\reg), X86_FEATURE_RETPOLINE_AMD
  66. #else
  67. call *\reg
  68. #endif
  69. .endm
  70. #else /* __ASSEMBLY__ */
  71. #define ANNOTATE_NOSPEC_ALTERNATIVE \
  72. "999:\n\t" \
  73. ".pushsection .discard.nospec\n\t" \
  74. ".long 999b - .\n\t" \
  75. ".popsection\n\t"
  76. #if defined(CONFIG_X86_64) && defined(RETPOLINE)
  77. /*
  78. * Since the inline asm uses the %V modifier which is only in newer GCC,
  79. * the 64-bit one is dependent on RETPOLINE not CONFIG_RETPOLINE.
  80. */
  81. # define CALL_NOSPEC \
  82. ANNOTATE_NOSPEC_ALTERNATIVE \
  83. ALTERNATIVE( \
  84. "call *%[thunk_target]\n", \
  85. "call __x86_indirect_thunk_%V[thunk_target]\n", \
  86. X86_FEATURE_RETPOLINE)
  87. # define THUNK_TARGET(addr) [thunk_target] "r" (addr)
  88. #elif defined(CONFIG_X86_32) && defined(CONFIG_RETPOLINE)
  89. /*
  90. * For i386 we use the original ret-equivalent retpoline, because
  91. * otherwise we'll run out of registers. We don't care about CET
  92. * here, anyway.
  93. */
  94. # define CALL_NOSPEC ALTERNATIVE("call *%[thunk_target]\n", \
  95. " jmp 904f;\n" \
  96. " .align 16\n" \
  97. "901: call 903f;\n" \
  98. "902: pause;\n" \
  99. " jmp 902b;\n" \
  100. " .align 16\n" \
  101. "903: addl $4, %%esp;\n" \
  102. " pushl %[thunk_target];\n" \
  103. " ret;\n" \
  104. " .align 16\n" \
  105. "904: call 901b;\n", \
  106. X86_FEATURE_RETPOLINE)
  107. # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
  108. #else /* No retpoline */
  109. # define CALL_NOSPEC "call *%[thunk_target]\n"
  110. # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
  111. #endif
  112. /* The Spectre V2 mitigation variants */
  113. enum spectre_v2_mitigation {
  114. SPECTRE_V2_NONE,
  115. SPECTRE_V2_RETPOLINE_MINIMAL,
  116. SPECTRE_V2_RETPOLINE_MINIMAL_AMD,
  117. SPECTRE_V2_RETPOLINE_GENERIC,
  118. SPECTRE_V2_RETPOLINE_AMD,
  119. SPECTRE_V2_IBRS,
  120. };
  121. #endif /* __ASSEMBLY__ */
  122. #endif /* __NOSPEC_BRANCH_H__ */