接前一篇文章:
本文内容参考:
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
《深度探索 Linux 系统虚拟化原理与实现》—— 王柏生 谢广军, 机械工业出版社
特此致谢!
二、x86架构CPU虚拟化
2. x86架构虚拟化的障碍
Gerald J.Popek和Robert P.Goldberg指出,修改系统资源的、或者在不同模式下行为有不同表现的,都属于敏感指令。在虚拟化场景下,VMM需要监测这些敏感指令。 一个支持虚拟化的体系结构(架构)的敏感指令都属于特权指令 ,即在非特权级别执行这些敏感指令时,CPU会抛出异常,进入VMM的异常处理函数,从而实现了控制VM访问敏感资源的目的。
但是,x86架构恰恰不能满足这个准则。 在x86架构下,并不是所有的敏感指令都是特权指令,有些敏感指令在非特权模式下执行时并不会抛出异常 。这一点也在前文中提到过,如下:
此时VMM就无法拦截处理VM的行为了。
以修改FLAGS寄存器中的IF(Interrupt Flag)为例。
1)首先,使用指令pushf,将FLAGS寄存器的内容压到栈中;
2)然后,将栈顶的IF清零;
3)最后,使用popf指令从栈中恢复FLAGS寄存器。
如果 虚拟机 内核没有运行在ring 0,x86的CPU并不会抛出异常,而只是默默地忽略指令popf,因此,虚拟机关闭IF的目的并没有生效。
有人提出了半虚拟化的解决方案,即修改Guest(客户机)的代码,但这并不符合虚拟化的透明准则。后来,人们提出了二进制翻译的方案,包括静态翻译和动态翻译。其中,静态翻译就是在运行前扫描整个可执行文件,对敏感指令进行翻译,形成一个新的文件。但是,静态翻译必须提前处理,而且对于有些指令只有在运行时才会产生的副作用,无法静态处理。于是, 动态翻译 应运而生, 即在运行时,以代码块为单元动态地修改二进制代码 。动态翻译在很多VMM中得到应用,而且优化的效果非常不错。
更多内容请看下回。