[Virtualization](七):RISC-V 虚拟化中的中断
2026/8/1 10:36:05 网站建设 项目流程

第六篇讨论了 RISC-V KVM 的 trap/exit 处理路径。本篇进入中断:当一个中断到达 host 时,Linux KVM/RISC-V 如何判断它是否、何时、以及怎样投递给 Guest Linux?

1. 为什么中断虚拟化很难

CPU 和内存虚拟化解决的是执行和地址空间问题。

中断虚拟化解决的是事件投递问题。

Guest Linux 需要看到自己的中断:

  • timer interrupt
  • IPI
  • virtio device interrupt
  • UART interrupt
  • external interrupt

但真实中断首先属于 host。

Host 需要决定:

  • 这个中断是不是给某个 guest 的?
  • guest 当前能不能接收?
  • 目标 vCPU 是哪个?
  • vCPU 正在运行还是被调度出去了?
  • 是否需要触发一次 guest exit 或 host wakeup?

所以中断虚拟化既是架构问题,也是调度问题。

2. RISC-V 中断模型的几个基本对象

RISC-V 中断可以先粗略分成几类:

  • software interrupt
  • timer interrupt
  • external interrupt

在传统 RISC-V 平台上,经常会看到:

  • CLINT:core-local interruptor,常用于 timer 和 software interrupt
  • PLIC:platform-level interrupt controller,用于外部中断

在更新的中断架构中,还会看到:

  • AIA:Advanced Interrupt Architecture
  • IMSIC:Incoming MSI Controller
  • APLIC:Advanced 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 handler

Guest 并不知道背后真实硬件如何投递中断。

它只需要看到符合 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 interrupt

Timer 是最重要的 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 shootdown
  • reschedule
  • wakeup
  • stop 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 与 virtio

virtio 设备完成请求后,通常需要通知 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 source
  • priority
  • pending
  • enable
  • threshold
  • claim/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 entry

KVM 往往会在进入 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 scheduler
  • vCPU placement
  • CPU overcommit
  • interrupt controller model
  • QEMU/KVM exit path
  • device backend

这也是为什么虚拟机实时性和低延迟调优非常复杂。

13. 源码阅读入口

RISC-V KVM 中断路径可以先看:

  • arch/riscv/kvm/vcpu.c
  • arch/riscv/kvm/vcpu_timer.c
  • arch/riscv/kvm/vcpu_sbi.c
  • arch/riscv/kvm/aia.c,如果内核版本包含相关实现
  • arch/riscv/include/asm/kvm_host.h
  • QEMU 的hw/intc/hw/riscv/virt.c

阅读时可以问:

  • guest timer interrupt 在哪里被设置 pending?
  • IPI 如何找到目标 vCPU?
  • guest external interrupt 由谁注入?
  • PLIC 或 AIA 是 QEMU 模拟还是 KVM 加速?
  • vCPU entry 前如何检查 interrupt state?
  • interrupt 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 extension
  • timer、IPI、HSM、system reset 的虚拟化路径
  • KVM 如何 dispatch SBI call
  • 哪些 SBI call 可以在 KVM 处理
  • 哪些可能需要 QEMU 或 firmware 参与

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询