On 25/10/2019 13:03, Jan Beulich wrote: > On 23.10.2019 15:58, Andrew Cooper wrote: >> evaluate_nospec() is incredibly fragile, and this is one giant bodge. >> >> To correctly protect jumps, the generated code needs to be of the form: >> >> cmp/test <cond> >> jcc 1f >> lfence >> ... >> 1: lfence >> ... >> >> Critically, the lfence must be at the head of both basic blocks, later in the >> instruction stream than the conditional jump in need of protection. >> >> When a static inline is involved, the optimiser decides to be clever and >> rearranges the code as: >> >> pred: >> lfence >> <calculate cond> >> ret >> >> call pred >> cmp $0, %eax >> jcc 1f >> ... >> 1: ... >> >> which breaks the speculative safety. > Aiui "pred" is a non-inlined static inline here. There's no "optimiser decides > to be clever" in this case imo - it all is a result of not inlining, when the > construct in evaluate_nospec() is specifically assuming this wouldn't happen. > Therefore I continue to think that the description is misleading. > >> Any use of evaluate_nospec() needs all static inline predicates which use it >> to be declared always_inline to prevent the optimiser having the flexibility >> to generate unsafe code. > I agree with this part.
How about: When the compiler chooses to out-of-line the condition calculation (e.g. by not inlining a predicate), the code layout can end up as: pred: lfence <calculate cond> ret call pred cmp $0, %eax jcc 1f ... 1: ... which breaks the speculative safety, as the lfences are earlier in the instruction stream than the jump in need of protection. ? ~Andrew _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel