自行车棚

  下载本文的PDF版本 PDF

线性地址空间

任何速度下都不安全

Poul-Henning Kamp

最近,我购买了一台配备全新 M1 CPU 的 Apple 电脑,以补充被称为 Varnish Cache 持续集成集群的兽群。让我有点印象深刻的是,它能够与从 IBM 借来的 s390x 虚拟机正面交锋,而且功耗从不超过 25 瓦,但除此之外:也就那样...

这就是作为系统程序员的一个缺点:你会近距离地看到,每一代架构都受到了又一个“扩展”、“加速器”、“缓存”、“旁路缓冲器”或某种其他“微架构”的影响,以至于曾经美好且正交的架构几乎被随之而来的“改进”所掩盖。这似乎就像一条自然规律:任何成功的计算机架构,在“改进”和“保持 100% 兼容”的巨大压力下,都会变成一团复杂的混乱。

如果有人把 IBM S/360 称为 RISC 设计,我会告诉你这个人今天正在使用 s390 指令集。

或者这样说:ARM 的第一条规则是,“我们不谈论 Thumb-2。”

当 AMD 创建 x86-64 指令集,以便在 x86 架构的名义所有者英特尔几乎完全放弃它,并因命运多舛的 Itanium 架构而完全陷入“第二系统综合症”之后,保持 x86 架构的活力时,就发生了这条规律的一个非常特殊的例子。

从根本上说,我们现在同时拥有 ARM 和 x64 这两种 CPU,而且它们都遭受着相同的架构问题。例如,以从线性虚拟地址到线性物理地址的转换为例。页表树不仅已经增长到整整几层,而且还有多种页面大小,每种页面大小都带有自己的一系列脚注,限制了可用性和通用性。

既然今天几乎所有东西都是面向对象的,那么我们为什么首先要有线性物理地址和虚拟地址呢?

线性虚拟地址是为了向后兼容具有线性物理地址但没有虚拟内存的小型计算机而创建的。仍然存在线性虚拟地址,它们向后兼容那些向后兼容...的计算机。

除了最小的微控制器之外,没有人会再使用线性地址空间了,无论是物理的还是虚拟的。任何实时内核或操作系统内核做的第一件事就是在线性空间之上实现一个抽象对象存储。如果机器有虚拟内存支持,那么它会尽力从虚拟地址映射到物理地址,考虑到五级页表以及随之而来的所有东西。

从线性虚拟地址转换为线性物理地址既缓慢又复杂,因为 64 位可以寻址大量内存。

拥有单个线性映射在映射本身所需的内存方面将是极其昂贵的,因此转换使用截断的树结构,但这增加了一系列新的可能异常:如果用于缺失页表项异常处理程序的页表项目录项的页表项本身为空怎么办?

这就是“双重错误异常”和“F00F 解决方法”的起源地。在最坏的情况下,使用五级页表,CPU 甚至需要进行五次内存访问才能知道数据在哪里。

本不该如此。

我在 datamuseum.dk 做的志愿活动之一是编写一个对一台独特而晦涩的计算机进行软件仿真的程序:Rational R1000/s400。(没关系;你可以查一下。我会等,因为直到一台机器摆在我们家门口,我才听说过它。)

R1000 有许多有趣的方面,其中最重要的一点是,它是由一些非常聪明且经验丰富的人创造的,他们敢于大胆创新。他们确实做到了:指令集是 Ada 原语,它对任何对齐方式的位字段进行操作,数据总线是 128 位宽:64 位用于数据,64 位用于数据类型。他们还将其制造成一个四 CPU 系统,所有 CPU 在相同的 64 位全局地址空间中运行。它还需要通过十几根焊接电缆向背板输送良好的 1000 安培 5 伏电压。

全局 64 位地址空间不是线性的;它是一个对象缓存,使用(对象 + 偏移量)元组寻址,如果对象的该页未缓存,则微代码陷阱会将其从磁盘中调入。

在营销材料中,对象缓存被宣传为“内存板”,但在硬件中,它们包含一个四路组相联缓存,它巧妙地在 DRAM 内存周期的 RAS(行地址选通)部分期间隐藏了标签 RAM 查找,因此它的速度与正常的线性 DRAM 内存完全一样快。

当今最先进的 CPU 仍然只能寻址大约 57 位的地址空间,使用五级页表,每一级都连续且缓慢地筛选出另外 10 位地址。

R1000 在每次内存访问中都能立即寻址 64 位地址空间。在您告诉我这是不可能的之前:这台计算机就在隔壁房间,它是在 20 世纪 80 年代后期使用 74xx-TTL(晶体管-晶体管逻辑)芯片制造的。它在当时可以工作,而且今天仍然可以工作。

