在硬件完全支持虚拟化之前,解决虚拟化漏洞有两个可行的方案,一个模拟执行,也就是软件的完全虚拟化,一个直接改源代码,而直接源代码改写就是类虚拟化。

这一章主要的内容是介绍借助于模拟执行的软件完全虚拟化,CPU虚拟化原理,包括解释执行、扫描与修补以及二进制代码翻译。

CPU 虚拟化

 基于软件的CPU完全虚拟化,本质就是软件模拟,好处就是VMM可以将虚拟机的整个执行过程至于控制中,VMM 执行每一条指令都有时机进行模拟,因而不会漏过需要模拟的敏感指令。

解释执行

最简单最直接的模拟技术是解释执行,模拟每条去到的指令,由于是一条条取指令而不会漏过,因此每条指令都可以看作是“陷入”了,所以解决了陷入再模拟的问题,进而避免了虚拟化漏洞。(陷入后模拟的方法,x86架构中部分敏感指令不能陷入,所以存在虚拟化漏洞)。可想而知,盲目的模拟每一条,性能会大打折扣,因此,进而诞生了改进技术。

扫描与修补

目的是让大多数的指令直接运行在物理CPU上,而把敏感指令替换为跳转指令或会陷入到VMM中去的指令。

坏处

  1. 由于特权指令和敏感指令都被模拟,各条指令的模拟执行时间或长或短
  2. 每个补丁都引入了额外的跳转,这些跳转会降低代码的局部性
  3. 由于扫描与修复直接在虚拟机内存中进行,因此需要维护一份原始的代码,用作必要时恢复

二进制代码翻译(BT binary translation)

在VMM中开辟一块代码缓存,将代码翻译好放在其中,这样Guest OS 代码不会直接被物理CPU执行,所有的代码都在缓冲中。

1.基本概念

  • 基本块:类似表示这块代码是一个队列
  • BT记住的动态翻译以基本块为单位,称之为动态代码块。
  • 翻译:模拟器对于读入的二进制代码不做限制,可以是应用程序代码、操作系统内核代码,读入的二进制代码可能包含x86 体系结构的指令,模拟器将其翻译输出为一个安全的子集,即不包含特权指令和敏感指令,因而可以运行在用户态。
    如果,原体系和目标体系结构相同的情况下,模拟器翻译方法大致可以分为:简单翻译和等值翻译。 简单翻译直接,但是指令数量会大大膨胀;等值翻译相对高效,但是动态信息困难。 大多数指令可以等值翻译,以下除外:
    1. PC相对寻址
    2. 直接控制转换
    3. 间接控制转换
    4. 特权指令