Lines Matching +full:architecturally +full:- +full:defined
1 //===- AArch64SpeculationHardening.cpp - Harden Against Missspeculation --===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 // vulnerabilities that may happen under control flow miss-speculation.
12 // The pass implements tracking of control flow miss-speculation into a "taint"
14 // sensitive data when executing under miss-speculation, a.k.a. "transient
16 // This pass is aimed at mitigating against SpectreV1-style vulnarabilities.
21 // As a possible follow-on improvement, also an intrinsics-based approach as
26 // tracking of control flow miss-speculation into a taint register:
29 // the instruction set characteristics result in different trade-offs.
30 // - The speculation hardening is done after register allocation. With a
40 // - It is easy to insert mask operations at this late stage as we have
42 // - The taint variable contains all-ones when no miss-speculation is detected,
43 // and contains all-zeros when miss-speculation is detected. Therefore, when
46 // - The tracking of miss-speculation is done by using a data-flow conditional
49 // instruction can be limited with a CSDB instruction - so the combination of
51 // aren't speculated. When conditional branch direction gets miss-speculated,
62 // - On function call boundaries, the miss-speculation state is transferred from
69 // - Many of the optimizations described at
71 // loads haven't been implemented yet - but for some of them there are
73 // - loads that load into general purpose (X or W) registers get hardened by
79 // - On AArch64, CSDB instructions are inserted between the masking of the
80 // register and its first use, to ensure there's no non-control-flow
84 // - Implement this functionality using full speculation barriers, akin to the
85 // x86-slh-lfence option. This may be more useful for the intrinsics-based
89 // - no indirect branch misprediction gets protected/instrumented; but this
91 //===----------------------------------------------------------------------===//
115 #define DEBUG_TYPE "aarch64-speculation-hardening"
119 static cl::opt<bool> HardenLoads("aarch64-slh-loads", cl::Hidden,
183 INITIALIZE_PASS(AArch64SpeculationHardening, "aarch64-speculation-hardening",
190 if (TII->analyzeBranch(MBB, TBB, FBB, analyzeBranchCondCode, false)) in endsWithCondControlFlow()
193 // Ignore if the BB ends in an unconditional branch/fall-through. in endsWithCondControlFlow()
198 // nullptr (see API docs for TII->analyzeBranch). For the rest of the in endsWithCondControlFlow()
205 // there isn't need for any protection - whether the branch is speculated in endsWithCondControlFlow()
206 // correctly or not, we end up executing the architecturally correct code. in endsWithCondControlFlow()
221 BuildMI(MBB, MBBI, DL, TII->get(AArch64::DSB)).addImm(0xf); in insertFullSpeculationBarrier()
222 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ISB)).addImm(0xf); in insertFullSpeculationBarrier()
231 BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::CSELXr)) in insertTrackingCode()
266 DL = (--MBB.instr_end())->getDebugLoc(); in instrumentControlFlow()
292 MachineInstr &MI = *--I; in instrumentControlFlow()
308 // already to do this - but it's unclear if that could easily be used here. in instrumentControlFlow()
324 // basic block where a propagate-taint-to-sp operation is needed, just in instrumentControlFlow()
328 (MBB.begin())->getDebugLoc()); in instrumentControlFlow()
363 // barrier to block potential miss-speculation in flight coming in to this in insertSPToRegTaintPropagation()
371 BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri)) in insertSPToRegTaintPropagation()
377 BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr)) in insertSPToRegTaintPropagation()
388 // miss-speculation when returning from this function, and therefore, also in insertRegToSPTaintPropagation()
389 // no need to encode potential miss-speculation into the stack pointer. in insertRegToSPTaintPropagation()
394 BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri)) in insertRegToSPTaintPropagation()
400 BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs)) in insertRegToSPTaintPropagation()
406 BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri)) in insertRegToSPTaintPropagation()
429 // Make GPR register Reg speculation-safe by putting it through the
453 TII->get(Is64Bit ? AArch64::SpeculationSafeValueX in makeGPRSpeculationSafe()
484 // easy to do efficiently on GPR registers, so for loads into non-GPR in slhLoads()
492 // hardened, leading to this load not able to execute on a miss-speculated in slhLoads()
498 // updated by this instruction - it makes them contain a new value that is in slhLoads()
507 // compile-time constant stack offsets", in in slhLoads()
515 // FIXME: For pre/post-increment addressing modes, the base register in slhLoads()
516 // used in address calculation is also defined by this instruction. in slhLoads()
530 // $s0 = LDRSui $sp, 22, implicit-def $q0 in slhLoads()
532 // We need to filter out these uses for non-GPR register which occur in slhLoads()
533 // because the load partially fills a non-GPR register with the loaded in slhLoads()
534 // data. Just skipping all non-GPR registers is safe (for now) as all in slhLoads()
564 // miss-speculation isn't happening because we're already inserting barriers in expandSpeculationSafeValue()
578 Is64Bit ? TII->get(AArch64::ANDXrs) : TII->get(AArch64::ANDWrs)) in expandSpeculationSafeValue()
595 "control flow miss-speculation " in insertCSDB()
598 BuildMI(MBB, MBBI, DL, TII->get(AArch64::HINT)).addImm(0x14); in insertCSDB()
662 RegsNeedingCSDBBeforeUse.resize(TRI->getNumRegs()); in runOnMachineFunction()
663 RegsAlreadyMasked.resize(TRI->getNumRegs()); in runOnMachineFunction()
671 dbgs() << "***** AArch64SpeculationHardening - automatic insertion of " in runOnMachineFunction()
680 << "***** AArch64SpeculationHardening - track control flow *****\n"); in runOnMachineFunction()
688 *Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin())); in runOnMachineFunction()