您好,这个问题非常关键,触及了虚拟化中 I/O 直通(Passthrough)的核心配置。
一个物理中断并不会被 KVM 默认地、自动地导向 Guest OS。这个“导向”关系是需要用户(或云管理平台)在启动虚拟机时,通过 QEMU 的参数明确配置的。KVM 只是执行这个配置好的“路由规则”。
这个配置过程的核心,是为了实现设备直通,即让虚拟机能独占并直接控制一个物理设备(如一个网卡、GPU 或 NVMe 硬盘)。
“导向”关系的建立过程
整个流程涉及到几个关键组件的协同工作:IOMMU (在 Arm 上称为 SMMU)、VFIO 框架、QEMU 和 KVM。
第 1 步:宿主机层面 - “隔离”设备
在启动虚拟机之前,管理员需要在宿主机上做准备:
- 解绑原生驱动: 将目标物理设备(比如一个物理网卡)从它原来的宿主机驱动(如
ixgbe
)上解绑。 - 绑定 VFIO 驱动: 将这个设备绑定到通用的
vfio-pci
驱动上。- VFIO (Virtual Function I/O) 是 Linux 内核中用于实现设备直通的标准框架。
- IOMMU/SMMU (Input-Output Memory Management Unit) 在这里扮演关键角色。它是一个硬件单元,能确保这个被“隔离”的设备只能访问分配给它的内存(即虚拟机的内存),而不能访问宿主机的其他内存,保证了系统的安全。同时,它也能对中断进行重映射。
完成这一步后,这个物理设备对于宿主机内核来说就变成了一个可以安全地交给用户态程序管理的“资源”。
第 2 步:QEMU 启动时 - “声明”设备归属
用户在启动 QEMU 时,会通过命令行参数来指定这个设备要直通给虚拟机:
qemu-system-aarch64 ... \
-device vfio-pci,host=0000:01:00.0
-device vfio-pci
: 告诉 QEMU 使用 VFIO 来管理一个设备。host=0000:01:00.0
: 指定要直通的物理设备在宿主机上的 PCI 地址。
第 3 步:QEMU 与 KVM 建立“中断路由表” (核心步骤)
这是回答您问题的关键。QEMU 启动后,它会与内核的 VFIO 和 KVM 模块进行一系列 ioctl
系统调用来建立映射关系。
QEMU 查询中断信息: QEMU 通过 VFIO 框架,查询到这个物理设备会产生哪些物理中断。VFIO 利用 IOMMU 的中断重映射功能,可以将一个物理中断抽象成一个可供 QEMU 监听的“事件通知句柄 (eventfd)”。
QEMU 设置中断路由: QEMU 拿到了代表物理中断的
eventfd
,然后它会调用一个非常关键的ioctl
给 KVM:KVM_IRQFD
这个调用的含义是:“你好 KVM,请建立一条路由规则:当这个
eventfd
被触发时(代表物理中断来了),请你在虚拟机内部,向虚拟中断控制器(VGIC)注入编号为 X 的虚拟中断。”fd
: 就是那个代表物理中断的eventfd
。gsi
: 就是X
,即 Global System Interrupt,要注入给虚拟机的虚拟中断号。
KVM 内部记录: KVM 收到
KVM_IRQFD
这个指令后,就在其内部的虚拟中断控制器(VGIC)模拟中,记录下了这条映射:物理中断源 (eventfd) -> 虚拟中断号 (gsi)
。
运行时中断的完整流程
当所有配置完成后,一个中断的完整旅程是这样的:
- 直通的物理网卡收到一个网络包,产生一个物理中断。
- 宿主机的物理中断控制器(GIC)和 IOMMU/SMMU 捕获到这个中断。
- IOMMU 识别出这个中断来自被隔离的设备,并通知 VFIO 驱动。
- VFIO 驱动触发了之前 QEMU 注册的那个
eventfd
。 - KVM 内核模块监听到这个
eventfd
被触发。 - KVM 查阅它内部由
KVM_IRQFD
建立的路由表,发现这个eventfd
对应的是要发给 Guest 的虚拟中断号X
。 - KVM 通过其核内 VGIC,向 Guest 注入一个编号为
X
的虚拟中断。 - Guest OS 的中断处理程序被调用,它以为是自己的虚拟网卡产生了中断,于是开始处理网络包。
总结一下:
KVM 是通过 QEMU 使用 KVM_IRQFD
这个明确的指令,来被告知“哪个物理中断最终是导向 Guest OS 的”。这个配置过程是实现设备直通不可或缺的一环,它在 KVM 内部建立了一张精确的“物理-虚拟中断路由表”。
当前时间: 2025 年 9 月 10 日, 星期三, 日本标准时间下午 2:44:11。