virtio背景介绍

virtio背景

vitro的内容用于半虚拟化的实现,这篇博客简单介绍了linux kernel中的vitro模块的实现

virtio 是一种 I/O 半虚拟化解决方案,是一套通用 I/O 设备虚拟化的程序,是对半虚拟化 Hypervisor 中的一组通用 I/O 设备的抽象。提供了一套上层应用与各 Hypervisor 虚拟化设备(KVM,Xen,VMware等)之间的通信框架和编程接口,减少跨平台所带来的兼容性问题,大大提高驱动程序开发效率。

在完全虚拟化的解决方案中,guest VM 要使用底层 host 资源,需要 Hypervisor 来截获所有的请求指令,然后模拟出这些指令的行为,这样势必会带来很多性能上的开销。半虚拟化通过底层硬件辅助的方式,将部分没必要虚拟化的指令通过硬件来完成,Hypervisor 只负责完成部分指令的虚拟化,要做到这点,需要 guest 来配合,guest 完成不同设备的前端驱动程序,Hypervisor 配合 guest 完成相应的后端驱动程序,这样两者之间通过某种交互机制就可以实现高效的虚拟化过程。

virtio论文解读:https://zhuanlan.zhihu.com/p/68154666

https://blog.csdn.net/wangquan1992/article/details/120649182

① virtio表示虚拟化IO,用于实现设备半虚拟化,即虚拟机中运行的操作系统需要加载特殊的驱动(e.g. virtio-net)且虚拟机知道自己是虚拟机

相较于基于完全模拟的全虚拟化,基于virtio的半虚拟化可以提升设备访问性能

② 运行在虚拟机中的部分称为前端驱动,负责对虚拟机提供统一的接口

③ 运行在宿主机中的部分称为后端驱动,负责适配不同的物理硬件设备

这篇文章介绍了vitro-net的原理:https://www.51cto.com/article/660499.html

virtio前端驱动:

运行在虚拟机中
针对不同类型的设备有不同的驱动程序,但是与后端驱动交互的接口都是统一的
本文分析virtio-net模块,源码位于drivers/net/virtio_net.c
virtio后端驱动

运行在宿主机中
实现virtio后端的逻辑,主要是操作硬件设备,比如向内核协议栈发送一个网络包完成虚拟机对于网络的操作
在Qemu + KVM虚拟化环境中,源码位于KVM或者Xen中,这里我们没有涉及到

总结:unikraft的virtio部分是在介绍virtio的前端部分

dev与driver

https://zhuanlan.zhihu.com/p/361918197

image.png

virtio分为driver和device,driver部分运行于guest操作系统中,device部分运行于hypervisor中,driver和device是生产者和消费者模式动作,driver生产内存,device消费内存。不同virtio版本之间是互相兼容的,driver和device版本不同也可以互相运转。

对比unikraft的结构来看。

hypervisor:Hypervisor——一种运行在基础物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享硬件。也可叫做VMM( virtual machine monitor ),即虚拟机监视器。Hypervisors是一种在虚拟环境中的“元”操作系统。他们可以访问服务器上包括磁盘和内存在内的所有物理设备。Hypervisors不但协调着这些硬件资源的访问,也同时在各个虚拟机之间施加防护。当服务器启动并执行Hypervisor时,它会加载所有虚拟机客户端的操作系统同时会分配给每一台虚拟机适量的内存,CPU,网络和磁盘。

KVM就属于unikraft的第一种类型,直接运行在裸金属上。KVM本身基于硬件辅助虚拟化,仅仅实现CPU和内存的虚拟化,但一台计算机不仅仅有CPU和内存,还需要各种各样的I/O设备,不过KVM不负责这些。这个时候,QEMU就和KVM搭上了线,经过改造后的QEMU,负责外部设备的虚拟,KVM负责底层执行引擎和内存的虚拟,两者彼此互补,成为新一代云计算虚拟化方案的宠儿。

guest OS:在我们这里就是Unikraft core,即虚拟机

Unikraft:

image.png

常规虚拟机:

image.png

容器:
image.pngdevice status field:driver发现了device,driver可以正常驱动device,driver或者device出错了,driver或者device要进行reset。

  • device feature bit:driver和device协商feature以便于不同virtio版本之间兼容。

  • notification:driver和device互通通知对方,driver生产好的内存要通知device去消费,device消费完了要通知driver回收内存。driver通知deivce用doorbell机制,在kvm中是写寄存器,kvm进行拦截再通知vhost。device通知driver用中断机制,在kvm中是中断注入。

  • config space:典型的如virtio-net-device的MAC地址/MTU/最大支持队列数等。

  • virtqueue:每个virtqueue分成这三部分,descriptor/available/used,descriptor/available/used就是三个大数组,descriptor数组内容存放真正东西,available和used数组内容存放descriptor数组的下标。driver生产内存,把生产的内存地址和长度写在descriptor,然后把descriptor数据下标写到available数组中,通知device,device消费内存,消费完再把descriptor的数据下标定到used数组中,通知driver进行内存回收。

chained descriptor,几个desciptor项连在一起,适用于scater-gather。

indirect descriptor,主descriptor中一项指向另一个descriptor数组。

一般设备的virtqueue基本可以分三类rx virtqueue/tx virtqueue/ctrl virtqueue,rx virtqueue和tx virtqueue用于进行IO,driver通过ctrl virtqueue控制device。

device准备,driver发现device,状态更新和feature协商,driver分配virtqueue,把virtqueue地址告诉device。