CPU纯软件半虚拟化技术

在2003年出现的Xen,使用了另外的一种半虚拟化的方案来解决x86架构下CPU的敏感指令问题。主要采用Hypercall技术。Guest OS的部分代码被改变,从而使Guest OS会将和特权指令相关的操作都转换为发给VMM的Hypercall(超级调用),由VMM继续进行处理。而Hypercall支持的批处理和异步这两种优化方式,使得通过Hypercall能得到近似于物理机的速度。

1、Hypercall技术

  对于x86体系结构CPU,Xen使用超级调用来替换被监控的操作,其中包括x86架构下的敏感指令。Xen所采用的超级替换的方法是一种全新的设计理念:它将问题的中心,由VMM移向Guest OS自身,通过主动的方式由Guest OS去处理这些指令,而不是被移交给VMM做处理,在这种设计理念下,修改Guest OS内核。

能修改Guest OS是半虚拟化的一个技术核心。通过修改Guest OS的内核。使Guest OS明确知道自己是运行在1环上,而不是通常OS的0环,有效的避免了虚拟化的执行冲突问题。Guest OS也清楚VMM给自己提供了一个虚拟的寄存器组,并能通过其他方式去访问他们,避免了访问冲突的问题。

解决了敏感指令问题只是解决了x86架构下的半虚拟化的第一步。运行在1环的操作系统没有权限执行的指令,交给0环的VMM来处理,这个很大程度上与应用程序的系统调用很类似:系统调用的作用是把应用程序无权执行的指令交给操作系统完成。因此,Xen向Guest OS提供了一套“系统调用”。以方便Guest OS调用,这部分”系统调用“就是超级调用Hypercall。

超级调用Hypercall的机制使用,不仅使x86架构的指令虚拟化得以实现,也为后面的内存虚拟化和I/O虚拟化提供了新的思路和方法,超级调用和事件通道是整个半虚拟化的基础。

下面我们来看看半虚拟化情况下整体的访问流程图,如图所示。

CPU半虚拟化技术

上图明确的显示了Hypercall的调用位置,在Xen中,各组件通信方式如下所示,Hypercall的调用性质是同步的。其他Xen的通信方式几乎都是异步的。

其中,在虚拟机和Xen的通信过程中,如果虚拟机需要调用敏感指令,会主动向虚拟机监控器发起Hypercall调用。Hypercall就如同传统操作系统下的系统调用,监管程序通过它向其上各虚拟机提供各种服务,如MMU 更新、Domain0 操作请求和虚拟处理器状态等。

下图显示了半虚拟化模式下的特权模式:

在x86架构下,原生系统和半虚拟化环境下存在差异。原生环境下,CPU有4个特权级(ring0--ring3),操作系统是处于最高级别的ring0,应用程序处于最低级别的ring3。而在半虚拟化环境下,虚拟机监视器是处于最高级别的ring0,操作系统是处于中级级别的ring1,应用程序处于最低级别的ring3。

只有特权级别为1 的代码(准虚拟化Guest VM 的内核)才能向Xen 发送Hypercall 请求,以防止应用程序(特权级3)的错误调用导致对系统可能的破坏。因此,只有运行在特权级1 的虚拟机操作系统内核才能申请Hypercall。但是,一些Xen 专用的特别程序,如xend 或xe也需要有Hypervisor 的服务来完成特殊的操作,如生成一个新的GuestVM 等,这在Xen Linux 中是通过一个称为privcmd 的内核驱动程序实现。应用程序通过ioctl 向该驱动程序提出服务请求,运行在虚拟机内核(特权级1)的privcmd 驱动程序再将服务请求以Hypercall 形式转向Hypervisor,并由后者真正完成生成新Guest VM 的动作。

上图中显示了Hypercall所在的位置,Hypercall位于图中右上方,内核向Hypervisor发起调用的哪里。Xen启用130号中断向量端口(十六进制的82H)作为超级调用的中断号。这一个中断向量的DPL被设置为类型为1,类型为中断门。这样,超级调用能够由处于特权级1的客户机操作系统发起,而不能从用户态发起。

另外,在x86指令集的指令中,有17 条指令不能有效的在ring 1 特权级上运行,Hypercall 的存在解决了这些指令不能正常执行的问题。

Hypercall 机制中,在32 位x86 架构下,Hypercall 通过int0x82陷阱(Trap)指令实现,因为传统操作系统本身并不使用int0x82 (Linux 使用int 0x80 作为系统调用指令,int 0x82 并未使用)。

  int0x82包括:

  • 超级调用号:xen/include/public/xen.h中定义了45个超级调用,其中有7个是平台相关调用。
  • 超级调用表:xen/arch/x86/x86_32/entry.S中定义了超级调用表,通过超级调用号索引就可以方便的找到对应的处理函数。
  • 超级调用页:超级调用页是Xen为Guest OS准备的一个页,可以做到不同Guest OS有不同的超级调用页内容。

  Hypercall 的具体功能识别号由eax 表明,而其他参数则在ebx, ecx, edx, esi 和edi 中。为了减少虚拟机和Hypervisor 之间的特权级别(Ring)切换次数,Xen 提供对Hypercall的批处理,即将几个Hypercall 功能请求放在一个列表中由专门的Hypercall 批处理请求完成。在Xen 中,系统调用表与Hypercall 表都在entry.S 文件中被定义。

