cpu_speculates
为了进一步提升指令执行效率,编译器与 CPU 都提供各自的优化策略。
编译器提供 likely() and unlikely()
函数给软件显式使用,用于告诉编译器哪一个分支执行概率大,从而帮忙编译器更好地优化代码执行,来提升指令执行效率。
CPU 提供了 speculative execution(推测执行),这是硬件内部优化技术,无需软件进行任何操作。主要动作是 CPU 尝试猜测下一步指令并预先执行,从而在需要时可以更快地提供结果,来提升指令执行效率。
这里有一个问题,CPU speculative execution 是来自于未经验证的数据,可能导致数组越界访问内存区域(如果这块内存区域刚好存储密码等重要信息),虽然该分支最终不会被实际执行,但是由于 L1/L2/L3 cache 的原因,这些预先执行指令得到的数据会存在 cache 中,然后就能够利用 cache 执行速度比普通内存快的特征来判断,得到这些缓存在 cache 中的数据。这也就是著名的 Meltdown/Spectre 安全漏洞。
下面是一个伪代码:
当 CPU 执行 foo()
时,CPU speculative execution 可能预先执行 val = array[index]
,这样即使后面真正执行 if (index < size)
无法成立, 但是 array[index]
值已经缓存在 cache 中,然后就能够利用 cache 执行速度比普通内存快的特征来判断,得到这些缓存在 cache 中的数据。
于是我们需要告诉 CPU 硬件不要做分支预测或者说控制 index
不要越界,这就是 array_index_nospec()
的功能。
修改后的伪代码:
修改后,当 CPU speculative execution 时,array_index_nospec()
能够保证 index 是一个合法值,从 而 不会导致非法 array[index]
值被缓存在 cache 中。
还有其它一些防止 CPU speculative execution 带来的额外问题,可以参考 include/linux/nospec.h
。
Last updated
Was this helpful?