Virtio协议学习篇

Virtqueues

virtqueues是一种virtio pci device的大量数据传输的机制。每个设备可有0或更多的virtqueues,例如网络设备有一个发送queue 一个接收queue,每个queue占用两个或者更多的物理地址连续的page(virtio spec定义4096byte为一个page),queue由以下部分组成:

当驱动往设备发送整个buffer的时候,填写descriptor table的一条,将descriptor index写到available ring, 然后通知设备。当设备完成buffer的传输时,它写描述符到used ring中并且发送中断。

PCI discovery

PCI设备的Vendor ID是1AF4,Device ID是0x1000~0x103F的为virtio设备。Subsystem Device ID指示当前的设备支持哪种virtio设备。

Device Configuration和Device初始化步骤

 为了配置设备,我们用PCI设备的first I/O region。 其中包含了virtio header, device-specific region。

virtio header格式如下:

其中,device status由guest更新,指示当前的过程。可以接在信号灯上作为各个设备的诊断,有ACKNOWLEDGE(指示guest OS已经发现并识别设备为virtio设备),DRIVER(指示guest OS知道如何驱动设备),DRIVER_OK(驱动已经准备好) FAILED(guest出错)

其中,Feature bit指示设备支持的Feature, 例如 Feature bit0对于网络设备(Subsystem Deive ID 1)指示设备支持packet checksumming。Feature bit是协商的,设备在Device Featrue字段列出所有支持的Feature, guest在Guest Featrue字段列出子集。

device-specfic格式如下:

Guest对Device进行初始化的步骤:

 Virtqueue Configuration

  1. 驱动需要配置queue:
  2. 写queue index(第一个为0)到Queue Select字段;
  3. 读Queue Size字段获取Size;
  4. 分配queue连续的物理地址空间(4K对齐)将物理地址写入到Queue Address字段;
  5. 若使能MSIX,选择vector,用于queue event触发中断, 写Queue Vector....

Descriptor Table: 指向guest和device收发数据的buffer,地址为物理地址,描述符可以为链表,每个描述符支持buffer是只读还是只写,链表中既可以存在只读的buffer也可以存在只写的bufer。 描述符的数量由Queue Size指定。如果协商了VIRTIO_F_INDIRECT_DESC feature则可以使用Indirect Descriptors来增加ring的容量。

Available Ring: 指向提供给设备的描述符,指向描述符链表的head。它仅由Driver写入并由Device读取,Device获取Descriptor后,Descriptor对应的缓冲区可能是可读的也可能是可写的,可读的用于Driver发送数据,可写的用于接收数据。

flag字段目前是0或1,1-表示设备从Available Ring消耗描述符的时候不需要产生中断。Guest也可以延时中断,直到一个由used ring中的“idx”已经累加到used_event指定Index值时才会产生kick。 idx域指示下一个描述符entry的位置(ring size的取模,因为ring是循环结构),idx从0开始增加。available ring结构:

Used Ring: 是为了设备处理完成buffer数据后返还buffer用的。flag字段用来指示当guest添加buffer时是否需要通知,avail_event也可以延迟,直到idx累加到avail_event时才通知。每个enty由描述符链表的head entry和写入buffer的总字节数组成。used ring结构:

 

 Device Operation

 包含两部分:提供新buffer给设备,处理used buffer。

 以virtio network device为例,有两个queue: 发送queue和接收queue。驱动添加outgoing packet(只读)给发送queue,用完后释放它们。相似地,incoming buffers(只写)添加到接收queue,用完后处理。

以下内容摘自 Virtio原理简介 | Lauren·weblog

当Driver想要向设备发送数据时,它会填充Descriptor Table中的一项(或将几项链接在一起),并将描述符索引写入Available Ring中,然后它通知Device,当Device完成后,它将描述符索引写入Used Ring中并发送中断。(详见SPEC 2.4)

Driver将sk_buffer填充进scatterlist table中(只是设置地址没有数据搬移),然后通过计算得到GPA并将GPA写入Descriptor Table中,同时将Desc chain的head记录到Available Ring中,然后通过PIO的方式通知Device,Device发包并更新Used Ring

The used ring is where the device returns buffers once it is done with them: it is only written to by the device,and read by the driver.简单来说,Used Ring的作用就是Device使用完Descriptor之后,将Descriptor放入这里,通知Driver回收。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值