在上一期《将特权关进笼子》中,我们提到,由于操作系统内核具有访问所有软硬件资源的特权,为了避免特权被滥用,工程师们将虚拟机上的操作系统关进了ring1的笼子,不允许它在ring0中为所欲为。但是,为了执行一些完成系统功能所必须的特权指令,系统会付出较高的性能代价。
实际上,由于这个原因,Intel x86被贴上了“不适合做虚拟化”,甚至“不适合作为服务器”的标签。
正如德国作家西蒙娜·波伏娃在《Le Deuxième Sexe》中提到的那样,即使一个群体身上被贴上低人一等或从属地位的标签,有非常厚重的历史原因,这个群体期望推翻不公正的待遇,最好的办法就是从自身做起。
因此,为了推翻这不公正的待遇,Intel在2008年推出了VMX(Virtual Machine eXtensions,虚拟机扩展)技术。VMX从体系架构层面正视了虚拟机的存在,定义了两种软件程序:
- VMM(Virtual Machine Monitors),在VMM中可以真正地访问所有的处理器资源和其他硬件资源,如物理内存、中断资源和IO端口(如果在ring0里面)。
- Guest Software,也就是虚拟机本身。在虚拟机内只能访问分配给该虚拟机的物理内存、存储、图形硬件及IO端口等资源,它受到VMM的监管。
同时,VMX也扩展了10条虚拟化专用指令和VMX Root和VMX Non-root两种工作模式,配合Ring3~Ring0四种特权环,一共出现了8种工作模式。为了避免有的读者读到这里进入迷惑状态,我们用一张图来表示这8种工作模式:
如图,宿主机上的操作系统内核,以及KVM这一类运行在内核中的VMM都运行在VMX Root的Ring0。而虚拟机上GuestOS的内核运行在VMX Non-root模式下的Ring0。
由于VMX Non-root下,即使代码跑在ring0中,也只能访问VMM为虚拟机分配的CPU、RAM、存储及其他IO资源,VMM不再需要在守护进程中捕捉GuestOS的特权指令防止其越权,并通过代价巨大的二进制翻译来使之正确执行,从前被诟病的Intel处理器的虚拟化性能损耗现象,也通过VMX的应用而不再存在。
那么,怎么样可以让处理器在VMX Root和VMX Non-root模式之间切换呢?
我们再次翻开厚厚的《Intel 64 & IA32 architectures software developer manual》,在3C卷中,给出了虚拟机与VMM的交互示意图:
如图,在root下执行VMXON指令,处理器使能VMX模式,并可以执行VMM程序,工作在VMX Root模式下。VMX Root切换到VMX Non-root需要在保护模式的ring0下执行VM Entry(否则会导致General Protection异常),而虚拟机中的一些事件也会导致VM Exit,退回到VMM中。而这些导致VM Exit的事件,正是虚拟机不应当处理,而应当由宿主机处理的事件:
1) 执行无条件引发VM exit的指令。包括CPUID,GETSEC,INVD与XSETBV指令以及除VMFUNC指令外其他VMX指令;
2) 遇到无条件引发VM exit的未被阻塞的事件。例如,INT信号,SIPI消息等;
3) 遇到VMM设置引发VM exit的条件,包括执行某些特殊指令或者遇到某些事件发生,如试图访问未授权的特定外设;
有了Intel的VMX指令体系,我们就可以在指令集层面真正支持虚拟化了。但是,正如西蒙娜·伏波娃指出的,当妇女从事具有创造性的工作,她们才会更有价值,而不是像所谓“田园女权”那样只会索取而不奉献。从这个意义而言,真正的女性解放,只有在十月革命和五四运动在俄国和中国开始萌芽,并在革命与建设中逐渐成为社会的共识。
同样地,Intel x86体系的虚拟化,仅仅甩掉性能方面的负面标签,在成为业界主流,并掀翻PowerPC的反动统治,还经历了很多艰辛。
我们将在下一期中解密这一切。