购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2.4 Intel VT-x中断虚拟化

2.1.3节介绍了中断虚拟化的一般思路,其中最为关键的两点便是中断设备的模拟(外部设备和中断控制器的模拟)以及中断处理流程的模拟,这也是早期Intel VT-x中断虚拟化采用的方法,后来Intel公司推出了APICv(APIC Virtualization,APIC虚拟化)技术对上述两个功能进行了优化。本节将分别介绍传统中断虚拟化和APICv支持的中断虚拟化。

1.传统中断虚拟化

在传统中断虚拟化中,Hypervisor会创建虚拟IOAPIC和虚拟LAPIC,以下统称为虚拟APIC。它们通常表现为存储在内存中的数据结构,而其中的寄存器则作为结构体中的若干域(fields)。默认情况下 ,虚拟机通过MMIO (Memory-Mapped I/O,内存映射I/O)的方式访问虚拟APIC,但是由于底层并没有相应的物理硬件供其访问,故Hypervisor需要截获这些MMIO请求进而访问存储在内存中的虚拟寄存器的值。Hypervisor通常会将虚拟机中APIC内存映射区域相应的EPT项状态设为不存在,这样虚拟机访问这一段地址空间时,便会触发缺页错误从而触发VM-Exit陷入Hypervisor中进行模拟。此外,虚拟APIC仍需要接收和传递中断。在物理环境下,外部设备产生的中断会通过连接线传输至APIC进而发送到CPU,在此过程中,硬件会设置相应寄存器的值。而在虚拟环境中,这些连接线则会被替换为一系列的函数调用,并在调用过程中设置内存中相应虚拟寄存器的值。2.2.3节提到了APIC中断处理的流程,即 中断产生 中断路由 中断接受 中断确认和中断交付 。其中中断产生到中断确认部分都是通过设置特定APIC寄存器完成,对于虚拟APIC而言,可以通过设置内存中相应的虚拟寄存器实现同样的功能。而对于中断交付而言,2.1.3节提到需要硬件提供某种机制,使得虚拟机恢复运行时发现待处理的虚拟中断从而执行相应的ISR。在Intel VT-x中,这是通过VMCS VM-Entry控制域中的VM-Entry中断信息字段(32位)实现的,该字段保存了待注入事件的类型(中断或异常等)和向量号等信息,其格式如图2-7所示。每次触发VM-Entry时,CPU会检查该域,发现是否有待处理的事件并用向量号索引执行相应的处理函数。

图2-7 VM-Entry中断信息字段格式

当Hypervisor需要向正在运行的vCPU注入中断时,需要给vCPU发送一个信号,使其触发VM-Exit,从而在VM-Entry时注入中断。如果vCPU正处于屏蔽外部中断的状态,如vCPU的RFLAGS.IF=0,将不允许在VM-Entry时进行中断注入。此时可以将VM-Execution控制域中的中断窗口退出(Interrupt-Window Exiting)字段置为1,这样一旦vCPU进入能够接收中断的状态,便会产生一个VM-Exit,Hypervisor就可以注入刚才无法注入的中断,并将中断窗口退出字段置为0。

2.APICv支持的中断虚拟化

APICv是Intel公司针对APIC虚拟化提出的优化技术,它主要包括两方面内容:虚拟APIC访问优化和虚拟中断递交。前面提到,当虚拟机通过MMIO的方式访问APIC寄存器时,需要VM-Exit陷入Hypervisor中设置内存中相应虚拟寄存器的值,这将会触发大量的VM-Exit,严重影响虚拟机的性能。于是APICv引入虚拟APIC页(Virtual APIC Page)的概念,它相当于一个影子APIC,虚拟机对APIC的部分甚至全部访问都可以被硬件重定向为对虚拟APIC页的访问,这样就不必频繁触发VM-Exit了。要启用虚拟APIC页,需要使能如下三个VM-Execution控制域字段。

(1)影子TPR(Use TPR Shadow)字段。该字段置1后,虚拟机访问CR8时将会自动访问虚拟APIC页中的TPR寄存器。否则,虚拟机访问CR8时将会触发VM-Exit

(2)虚拟APIC访问(Virtualize APIC Accesses)字段。该字段置1后,虚拟机对于APIC访问页(APIC Access Page)的访问将会触发APIC访问(APIC Access)异常类型的VM-Exit。单独设置该域时,与以前通过设置EPT页表项触发VM-Exit相比,仅仅只是将VM-Exit类型从EPT违例(EPT Violation)变为了APIC访问。需要进一步设置APIC寄存器虚拟化(APIC-Register Virtualization)字段消除VM-Exit。

(3)APIC寄存器虚拟化字段。该字段置1后,通常虚拟机对于APIC访问页的访问将被重定向到虚拟APIC页而不会触发VM-Exit,部分情况下仍需要VM-Exit到Hypervisor中处理。

