在上期《虚拟化与云计算硬核技术内幕 (8) —— “饭圈互撕的末路”》中,我们小结了,为了让虚拟机能够正常运作,除了需要让虚拟机的ring0对执行特权指令或敏感指令做限制,在TLB中为不同虚拟机分配虚拟地址,还需要将虚拟化的外部设备分配给虚拟机使用,如网卡和磁盘。
解决虚拟机使用外设,实际上是要解决两个问题:
DMA和中断。
DMA是Direct Memory Access (直接内存访问)的缩写,这是大家都知道的。但大家往往不知道的是,DMA的反义词是PIO(Programmed Input and Output)。
所谓PIO,指的就是,CPU通过每一条指令,逐字从IO缓冲区向外设搬运输出内容,或逐字从外设向内存中的IO缓冲区搬运输入内容。显而易见地,这种行为会使得外设的输入输出严重占用CPU时间,易言之,宝贵的CPU时间被浪费在轮询IO设备上了。
而DMA技术的出现,改变了这种不合理的现象。
DMA是异步的。所谓异步,就是CPU不需要实时关注IO的运行情况,而是由外设通过中断的方式,把IO的执行情况通知给CPU,CPU再作出处理。
我们以网卡驱动程序中发送数据包的工作流程为例:
当CPU打算发送一个数据包的时候,会执行以下动作:
- 把数据包存放到内存缓冲区(memory buffer, 可缩写为mbuf);
- 通知网卡,发送从mbuf开始的地址的数据包;
- CPU想办法知道数据包是否发送完毕。发送完毕后,才可以将申请的mbuf归还,或用于其他用途。
其中第3点是重点。如果CPU在一直查询网卡的发送成功状态,依然会浪费大量的时间。因此,我们需要引入中断方式来将IO执行情况通知给CPU,才能够发挥DMA的真正优势。
什么是中断呢?
方老师有一个朋友名叫A,给方老师讲了自己读书时的故事:
当A还是小A的时候,系里有一位老师叫L,教《微机原理与接口技术》。
有一天,L老师正在给大家讲“系统中断”一章的时候,突然,教室里有一位同学晕倒了。
L老师指挥着班上的同学们把晕倒的同学送到校医院,回到讲台上,告诉大家:同学们,计算机的中断就像刚才发生的事情,来自处理器外部的事件或内部的指令触发了中断,处理器会暂停当前执行的程序,转到中断处理程序中,处理完毕了,再恢复当前现场。
L老师的讲授和为人,给小A留下了深刻的印象,从此小A每次看到“中断”的概念,都会想起L老师的嘉言懿行。
那么,让我们回到虚拟化的场景中:
在没有虚拟化的情况下,处理器对于DMA和中断的处理很简单,在初始化设备的时候,为其分配好接收数据的DMA缓冲区,并准备对应的中断处理程序来正确处理设备产生的中断。但在虚拟化的情况下,如果我们要将一个外设分配给虚拟机,就需要解决两个问题:
- 虚拟机所拥有的外设,其DMA的目的地址需要是这个虚拟机可访问,而其他虚拟机不可以访问的地址,否则会有安全问题;
- 虚拟机所拥有的外设,产生的中断应当只有这个虚拟机可以感知到并处理,而不会中断其他虚拟机中程序指令的执行,其他虚拟机也感知不到;
因此,Intel引入了IOMMU(i/o memory management unit)技术,对APIC(Advanced Programmable Interrupt Controller)进行了为虚拟化而设计的增强,并引入了DMA重定向机制,解决了这两个问题。
下期我们将为大家详解IOMMU里面的关键技术。
下周是教师节,因此,以本文中的故事,向各位学高为师,身正为范的老师们致敬!