VirtIO驱动——规范1

    1  前言

    VirtIO驱动定义了一组规范,只要guest和host按照此规范进行数据操作,就可以使虚拟机IO绕过内核空间而直接再用户空间的两个进程间传输数据,以此达到提高IO性能的目的。

    VirtIO驱动的实现可以有很多种,最广泛的就是VirtIO Over PCI Bus,其它实现:VirtIO Over MMIO和VirtIO Over Channel IO不熟悉,不做介绍,这里只介绍qemu实现的VirtO驱动。

    2  VirtIO基础组件

    VirtIO设备被发现和识别的方法,通常和基于哪种总线实现方式有关。但无论是基于何种方式,一个VirtIO设备必须具备以下几个功能组件:

  •     设备状态域
  •     特性标志位
  •     设备配置空间

    2.1 设备状态域

    VirtIO设备的初始化必须按照以下步骤顺序进行才被认为被识别:

  •     重启设备。
  •     标记ACKNOWLEDGE状态标志位,表示客户机发现了此设备。
  •     标记DRIVER状态标志位,表示客户机知道怎么驱动这个设备。
  •     读取设备特性标志位并给VirtIO设备设置特性标志,在此阶段,驱动可以读取特定设备相关的一些域的数据,驱动依赖检查自己是否支持这些特性,如果支持,就采纳之。
  •     设置FEATURES_OK状态标志位,此阶段之后,驱动就不能再采纳新的特性了。
  •     再次读取设备状态,确认FEATURES_OK标志已经被设备成功:如果没有被设置成功,表示这个设备不支持该特性,设备无法就无法使用。
  •     执行具体设备的设置操作:包括扫描设备关联的virtqueues,总线设置,如果是VirtIO over PCI还需要写设备的VirtIO配置空间,还有virtqueues的使能以及运用。
  •     最后标记DRIVER_OK状态标志位,自此VirtIO设备就初始化完成,可以使用了。

    以上步骤中涉及的状态标志位,由设备状态域表示。它指出完成初始化时需要drivert做的动作。可以把它想象成指示灯,同设备状态域,外部可以知道这个设备处于什么阶段。设备状态域定义如下:

    ACKNOWLEDGE                1

    表示客户机发现了此设备,并识别到它是一个有效地VirtIO设备。

    DRIVER                                 2

    表示客户机知道怎么驱动这个设备,设置该标志位后可能有一段较长延时。比如在Linux系统中,驱动作为可加载模块,需要等模块加载完毕。

    FAILED                                  128

    表示客户机出错,该设备被置弃。出现这种情况的原因可能是内部错误,或者driver在设备操作过程中产生了致命错误等。

    FEATURES_OK                   8

    表示客户机已经识别并接受设备的所有特性,并完成了特性协商。

    DRIVER_OK                          4

    表示驱动设置完毕,可以对设备进行正常的操作。

    DEVICE_NEEDS_RESET  64

    表示设备出错,并且无法恢复,只能重启设备。

     驱动对设备状态域的支持:

    驱动需要更新设备状态域,实时标记设备状态域以此指示驱动初始化处于哪一个阶段,驱动禁止清楚设备状态位。如果驱动将设备状态置为FAILED,那么必须在执行设备复位操作后才能重新初始化。

    驱动不能根据DEVICE_NEEDS_RESET位是否置位来判断操作是否完成。比如,如果DEVICE_NEEDS_RESET被置位,驱动不能根据这个信息认为当前的请求已经完成或者未完成。好的驱动实现,是重启设备并恢复设备。

     设备对设备状态域的支持:

    设备被复位后,需要将设备状态域置0,这个动作由设备负责。

    在DRIVER_OK状态前,设备禁止使用buffer,禁止向驱动发送通知消息。

    设备遇到错误时,负责将状态域设备为DEVICE_NEEDS_RESET,通知驱动该设备需要复位。DEVICE_NEEDS_RESET状态后如果DRIVER_OK 被置位,设备需要将其配置更改通知到驱动。

    2.2  特性标志位

     每个VirtIO设备都需要支持各种特性。在设备初始化阶段,驱动读取这个特性标志,然后通知VirtIO设备驱动可以接受的特性子集。特性一定确定,只有复位VirtIO设备,才能重新协商。特性标志前后端必须一致,必须向后兼容,如果驱动支持的特性设备不支持,以设备的特性为准;如果设备支持的特性驱动不支持,以驱动特性为准。

    特性标志位各个字段含义:

    0~23:特性标志

    24~32:预留的特性标志位,用于queue和特性协商机制的扩展

    33及以上:保留,用于将来的扩展

    比如,特性标志为0,对网络设备来说,表示支持包checksum。如果设备中增加了新的配置空间,也会通过新增特性标志bit来表示。

    驱动对特性标志的支持:

    驱动禁止接受设备没有提供的特性,也不能接受依赖其它未提供特性的特性。同时,驱动必须向后兼容:如果设备提供的特性驱动无法理解,则必须以驱动的为准。

    设备对特性标志的支持:

    设备提供的特性,不能依赖其它无法支持的特性。驱动接受的任何特性子集,设备都应该支持,否则,在将设备状态域设置为FEATURES_OK时会失败。

    2.3 设备配置空间

    设备配置空间,通常用于配置不常变动的参数,或者初始化阶段设置的参数。特性标志位包含表示配置空间是否存在的bit位,后面的版本会通过在特性标志位的末尾新添新的bit位来扩展配置空间。

    Virtio设备的每一次数据传递,都附带一个配置空间的统计计数,该计数可变。因此对同一配置空间进行访问,两个访问者可能获取到不同的配置空间版本。

    驱动对设备配置空间的支持:

    驱动对配置空间的读取大于32-bit位宽,就不能保证读操作时原子的。驱动应该按照以下方式访问配置空间条目:

u32 before, after; 
do { 
        before = get_config_generation(device); 
        // read config entry/entries. 
        after = get_config_generation(device); 
} while (after != before);

    对可选的配置空间域,驱动在访问时需要通过特性标志位预先检查其是否被支持。

    驱动不能限制设备配置空间的长度。相反,驱动只能检查设备配置空间是否足够长,是否能满足必要的设备操作。举例:比如Virtio规范申明设备配置空间包含8-bit长度的空间,对驱动来说,除了这已经申明的8-bit空间外,配置空间可能还包括末尾扩展的任意长度的空间,驱动必须要处理长度大于8-bit的配置信息。

    设备对设备配置空间的支持:

    在FEATURES_OK状态被设置前,设备需要支持驱动对所有配置空间的访问,这些空间包含特性标志中指明提供的特性对应的配置空间域。

 

 

 

 

 

你可能感兴趣的:(VirtIO)