非虚拟化的中断注入
硬件 -> apic -> lapic -> 中断管脚的入口
指令和时钟也是同步的,cpu在一个指令周期结束后,要么去执行下一条指令,要么就触发中断(会从中断向量表找到中断处理函数入口,然后跳到该函数),没有”主动轮询“某个信号的概念。有INT电平信号了,就去触发一个中断,没有电平信号,就继续取指令干活。这个判断的过程,在宏观上看,是“同时”完成的,没有先查询状态,然后要做什么的动作的过程,不要把软件编程的概念带入到电路设计中。
虚拟化下的硬件支持
可以看到上面的过程中大部分都是cpu的体系架构中实现的,操作系统只要指定好中断向量表即可,剩下的事情其实没有操作系统的事情。
所以当到虚拟化的时候,硬件也是虚拟化的时候,就不能由硬件来实现这些中断注入了;或者再增加新的寄存器,然后在cpu硬件架构这个层面就实现虚拟中断注入
interruption-information
中断注入最底层要依靠硬件实现,VMCS中VM-entry控制类字段,interruption-information是实现中断注入的基础,这个字段32bit,各字段含义如下,截图来自Intel手册vol3-24.8.3
CPU进入客户态时,中断注入区域VM-entry interruption-information的加载,是在guest state区域加载之后——跳转到guest state中RIP指向的地址之前。实际上,中断注入的本质就是在硬件上deliver中断信息到CPU,而deliver的时机必须在CPU VM-entry建立好guest上下文,但还没开始运行的时
Posted-Interrupt Descriptor
现在Intel提供了另外一种中断检查机制,通过VMCS域中的 Posted-Interrupt Descriptor字段就可以让Guest态的CPU感知到中断,并且这个字段Host可以直接写,不需要在VM-Entry时通过写VMCS间接设置。
基于interruption-information的实现
在上面讲到,VM-entry会检查VMCS,而虚拟中断信息 interruption-information也在VMCS中
所以要做以下步骤:
- IOAPIC告诉kvm有中断来了
- kvm要找到对应的vcpu,然后往模拟的lapic的寄存器地址上,IRR对应的地方写1,之后标记vcpu上的request的对应bit,这里是event
- 然后kick掉vcpu对应的进程(让它能重新进入到vm-entry:睡眠->唤醒, guest运行->vm_exit(核间中断))
reference: