虚拟化与云计算硬核技术内幕 (10) —— 事事有人管,人人有事管

2022-09-08 16:53:53 浏览数 (1)

在前几期,我们提到,计算机的外部设备需要通过两个机制与CPU进行数据的输入输出:

在数据平面,外设可以通过DMA方式直接从系统RAM读写数据,如将从外部接收到的数据写入到RAM,或从RAM直接读取需要输出到外部的数据。而在控制平面,外设可以通过中断,将数据输入和输出完成事件,以异步方式通知CPU。

Intel的处理器早在8086时代就支持了这一机制。熟悉《微机原理与接口技术》的同学可能会回忆起,Intel使用8259芯片实现可编程中断控制,用8257芯片实现可编程DMA控制。

但是,当Intel CPU演进到多核时代,出现了一个问题:

我们在前文中提到,中断实际上是会打断CPU程序的执行。在多核处理器中,可以视为具有多个CPU,那么,外部中断发生时,将打断哪个CPU程序的执行呢?

Intel为解决这一问题,引入了一个概念:APIC (Advanced Programmable Interrupt Controller)。

我们知道,在80386以后的时代,Intel将主板上各种IO控制芯片都集成在主板的ICH芯片(IO Controller Hub,俗称南桥)上,包括中断控制器8259(又被称为PIC)。对于多核处理器所配套的ICH,就需要将集成的PIC升级为APIC了。南桥上集成的APIC被称为IO APIC,而每个处理器核上还有本地的PIC,被称为Local APIC。Local APIC可以接收来自IO APIC的中断,并使得所在的CPU进入中断处理程序。

如图,IO APIC和Local APIC在程序看来,是合为一体的,当外设的中断发生时,I/O APIC会将中断送到目标的CPU上,目标CPU上的Local APIC触发真正的中断。

当系统中存在多个虚拟机的时候,VMM就需要让每个虚拟机的操作系统都可以识别到一个虚拟的APIC,并且能够让虚拟机上的外设产生的中断被送到虚拟机上的CPU内核上。最初的KVM在内核中通过软件模拟的方式为每个虚拟机模拟了这个虚拟的APIC,接管虚拟机操作系统对虚拟APIC的配置,并通过软件查表的方式将真实硬件的中断重定向到虚拟机的CPU上。这种处理的效率是可想而知的。

Intel引入了VT-d技术后,在硬件层面实现了中断虚拟化的支持。

由于我们在系统中运行了虚拟机,首先会在系统中虚拟出一个或多个虚拟机的CPU,每个CPU也会有自己的Local APIC。那么,即使系统没有超分,每个CPU都是物理的内核/超线程,在GuestOS下,对物理CPU的Local APIC寄存器进行配置,后果是会发生VM Exit,也就是会使得性能极其低下。

因此,Intel引入虚拟的APIC,首先为所有的VM中每个CPU的vAPIC实现了一套虚拟的寄存器,它叫做virtual APIC Page, GuestOS对vAPIC进行操作的时候,不会导致VM Exit。

第二,vAPIC对原来的中断投递体系做了根本的变革。

在没有硬件支持终端虚拟化时,KVM对Guest模式下的中断采取的是模拟的方式。当来自IO APIC或PCIE MSI(这个概念以后会详解)外部中断到达的时候,KVM软件会根据内部的IRQ Routing机制,找到中断投递的目标虚拟机上的目标CPU,向CPU注入中断,并让目标CPU产生一次VM_Exit和VM_Entry,让系统评估是否应当响应中断。可想而知,这大大增加了VM的性能损耗。而vAPIC可以让虚拟机的CPU在Guest模式下就评估中断,让系统运行效率大大提升了。

有了vAPIC,在物理设备透传到设备的时候,物理设备的中断也可以透传到CPU。

我们小结一下:vAPIC能够让各个虚拟机减少了不必要的vm_entry和vm_exit,也就是做到了“时间就是金钱,效率就是生命”。

同时,vAPIC还可以让中断高效的投递到目的VM的目的CPU,做到了“事事有人管,人人有事管”。

在中断实现了虚拟化后,我们离实现虚拟机的虚拟设备还差最后一步——

请看下回分解。

0 人点赞