对 MMIO 页的访问导致缺页异常,被 KVM 捕获,通过 X86 模拟器模拟执行 MMIO 指令。
KVM 中的 I/O 虚拟化都是用户空间的 Qemu 实现的。所有 PIO 和 MMIO 的访问都是被转发
到 Qemu 的。Qemu 模拟硬件设备提供给虚拟机使用。KVM 通过异步通知机制以及 I/O 指令
的模拟来完成设备访问,这些通知包括:虚拟中断请求,信号驱动机制以及 VM 间的通信。
以虚拟机接收数据包来说明虚拟机和设备的交互。
图 3 I/O 分析
(1)当数据包到达主机的物理网卡后,调用物理网卡的驱动程序,在其中利用 Linux 内核中
的软件网桥,实现数据的转发。
(2)在软件网挢这一层,会判断数据包是发往那个设备的,同时调用网桥的发送函数,向对
应的端口发送数据包。
(3)若数据包是发往虚拟机的,则要通过 tap 设备进行转发,tap 设备由两部分组成,网络设
备和字符设备。网络设备负责接收和发送数据包,字符设备负责将数据包往内核空间和用
户空间进行转发。Tap 网络部分收到数据包后,将其设备文件符置位,同时向正在运行 VM
的进程发出 I/O 可用信号,引起 VM Exit,停止 VM 运行,进入根操作状态。 KVM 根据
KVM_EXIT_REASON 判断原因,模拟 I/O 指令的执行,将中断注入到 VM 的中断向量表中。
(4)返回用户模式的 Qemu 中,执行设备模型。返回到 kvm_main loop 中,执行 Kvm—main
—loop—wait,之后进入 main_loop wait 中,在这个函数里收集对应设备的设备文件描述符
的状态,此时 tap 设备文件描述符的状态同样被集到 fd set。
(5)Kvm main—loop 不停地循环,通过 select 系统调用判断哪螋文件描述符的状态发生变化,
相应的调用对应的处理函数。对予 tap 来说,就会通过 Qemu—send_packet 将数据发往
rtl8139 一 do—receiver,在这个函数中完成相当于硬件 RTL8139 网卡的逻辑操作。KVM 通
过模拟 I/O 指令操作虚拟 RTL8139 将数据拷贝到用户地址空间,放在相应的 I/O 地址。用
户模式处理完毕后返回内核模式,而后进入客户模式,VM 被再次执行,继续收发数据包。