CPU虚拟化及中断虚拟化

软件完全虚拟化-CPU虚拟化

对于软件完全虚拟化来说,主要采用解释执行,扫描与修补,二进制代码翻译(BT)等技术的方式来避免虚拟化漏洞,并相对的尽量提升性能

硬件辅助虚拟化-CPU虚拟化

Intel VT-x引入了VMX操作模式

  • 根操作模式(VMX Root Operation): VMM运行所处的模式
  • 非根模式(VMX Non-Root Operation): 客户机运行所处的模式
    这两种模式与特权级ring0-ring3是正交的, 也就是说使用的VT-x的情况下,描述程序处在哪个特权级别,如ring0,还需指出处于根模式还是非根模式。
    另外,VT-x中,敏感指令的陷入被称为VM-Exit, 并从非根模式切换到根模式; 反之调度客户机执行从根模式切换到非根模式,称为VM-Entry

VCPU结构

软件虚拟化使用”CPU执行环境”来描述虚拟CPU, 而硬件虚拟化使用VCPU描述符来描述虚拟CPU。
整个VCPU主要分为两部分: VMCS硬件部分以及非VMCS的软件部分
VCPU结构

VMCS: Intel VT-x引入的概念,保存了根模式和非根模式下的一些特权寄存器的值和控制信息,由硬件CPU操作,每个VMCS对应一个VCPU,并只能绑定到一个物理CPU中。

  • 客户机状态域: 当VM-Exit的时候,保存CPU状态信息; 当VM-Entry的时候,从中恢复
  • 宿主机状态域: 保存VMM运行时,即根模式的CPU状态,当VM-Exit的时候,从中恢复
  • VM-Entry控制域: 需要注意的是,可以配置事件注入控制, 当VM-Entry的时候,CPU会检查这个字段,调用客户机自己IDT里面对应的处理函数来进行处理, 比如中断异常等。
  • VM-Execution控制域: 可以控制哪些敏感指令可以产生VM-Exit, 异常和中断是否产生VM-Exit
  • VM-Exit控制域: 规定了VM-Exit时CPU的行为
  • VM-Exit信息域: VM-Exit的原因

非VMCS部分

比如VMCS中不包括通用寄存器和浮点寄存器等,它们的保存和恢复,可以由VMM来控制,以便进行优化处理

VCPU的创建

创建VCPU描述符后 ,主要模拟物理CPU行为进行初始化,同时对VMCS进行创建和各个域初始化

VCPU的运行

VCPU创建并初始化后救可以通过调度程序根据一定的算法策略被调度运行。
在调度算法选定VCPU后,需要将VCPU切换到物理CPU上运行

上下文切换

  • VMM保存自己的上下文,主要保存VMCS不保存的寄存器
  • VMM将保存在VCPU中的由软件切换的上下文加载到物理CPU
  • VNN执行VMRESUME/VMLAUNCH指令,触发VM-Entry,此时CPU自动将VCPU中的VMCS部分加载到物理CPU,并切换到非根模式

VCPU的硬件优化

  • 无条件优化: 以往在软件虚拟化中必须陷入到VMM中的敏感指令,通过Intel VT-x可以在客户机中直接执行。 如CR2访问,SYSENTRY/SYSEXIT指令
  • 条件优化: 通过VMCS的VM-Execution控制域配置某些敏感指令是否产生VM-Exit而陷入到VMM中,如CR0,TSC的访问。

VCPU的退出

VCPU作为调度单位不能永远运行,如执行了特权指令,发生了物理中断等,就会发生VM-Exit

  • 发生VM-Exit, CPU自动进行一部分上下文切换
  • 切换到根模式后,根据VM-Exit信息域获得发生原因,分发到对应的处理模块处理,进行另一部分上下文切换工作

vm-exit处理

缺页异常处理流程,先判断产生异常的原因:

  1. 如果是因为访问MMIO地址导致的异常,VMM会调用IO虚拟化模块处理
  2. 如果是影子页表导致的异常,VMM会调用内存虚拟化模块处理
  3. 否则,就是客户机正常的缺页异常(即不需要VMM处理的缺页异常), 该异常会被注入给客户机,由客户机os自己处理

VCPU的再运行

尽量将VCPU继续在相同的物理CPU上运行, 如果被调度算法调度到其他CPU上,则需要将VCPU对应的VMCS迁移到另一个物理CPU上,迁移完成后,在重新绑定的物理CPU上执行VMLAUNCH发起VM-Entry

中断虚拟化

中断虚拟化架构

虚拟PIC

VMM可以设置VMCS的I/O bitmap中的相应位,使得客户机在访问特定IO端口的时候发生VM-Exit,以便截获,然后根据PIC规范进行模拟

虚拟I/O APIC

PIC只适用于单CPU系统,对于多CPU必须通过I/O APIC来发送中断,因此多CPU的虚拟平台,必须实现虚拟I/O APIC
与虚拟PIC不同的是,操作系统通过MMIO的方式访问I/O APIC。 VMM会将MMIO地址对应的页表项设置为不存在,因此访问时会发生Page Fault的VM-Exit,然后被截获

虚拟Local APIC

Local APIC是CPU上的一个内部部件,负责接收中断和产生中断的功能,比如Timer Interrupt和IPI中断。
与上述两者一样,在VMM中被实现为一个模拟设备, 并且是通过MMIO来访问, 主要功能是向VCPU注入中断。

中断采集

  • 来自软件模拟的虚拟设备, 可以通过虚拟中断控制器提供的接口发出中断请求
  • 来自于直接分配给客户机的物理设备的中断,比如网卡。 物理中断需要首先由VMM的中断处理函数接收(因为物理中断控制器由VMM控制,且发生时CPU的IDT表可能不是客户机的),再注入给客户机。
  1. 创建客户机的时候,给客户机分配中断号,然后通知VMM相关绑定信息
  2. 当CPU收到中断,执行标准的中断处理,最后跳转到IDT表对应的处理函数,该处理函数是VMM提供的
  3. VMM的中断处理函数对中断进行检查,发现该中断是分配给客户机的设备产生的,因此就调用虚拟中断控制器的接口,将中断发送到虚拟Local APIC,之后虚拟Local APIC在适当时机将该中断注入客户机,由客户机os的处理函数处理
  4. 将中断注入后,VMM进行后续处理,比如开中断等
    直接分配设备的中断虚拟化

中断注入

中断注入过程

  • 如果VCPU在运行,需要发IPI使之VM-Exit, 然后再VM-Entry注入
  • 如果VCPU当前无法中断,通过中断窗口(VMCS的一个特定字段告诉CPU当前VCPU有一个中断需要注入),一旦VCPU可以接收中断,物理CPU会主动触发VM-Exit,然后就可以注入等待的中断了