浅谈虚拟化技术难点


VMM 在 2006 年之后的确变简单了。1998年之前的 x86 是号称无法完全虚拟化的,然后“某几个人”搞了出来,于是就有了 VMware。

早期 VMM 难以实现的原因:

  • 最大难题:x86 的某些指令,在非 ring 0 的情况下执行,行为和在 ring 0 下不同,并且不会产生 fault,这导致了 trap-n-emulate 形式的 Virtualization 没办法直接实现,这也是早期被认为是无法虚拟化的主要原因。
  • 解决方法是 binary translation,代码极其复杂,需要深厚内力才能读懂,更别说写出来。compiler、OS、architecture的知识一样不能少。
  • MMU的虚拟化。虚拟内存提供了virtual address -> physical address 的 mapping,但是要想 virtualize 一个 guest OS,那么就要做到virtual address -> guest virtual physical address -> machine address 的 mapping。于是就要在MMU里面动手脚,创建一个 shadow page table,完成 virtual address -> machine address 的直接翻译,为了保持正确性,必须对OS透明地维护好TLB,并监视 guest OS 对自己认为的真正的 page table 的一切修改。这个过程可以简单粗暴,只要guest一load CR3就清空shadow page table,flush TLB。也可是十分细腻,对 shadow page table 做更加细致的更新。前者实现复杂度略低,性能自然很差,因为TLB miss rate奇高,并且由于要经常清空 shadow page table,page fault 也更多。后者性能好,但是实现异常复杂,cache consistency难以维护。
  • IO。如果不计性能,这块其实比较容易解决,但是也需要对 PCI device 的工作机制有着深厚的理解。早期的 vmm 对 IO 几乎就是直接 emulate。
  • CPU 的虚拟化,CPU 的型号一大堆,每个型号之间的指令集和指令行为都有不同。还有很多 CPU 有bug,于是为了 over come 这些,monitor 里面要做很多 ad hoc 的修改。
  • 其他:BIOS,perforamce monitoring,hardware counters,graphics,guest crash handling,interrupt delivery 等今天 VMM 难以实现:
  • CPU种类繁多
  • PCI pass through 的维护
  • 达到近乎 native running 的速度
  • 高并发 I/O
  • concurrent bugs 和 lock contention
  • numa
  • security
  • cache consistency...
  • Virtualization 的好朋友 Emulation 本身也很复杂,参考 qemu

在硬件虚拟化技术推出之前,VMware 使用动态二进制翻译(Dynamic Binary Translation,DBT)技术,其中的工作个人认为和搞编译器后端的那帮人从事的差不多,只不过 DBT 的输入已经是一段二进制指令,DBT 要将其翻译成另一段“对虚拟化友好”(能降权在 Ring 3 执行并在适当的时候让VMM得到通知)的二进制指令。概要地说,大部分算术运算指令(add、inc之类)可以保持原样或仅需微小改动,涉及处理器状态的指令(如 CLI、load/store cr3、r/w msr 等)需要产生到 VMM 的 function call 并由 VMM 模拟执行,跳转指令也需要做特殊处理。其实光写一个 x86 的 disassembler 就已经够费劲的了,更不必说这种还要对指令进行精密调整的工作了。


文章作者: sfc9982
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 sfc9982 !
  目录