标题:
KVM 虚拟化技术在 AMD 平台上的实现(2)
[打印本页]
作者:
look_w
时间:
2018-4-23 12:16
标题:
KVM 虚拟化技术在 AMD 平台上的实现(2)
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”带来的三个问题被简单解决。
VMCB VMCB 数据结构主要包含如下内容 :
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 字段即可。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0