gpt4 book ai didi

memory - 是否有任何 CPU 具有边界检查的硬件支持?

转载 作者:行者123 更新时间:2023-12-04 18:02:49 25 4
gpt4 key购买 nike

将范围与内存段相关联似乎并不困难。然后有一个汇编指令,它将 2 个整数视为“位置”和“偏移量”(如果设置,则另一个为“数据”),并返回数据和错误代码。这意味着在使用阵列时不再需要在速度和安全性/安全性之间做出选择。

另一个示例可能是验证源自特定内存范围的指令不能物理访问该范围之外的内存的函数。如果连接到主板的所有硬件都具有此功能(并且相互兼容),那么制作以与物理机几乎相同速度运行的完美虚拟机将是微不足道的。

达斯汀·苏达克

最佳答案

是的。
几十年前,Lisp machines执行同时验证检查(例如类型检查和边界检查),因为程序运行时假设程序和状态是有效的,如果检查失败则“回到过去”——不幸的是,这种获得“免费”运行时验证的能力在以下情况下丢失了传统(即 x86)机器成为主导。

https://en.wikipedia.org/wiki/Lisp_machine

Lisp Machines ran the tests in parallel with the more conventional single instruction additions. If the simultaneous tests failed, then the result was discarded and recomputed; this meant in many cases a speed increase by several factors. This simultaneous checking approach was used as well in testing the bounds of arrays when referenced, and other memory management necessities (not merely garbage collection or arrays).


幸运的是,我们终于从过去慢慢地、逐步地​​重新引入这些创新 - Intel's "MPX" (Memory Protection eXtensions)用于 x86 的 Skylake 代处理器中引入了硬件边界检查 - 尽管它并不完美。
(x86 在其他方面也是一种回归:IBM 的大型机在 1980 年代具有真正的硬件加速系统虚拟化——直到 2005 年我们才在 x86 上使用英特尔的“VT-x”和 AMD 的“AMD-V”扩展)。
x86 BOUND从技术上讲,x86 确实有硬件边界检查: the BOUND instruction于 1982 年在 Intel 80188 中推出(以及 Intel 286 及更高版本,但不包括 Intel 8086、8088 或 80186 处理器)。
BOUND指令确实提供了硬件边界检查,我知道它间接导致了性能问题,因为它破坏了硬件分支预测器( according to a Reddit thread ,但我不确定为什么),但也因为它需要在内存中的元组中指定边界- 这对性能来说很糟糕 - 我知道在运行时它并不比手动执行“如果 index 不在范围内 [x,y] 然后向程序或操作系统发出 BR 异常信号”的指令更快(所以你可能会想象添加 BOUND 指令是为了方便那些手工编写汇编代码的人,这在 1980 年代非常普遍)。 BOUND指令仍然存在于今天的处理器中,但它没有包含在 AMD64 (x64) 中 - 可能是出于我上面解释的性能原因,也因为可能很少有人使用它(编译器可以轻松地用手动边界检查替换它) ,无论如何这可能具有更好的性能,因为它可以使用寄存器)。
将数组边界存储在内存中的另一个缺点是其他地方的代码(不受 BOUNDS 检查的约束)可能会覆盖先前为另一个指针编写的边界并以这种方式绕过检查 - 这主要是故意的代码问题尝试禁用安全功能(即恶意软件),但如果边界存储在堆栈中 - 并且考虑到破坏堆栈是多么容易,它的实用性就更少了。
英特尔 MPX
英特尔 MPX 于 2015 年在 Skylake 架构中引入,应该出现在主流英特尔酷睿家族(包括至强、赛扬和奔腾的非 SoC 版本)的所有 Skylake 和后续处理器型号中。从 2016 年开始,英特尔还在 Goldmont 架构(Atom 以及赛扬和奔腾的 SoC 版本)中实现了 MPX。
MPX优于 BOUND因为它提供了专用寄存器来存储边界范围,因此与 BOUND 相比,边界检查应该几乎为零成本。这需要内存访问。在 Intel 486 上 BOUND说明 takes 7 cycles (与 CMP 相比,即使操作数是内存地址,它也需要 only 2 cycles)。在 Skylake 中,MPX 等价物( BNDMKBNDCLBNDCU )都是 1 周期指令和 BNDMK可以摊销,因为它只需要为每个新指针调用一次)。
我找不到任何关于 AMD 是否已经实现了他们自己的 MPX 版本的信息(截至 2017 年 6 月)。
对 MPX 的批判性思考
不幸的是,MPX 的当前状态并不是那么乐观 - a recent paper by Oleksenko, Kuvaiskii, et al. in February 2017 "Intel MPX Explained" ( PDF link :警告:尚未经过同行评审)有点关键:

Our main conclusion is that Intel MPX is a promising technique that is not yet practical for widespread adoption. Intel MPX’s performance overheads are still high (~50% on average), and the supporting infrastructure has bugs which may cause compilation or runtime errors. Moreover, we showcase the design limitations of Intel MPX: it cannot detect temporal errors, may have false positives and false negatives in multithreaded code, and its restrictionson memory layout require substantial code changes for some programs.


还要注意,与过去的 Lisp 机器相比,英特尔 MPX 仍然是内联执行的——而在 Lisp 机器中(如果我的理解是正确的)边界检查在硬件中同时发生,如果检查失败则向后跳转;因此,只要正在运行的程序的指针不指向越界位置,那么运行时性能成本就绝对为零,所以如果您有以下 C 代码:
char arr[10];
arr[9] = 'a';
arr[8] = 'b';
然后在 MPX 下执行:
Time    Instruction              Notes
1 BNDMK arr, arr+9 Set bounds 0 to 9.
2 BNDCL arr Check `arr` meets lower-bound.
3 BNDCU arr Check `arr` meets upper-bound.
4 MOV 'a' arr+9 Assign 'a' to arr+9.
5 MOV 'a' arr+8 Assign 'a' to arr+8.
但是在 Lisp 机器上(如果可以神奇地将 C 编译为 Lisp...),那么计算机中的程序-阅读器-硬件就有能力在执行“实际”指令的同时执行额外的“辅助”指令,从而允许“边”指令指示计算机在出现错误时忽略“实际”指令的结果:
Time    Actual instruction    Side instruction
1 MOV 'A' arr+9 ENSURE arr+9 BETWEEN arr, arr+9
2 MOV 'A' arr+8 ENSURE arr+8 BETWEEN arr, arr+9
我了解“侧面”指令的每周期指令与“实际”指令不同 - 因此对 Time=1 处的指令进行侧面检查可能只有在“实际”说明已经进展到 Time=3 后才能完成。 - 但如果检查失败,那么它会将失败指令的指令指针传递给异常处理程序,该异常处理程序将指示程序忽略在 Time=1 之后执行的指令的结果。 .我不知道他们如何在没有大量内存或一些强制执行暂停的情况下实现这一目标,也可能是内存围栏 -
这超出了我的回答范围,但至少在理论上是可能的。
(请注意,在这个人为的示例中,我使用了 constexpr 编译器可以证明的索引值永远不会越界,因此将完全省略 MPX 检查 - 所以假装它们是用户提供的变量 :) )。
我不是 x86 方面的专家(或者在微处理器设计方面有任何经验,我没有在 UW 上过 CS500 级别的类(class)并且没有做功课......)但我不相信边界的并发执行 -尽管存在乱序执行的现存实现,但 x86 的当前设计不可能进行检查或“时间旅行”——但是,我可能是错的。我推测,如果所有指针类型都被提升为 3 元组( struct BoundedPointer<T> { T* ptr, T* min, T* max } - 这在技术上已经发生在 MPX 和其他基于软件的边界检查中,因为每个 protected 指针在 BNDMK 被调用时都定义了其边界)然后MMU 可以免费提供保护——但现在每个指针将消耗 24 个字节的内存,而不是当前的 8 个字节——或者与 32 位 x86 下的 4 个字节相比——RAM 充足,但仍然是有限的不应该浪费的资源。
海湾合作委员会中的 MPX
GCC 支持 MPX 从 5.0 到 9.1 ( https://gcc.gnu.org/wiki/Intel%20MPX%20support%20in%20the%20GCC%20compiler ),因为它的 maintenance burden 被删除了.
Visual Studio/Visual C++ 中的 MPX
Visual Studio 2015 Update 1 (2015.1) 添加了对 MPX 的“实验性”支持 /d2MPX开关( https://blogs.msdn.microsoft.com/vcblog/2016/01/20/visual-studio-2015-update-1-new-experimental-feature-mpx/ )。 Visual Studio 2017 中仍然提供支持,但微软尚未宣布它是否被视为主流(即非实验性)功能。
Clang/LLVM 中的 MPX
Clang 过去部分支持手动使用 MPX,但在 10.0 版本中完全删除了该支持
截至 2021 年 7 月,LLVM 似乎仍然能够输出 MPX 指令,但我看不到任何 MPX“通过”的证据。
英特尔 C/C++ 编译器中的 MPX
英特尔 C/C++ 编译器从 15.0 版开始支持 MPX。

关于memory - 是否有任何 CPU 具有边界检查的硬件支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40752436/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com