2、X86架构特权级

x86 硬件支持 4 个特权级 (Ring),一般内核运行在 Ring 0, 用户应用运行在 Ring 3, 更小的 Ring 有比更高的 Ring 能访问更多的系统全局资源,即更高的特权。有些指令只能在 Ring 0 才能正确执行,如 LGDT、LMSW 指令,我们称之为特权指令;另外有些指令可以在 Ring 3 正确执行,如 SGDT、 SMSW、PUSHF/POPF,我们称之为非特权指令。

正常模式和虚拟化两种情况叙述下,特权模式说明如下:

正常模式:特权级别是针对段来讲的,段描述符的最后两位标识了该段所位于的特权级别,比如,中断处理程序运行于ring0(),此时的内核程序是具有特权的,即ring0。位于ring3用户程序可以通过系统调用的方式,int80,后特权翻转入ring0,然后就可以顺利执行中断处理程序(好像是用户程序调用内核程序的唯一途径)。

虚拟化情况下

特权解除:是指解除正常情况下运行于ring0的段,比如中断处理程序,为了虚拟化需要,此时解除其特权,将其运行于ring1。当用户程序通过系统调用时,其跳转到的中断处理程序运行于ring1。但是,在中断处理程序中,有部分指令是必须在ring0才能执行的,此时,便会自动陷入,然后模拟。也就是说,用户程序运行特权指令,会有两次特权下降,一次是通过系统调用进入ring1,第二次是通过特权指令陷入进入ring0。这说明,中断发生时的中断处理程序还是以前的位于内核的代码,但是其运行级别为ring1,部分指令还需要再次陷入,才能执行。另外,还有一个重要问题,就是部分敏感非特权指令无法陷入的问题:存在二进制翻译、超级调用等方式,强迫其陷入,然后模拟。

  在传统的 X86 平台上支持虚拟化上存在如下问题 :

X86 指令集中存在 17 条敏感的非特权指令,“非特权指令”表明这些指令可以在 x86 的 ring 3 执行, 而“敏感性”说明 VMM 是不可以轻易让客操作系统执行这些指令的。 这 17 条指令在客操作系统上的执行或者会导致系统全局状态的破坏,如 POPF 指令,或者会导致客操作系统逻辑上的问题,如 SMSW 等读系统状态或控制寄存器的指令。传统的 X86 没法捕获这些敏感的非特权指令。

除了那 17 条敏感的非特权指令,其他敏感的指令都是敏感的特权指令。在 x86 虚拟化环境,VMM 需要对系统资源进行统一的控制,所以其必然要占据最高的特权级,即 Ring 0, 所以为了捕获特权指令,在传统 x86 上一个直接可行的方法是 “Ring deprivileging”, 如将客操作系统内核的特权级从 Ring 0改为 Ring 1 或 Ring 3, 即 “消除” 客内核的特权,以低于 VMM所在的 Ring 0, 从而让 VMM 捕获敏感的特权指令。

3、总结

  半虚拟化的思想就是,让客户操作系统知道自己是在虚拟机上跑的,工作在非ring0状态,那么它原先在物理机上执行的一些特权指令,就会修改成其他方式,这种方式是可以和VMM约定好的,这就相当于,通过修改代码把操作系统移植到一种新的架构上来,就像是定制化。所以XEN这种半虚拟化技术,客户机操作系统都是有一个专门的定制内核版本,和x86、mips、arm这些内核版本。这样以来,就不会有捕获异常、翻译、模拟的过程了,性能损耗非常低。这就是XEN这种半虚拟化架构的优势。这也是为什么XEN半虚拟化只支持虚拟化Linux,无法虚拟化windows原因,微软不修改代码无法实现半虚拟化。

时间: 2024-11-07 08:45:30

CPU纯软件半虚拟化技术的相关文章

CPU纯软件全虚拟化技术

我们在前面的文章中提到了虚拟化技术的大致分类情况,即分为全虚拟化.半虚拟化和硬件辅助虚拟化技术3大类别.而我们虚拟化技术最主要的虚拟主体就是我们的硬件CPU.内存和IO,那么我们的CPU在全虚拟化模式下如何工作?在半虚拟化下如何工作?在硬件辅助虚拟化模式下如何工作?或着说细分下来,我们又可以分为CPU的全虚拟化技术.半虚拟化技术和硬件辅助虚拟化技术,内存的全虚拟化技术.半虚拟化技术和硬件辅助虚拟化技术以及IO设备的全虚拟化技术.半虚拟化技术和硬件辅助虚拟化技术.本次我们就来说说CPU的全虚拟化技

纯软件半虚拟化

