X86SpeculativeExecutionSideEffectSuppression.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //===-- X86SpeculativeExecutionSideEffectSuppression.cpp ------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. ///
  10. /// This file contains the X86 implementation of the speculative execution side
  11. /// effect suppression mitigation.
  12. ///
  13. /// This must be used with the -mlvi-cfi flag in order to mitigate indirect
  14. /// branches and returns.
  15. //===----------------------------------------------------------------------===//
  16. #include "X86.h"
  17. #include "X86InstrInfo.h"
  18. #include "X86Subtarget.h"
  19. #include "llvm/ADT/Statistic.h"
  20. #include "llvm/CodeGen/MachineFunction.h"
  21. #include "llvm/CodeGen/MachineFunctionPass.h"
  22. #include "llvm/CodeGen/MachineInstrBuilder.h"
  23. #include "llvm/Pass.h"
  24. #include "llvm/Target/TargetMachine.h"
  25. using namespace llvm;
  26. #define DEBUG_TYPE "x86-seses"
  27. STATISTIC(NumLFENCEsInserted, "Number of lfence instructions inserted");
  28. static cl::opt<bool> EnableSpeculativeExecutionSideEffectSuppression(
  29. "x86-seses-enable-without-lvi-cfi",
  30. cl::desc("Force enable speculative execution side effect suppression. "
  31. "(Note: User must pass -mlvi-cfi in order to mitigate indirect "
  32. "branches and returns.)"),
  33. cl::init(false), cl::Hidden);
  34. static cl::opt<bool> OneLFENCEPerBasicBlock(
  35. "x86-seses-one-lfence-per-bb",
  36. cl::desc(
  37. "Omit all lfences other than the first to be placed in a basic block."),
  38. cl::init(false), cl::Hidden);
  39. static cl::opt<bool> OnlyLFENCENonConst(
  40. "x86-seses-only-lfence-non-const",
  41. cl::desc("Only lfence before groups of terminators where at least one "
  42. "branch instruction has an input to the addressing mode that is a "
  43. "register other than %rip."),
  44. cl::init(false), cl::Hidden);
  45. static cl::opt<bool>
  46. OmitBranchLFENCEs("x86-seses-omit-branch-lfences",
  47. cl::desc("Omit all lfences before branch instructions."),
  48. cl::init(false), cl::Hidden);
  49. namespace {
  50. class X86SpeculativeExecutionSideEffectSuppression
  51. : public MachineFunctionPass {
  52. public:
  53. X86SpeculativeExecutionSideEffectSuppression() : MachineFunctionPass(ID) {}
  54. static char ID;
  55. StringRef getPassName() const override {
  56. return "X86 Speculative Execution Side Effect Suppression";
  57. }
  58. bool runOnMachineFunction(MachineFunction &MF) override;
  59. };
  60. } // namespace
  61. char X86SpeculativeExecutionSideEffectSuppression::ID = 0;
  62. // This function returns whether the passed instruction uses a memory addressing
  63. // mode that is constant. We treat all memory addressing modes that read
  64. // from a register that is not %rip as non-constant. Note that the use
  65. // of the EFLAGS register results in an addressing mode being considered
  66. // non-constant, therefore all JCC instructions will return false from this
  67. // function since one of their operands will always be the EFLAGS register.
  68. static bool hasConstantAddressingMode(const MachineInstr &MI) {
  69. for (const MachineOperand &MO : MI.uses())
  70. if (MO.isReg() && X86::RIP != MO.getReg())
  71. return false;
  72. return true;
  73. }
  74. bool X86SpeculativeExecutionSideEffectSuppression::runOnMachineFunction(
  75. MachineFunction &MF) {
  76. const auto &OptLevel = MF.getTarget().getOptLevel();
  77. const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
  78. // Check whether SESES needs to run as the fallback for LVI at O0, whether the
  79. // user explicitly passed an SESES flag, or whether the SESES target feature
  80. // was set.
  81. if (!EnableSpeculativeExecutionSideEffectSuppression &&
  82. !(Subtarget.useLVILoadHardening() && OptLevel == CodeGenOpt::None) &&
  83. !Subtarget.useSpeculativeExecutionSideEffectSuppression())
  84. return false;
  85. LLVM_DEBUG(dbgs() << "********** " << getPassName() << " : " << MF.getName()
  86. << " **********\n");
  87. bool Modified = false;
  88. const X86InstrInfo *TII = Subtarget.getInstrInfo();
  89. for (MachineBasicBlock &MBB : MF) {
  90. MachineInstr *FirstTerminator = nullptr;
  91. // Keep track of whether the previous instruction was an LFENCE to avoid
  92. // adding redundant LFENCEs.
  93. bool PrevInstIsLFENCE = false;
  94. for (auto &MI : MBB) {
  95. if (MI.getOpcode() == X86::LFENCE) {
  96. PrevInstIsLFENCE = true;
  97. continue;
  98. }
  99. // We want to put an LFENCE before any instruction that
  100. // may load or store. This LFENCE is intended to avoid leaking any secret
  101. // data due to a given load or store. This results in closing the cache
  102. // and memory timing side channels. We will treat terminators that load
  103. // or store separately.
  104. if (MI.mayLoadOrStore() && !MI.isTerminator()) {
  105. if (!PrevInstIsLFENCE) {
  106. BuildMI(MBB, MI, DebugLoc(), TII->get(X86::LFENCE));
  107. NumLFENCEsInserted++;
  108. Modified = true;
  109. }
  110. if (OneLFENCEPerBasicBlock)
  111. break;
  112. }
  113. // The following section will be LFENCEing before groups of terminators
  114. // that include branches. This will close the branch prediction side
  115. // channels since we will prevent code executing after misspeculation as
  116. // a result of the LFENCEs placed with this logic.
  117. // Keep track of the first terminator in a basic block since if we need
  118. // to LFENCE the terminators in this basic block we must add the
  119. // instruction before the first terminator in the basic block (as
  120. // opposed to before the terminator that indicates an LFENCE is
  121. // required). An example of why this is necessary is that the
  122. // X86InstrInfo::analyzeBranch method assumes all terminators are grouped
  123. // together and terminates it's analysis once the first non-termintor
  124. // instruction is found.
  125. if (MI.isTerminator() && FirstTerminator == nullptr)
  126. FirstTerminator = &MI;
  127. // Look for branch instructions that will require an LFENCE to be put
  128. // before this basic block's terminators.
  129. if (!MI.isBranch() || OmitBranchLFENCEs) {
  130. // This isn't a branch or we're not putting LFENCEs before branches.
  131. PrevInstIsLFENCE = false;
  132. continue;
  133. }
  134. if (OnlyLFENCENonConst && hasConstantAddressingMode(MI)) {
  135. // This is a branch, but it only has constant addressing mode and we're
  136. // not adding LFENCEs before such branches.
  137. PrevInstIsLFENCE = false;
  138. continue;
  139. }
  140. // This branch requires adding an LFENCE.
  141. if (!PrevInstIsLFENCE) {
  142. assert(FirstTerminator && "Unknown terminator instruction");
  143. BuildMI(MBB, FirstTerminator, DebugLoc(), TII->get(X86::LFENCE));
  144. NumLFENCEsInserted++;
  145. Modified = true;
  146. }
  147. break;
  148. }
  149. }
  150. return Modified;
  151. }
  152. FunctionPass *llvm::createX86SpeculativeExecutionSideEffectSuppression() {
  153. return new X86SpeculativeExecutionSideEffectSuppression();
  154. }
  155. INITIALIZE_PASS(X86SpeculativeExecutionSideEffectSuppression, "x86-seses",
  156. "X86 Speculative Execution Side Effect Suppression", false,
  157. false)