文章目录
概述
作为一个通用半虚拟化框架,virtio技术能够应用到不同的体系架构中,并为各种业务类型提供服务。virtio协议支持基于多种类型设备总线进行实现,包括PCI、MMIO、channel IO等,同时也扩展实现了多种设备类型。
virtio设备管理
virtio设备属性
一个标准的virtio设备通常定义了以下几个部分的属性:
- Device status field:用于指示设备状态;
- Feature bits:用于设备功能协商;
- Notifications:通知机制;
- Device Configuration space:特定于设备的配置;
- Virtqueues:设备支持一个或多个virtqueue实现前后端通信。
Device status field
virtio驱动需要遵循标准定义的顺序来对virtio设备进行初始化,Device status field提供了特定的一些位,用于配合完成设备的初始化。
- ACKNOWLEDGE:表示GuestOS已正确探测到virtio设备;
- DRIVER:表示GuestOS已经知道如何驱动设备;
- FAILED:表示GuestOS出现问题,并且已放弃使用设备;
- FEATURES_OK:表示GuestOS已经完成Feature的协商;
- DRIVER_OK:表示驱动程序已经完成设置并准备使用;
- DEVICE_NEEDS_RESET:表示设备出现错误,需要复位进行修复。
Feature Bits
virtio设备使用Feature bits描述它所支持的所有功能,在设备初始化期间,驱动程序读取此信息,并选择需要的功能与设备进行协商。
Feature bits | 作用 |
---|---|
0~23 | 特定设备类型的Feature bits |
24~37 | 保留,用于队列和Feature协商机制的扩展 |
38及以上 | 保留,用于未来扩展的Feature bits |
virtio设备类型
virtio协议规范中定义的virtio设备类型如下:
Virtio Device ID | Virio Device Type |
---|---|
0 | reserved(invalid) |
1 | network card |
2 | block device |
3 | console |
4 | entropy source |
5 | memory ballooning(traditional) |
6 | ioMemory |
7 | rpmsg |
8 | SCSI host |
9 | 9P transport |
10 | mac80211 wlan |
11 | rproc serial |
12 | virtio CAIF |
13 | memory ballon |
16 | GPU device |
17 | Timer/Clock device |
18 | Input device |
virtio设备初始化
在virtio协议规范中,约束了驱动程序如何初始化和配置一个virtio设备。
驱动必须遵循定义的顺序对设备进行初始化:
- 重置设备;
- 设置ACKNOWLEDGE状态位:GuestOS已经探测到该设备;
- 设置DRIVER状态位:GuestOS已经确定如何驱动设备;
- 读取设备Feature bits,并将驱动需要配置的Feature bits写入设备。这个步骤中,驱动程序可以读取设备特定的配置字段,以在接受设备之前检查其是否能够支持设备;
- 设置FEATURES_OK状态位,执行完成之后,驱动程序不得再更改Feature;如果驱动需要与设备重新协商功能,唯一方法就是是重置设备;
- 重新读取设备状态,以确保FEATURES_OK位仍然设置:否则,设备不支持我们的功能子集,设备不可用;
- 执行特定于设备的设置,包括配置virtqueues,读取和修改设备的virtio配置空间,以及生成virtqueues等;
- 设置DRIVER_OK状态。
virtio-pci设备
在通用服务器上,virtio设备主要基于PCI总线进行实现。基于PCI总线的virtio设备有着专属的Vendor ID(0x1AF4)和特定的Device ID区间(0x1000~0x107F),其中0x1000~0x103F用于传统模式设备,0x1040~0x107F用于现代模式设备。系统可以通过Vendor ID可以识别出virtio pci设备,而Device ID则可以用于指示该virtio pci设备支持的virtio设备类型。
virtio-pci设备发现
virito使用PCI接口实现时,Hypervisor会在后端模拟一个PCI设备,并将这个设备添加到虚拟机配置中,虚拟机启动的时候会发现设备并接入到系统中。virtio-pci设备接入系统的拓扑关系如下:
为了支持PCI总线,每种virtio设备需要对应一个virtio-pci代理设备。virtio-pci代理设备能够通过与PCI设备相似的方式被虚拟机中的BIOS或客户机操作系统识别,并挂载到PCI总线。virtio-pci代理设备的一个重要作用是提供virtio设备的访问接口,它会创建一条virtio总线,并将virtio设备挂载到virtio总线,这样virtio驱动便能够访问virtio设备。
virtio-pci设备配置
传统virtio-pci设备的配置
传统virtio-pci设备使用PCI设备的BAR0指向的IO区域来对virtio-pci设备进行配置。该IO区域包含一个virito-header结构,用于存放virtio设备的通用配置项以及设备的专属配置。下图展示了virtio-header中的通用配置项:
各个配置项的作用描述如下:
- Device Features:由virtio设备填写,用于告诉驱动支持的设备特性;
- Guest Features:用于告诉驱动支持的设备特性;
- Queue Address:表示virtqueue所在的地址,这个地址由驱动分配,并告知设备;
- Queue Size:表示virtqueue的描述符表中描述符的个数,设备端初始化队列时设置;
- Queue Select:当某个操作是针对某个virtqueue时,驱动通过Queue Select指定这个virtqueue;
- Queue Notify:当某个virtqueue准备好后,驱动需要通知设备进行消费,virtio协议采用的方式就是对某个约定地址进行IO,触发CPU从Guest切换到Host;
- Device Status:用于表示设备的状态;
- ISR Status:中断相关。
现代virtio-pci设备的配置
和传统设备固定使用BAR0不同,现代virtio-pci设备通过标准的PCI配置空间中的能力列表(capability list),可以指定配置信息的存储位置(使用哪个BAR,从BAR空间开始的偏移地址等)。1.0规范中定义了4种配置信息:通用配置、中断配置、通知配置、设备专属配置。相应的配置信息和内存区域的空间分布图如下:
相关参考
- 《深入浅出DPDK》
- 《深入浅出系统虚拟化:原理与实践》
- 《深度探索Linux系统虚拟化:原理与实现》