虚拟化是一块"肥肉",思杰公司也想分一杯羹,于2003年推出了XEN虚拟化解决方案,它采用的解决方案与vmware公司的虚拟化有些不同,但是vmware公司已经占据了市场的制高点,成了虚拟化市场的霸主.我们下面来看一下,思杰公司是如何解决X86架构CPU的缺陷的,这里的缺陷就是指的是敏感指令并不全是特权指令.hypercall超级调用思杰公司采用hypercall的技术解决部门敏感指令不能被捕捉的问题.他们的思路有点像<×××帝国>的"莫费斯",他告诉了

KVM虚拟化技术(一)虚拟化简介

一 .虚拟化 虚拟化是指计算机元件在虚拟的基础上而不是真实的基础上运行.虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程.CPU的虚拟化技术可以单CPU模 拟多CPU并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率. 虚拟化的类型: 全虚拟化 半虚拟化(涉及修改guestos内核,因此仅支持开源kernel的系统) 硬件辅助虚拟化(主板上开启虚拟化支持) 几种虚拟化软件简介 KVM 完全虚拟化 架构:寄居架构(linux

虚拟化技术简介(转载学习)

虚拟化 虚拟化是指计算机元件在虚拟的基础上而不是真实的基础上运行.虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程.CPU的虚拟化技术可以单CPU模拟多CPU并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率. 几种虚拟化软件 1.RedHat KVM虚拟化方式:完全虚拟化 架构:寄居架构(linux内核);祼金属架构RHEV-H 特点:祼金属架构RHEV-H或在关键的硬盘和网卡上支持半虚拟化VirtIO,达到最佳性能.

虚拟化技术研究及架构分析

什么是虚拟化 虚拟化是指计算机元件在虚拟的基础上而不是真实的基础上运行.虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程.CPU的虚拟化技术可以单CPU模拟多CPU并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率. 几种虚拟化软件介绍 RedHat KVM 虚拟化方式:完全虚拟化 架构:寄居架构(linux内核);祼金属架构RHEV-H 特点:祼金属架构RHEV-H或在关键的硬盘和网卡上支持半虚拟化VirtIO,达到最佳

虚拟化技术原理(CPU、内存、IO)

本文来自:http://www.ywnds.com/?p=5856 虚拟化 云计算现在已经非常成熟了,而虚拟化是构建云计算基础架构不可或缺的关键技术之一. 云计算的云端系统, 其实质上就是一个大型的分布式系统. 虚拟化通过在一个物理平台上虚拟出更多的虚拟平台, 而其中的每一个虚拟平台则可以作为独立的终端加入云端的分布式系统. 比起直接使用物理平台, 虚拟化在资源的有效利用. 动态调配和高可靠性方面有着巨大的优势. 利用虚拟化, 企业不必抛弃现有的基础架构即可构建全新的信息基础架构,从而更加充分地

[虚拟化] CPU虚拟化技术 - Introduction

虚拟化技术的分类主要有服务器虚拟化.存储虚拟化.网络虚拟化.应用虚拟化. 服务器虚拟化技术按照虚拟对象来分,可分为:CPU虚拟化.内存虚拟化.I/O虚拟化: 按照虚拟化程度可分为:全虚拟化.半虚拟化.硬件辅助虚拟化. 将不同的虚拟化对象和程度组合,可得出 9种 不同的服务器虚拟化技术. 首先详细介绍下服务器虚拟化之CPU虚拟化,后续讲解中再详细介绍内存虚拟化及I/O虚拟化. 二.CPU虚拟化 ·CPU全虚拟化技术 主要采用优先级压缩技术(Ring Compression)和 二进制代码翻译技术(

全虚拟化和半虚拟化的区别 cpu的ring0~ring3又是什么概念?

ring0是指CPU的运行级别,ring0是最高级别,ring1次之,ring2更次之-- 拿Linux+x86来说, 操作系统(内核)的代码运行在最高运行级别ring0上,可以使用特权指令,控制中断.修改页表.访问设备等等. 应用程序的代码运行在最低运行级别上ring3上,不能做受控操作.如果要做,比如要访问磁盘,写文件,那就要通过执行系统调用(函数),执行系统调用的时候,CPU的运行级别会发生从ring3到ring0的切换,并跳转到系统调用对应的内核代码位置执行,这样内核就为你完成了设备访问

全虚拟化和半虚拟化的区别 cpu的ring0 ring1又是什么概念?

ring0是指CPU的运行级别,ring0是最高级别,ring1次之,ring2更次之…… 拿Linux+x86来说, 操作系统(内核)的代码运行在最高运行级别ring0上,可以使用特权指令,控制中断.修改页表.访问设备等等. 应用程序的代码运行在最低运行级别上ring3上,不能做受控操作.如果要做,比如要访问磁盘,写文件,那就要通过执行系统调用(函数),执行系统调用的时候,CPU的运行级别会发生从ring3到ring0的切换,并跳转到系统调用对应的内核代码位置执行,这样内核就为你完成了设备访问