[Virtualization](七):RISC-V 虚拟化中的中断 第六篇讨论了 RISC-V KVM 的 trap/exit 处理路径。本篇进入中断当一个中断到达 host 时Linux KVM/RISC-V 如何判断它是否、何时、以及怎样投递给 Guest Linux1. 为什么中断虚拟化很难CPU 和内存虚拟化解决的是执行和地址空间问题。中断虚拟化解决的是事件投递问题。Guest Linux 需要看到自己的中断timer interruptIPIvirtio device interruptUART interruptexternal interrupt但真实中断首先属于 host。Host 需要决定这个中断是不是给某个 guest 的guest 当前能不能接收目标 vCPU 是哪个vCPU 正在运行还是被调度出去了是否需要触发一次 guest exit 或 host wakeup所以中断虚拟化既是架构问题也是调度问题。2. RISC-V 中断模型的几个基本对象RISC-V 中断可以先粗略分成几类software interrupttimer interruptexternal interrupt在传统 RISC-V 平台上经常会看到CLINTcore-local interruptor常用于 timer 和 software interruptPLICplatform-level interrupt controller用于外部中断在更新的中断架构中还会看到AIAAdvanced Interrupt ArchitectureIMSICIncoming MSI ControllerAPLICAdvanced Platform-Level Interrupt Controller不同平台和 QEMU 配置可能使用不同模型。本篇先建立概念不把每个寄存器展开。3. Guest 看到的中断不是 Host 原样转交Guest Linux 看到的 interrupt controller 是 QEMU/KVM 为它构造的虚拟硬件。这意味着real host interrupt | v Host Linux interrupt handling | v KVM/QEMU decide guest delivery | v virtual interrupt pending state | v Guest Linux interrupt handlerGuest 并不知道背后真实硬件如何投递中断。它只需要看到符合 RISC-V 平台约定的中断行为。4. virtual interrupt pending state中断不是一个函数调用。如果 guest 当前关中断或者 vCPU 没有运行中断不能简单地“立刻执行”。KVM 需要维护虚拟中断状态例如哪些 interrupt pending哪些 interrupt enabled目标 vCPU 是谁是否需要唤醒 vCPU thread是否需要在下一次 guest entry 前注入可以简化为event happens | v mark virtual interrupt pending | v when guest is ready | v inject interrupt into Guest Linux这就是 virtual interrupt injection 的基本直觉。5. timer interruptTimer 是最重要的 guest 中断之一。Guest Linux 依赖 timer 做调度和时间管理。Guest 设置 timer 的路径可能是Guest Linux | | SBI set_timer v KVM handles SBI timer call | | program host timer v host timer fires | | mark guest timer interrupt pending v Guest receives virtual timer interrupt这里有两个转换。第一guest 的 timer deadline 要转换成 host 能理解的 timer 事件。第二host timer 到期后要转换成 guest 可见的 virtual timer interrupt。Timer 虚拟化的质量会直接影响 guest scheduler 的行为。6. IPI 虚拟化IPI 是 inter-processor interrupt。Guest 多核系统中一个 vCPU 可能需要向另一个 vCPU 发送 IPI。例如TLB shootdownreschedulewakeupstop CPU路径大致是Guest vCPU0 sends IPI | | SBI or interrupt controller path v KVM records target vCPU interrupt | v wake or mark vCPU1 pending | v Guest vCPU1 receives virtual IPI这里的难点是目标 vCPU 可能并不在运行。它可能在 host 上睡眠也可能正在另一个 pCPU 上运行。KVM 需要和 host scheduler 协作确保虚拟 IPI 最终能被目标 vCPU 看见。7. external interrupt 与 virtiovirtio 设备完成请求后通常需要通知 guest。例如 virtio-blk 完成一次读请求。简化路径host I/O completes | v QEMU or vhost marks virtqueue used | v virtual device interrupt pending | v KVM injects external interrupt | v Guest virtio driver handles completion如果设备模型在 QEMU 用户态QEMU 可能需要通过 irqfd、eventfd 或 KVM API 通知 KVM。如果数据面走 vhost部分路径可能在内核中完成减少 QEMU 参与。这就是中断虚拟化和 I/O 虚拟化交叉的地方。8. PLIC 虚拟化PLIC 是传统 RISC-V 外部中断控制器。Guest 可能看到一个虚拟 PLIC。它需要支持类似的语义interrupt sourceprioritypendingenablethresholdclaim/complete如果 PLIC 由 QEMU 设备模型模拟那么 guest 对 PLIC MMIO 寄存器的访问可能会返回 QEMU。Guest PLIC MMIO access | v KVM MMIO exit | v QEMU virtual PLIC model这种路径语义清楚但频繁 MMIO 会有开销。9. AIA 与 IMSIC 为什么重要AIA 是 RISC-V 较新的高级中断架构。IMSIC 提供更适合 MSI 和虚拟化的中断投递模型。从虚拟化角度看AIA/IMSIC 的价值在于更适合多核和 MSI 设备更容易做中断直投或硬件辅助可以减少部分中断路径的软件开销对高性能虚拟化更友好不需要一开始就记住所有细节。先建立方向PLIC 更像传统平台级中断控制器AIA/IMSIC 更面向现代多核和虚拟化场景。后续如果系列深入设备直通和高性能中断可以单独写 AIA。10. 中断注入与 guest entryKVM 往往会在进入 guest 前检查是否有 pending virtual interrupt。如果有并且 guest 当前允许接收KVM 会准备相应状态让 guest 在恢复执行后进入中断处理。简化流程before guest entry | | check pending interrupt | check guest interrupt enable v prepare injection state | v enter guest | v Guest trap handler receives interrupt这说明中断注入和 vCPU run loop 紧密相关。不是只有“中断发生时”才处理中断状态也会在 guest entry/exit 边界被维护。11. posted interrupt 的直觉在高性能虚拟化里一个重要优化方向是减少中断导致的 VM exit。posted interrupt 的直觉是如果硬件能把某些中断直接投递到正在运行的 guest就可以减少 host 软件介入。不同架构具体机制不同。在 RISC-V 场景下AIA/IMSIC 等能力会影响未来中断虚拟化效率。本系列后续如果写设备直通和高性能 I/O可以把 posted interrupt、MSI、IOMMU 放在一起讨论。12. 中断与 vCPU 调度中断虚拟化离不开 vCPU 调度。如果目标 vCPU 正在运行KVM 可以尝试尽快注入。如果目标 vCPU 睡眠KVM 可能需要唤醒对应 QEMU vCPU thread。如果目标 vCPU 被 host 抢占中断延迟会受 host 调度影响。所以 guest 看到的 interrupt latency 实际上受多层因素影响host schedulervCPU placementCPU overcommitinterrupt controller modelQEMU/KVM exit pathdevice backend这也是为什么虚拟机实时性和低延迟调优非常复杂。13. 源码阅读入口RISC-V KVM 中断路径可以先看arch/riscv/kvm/vcpu.carch/riscv/kvm/vcpu_timer.carch/riscv/kvm/vcpu_sbi.carch/riscv/kvm/aia.c如果内核版本包含相关实现arch/riscv/include/asm/kvm_host.hQEMU 的hw/intc/和hw/riscv/virt.c阅读时可以问guest timer interrupt 在哪里被设置 pendingIPI 如何找到目标 vCPUguest external interrupt 由谁注入PLIC 或 AIA 是 QEMU 模拟还是 KVM 加速vCPU entry 前如何检查 interrupt stateinterrupt pending state 如何和 guest CSR 对应14. 本篇小结这一篇把 RISC-V 虚拟化中的中断拆成几条路径。第一timer interrupt 通常与 SBI 和 host timer 相关。第二IPI 需要 KVM 管理 vCPU 之间的虚拟中断投递。第三virtio 等设备中断常常跨越 QEMU、vhost、KVM 和 guest driver。第四PLIC、AIA、IMSIC 决定了外部中断虚拟化的架构基础。第五中断延迟不只取决于硬件还取决于 vCPU 调度和 exit 路径。可以把本篇压缩成一句话RISC-V 中断虚拟化的核心不是简单转发中断而是在 host 调度、KVM 状态机和 guest interrupt model 之间维护一个可信的事件投递系统。15. 下一篇预告SBI 在 RISC-V Guest 中如何被虚拟化下一篇专门看 SBI。会讨论SBI 为什么是 RISC-V 软件栈的关键接口Guest Linux 常用哪些 SBI extensiontimer、IPI、HSM、system reset 的虚拟化路径KVM 如何 dispatch SBI call哪些 SBI call 可以在 KVM 处理哪些可能需要 QEMU 或 firmware 参与