Rag*_*thy 18 c c++ x86-64 sandbox virtual-memory
我正在hacks.mozilla.org上阅读64位Firefox版本的博客.
作者说:
对于
asm.js
代码,增加的地址空间还允许我们使用硬件内存保护来安全地从asm.js
堆访问中删除边界检查.收益非常显着:asmjs-apps上的8%-17%- * - arewefastyet.com上报告的吞吐量测试.
我试图了解64位硬件如何对C/C++进行自动边界检查(假设编译器支持硬件).我在SO中找不到任何答案.我找到了一篇关于这个主题的技术论文,但我无法理解这是怎么做到的.
有人可以在边界检查中解释64位硬件辅助吗?
ant*_*duh 11
大多数现代CPU实现虚拟寻址/虚拟内存 - 当程序引用特定地址时,该地址是虚拟的; 如果有的话,映射到物理页面由CPU的MMU(内存管理单元)实现.CPU通过在为当前进程设置的OS 的页表中查找,将每个虚拟地址转换为物理地址.这些查找由TLB缓存,因此大多数时候没有额外的延迟.(在某些非x86 CPU设计中,操作系统会在软件中处理TLB未命中.)
所以我的程序访问地址0x8050,它位于虚拟页面8中(假设标准的4096字节(0x1000)页面大小).CPU看到虚拟页面8被映射到物理页面200,因此在物理地址处执行读取200 * 4096 + 0x50 == 0xC8050
.(正如TLB缓存页表查找一样,更熟悉的L1/L2/L3缓存对物理RAM的缓存访问.)
当CPU没有该虚拟地址的TLB映射时会发生什么?这种情况经常发生,因为TLB的大小有限.答案是CPU生成页面错误,由OS处理.
页面错误可能会导致多种结果:
相关案例是3号.当发生段错误时,操作系统的默认行为是中止该过程并执行诸如写出核心文件之类的操作.但是,允许进程捕获自己的段错误并尝试处理它们,甚至可能不停止.这是事情变得有趣的地方.
我们可以利用这个优势来执行"硬件加速"索引检查,但是我们尝试这样做时会遇到更多绊脚石.
首先,一般的想法:对于每个数组,我们将它放在自己的虚拟内存区域中,所有包含数组数据的页面都照常映射.在实际数组数据的任一侧,我们创建了不可读和不可写的虚拟页面映射.如果您尝试在阵列外部读取,则会生成页面错误.编译器在创建程序时插入自己的页面错误处理程序,它处理页面错误,将其转换为索引越界异常.
第一个绊脚石是我们只能将整个页面标记为可读或不可读.数组大小可能不是页面大小的偶数倍,因此我们遇到问题 - 我们无法在数组结束之前和之后准确地放置数据块.我们能做的最好的事情是在数组开始之前或数组与最近的'fence'页面之间的数组结束之后留下一个小间隙.
他们如何解决这个问题?那么,在Java的情况下,编译执行负索引的代码并不容易; 如果确实如此,那么无论如何都是无关紧要的,因为负索引被视为无符号,这使得索引远远超出数组的开头,这意味着它很可能会击中未映射的内存,并且无论如何都会导致错误.
所以他们所做的就是对齐数组,使数组的末端直接对着页面的末端,就像这样(' - '表示未映射,'+'表示已映射):
-----------++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
| Page 1 | Page 2 | Page 3 | Page 4 | Page 5 | Page 6 | Page 7 | ...
|----------------array---------------------------|
Run Code Online (Sandbox Code Playgroud)
现在,如果索引是数组的末尾,它将触及第7页,这是未映射的,这将导致页面错误,这将变成索引超出范围的异常.如果索引在数组的开头之前(也就是说,它是负数),那么因为它被视为无符号值,它将变得非常大且为正,使我们再次超过第7页,导致未映射的内存读取,从而导致页面错误,它将再次变成索引超出范围的异常.
第二个绊倒的是我们在映射下一个对象之前应该留下大量未映射的虚拟内存超过数组的末尾,否则,如果索引超出范围,但是远远超出界限,它可能会命中一个有效页面并且不会导致索引越界异常,而是会读取或写入任意内存.
为了解决这个问题,我们只使用了大量的虚拟内存 - 我们将每个数组放入其自己的4 GiB内存区域,其中只有前N个页面实际映射.我们可以这样做,因为我们只是在这里使用地址空间,而不是实际的物理内存.64位进程有大约40亿个4 GiB区域的内存块,因此在用完之前我们有足够的地址空间可供使用.在32位CPU或进程上,我们只能使用很少的地址空间,因此这种技术不太可行.事实上,许多32位程序现在正在耗尽虚拟地址空间,只是试图访问实际内存,从未尝试在该空间中映射空的"fence"页面以尝试用作"硬件加速"索引范围检查.
归档时间: |
|
查看次数: |
548 次 |
最近记录: |