IA-32 架构的纯软件虚拟化解决方案简介

写在前面

本文章属于虚拟化技术系列文章,点击查看本系列的说明

阅读本文请先阅读下面的虚拟化技术的术语以了解相关术语。

IA-32 架构面临的挑战

IA-32 架构起初并不是为了虚拟化设计的,它的目标是在处理器上运行最多一个操作系统,所以在 Intel VT 出现之前, IA-32 架构上的虚拟化解决方案就只有纯软件虚拟化了。

IA-32 架构的权限等级

Intel 处理器提供了四种权限级别,分别为 Ring0、Ring1、Ring2 和 Ring3,权限依次降低,Ring0 拥有最高权限。所以一些特权指令只能在 Ring0 下才可以正常使用。大多数 IA-32 架构的应用运行在 Ring3。

然而一些操作系统的组件必须运行在 Ring0,但是要实现纯软件的虚拟化就必须让 VMM 独占 Ring0。因为 VMM 要虚拟化出若干组硬件来供 GuestOS 使用,这就要保证 GuestOS 不能直接控制物理硬件。

特权解除和陷入模拟

因此出现了一种技术被称为“特权解除和陷入模拟”。

特权解除是指将 VMM 运行在 Ring0,而虚拟机中的操作系统运行在 Ring1。这样就可以保证 GuestOS 无法越过 VMM 去执行特权指令导致虚拟化失效。

同时由于 IA-32 架构下运行特权指令的时候如果权限不足会自动陷入权限更高的 Ring 中。所以当 GuestOS 执行特权指令的时候会陷入 Ring0,此时由 VMM 接管并模拟特权指令的执行,这就叫陷入模拟。

不幸的是整个过程没有看起来那么简单。究其根本是因为虚拟机中的软件并不是为了虚拟化而编写的。

有的指令在非 Ring0 下运行会返回一个包含当前 Ring 值的返回值,GuestOS 会去读取这个值,一旦发现自己没有运行在 Ring0 下就会出现错误。这也就导致了这类指令的调用无法被 VMM 检测到,自然也就无法模拟了。

另一个问题是操作系统在编写的时候并没有支持操作系统级的上下文切换,所以一些上下文可能会在很隐蔽的角落。当 VMM 切换上下文的时候这些信息就会丢失导致错误。

并非只有这些问题,受限于篇幅问题就不再多说了,读者有兴趣可以自行查阅资料。

纯软件解决方案

为了应对这些挑战,设计人员给出了两种软件层面的途径去开发 VMM,分别是半虚拟化(Paravirtualization)和二进制翻译(Binary Translation)。

半虚拟化(Paravirtualization)

这种方法需要修改 GuestOS 的源代码使得其可以在特定的 VMM 下运行。比如敏感指令替换为 hypercall。hypercall 直译为超级调用,可以陷入到 VMM 中以便 VMM 去模拟指令的运行。

这种方式的好处是基本没有性能损失。但是坏处也很明显,它只能用于开源的操作系统,比如 Linux。

二进制翻译(Binary Translation)

这个方法是将 GuestOS 的二进制指令翻译为另一种类指令,通常是翻译为 vCPU 可以识别的指令。它的特殊之处在于大多数情况下我们都是将源代码或者 IR(Intermediate Representation) 翻译为二进制代码,但是二进制翻译是将二进制代码翻译为另一类代码。按照翻译的时机分类又分为静态翻译和动态翻译。

静态翻译(Static Binary Translation)

即在运行 GuestOS 前一次性地将全部的代码翻译为目标指令。这样做可以最大限度地提高性能,但是这个方法实际上并不可行。

最大的难题是冯·诺依曼体系结构下指令和数据存储在一个存储器上,并未区分指令存储器和数据存储器。也就是说对于一堆静态的二进制数据,我们无法确定它到底是代码还是数据。这也就导致静态翻译可能错误地将数据翻译为代码从而导致错误。

还有一个问题是有些程序会在运行时修改自己,而静态翻译是一次性的,这也会导致错误。

动态翻译(Dynamic Binary Translation)

动态翻译就是在运行时以一种类似按需翻译的方式去翻译 GuestOS 的二进制指令。这可以很好地解决静态翻译带来的问题。

因为只会翻译被执行的部分,所以不会错误地将数据翻译为二进制代码。同时由于翻译并不是一次性地工作,也可以解决程序修改自身所带来的问题。

不过实际实现起来会有很多问题,比如何时启动翻译、翻译什么和翻译多少。这也是本系列的后续任务,将会简单地介绍一些实现动态翻译中遇到的问题和解决方法。本文在这一点不做过多讨论。

参考资料

本文作者:ADD-SP
本文链接https://www.addesp.com/archives/1891
版权声明:本博客所有文章除特别声明外,均默认采用 CC-BY-NC-SA 4.0 许可协议。
暂无评论

发送评论 编辑评论


上一篇
下一篇