d.virtioqueue针对于不通的VMM,是可以有不同的数据传输实现方式的。对于目前的 KVM 来说,virtioqueue 采用的实现方式称为 vring。 Vring 规定了客操作系统发布到 virtioqueue 的 buf 的组织方式。物理的 vring 包括 vring_desc 数组, 可用的 vring_desc 环,已用的 vring_desc 环三个部分。 其中 vring_desc 数组用来将客操作系统向 virtIO 设备发送的 IO Request 组织称 vring_desc 链表的形式linux; 可用的 vring_desc 环用来标识那些 VMM 端当前可以处理的描述符; 已用的 vring_desc 环是 VMM 用来标识当前客操作系统端可处理的描述符。 Vring 的这三个部分处于一个连续的客操作系统物理内存块上,其 gpa 由 virtioqueue 在初始化时确定。 vring 的三个部分中用到的全部指针,包括客操作系统分配的 buf, 协议控制头数据,状态块数据的指针也都是用的 gpa,所以 VMM 端不存在困难理解vring。 Vring 和 virtio 设备的 PCI 配置空间一起,提供了一个明确的实现虚拟设备机制的 ABI linux。 e.virtioqueue的 notify 接口是客操作系统端用来向 VMM 发通知的,如一组数据相关的若干 vring_desc 写入到 vring 后,客操作系统可通过 notify 通知 VMM,以便 VMM 能立即处理。Notify 的实现实际上就是向 virtio 设备的 PCI配置空间的某寄存器写入某个值,VMM 通过 MMIO 捕获机制接收到该通知。另外 virtio 后端在合适的时候还会通过虚拟中断的方式向客操作系统发中断,virtio 驱动提供的 callback 函数就是由中断处理程序激活了 work_queue 的方式执行的linux。 目前 virtIO 设备的后端主要在 qemu-kvm 用户空间实现,但对于 virtio-net 设备,RHEL6.2 已经将后端驱动的代码移植到了内核层,称为 vhost-net,这样做消除了不必要的用户和内核空间的交互,能明显提高 virtio-net 的性能linux。 目前 KVM 上除 virtIO 外,还有其他的方式的虚拟设备的实现,如 kvmclock。 kvmclock 实现的是一个时钟源 kvm_clock, 为客操作系统提供精确的System Time 和 Wall Clock。 kvm_clock 的实现使用了硬件的支持,如 AMD-V 的 VMCB.CONTROL 提供的 TSC_OFFSET, linux以及 KVM 使用的一些技巧,如用两个定制的 MSR 寄存器 MSR_KVM_WALL_CLOCK 和 MSR_KVM_SYSTIME_TIME,通过截取这两个定制的 MSR 让 KVM 来直接访问客操作系统的时间变量。 详细:http://www.51rhca.com/archives/578
|