为何x86/ARM CPU在无硬件预测时不停止间接分支推测?
正如《Intel优化手册》所述:
间接分支与调用的默认预测目标为直通路径。当该分支存在可用硬件预测时,将覆盖默认的直通预测。
对于间接JMP指令,CPU仅执行后续的直线指令。在硬件预测可用前,默认预测通常会损害性能(可能引发资源冲突并减慢分支恢复速度),还会引入*Straight-Line Speculation (SLS)*漏洞。
在间接分支后紧跟数据可能导致性能问题。若数据全为零,会被识别为一连串向内存地址的ADD指令,进而引发资源冲突并减慢分支恢复速度。此外,间接分支后的数据可能被分支预测硬件识别为分支,从而跳转到其他数据页执行,这可能导致后续的自修改代码问题。
间接调用的情况与此类似,仅解码后的指令可被复用。
为什么CPU设计者不采用类似INT3/UD2的方式停止推测?
核心原因在于性能、兼容性与硬件实现的多重约束:
性能开销过大
INT3/UD2属于异常触发指令,触发后会进入内核态处理异常,涉及流水线清空、上下文切换等操作,其延迟远高于默认预测错误带来的性能损失。在高频执行路径中,这种异常触发会导致整体性能暴跌,完全违背CPU追求高效流水线利用的设计目标。破坏向后兼容性
大量现有二进制程序(尤其是 legacy 程序)存在间接分支后紧跟数据的情况,若CPU默认触发类似INT3的行为,会直接导致这些程序崩溃,这是CPU厂商无法接受的——向后兼容是x86等指令集生态的核心支柱之一。推测机制的设计妥协
分支预测的默认直通策略是“无历史信息时的最优选择”:虽然存在安全风险,但能避免流水线空转,最大化执行效率。SLS这类漏洞属于后续发现的问题,厂商更倾向于通过微码更新、编译器插入屏障指令(如LFENCE)等软件/微代码层面的缓解方案修复,而非彻底修改硬件推测逻辑。硬件实现复杂度高
硬件层面无法100%准确区分“间接分支后的二进制内容是数据还是指令”——二者没有绝对的边界。额外添加检测逻辑会增加CPU的面积和功耗,还可能出现误判,引发新的稳定性问题。
内容的提问来源于stack exchange,提问作者Changbin Du