使用APICv前后,虚拟APIC访问方式如图2-8所示。

图2-8 使用APICv前后虚拟APIC访问方式

而虚拟中断递交(Virtual-Interrupt Delivery)通过VM-Execution控制域中的虚拟中断递交字段开启。在引入该机制前,Hypervisor需要设置VIRR和VISR相应位(虚拟APIC中的IRR和ISR),然后通过上文提到的事件注入机制在下一次VM-Entry时注入一个虚拟中断,调用客户机中相应的中断处理例程。开启虚拟中断递交后,虚拟中断注入通过VMCS客户机状态域中的客户机中断状态(Guest Interrupt Status)字段完成,其低8位为RVI(Requesting Virtual Interrupt,待处理虚拟中断),表示虚拟机待处理中断中优先级最高的中断向量号,相当于IRRV;而高8位为SVI(Servicing Virtual Interrupt,处理中虚拟中断),表示虚拟机正在处理中断中优先级最高的中断向量号,相当于ISRV。开启虚拟中断传送后,Hypervisor只需要设置RVI的值,在VM-Entry时,CPU将会根据RVI的值进行虚拟中断提交,过程如下。

(1)若VM-Execution控制域中断窗口退出(Interrupt-Window Exiting)字段为0且RVI[7∶4]>VPPR[7∶4],则确认存在待处理的虚拟中断,其中VPPR指的是vCPU的PPR寄存器。

(2)根据RVI,清除VIRR中对应位,设置VISR中对应位,并设置SVI=RVI。

(3)设置VPPR=RVI & 0xf0。

(4)若VIRR中还有非零位,则设置RVI=VIRRV,即VIRR中优先级最高的中断向量号,否则设置RVI=0。

(5)根据RVI提供的中断向量号,调用虚拟机中注册的中断处理例程。

在上述流程中,中断确认和中断交付工作将由硬件自动完成,Hypervisor无须手动设置虚拟APIC中VIRR和VISR寄存器的值。此外,设置RVI后,即使当前vCPU处于屏蔽中断的状态也无妨,硬件会持续检查vCPU是否能够接收中断。一旦vCPU能接收中断,则立即进行虚拟中断交付,无须再通过前述中断窗口产生VM-Exit注入中断。

虚拟中断虽然省略了中断确认和中断递交的过程,但是中断接受仍需要Hypervisor完成。当Hypervisor需要将虚拟中断注入vCPU时,必须使其发生VM-Exit并设置好RVI的值,才能顺利进行后续操作。而发布-中断(Posted-Interrupt)机制可以省略中断接受的过程,直接让正在运行的vCPU收到一个虚拟中断,而不产生VM-Exit。它还可以配合VT-d的发布-中断功能使用,实现直通设备的中断直接发给vCPU而不引起VM-Exit。发布-中断机制通过VM-Execution控制域中的发布-中断处理(Process Posted-Interrupt)字段开启,它引入了发布-中断通知向量(Posted-Interrupt Notification Vector)和发布-中断描述符(Posted-Interrupt Descriptor)。其中发布-中断描述符保存在内存中,而发布-中断描述符的地址保存在VMCS的发布-中断描述符地址(Posted-Interrupt Descriptor Address)字段中。发布-中断描述符的格式如图2-9所示。

其中PIR(Posted-Interrupt Requests,发布-中断请求)是一个256位的位图,与IRR类似,相应位置1表示有待处理中断。ON(Outstanding Notification,通知已完成)表示是否已经向CPU发送通知事件(ON本质上是一个物理中断),向CPU通知PIR中有待处理中断。发布-中断处理字段置1后,当处于非根模式的CPU收到一个外部中断时,它首先完成中断接受和中断确认,并取得中断向量号。然后,若中断向量号与发布-中断通知向量相等,则进入发布-中断处理流程,否则照常产生VM-Exit。发布-中断处理流程如下:

图2-9 发布-中断描述符格式

(1)清除发布-中断描述符的ON位。

(2)向CPU的EOI寄存器写入0并执行,至此在硬件APIC上该中断已经处理完毕。

(3)令VIRR|=PIR,并清空PIR。

(4)设置RVI=max(RVI,PIRV),其中PIRV为PIR中优先级最高的中断向量号。

(5)CPU根据RVI按照前述流程递交虚拟中断。

从上述流程不难发现,只需要将待注入的中断放置在发布-中断描述符的PIR中,并向CPU发送一个发布-中断通知,CPU就会自动将PIR中存储的虚拟中断同步到RVI中,无须Hypervisor手动设置RVI的值。通过发布-中断机制便可以在不发生VM-Exit的情况下向vCPU中注入一个或者多个虚拟中断。 mljr/nUyUbugYMc9wJnKqMBb+0h9pF8uESL4wSGSxN7p4we7Bycg9cgKPHdmSqZv

点击中间区域
呼出菜单
上一章
目录
下一章
×