先执行,后确认

推测执行是在某些控制或数据条件尚未确定时,先按暂定判断执行指令的技术。这里讨论现代处理器中的机制,以英特尔公开文档描述的实现为例,而非所有形式的预计算。它的用途是减少等待,让处理器在确认分支方向或数据依赖的同时,利用执行资源开展后续工作。

例如程序必须先判断某个值是否为零,才能选择下一段计算。若条件结果还在等待内存,处理器可以预测分支方向并先执行该路径。预测正确,且其他必要条件满足后,结果才可成为架构上可见的状态;预测错误,则丢弃依赖错误判断的执行结果,转向正确路径。这不是允许程序最后算错,而是把计算与确认分开。

参考:[1] [3]

预测、乱序与推测并非同义

预测给出“接下来可能怎样”的判断,推测执行则据此真正开展工作。乱序执行关注指令的实际执行次序:后面的指令若已具备条件,可以早于受阻的前序指令执行。三者常结合,却描述不同问题。仅有预测并不等于已经执行;也不能把每一次调整执行顺序都视为猜测分支。

架构规定的程序行为与内部时序之间有一道提交边界。英特尔手册描述的实现用重排序缓冲区分隔执行与退休阶段,并按每个逻辑处理器的程序顺序退休指令。数据也能成为推测对象:在 Intel Core 微架构所述的内存消歧机制中,某些读操作可越过地址尚未确定的较早写操作;若后来发现两者地址重叠,就重新执行该读及后续指令。因而推测不只发生在条件跳转处。

参考:[1] [2] [3]

架构撤销不等于毫无痕迹

架构状态是程序按指令集规则能依赖的寄存器、内存等状态;微架构状态则涉及实现这些规则的缓存等内部结构。被丢弃的推测指令不能提交错误的架构结果,却可能已经改变缓存内容。之后访问数据的快慢差异,便可能携带有关先前执行的信息。

这解释了为什么恢复正确控制流不等于消除所有安全影响。Spectre 类问题利用预测与推测行为形成的信息泄漏,而不是要求错误指令永久改写程序结果。不过,“存在推测”也不自动等于“任意秘密都能被读取”:能否形成泄漏,还取决于可受影响的执行路径、敏感数据、可观察通道以及实际隔离和缓解措施。

参考:[3] [4]

防护要对应具体边界

防护可以限制敏感位置的推测、约束推测路径上的数据访问,或隔离不同安全域之间的预测影响。英特尔文档区分间接分支限制与数据推测控制;这些机制各有作用对象,并不是一个开关覆盖所有情况。具体处理器上的屏障语义,也不能不加核对地照搬到另一种架构。

Linux 的 Spectre 文档分别讨论条件分支和间接分支风险,并说明缓解可能需要编译器、内核和微码配合,部分保护针对已识别代码逐处加入。系统报告的缓解状态应结合处理器型号、软件版本和威胁模型解释,不能把某项措施启用当作所有侧信道已经消失。限制推测还可能付出性能代价,安全边界与性能收益必须分开评估。

参考:[1] [4]