-
设备初始化
- 驱动初始化步骤
- Reset 设备
- 设置 ACKNOWLEDGE 状态,通知设备:客户机设别了设备
- 设置 DRIVER 状态,客户机找到了对应的驱动
- 读取设备的 feature bit 并写会驱动支持的 feature bit 子集到设备,接收feature bit前驱动可能读取 device-specific configuration 进行细粒度校验
- 设置 FEATURES_OK,此后,驱动不能在接受更多新的 feature bit
- 读取设备状态,确保FEATURES_OK 写入成功,如果不是 FEATURES_OK,说明特性协商不成功,设备不可用
- 进行 device-specific 设定,包括配置 virtio configuration space,设定 virtqueue等
- 设定 DRIVER_OK,表示设备可用,驱动加载完成
- 如果任何一个步骤有错,驱动设置FAILED状态,放弃设备初始化
- 在 DRIVER_OK 前,不能下发 KICK
- 区别
- Legacy 设备不支持 FEATURES_OK 状态,没有机会检查兼容性
- Legacy 设备没有明确的feature协商状态
- 步骤5,6没有;
-
设备操作
- 两种设备操作:发送(发送给设备,tx)和接收(从设备接收,rx)
- 发送
- 驱动发送buffer到设备的一个或多个TX队列
- 驱动将buffer存到desc表的free desc中,可能desc成链
- 驱动将desc链的第一个desc的idx写入avail ring的生产位置(avail ring->idx)
- 重复步骤1,2进行批量操作
- 加入内存屏障
- 增加 avail ring->idx,指向下一次驱动会生产填入的位置
- KICK没有被抑制,发送KICK
- avail ring 的填写不会超过一圈,因为 ring深度和desc 表大小一样,不会填写超过一个ring深度的desc到avail ring
- 最大queue size是32768
- 用buffer填写desc表中的desc
- 0个或多个客户物理地址连续的设备可读buffer
- 后面是0个或多个客户物理地址连续的设备可写buffer
- 填充到一个desc链里面
- 填充buffer b的步骤
- 从desc表取得下一个空闲的desc(d)
- d.addr = b 的客户物理地址
- d.len = b 的长度
- 如果 b 是设备可写, d.flags |= VIRTQ_DESC_F_WRITE;否则 d.flag = 0
- 如果后面还有下一个buffer
- d.next = 下一个空闲desc的idx
- d.flags |= VIRTQ_DESC_F_NEXT
- 注意填充buffer前驱动需要确认有足够多的空闲desc可以使用
- 更新 avail ring
- desc 表头是第一个desc(d)的idx,填入avail ring中
- 驱动可能一次加入多个desc链
- 更新 avail ring -> idx
- avail ring -> idx 单向自增,直到65535
- 驱动更新 avail ring -> idx
- 设备根据 avail ring -> idx 来取desc表和buffer的内存
- 驱动
- 驱动在更新 avail ring -> idx 前,必须加入内存屏障,保证设备能读到desc链和buffer
- 向设备发送KICK
- 根据不同的总线类型有不同方式的KICK
- 操作代价很高
- 设备可能会对KICK进行限流抑制
- 驱动使用更新后的avail ring -> idx(下一个位置)来对是否抑制进行判断
- 驱动
- 驱动在读取flags 或 avail_event之前,必须加入内存屏障
- 接收
- 设备使用了desc所指向的内存后(读或写),会发送中断给驱动
- 驱动可能关闭中断,使能后,驱动需要再次 used ring->idx
- 配置变更中断
- device-specific configuration信息在运行期间可能发生变化,设备需要发送Config chang 中断给设备
- 设备设置了 DEVICE_NEEDS_RESET 状态,会触发 Config chang 中断
- 驱动发送buffer到设备的一个或多个TX队列
-
设备清理移除
- 设置 DRIVER_OK 状态,队列的配置认为了被激活
- 设备发生重启,队列就是不可用状态
- 驱动
- 写入available ring后的desc不能被修改
- 队列使能后,available idx只能单向增长
virtio协议1.0 -- 设备初始和操作
最新推荐文章于 2022-08-31 22:14:41 发布