R1000 取得了巨大的商业成功,或者我猜我应该说是军事上的成功,因为大多数客户都在国防工业,而且价格令人瞠目结舌,每台 100 万美元。它还配备了第一个完全语义化的 IDE,但这又是另一个故事了。

考虑到 Ada 以强类型而闻名,在硬件而不是编译器中处理类型信息可能听起来很奇怪,但这里有一个问题:Ada 的变体数据结构可能会使确定对象有多大以及在其中找到东西的位置成为一项非常艰巨的任务。在硬件中将数据+类型作为一个单元处理可以使其速度更快。

并非在硬件中进行类型检查是一个坏主意。恰恰相反:ARM 最近宣布,它已使用剑桥大学 CHERI 架构的 Morello 实现原型化了硅芯片,这让我对未来更好的软件质量充满了希望。

简而言之,CHERI 使指针在硬件中成为与整数不同的数据类型,并阻止两种类型之间的转换。在 CHERI 下,新的有效指针只能通过从现有的有效指针派生来创建,可以通过限制允许的范围或限制权限。如果您尝试通过任何其他方式创建或修改指针,它将不再是指针,因为硬件将清除内存中将其标记为有效指针的特殊位。

根据微软研究院的说法,CHERI 将确定性地检测并阻止 2019 年报告给该公司的安全问题的整整 43%。为了让您对这个数字有一个概念:美国国家公路交通安全管理局报告称,在交通事故中丧生的人中,有 47% 没有系安全带。

就像强制性安全带一样,有些人认为,如果每个人都“只使用类型安全的语言”,或者他们会声称 CHERI 指针携带的“能力”的额外位会使他们的程序看起来臃肿,那么就没有必要使用 CHERI。

我对此不屑一顾。

线性地址空间作为一个概念,在任何速度下都是不安全的,并且它迫切需要强制性的 CHERI 安全带。但更好的做法是完全摆脱线性地址空间,回到未来,就像 30 多年前在 Rational R1000 计算机中成功实现的那样。

 

Poul-Henning Kamp ([email protected]) 在创建 Varnish HTTP Cache 软件之前,曾作为 FreeBSD 操作系统的主要开发人员之一工作了十多年,大约五分之一的网络流量会在某个时候通过该软件。他居住在他的家乡丹麦,在那里他作为一名独立承包商谋生,专门从事让计算机做奇怪的事情。他最近的项目之一是一个超级计算机集群,用于阻止欧洲南方天文台 (ESO) 新 ELT(极大望远镜)的镜子中的星星闪烁。

版权所有 © 2022,所有者/作者持有。出版权已授权给 。

acmqueue

最初发表于 Queue 第 20 卷,第 2 期
数字图书馆 中评论本文





更多相关文章

Catherine Hayes, David Malone - 质疑非密码散列函数的评估标准
虽然密码和非密码散列函数无处不在,但在它们的设计方式上似乎存在差距。密码散列存在许多由各种安全需求驱动的标准,但在非密码方面,存在一定程度的民间传说,尽管散列函数历史悠久,但尚未得到充分探索。虽然针对现实世界数据集的均匀分布很有意义,但在面对具有特定模式的数据集时,这可能是一个挑战。


Nicole Forsgren, Eirini Kalliamvakou, Abi Noda, Michaela Greiler, Brian Houck, Margaret-Anne Storey - DevEx 行动
随着领导者寻求在财政紧缩和人工智能等变革性技术的背景下优化软件交付,DevEx(开发者体验)在许多软件组织中越来越受到关注。技术领导者凭直觉接受良好的开发者体验能够实现更有效的软件交付和开发者幸福感。然而,在许多组织中,旨在改进 DevEx 的拟议举措和投资难以获得支持,因为业务利益相关者质疑改进的价值主张。


João Varajão, António Trigo, Miguel Almeida - 低代码开发生产力
本文旨在通过展示使用基于代码、低代码和极端低代码技术进行的实验室实验结果来提供关于该主题的新见解,以研究生产力方面的差异。低代码技术已清楚地显示出更高的生产力水平,为低代码在短期/中期内主导软件开发主流提供了强有力的论据。本文报告了程序和协议、结果、局限性和未来研究的机会。


Ivar Jacobson, Alistair Cockburn - 用例至关重要
虽然软件行业是一个快节奏且令人兴奋的世界,其中不断开发新的工具、技术和技术来服务于商业和社会,但它也很健忘。在其快速前进的过程中,它容易受到时尚潮流的影响,并且可能会忘记或忽略针对其面临的一些永恒问题的行之有效的解决方案。用例最初于 1986 年引入,后来得到普及,就是这些行之有效的解决方案之一。





© 保留所有权利。

© . All rights reserved.