已阅读5页,还剩23页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
虚拟化,即在一个物理机上同时运行多个操作系统实例的技术, 自 20 世纪 60 年代开始在 IBM 的大型主机等专有平台上获得了重要的应用。 自 80 年代以来,基于 X86 处理器的 PC 技术开始高速发展并变得无处不在。 然而由于 PC 的低廉价格,人们似乎淡忘虚拟化的存在意义。进入 21 世纪,随着数据中心技术的发展和 VMware 等厂商的推动,虚拟化开始进入 PC 领域,直到今天在有着广泛应用的 PC 平台上施用虚拟化技术已经成为了趋势性的事件。在 IBM 的大型主机上,虚拟化主要目的是用来让多个操作系统共享单个主机的资源,以最大化资源的利用率。 然而在今天,由于 PC 的无处不在,虚拟化的价值已经远不仅在于最大化单台物理机的资源利用率。 相比较于传统的裸机操作系统,虚拟化能带来很多新的机会和优势。 在笔者看来,虚拟化最少在如下方面好处明显 :1、应用服务的整合和安全隔离。 将多个物理机上运行的服务应用整合到一个物理机上,提高物理资源的利用率,极大的节省机房空间,提供灵活的电源管理,满足绿色经济的要求; 同时为在小的空间内部署复杂的计算或网络环境提供可能 ( 如 IP 测试床 )。 另一方面,原本运行在相同物理机上的多个应用可利用虚拟化方式部署进行隔离,提高应用的安全性。2、快速动态部署能力 快速及动态的部署使应用服务的高可用性变的更简单, 使部署大规模的计算工作变的容易; 提供商在动态部署的基础上,实行精确的按使用计费或按需计费,使计算资源租用作为一种商业模式变得更有吸引力,而计算资源租用模式本身可利用对资源的灵活分配,统一管理来节省对总体资源的消耗。3、削减操作系统和应用软件对硬件的依赖性 使大量无需或者难以升级的旧的应用系统得以在新的硬件平台上继续运行, 减少重新投资软件的必要。4、建立复杂的软件测试环境 复杂的软件测试环境通常要求多个不同级别的处理器硬件平台,并搭配不通的操作系统和编译器版本,对于一个中小型用户来说,利用物理硬件来满足这个要求通常是很困难的,然而虚拟化技术让这个要求变得容易实现,只需要虚拟化软件创建多个不同的虚拟机,仿真出不通的处理器特征,然后再安装各自的软件环境即可。 为保持 x86 平台继续在数据中心服务器,计算工作站,个人电脑等市场的无处不在地位,Intel 等 x86 厂商必然会想方设法适应虚拟化所带来的变化和要求, 在 x86 上如何优化虚拟化技术的实现,提高虚拟化的性能是他们需要考虑的重大问题。在 x86 上运行虚拟化的具体问题 虚拟化技术的一个重要要求之一就是通过虚拟机监控软件 (VMM) 运行的操作系统 ( 我们称之为客操作系统 ) 在运行时,其运行效果应该和直接在裸机上运行操作系统是一致的,即客操作系统不应该感觉到虚拟化技术的存在。 IBM 的主机采用 “trap-and-emulate” 的方法来实现 CPU 的虚拟化,即一般的指令直接运行,那些可能改变主机全局行为的“敏感指令”则会被截取,交由 VMM 通过仿真来完成其功能。 “trap-and-emulate” 被认为是实现 CPU 虚拟化的最好方法。 作者 Popek 和 GoldBerg 在 1974 年的一篇文章提出了 “classic virtualization” 的概念,该概念认为能够比较完好的实现 “trap-and-emulate”的硬件平台才是 “classically virtualizable” 的平台,即如果该平台上的 VMM 如果能够比较容易的捕获敏感指令,我们才认为该平台是典型的比较易于虚拟化的平台。 X86 平台由于其迅速的无处不在的统治力,在最初的设计上并没太多考虑虚拟化的要求,根据 GoldBerg 的标准,传统的 x86 属于非 “classically virtualizable”的平台。 Scott Robin 在 2000 年的文章以 Intel Pentium 为例详细介绍了 x86 平台在支持虚拟化方面存在的问题。GoldBerg 的标准并不排除用其他方法解决“trap-and-emulate”的问题, 如 X86 上的虚拟化提供商 VMware 和 XenSource 分别采用“Binary Translation” 和“Para-virtualization”来解决敏感指令问题。其中“Binary Translation”技术提前发现敏感的指令并通过插入断点来截获之,交由 VMM 来解释执行。 “Para-virtualization” 方法则直接修改客操作系统代码,修改其特权级,并将敏感指令改为 Trap Call 直接通知 VMM 来处理。 这两种在软件上处心积虑的方法会导致软件实现的复杂性,限制了 VMM 性能的提升空间,“Para-virtualization” 更是没法施用在 Windows 等私有操作系统上。 在说明 X86 平台对虚拟化的支持能力之前,我们有必要解释一下特权级的概念。 x86 硬件支持 4 个特权级 (Ring),一般内核运行在 Ring 0, 用户应用运行在 Ring 3, 更小的 Ring 有比更高的 Ring 能访问更多的系统全局资源,即更高的特权。 有些指令只能在 Ring 0 才能正确执行,如 LGDT、LMSW 指令,我们称之为特权指令;另外有些指令可以在 Ring 3 正确执行,如 SGDT、 SMSW、PUSHF/POPF,我们称之为非特权指令。在传统的 X86 平台上支持虚拟化上存在如下问题 :X86 指令集中存在 17 条敏感的非特权指令“非特权指令”表明这些指令可以在 x86 的 ring 3 执行, 而 “敏感性” 说明 VMM 是不可以轻易让客操作系统执行这些指令的。 这 17 条指令在客操作系统上的执行或者会导致系统全局状态的破坏,如 POPF 指令,或者会导致客操作系统逻辑上的问题,如 SMSW 等读系统状态或控制寄存器的指令。 传统的 X86 没法捕获这些敏感的非特权指令“Ring deprivileging” 带来的问题除了那 17 条敏感的非特权指令,其他敏感的指令都是敏感的特权指令。 在 x86 虚拟化环境,VMM 需要对系统资源进行统一的控制,所以其必然要占据最高的特权级,即 Ring 0, 所以为了捕获特权指令,在传统 x86 上一个直接可行的方法是 “Ring deprivileging”, 如将客操作系统内核的特权级从 Ring 0 改为 Ring 1 或 Ring 3, 即 “消除” 客内核的特权,以低于 VMM 所在的 Ring 0, 从而让 VMM 捕获敏感的特权指令。 然而,采用 “Ring deprivileging” 又会带来如下问题 : “Ring aliasing”。 该问题是指客操作系统可通过读取 cs,ss 段寄存器的值而知道其自身已经不处于 Ring 0, 这一结果理论上可以让客操作系统改变自己的行为,违背了虚拟化应该对客操作系统透明的原则。 “Ring compression”。 无论采用哪些特权级,传统 x86 都需通过分段或分页的方法来实现地址空间间的访问控制。然而传统 x86 上所有 64 位的操作系统都没使用分段,另外 x86 上的分页不区分 Ring 0、Ring 1 和 Ring 2, 也就是说 x86 上没法通过分段或分页机制来阻止 Ring 1 上的 64 位客操作系统内核来访问 VMM 的地址空间。 所以,客内核被迫采用 Ring 3, 也就是和客操作系统上的应用相同的运行级,这当然就会导致新的问题。 “Adverse Impact on Guest system calls”。 该问题和用 sysenter/sysexit 指令实现的系统调用机制有关。Sysenter 不同于 “int 0x80”, 其不需要经过异常表的控制而明确切换到 Ring 0, 所以 sysenter 是 x86 平台上性能更高的系统调用实现方式。 但在虚拟化情况下 sysenter/sysexit 带来的问题是, sysenter 让客操作系统上的应用进入 Ring 0 而不是客内核的 Ring 1, sysexit 在 Ring 1 上执行直接导致 fault, 解决这一问题的方法只能是让 VMM 来仿真 sysenter/sysexit, 或者让 VMM 向客操作系统屏蔽掉虚拟 CPU 的 sysenter 能力,无论哪种做法,都会导致客操作系统上应用性能下降。 “Address-space Compression”问题 传统 x86 上的操作系统如 Linux 都采用统一的线性地址空间,通过页表和特权级来控制用户进程对内核地址区域的访问,用户进程执行系统调用,只是改变自己的特权级,并不改变自己的地址空间,所有进程可以通过多级页表机制共享内核地址区域的内容。 那么在虚拟化环境下需要考虑的问题是, 是应该让 VMM 占据客操作系统地址空间的一部分,还是让其采用独立的地址空间? 采用前一方法对只有 4G 地址空间的 32 位客操作系统难一解决,另外要考虑如何防止客内核对 VMM 地址区域的访问,及如何保持对客操作系统的透明性。 采用后一种方法需要考虑如何快速实现地址空间切换,如何建构用于客操作系统和 VMM 间互相切换的控制结构 ( 类似于 IDT 和 GDT)。传统的 x86 似乎还没有很好的机制支持这个问题的解决 。中断的虚拟化问题。X86 操作系统的内核通过修改 EFLAGS 的 IF 位来控制外部中断的投放。 在虚拟化环境下 VMM 有诸多理由希望能统一的控制中断的投放, 然而通常情况下客操作系统对 EFLAGS.IF 的修改是很频繁的行为, 如果 VMM 通过捕获客操作系统对 EFLAGS.IF 的修改而获得对中断的控制权,显然代价过于高昂。另外一个方面是虚拟化的中断,VMM 该如何向客操作系统发起一个中断?该如何控制虚拟的中断被客操作系统投放的时间 ?对特权资源的频繁访问问题VMM 通过特权级控制来捕获客操作系统对特权资源的访问,在一般情况下不是一个问题,但对某些特权资源,如 APIC 的 TPR 寄存器,一方面客操作系统可能会频繁访问,另一方面 VMM 为了统一控制而又不得不截取之,导致的巨大性能开销是一个不得不严肃考虑的问题。Intel 和 AMD 的解决方法Intel 和 AMD 通过对其 X86 硬件架构进行扩展,解决了 X86 架构不能很好支持 “Classic Virtualization” 的问题,Intel 和 AMD 的这种 x86 虚拟化扩展分别称为 Intel VT-x 和 AMD-V( 或从代码的角度分别称为 VMX 和 SVM)。 我们认为,具有 Intel VT-x 或 AMD-V 能力的处理器都是 “classically virtualizable”的, 当然 Intel 和 AMD 不会满足于此,除了解决了前面提到的 x86 平台虚拟化存在的问题外,目前的 Intel 和 AMD 的处理器在 MMU 虚拟化和 IO 虚拟化方面都会提供相当的支持,并且在许多细节问题方面都会有所考虑。Intel VT-x 和 AMD-V 提供的特征大多功能类似,但名称可能不一样,如 Intel VT-x 将用于存放虚拟机状态和控制信息的数据结构称为 VMCS, 而 AMD-V 称之为 VMCB; Intel VT-x 将 TLB 记录中用于标记 VM 地址空间的字段为 VPID, 而 AMD-V 称之为 ASID; Intel VT-x 将二级地址翻译称之为 EPT, AMD 则称为 NPT, 等等一些区别。 读者必须注意,尽管其相似性,Intel VT-x 和 AMD-V 在实现上对 VMM 而言是不兼容的,我们后面的介绍只限于 AMD-V。AMD-V 结构简介AMD-V 在 AMD 传统的 x86-64 基础上引入了 “guest” 操作模式。 “guest”操作模式就是 CPU 在进入客操作系统运行时所处的模式。 “guest”操作模式为客操作系统设定了一个不同于 VMM 的运行环境而不需要改变客操作系统已有的 4 个特权级机制,也就是说在“guest”模式下,客操作系统的内核仍然运行在 Ring 0, 用户程序仍然在 Ring 3。 裸机上的操作系统和 VMM 所在的操作模式依然和传统的 x86 中一样,我们姑且称之为“host”操作模式。 VMM 通过执行 VMRUN 指令使 CPU 进入“guest”操作模式而执行客操作系统的代码; 客操作系统在运行时,遇到敏感指令或事件,硬件就执行 VMEXIT 行为,使 CPU 回到“host”模式而执行 VMM 的代码。 VMRUN 指令运行的参数是一个物理地址指针,其指向一个 Virtual Machine Control Block (VMCB) 的内存数据结构, 该数据结构包含了启动和控制一个虚拟机的全部信息。“guest”模式的意义在于其让客操作系统处于完全不同的运行环境,而不需要改变客操作系统的代码。“guest”模式的设立在系统中建立了一个比 Ring 0 更强的特权控制,即客操作系统的 Ring 0 特权必须让位于 VMM 的 Ring 0 特权。 客操作系统上运行的那些特权指令,即便是在 Ring 0 上也变的可以被 VMM 截取的了, “Ring Deprivileging”由硬件自动搞定。 此外,VMM 还可以通过 VMCB 中的各种截取控制字段选择性的对指令和事情进行截取,或设置有条件的截取,所有的敏感的特权或非特权指令都在其控制之中。 有了“guest”模式,前面提到的 17 条敏感非特权指令问题和 “Ring Deprivileging”带来的三个问题被简单解决。VMCBVMCB 数据结构主要包含如下内容 :1. 用于描述需要截取的指令或事件的字段列表。其中 :2 个 16 位的字段用于控制对 CR 类控制寄存器读写的截取 2 个 16 位的字段用于控制对 DR 类调试寄存器的读写的截取 一个 32 位的字段用于控制 exceptions 的截取 一个 64 位的字段用于控制各种引起系统状态变化的事件或指令的截取,如 INTR, NMI, SMI 等事 件, HLT, CPUID,INVD/WBINVD, INVLPG/INVLPGA,MWAIT 等指令, 还包括两位分别标志是否对 IO 指令和 MSR 寄存器的读写进行控制 2. 指向IO端口访问控制位图和MSR读写控制位图的物理地址指针字段。该位图用于差别性地控制虚拟机对不同的 IO 端口和 MSR 寄存器进行读写访问。3. 描述虚拟机CPU状态的信息。包含除通用寄存器外的大部分控制寄存器,段寄存器,描述符表寄存器,代码指针等。 RAX 寄存器也在其中,因为 RAX 在 VMM 执行 VMRUN 时是用来存放 VMCB 物理地址的。 对于段寄存器,该信息中还包含段寄存器对应的段描述符,也就那些传统 x86 上对软件隐藏的信息。4. 对虚拟机的执行进行控制的字段。主要是控制虚拟机中断和 NPT 的字段。5. 指示虚拟机进入“guest”模式后要执行的行动的字段。包括用来描述 VMM 向虚拟机注入的中断或异常的信息的字段。 注入的中断或异常在 VMRUN 进入“guest”模式后立即执行,就象完全发生在虚拟机内一样。6. 提供VMEXIT信息的字段。包括导致 VMEXIT 的事件的代码,异常或中断的号码,page fault 的线性地址,被截获的指令的编码等。VMCB 以及其涉及的控制位图,完全通过物理地址进行指向,这就避免了“guest”和“host”模式切换的过程依赖于“guest”空间的线性地址 ( 传统操作系统内用户空间到内核的切换确实依赖于 IDT 中提供的目标的线性地址 ), 使得 VMM 可以采用和客操作系统完全不同的地址空间,避免了前面提到的“Address-space compression”问题。VMCB 的内容在物理上被分成了俩部分,其中用于保存虚拟机 CPU 状态的信息占据 2048 字节的后半部分,我们可称之为 VMCB.SAVE; 其他信息,占据前 1024 字节范围,我们可称之为 VMCB.CONTROL。VMRUN 命令以 VMCB 为参数,使 CPU 进入“guest”状态, 按 VMCB.SAVE 的内容恢复虚拟机的 CPU 寄存器状态,并按 VMCB.SAVE 中 CS:RIP 字段指示的地址开始执行虚拟机 的代码, 并将之前 VMM 的 CPU 状态保存在 MSR_VM_HSAVE_PA 寄存器所指向的物理内存区域中。VMRUN 所保存的 VMM 的 CPU 状态的 CS:RIP 实际上就是 VMM 的代码中 VMCB 的下一个指令, 当虚拟机因某种原因而导致 #VMEXIT 时,VMM 会从 VMRUN 后的一条指令开始执行。 CPU 执行 #VMEXIT 行为时,会自动将虚拟机的状态保存到 VMCB.SAVE 区,并从 MSR_VM_HSAVE_PA 指定的区域加载 VMM 的 CPU 状态。VMLOAD 和 VMSAVE 指令是对 VMRUN 的补充,他们用来加载和恢复一些并不需要经常使用的 CPU 状态,如 FS, GS, TR, LDTR 寄存器以及其相关的隐含的描述符寄存器的内容,VMLOAD 和 VMSAVE 可以让 VMM 的实现对 “guest”进入和退出的过程进行优化,让多数情况下只使用 VMRUN 进行最少的状态保存和恢复。VMMCALL 指令是 AMD-V 为客操作系统内核提供的明确的功能调用接口,类似于 syscall 指令 ( 从 Ring 3 到 Ring 0), VMMCALL 让客操作系统直接执行 #VMEXIT 而进入 VMM,请求 VMM 的服务。中断的虚拟化AMD-V 对中断的虚拟化有如下支持 :虚拟中断虚拟中断是指由虚拟机的 EFLAGS.IF 标志控制的中断。 AMD-V 在 VMCB.CONTROL 中加入了一个 V_INTR_MASKING 字段, 当 V_INTR_MASKING 设置为 0 时, EFLAGS.IF 同时控制虚拟中断和物理中断; 当 V_INTR_MASKING 设置为 1 时,ELAGS.IF 值只控制虚拟中断,而 VMM 在执行 VMRUN 时保存的主机的 EFLAGS.IF 则控制物理中断。 VMCB 还提供了几个字段 V_IRQ, V_INTR_PRIO, V_INTR_VECTOR 及 V_TPR。 其中 V_TPR 代表虚拟 CPU 的 TPR, 当 V_INTR_MASKING 为 1 时,虚拟机上对 CR8 寄存器的访问被映射到对 V_TPR 字段的访问, 并由 V_TPR 和 V_INTR_PRIO 一起决定是否产生虚拟中断。 V_IRQ 表示当前存在虚拟中断请求,V_INTR_PRIO 是当前虚拟中断的优先级,如果 V_INTR_PRIO 比 V_TPR 高,则当虚拟机的 EFLAGS.IF 变为 1 时,虚拟中断就可被递交,V_INTR_VECTOR 就是中断的向量号。VMM 可以通过设置 VMCB 的 V_IRQ, V_INTR_PRIO, V_INTR_VECTOR 字段向虚拟机发起一个虚拟中断。 虚拟中断的机制扩展了中断的概念,不需要物理设备的存在,VMM 可以代表其仿真的虚拟设备,向虚拟机发起中断请求。全局的中断控制AMD-V 的硬件扩展包含一个标志位 GIF 可用来对物理中断和虚拟中断进行统一控制,当 GIF 被清 0 时,物理中断和虚拟中断均被屏蔽,当 GIF 被设置时,物理中断和虚拟中断才能按各自的控制机制进行递交。 STGI 指令设置 GIF, CLGI 指令清除 GIF。中断截取通过 VMCB.CONTROL 的 5 个控制位,物理的、虚拟的、NMI、SMI、 INIT 类型的中断都可以被截取或不截取,以便于 VMM 来控制中断相关的行为。一般来说,固定的低优先级的虚拟中断可不被截取由客操作系统自己处理, 高优先级的虚拟中断一般需要截取,以便 VMM 能快速的应答或通过 IER 关闭该中断以避免该中断延迟更低优先级的中断。事件注入VMCB.CONTROL 提供一个 EVENTINJ 字段,在执行 VMRUN 之前,VMM 通过设置该字段,向虚拟机注入一个异常或中断 . 被注入的事件完全在虚拟机的环境执行,就象完全发生在客操作系统中一样。被注入的事件是虚拟机返回“guest”模式后最先执行的代码,在 VMCB.SAVE 的 CS:RIP 字段指定的返回代码之前执行。扩展的 APIC 特征增加了 IER 控制寄存器和 SEOI 寄存器。IER 可被 VMM 软件用来控制 Local APIC 上 Pending 的中断,让某 Pending 中断不参与优先级的裁决,每个中断在 IER 中都有一个对应的控制位。SEOI 可被 VMM 软件用来结束中断的 Pending 状态,软件将需要结束的中断的向量号写入 SEOI 的 Vector 字段即可。KVM 简介KVM 全称 Kernel-based Virtual Machine, 即基于 Linux 内核的虚拟化技术, 精确的说,就是 KVM VMM 的核心功能是通过一个 Linux 内核模块实现的。 “基于 Linux 内核”是 KVM 在软件实现上不同于其他 VMM 实现的最重要特点, 使得 KVM 在实现上能获得如下好处 :利用 Linux 内核已有的功能和基础服务,减少不必要的重新开发。 如任务调度,物理内存管理,内存空间虚拟化,电源管理等功能,通常是一个 VMM 所必须具备的,但 KVM 可不必重新开发这些功能,直接使用 Linux 上已经相当成熟的技术。 利用强大的 Linux 社区,吸引优秀的 Linux 内核程序员参与到 KVM 的开发中, 壮大 KVM 的群体, 这些程序员以及红帽等 Linux 社区背后的厂商,也乐于在 Linux 上发展一个成熟的 VMM 技术。 可以长期享受 Linux 内核技术不断成熟和进步的好处,优化 KVM 的实现。 如 Linux 内核的 HugeTLBPage 技术可以用于削减 KVM 在虚拟机内存使用上的性能开销, eventfd 可以用于提升 KVM 内核执行路径和 Qemu-kvm 用户空间的交互效率。 KVM 在 VMM 的理论上属于硬件辅助的虚拟化技术, 即 KVM 需要利用 AMD-V 提供的虚拟化能力。AMD-V 让 KVM 上的虚拟机正常情况下运行在 “guest” 模式, 在执行敏感的的指令或行为时透明地切换到 “host” 模式,并在 “host”模式由 KVM VMM 的代码仿真那些敏感的指令或行为,完成后又回到“guest”模式由虚拟机运行其正常的代码。 KVM 的 VMM 代码实际上就是当虚拟机被捕获时才进入,执行仿真代码,然后又执行状态切换回到虚拟机代码直到其下一次被捕获,如此循环不断。 当然 KVM 的 VMM 在仿真复杂的行为时,可能需要用户空间的帮助, 所以 KVM 在此期间切换到用户空间。KVM 在 Linux 上的实现KVM 的 VMM 代码包括内核代码和用户空间代码俩部分。 内核代码即 kvm.ko 模块的代码,分布在内核源码的 virt/kvm 和 arch/x86/kvm 两个目录下, 前者是和硬件结构无关的代码, 后者是和硬件结构相关的代码,其中和 AMD-V 相关的代码由 arch/x86/kvm/svm.c 文件提供。KVM 内核空间代码实现的功能包括如下几个方面 :1. 实现硬件辅助的虚拟化的核心功能。包括实现“guest”模式及模式切换,虚拟 CPU 的状态和控制,指令仿真等所有之前提到的 x86 虚拟化所要解决的问题。代码分布在 arch/x86/kvm 下 x86.c, svm.c, emulate.c 等文件中。2. 提供用户空间对KVM控制。实现 /dev/kvm 字符设备接口用于 qemu-kvm 对 KVM 的控制,包括创建虚拟机,创建虚拟 CPU, 创建虚拟机内存空间,运行虚拟机等功能的 ioctl() 接口 . 其实现的 ioctl() 功能主要分成二类,针对单个虚拟机整体的功能和针对单个虚拟 CPU 的功能。 相关代码分布在 kvm_main.c, x86.c, svm.c 等文件中。3. 对x86平台设备进行仿真。包括仿真 PIC,IOAPIC,Local APIC 及 PIT 的代码。4. 实现IO Port空间和MMIO空间的仿真。这是实现平台设备和外部设备仿真所需要的基础功能。代码分布在 coalesced_mmio.c, iodev.h, emulate.c, x86.c 及 svm.c 等文件中。5. 实现基于文件描述符的通知机制。代码在 eventfd.c 文件中。 其中 ioeventfd 机制用于内核空间仿真 PIO 后向用户空间发送通知, irqfd 机制用于 qemu-kvm 进程向虚拟机注入中断。6.MMU虚拟化的支持。包括 shadow 页表的实现,TLB 的虚拟化。 主要代码在 mmu.c 文件中。7. 和PCI-Passthrough相关的功能。代码分布在 kvm_main.c 和 iommu.c 中。当然对物理 IOMMU 单元的管理还需要 Linux 内核 IOMMU 设备抽象层的代码及厂家 IOMMU 驱动的代码,分别分布在 driver/base/iommu.c 及 arch/x86/kernel/ 下的 amd_iommu.c 和 amd_iommu_init.c 文件中。 对 IOMMU 的支持是独立于 KVM 的,它也可以被用于非系统虚拟化的情景。用户空间的代码就是 qemu-kvm 的代码。 Qemu-kvm 是从 qemu 分支出来的项目 , 其目的就是利用传统 qemu 的功能,来实现各种虚拟设备的仿真,并提供对 KVM 进行控制的用户空间接口。Qemu-kvm 实现的功能包括如下方面 :1. 实现与KVM内核接口的用户空间逻辑。包括对 x86 虚拟机 PC 结构的定义,虚拟机的创建,平台设备的创建,虚拟 CPU 的创建接口。2. 各种层次和类型的硬件设备的仿真。包括 BIOS, PCI Hub,PCI 设备 ( 包括 USB 控制器,IDE 控制器,SCSI 适配器, 声卡,显卡,网卡等 ),USB 设备, IDE 磁盘, SCSI 磁盘。 Qemu-kvm 采用一个 qdev 的设备模型,来简化不同类型设备的仿真实现。3. 虚拟块设备的不同磁盘Image文件格式的支持。包括 qcow2, qed, vmdk, vpc 等。 这方面的能力影响 KVM 平台的可管理性 ( 如快照 ) 及 KVM 虚拟化技术和管理软件的兼容性。4.VNC,SPICE等表示层协议的支持。这方面的支持能力决定声卡,显卡的仿真在用户使用层次的效果。5.Virtio设备的后端。VirtIO 是 KVM 上设备虚拟化的标准,即完全虚拟出来的网络和块设备,客操作系统端使用虚拟的前端驱动和 Qemu-kvm 实现的后端之间紧密合作实现的网络和块设备逻辑, VirtIO 设备的效率要远高于完全由 Qemu-kvm 仿真出的传统的网络和块设备。6.QMP 协议的支持。 QMP 即 Qemu Monitor Protocol, 是虚拟化管理接口层,如 libvirtd, 用来控制和查询 Qemu-kvm 状态及信息的协议。Qemu-kvm 的代码很大,笔者难以解释各代码文件实现的功能,但有必要介绍一下 qemu-kvm 代码的组织结构和编译过程, 弄清楚 qem-kvm 可执行文件是如何编译出来的,图一和图二的内容分别是经过笔者裁剪的 Qemu-kvm 的源码根目录和 x86_64-softmmu 目录下的 Makefile 文件 :图 1. Qemu-kvm 的源码根目录图 2. x86_64-softmmu 目录下的 Makefile 文件结合这两个文件和 qemu-kvm 的源码树,笔者有如下几点说明:1.Qemu-kvm可执行文件是通过X86_64-softmmu/Makefile制作的。根目录下的 Makefile 在调用 x86_64-softmmu/Makefile 之前需要编译 qemu-io, qemu-img, qemu-nbd 三个工具以及 libqemu_common.a 这个库。 libqemu_common.a 包含了所有和处理器结构及平台无关的代码,如 spice, vnc, usb 等协议的实现,qed,qcow2 等虚拟磁盘格式实现,Slirp, VDE 网络功能代码, 还有那些独立于系统平台的硬件设备的仿真代码。2.Qemu-kvm可执行文件由“若干目标文件”和libqemu_common.a,libqemu.a,libqemuhw64.a三个库一起链接而成。其中 libqemu.a 所包含的代码主要是用于各种 CPU 结构的仿真的,在 qemu-kvm 中用不上。libqemuhw64.a 是通过 libhw64/Makefile 生成的,主要提供 x86 结构下特有的物理设备的仿真代码,如 Intel 的网卡 ne2000 的仿真。 “若干目标文件” 主要包含和虚拟化实现相关的内容, 有 x86 平台专有的部分如 vga,ide 等 x86 专用设备的仿真;还有和平台无关的部分,如 virtIO 设备的后端,e1000 等在多种平台上被使用的设备的仿真代码。3.源码文件主要分布在源码根目录, 以及hw/,block/,audio,net/,slirp/,ui/,QMP/与target-i386等子目录下。Libhw64/ 和 X86_64-softmmu/ 目录下不提供源码文件。4. 子目录 Kvm/ 是一个独立的目录,其下面也包含 Makefile 和源码文件,是用来实现一个微小型的系统仿真器,用来测试 KVM 的内核提供的功能的,可以看成是一个高度简化的 qemu-kvm 的实现,和 qemu-kvm 本身没关系。初学读者可先学习 kvm/ 目录下的内容了解 KVM 内核提供的接口的功能。5.Qemu-kvm 直接和 KVM 内核层相关的代码主要存在于 vl.c, kvm-all.c, qemu-kvm.c, target-i386/kvm.c 及 qemu-kvm-x86.c 中, 其中后两个文件是直接和 x86 硬件结构相关的原文出自【风信网】,转载请保留原文链接:/server/118983_5.shtml-重要的数据结构和接口一个快速分析,理解 KVM 实现的方法是了解其代码中一些重要数据结构和接口函数 :1.struct kvm 和 struct kvm_arch。 用来描述单个虚拟机全局的状态, 如代表虚拟机物理内存区域的 memslots, 代表当前需要仿真的 Coalesced MMIO 的 coalesced_mmio_ring, 用来仿真平台设备 PIC, IOAPIC, PIT, KVMCLOCK 的数据结构, 用来组织 Shadow 页表的数据结构等等。2.struct kvm_vcpu 和 struct kvm_vcpu_arch。 用来描述单个虚拟 CPU 的状态, 如需要仿真的虚拟 CPU 的特征位 ( 客操作系统 CPUID 看到的东西 ), 当前尚未处理完的 PIO,等待注入的异常和中断事件,用来仿真 Local APIC 的数据结构,尚未同步到 VMCB 中的修改过的寄存器的缓存等等。3.struct vmcb。 用来实现 AMD-V 的 VMCB 的数据结构。 其中的字段的格式和长度当然需要严格遵守 VMCB 的规范。 两个子结构 struct vmcb_control_area 和 struct vmcb_save_area 分别代表物理上的 VMCB.CONTROL 和 VMCB.SAVE。4.Struct vcpu_svm。用来代表 AMD-V 实现下的 VCPU, 除关联 struct kvm_vcpu 和 struct vmcb 外, 还用来实现一些 AMD-V 特定的东西,如 ASID 和 Sysenter 的支持。5.Struct kvm_memslots。 该结构挂在 struct kvm 下,用来描述虚拟机的全部物理内存区域, 每个区域对应一个 struct kvm_memory_slot 结构,其中包含该区域的 gpa 起点,大小及在 qemu-kvm 用户空间的 hva 起点。6.Struct kvm_x86_ops。该接口定义了若干操作,规定 KVM 在 x86 平台上的基本实现方式,svm.c 中提供了大部分操作的独立实现,其中多数函数以 “svm_xxx”方式命名,读者可直接查找 svm_x86_ops 变量了解每个操作在 svm.c 中对应的函数。7.Struct kvm_io_dev_ops。该接口定义了三个操作 (read,write,destructor),规定了在 KVM 内核中 PIO 或 MMIO 仿真的实现结构,目前平台设备 PIT, PIC, IOAPIC 的 PIO/MMIO 仿真处理都是按该接口的方式实现的。有趣的是,Ioeventfd 机制也使用了该接口, Ioeventfd 实现该接口的 write 操作,当 KVM 截取客操作系统向某特定的 PIO 或 MMIO 地址写入某特定的值时,Ioeventfd 实现的 ioeventfd_write() 操作就会执行, 唤醒等待在指定的文件描述符上的 qemu-kvm 线程。RHEL6.2 上 qemu-kvm 实现的 virtIO 设备的后端,已经使用了 ioev
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026中考英语语法复习分类训练:宾语从句100题(中考试题+中考模拟)原卷版
- 医学生基础医学 肺结核护理课件
- 2026年高考数学一轮复习:对数与对数函数(讲义)解析版
- 医学肾病综合征饮食干预方案案例教学课件
- 医学女性冠心病微血管病变案例教学课件
- 2026年中考作文备考之10篇高分考场范文
- 医学脑梗死言语康复案例教学课件
- 2026年春季高考语文总复习:文言词汇(重点实词、高频虚词)(知识梳理+考点讲练)原卷版
- 医学轮状病毒腹泻防控教学课件
- 临床路径变异对成本管控绩效的影响分析
- 物业反恐防暴培训
- 2025初中英语复习策略
- 国企管理供应链管理规定
- 2025版痛风病常见症状及代谢疾病护理建议
- 2024年6月GESP编程能力认证C++等级考试二级真题试卷(含答案)
- 2024年会昌县招聘城市社区工作者笔试真题
- 2026年广东公务员考试行测真题之言语理解和表达含答案(巩固)
- 欧盟新法规MDR专题培训
- 2025年社区网格员招录考试真题及答案
- TCNAS50-2025成人吞咽障碍患者口服给药护理学习解读课件
- 2025年老年消费者购买力及消费习惯可行性分析报告
评论
0/150
提交评论