背景知识

什么是VIRTIO

使用完全虚拟化,Guest不加任何修改就可以运行在任何VMM上,VMM对于Guest是完全透明的。但每次I/O都将导致CPU在Guest模式与Host模式间切换,在I/O操作密集时,这个切换是影响虚拟机性能的一个重要因素。对于通过软件方式模拟的虚拟化而言,完全可以制定一个更加高效简洁地适用于软件模拟环境下的驱动和模拟设备交互的标准,于是Virtio诞生了。与完全虚拟化相比,使用Virtio标准的驱动和模拟设备的交互不再使用寄存器等传统的I/O方式,而是采用了Virtqueue的方式传输数据。这种设计降低了设备模拟器实现的复杂度,I/O不再受数据总线宽度、寄存器宽度等因素的影响,一次I/O传递的数据量不受限制,减少了CPU在Guest模式与Host模式之间的切换,提高了虚拟化的性能。

作为一个统一的标准,越来越多的操作系统(例如Linux与Windows)已经提供了对Virtio的支持。

本文将根据Virtio1.0文档讲述VIRTIO的实现。

Dirver 与 Device

在VIRTIO中,Driver实现在虚拟机,是VIRTIO的前端;Device实现在虚拟机监控器,是VIRTIO的后端。

描述符表

Virtqueue是VIRTIO中数据传输的载体,是VIRTIO的核心部分。Virtqueue主要包括三个部分,分别是描述符表(Descriptor Table),可用描述符区域(Available Ring),已用描述符区域(Used Ring)。

VIRTIO要求描述符表,可用描述符表,已用描述符表分别在GPA上连续。

这三个表可以通过下图表示:

从左到右依次是,可用描述符表,描述符表,已用描述符表。

描述符表

描述符表是Virqqueue的核心,它包括Queue Size个描述符(Queue Size由driver决定,必须是2的指数,它的值保存在QueueSize寄存器上)。

每个描述符会指向一块共享内存,如果这块内存是驱动写给设备的数据,则称这个描述符为out类型的,如果这块内存是设备写给驱动的数据,则称这个描述符为in类型。

描述符并不是单独存在的,它们可以通过指针组成描述符链,一个描述符表中会有多条描述符链,一条描述符链记录一次I/O事件。

描述符有4个字段,如上图所示。描述符通过addr指向一块保存有I/O数据的共享内存,需要注意的是addr保存的是GPA,当后端需要根据通过addr读写该块共享内存时,需要视虚拟机监控器的实现将GPA转换成HVA或者HPA。len表示该块共享内存的长度。flags标识了描述符的属性,当flags * F_NEXT成立,则描述符可以通过next指向下一个描述符;当flags * F_WRITE成立,则这个描述符属于in类型,否则则是out类型;当flags * F_INDIRECT成立时,共享内存上将不是直接保存数据,而是保存一连串描述符。next指针则指向描述符链中的下一个描述符。

可用描述符表

driver将数据写入描述符记录的共享内存后,需要让device知道哪些描述符可以消费(可用)。可用描述符负责完成这个任务。

可用描述符中的ring是一个数组,因virtqueue中最多可能有Queue Size可用描述符链,ring的大小是Queue Size。ring中每个元素都记录了对应的描述符链的第一个描述符的ID,因此ring中一个元素对应一条描述符链,也即对应一次I/O事件。可用描述符中idx变量记录的是driver下一个填充的可用描述符,与之对应的是device将在变量last_avail_idx中记录上一个处理完的可用描述符,因此在last_avail_idx到idx之间是等待device处理的可用描述符。

已用描述符表

device将已经处理好的IO请求对应的描述符记录在已用描述符中,从这里可以看出,可用,已用这两个概念都是对device而言的。一个需要注意的点是,可用描述符和已用描述符都是指向描述符链,它们只是说明该条描述符链的状态,并不是代表描述符链的in/out类型。

与可用描述符不同的是,已用描述符的数组中每个元素的大小是8byte,它不仅记录了描述符链第一个描述符的ID,还记录了device向描述符链中写入的byte数。已用描述符通过idx和last_used_idx记录了等待driver回收的描述符链。idx由设备维护,表示设备下一个处理完的描述符链将记录在已用描述符表中的位置,last_used_idx由驱动维护,记录的是驱动上一个回收的描述符链在已用描述符表中的位置。

VIRTIO MMIO寄存器(部分

在MMIO实现VIRTIO的情况下,每个VIRTIO设备都有一个MMIO REGION。这个REGION在设备树中的声明如图:

上图表示GPA 0x1e000 到 0x1e200 的地址段是这个virtio_block设备的MMIO REGION。这个REGION中分布着VIRTIO MMIO寄存器。

42是这个virtio设备对应的中断号,注意42需要加上SPI中断的基础值:32,因此这个virtio driver实际上能够识别的中断号是74。

一些重要的MMIO 寄存器如下:

DeviceFeatures & DeviceFeaturesSel

设备通过DeviceFeatures寄存器告诉驱动设备支持的一些机制,比如VIRTIO_RING_F_INDIRECT_DESC这个bit就是告诉driver:device支持virtqueue通过indirection扩大共享内存区域。driver只能够在device提供的机制上工作,不能够在device没有提供该机制的情况下运行对应的代码。由于DeviceFeatures的区域要大于4bytes,driver需要通过DeviceFeaturesSel寄存器用查看DeviceFeatures的部分bits。

DriverFeatures & DriverFeaturesSel

驱动通过DriverFeatures寄存器告诉设备,驱动支持了设备的哪些机制,DriverFeaturesSel则用于设备查看DriverFeatures。

QueueSel

对于某些virtio设备,比如virtio-net,virtio-console会包括多个virtqueue。为了让设备知道该对在哪条virtqueue上进行处理,driver会通过QueueSel寄存器告诉驱动后续的操作是在哪条virtqueue进行的。

QueueReady

driver会通过写QueueReady寄存器通知设备,当前virtqueue已经初始化好了,设备可以通过读描述符寄存器来获得virtqueue的地址。

QueueNotify

当driver准备了新的可用描述符时,会通过写QueueNotify寄存器通知device进行处理。

InterruptStatus

Virtio设备可以通过发送中断通知虚拟机,每个virtio设备有一个对应的中断号(这个中断号在设备树中声明),虚拟机在收到中断后,会根据中断号找到对应的driver,driver则需要通过InterruptStatus寄存器搞清楚产生这次中断的事件是什么,比如bit 0表示已用描述符更新,bit 1表示设备配置空间更新。

QueueDescLow & QueueDescHigh

driver通过写这两个寄存器告诉device描述符表的GPA。由于每个MMIO寄存器只有32个bit,因此需要两个寄存器。

QueueAvailLow & QueueAvailHigh

driver通过写这两个寄存器告诉device可用描述符表的GPA。

QueueUsedLow & QueueUsedHigh

driver通过写这两个寄存器告诉device已用描述符表的GPA。

Config

Config不是一个寄存器,而是一个区域,这个区域由device进行配置,每种device会有不一样的配置区域。

下图展示的就是block设备配置空间的数据结构。

参考资料

《深度探索Linux系统虚拟化:原理与实现》

《Virtual I/O Device Version 1.0》

《Linux虚拟化KVM-Qemu分析(十一)之virtqueue》

https://github.com/minosproject/minos/

下一期将介绍实现VIRTIO-BLK设备时,虚拟机image,rootfs,dtb文件的制作

通过MMIO的方式实现VIRTIO-BLK设备(一)的更多相关文章

  1. Virtio SCSI设备介绍

    Qemu的存储栈 在KVM虚拟化环境中,当客户机的内核存储系统像在物理机上一样通过页缓存.文件系统.通用块设备层运行到实际设备驱动时,这时驱动对设备寄存器的访问会触发CPU从客户机代码切换到物理机内的 ...

  2. 每日技术总结:vue router传参方式,js获取设备高度

    今天貌似没什么问题,23333…… 1.vue router 路由传参的方式 应用情景:从分类页(category.vue)进入商品列表页(list.vue),需要传递商品分类id(catId),商品 ...

  3. Tcp方式采集CNC兄弟设备数据

    先说下为了采集CNC兄弟设备的数据可谓是一波三折. 因为首次接触brother设备(CNC)是直接在设备上设置IP.用户名.密码,然后直连PC,用Ftp可以查看和下载CNC brother设备里的数据 ...

  4. 三种方式设置特定设备UWP XAML view

    开发者可以设置UWP特定设备xaml view,在桌面,手机,Iot,这个对于设置对不同设备的不同屏幕有用.我们可以使用RelativePanel,VisualStateTriggers,但是这样我们 ...

  5. 基于Linux的USB 主/从设备之间通讯的三种方式

    转载:http://archive.eet-china.com/www.eet-china.com/ART_8800323770_617693_TA_eda530e7.HTM 随着简单易用的USB接口 ...

  6. 计算机组成原理——I/O接口以及I/O设备数据传送控制方式

    接口可以看作是两个部件之间交接的部分.硬件与硬件之间有接口,硬件与软件之间有接口,软件与软件之间也有接口. 这里我们所说的I/O接口,一边连接着主机,一边连接着外设. I/O接口的功能 I/O接口的基 ...

  7. 5-(微信小程序篇)关于WiFi模块配网以后利用小程序绑定设备,绑定方式说明

    https://www.cnblogs.com/yangfengwu/p/11625189.html 众所周知:使用微信Airkiss 只能给设备配网,并不能够获取设备的MAC地址信息,但是我在 ht ...

  8. 2018-8-10-三种方式设置特定设备UWP-XAML-view

    title author date CreateTime categories 三种方式设置特定设备UWP XAML view lindexi 2018-08-10 19:16:52 +0800 20 ...

  9. iNeuOS工业互联网操作系统,发布实时存储方式:实时存储、变化存储、定时存储,增加设备振动状态和电能状态监测驱动,v3.6.2

    目       录 1.      概述... 1 2.      平台演示... 2 3.      存储方式... 2 4.      设备状态和用电状态监控驱动... 3 1.   概述 本次升 ...

随机推荐

  1. 使用Mybatis插件 PageHelper 模拟百度分页(Day_20)

    生活中,要学会沉淀生命,沉淀心情,沉淀自己 模拟百度分页最终实现效果如图: 本篇博客运行环境 JDK8 + IntelliJ IDEA 2018.3 + Tomcat 8.5.31 准备好了我们就开始 ...

  2. 第14讲 | HTTP协议:看个新闻原来这么麻烦

    第14讲 | HTTP协议:看个新闻原来这么麻烦 http://www.163.com 是个 URL,叫作统一资源定位符. 之所以叫统一,是因为它是有格式的.HTTP 称为协议,www.163.com ...

  3. NVIDIA 认证系统

    NVIDIA 认证系统 AI 是这个时代最强大的技术,需要新一代经过调整和测试的计算机来推动其发展. 自 1 月 27 日开始,可从 NVIDIA 合作伙伴处获取用于数据中心的新型加速服务器,推动 A ...

  4. 如何选择视觉CV光源颜色

    如何选择视觉CV光源颜色 一.光源颜色分类 光源颜色的选择对机器视觉光源有什么影响及意义呢,常用的光源颜色有白色(W).蓝色(B).红色(R).绿色(G).红外光(IR).紫外光(UV),这六种颜色. ...

  5. 腾讯TencentOS 十年云原生的迭代演进之路

    导语 TencentOS Server (又名 Tencent Linux 简称 Tlinux) 是腾讯针对云的场景研发的 Linux 操作系统,提供了专门的功能特性和性能优化,为云服务器实例中的应用 ...

  6. Docker 版 3分钟部署 .net core 开源在线客服系统,他来了

    我在博客园发表了一系列文章,开始介绍基于 .net core 的在线客服系统开发过程. 前些天又应朋友的要求,发了一篇 CentOS 版本的安装部署教程:https://www.cnblogs.com ...

  7. 一款基于SpringBoot+SpringSecurity的后台管理系统,强烈推荐

    简介 Base Admin一套简单通用的后台管理系统,主要功能有:权限管理.菜单管理.用户管理,系统设置.实时日志,API加密,以及登录用户修改密码.配置个性菜单等. 技术栈 前端:Layui 后端: ...

  8. 【模拟7.25】回家(tarjan V-DCC点双连通分量的求法及缩点 求割点)模板题

    作为一道板子题放在第二题令人身心愉悦,不到一个小时码完连对拍都没打. 关于tarjan割点的注意事项: 1.在该板子中我们求的是V-DCC,而不是缩点,V-DCC最少有两个点组成,表示出掉一个块里的任 ...

  9. 【数论】8.30题解-prime素数密度 洛谷p1835

    prime 洛谷p1835 题目描述 给定区间[L, R](L <= R <= 2147483647, R-L <= 1000000),请计算区间中 素数的个数. 输入输出 输入 两 ...

  10. Windows内核开发-Windows内部概述-2-

    Windows内部概述-2- 线程: 执行代码的实体是线程.一个线程的包含在进程里面的,线程使用进程提供的资源来运行代码. 一个线程拥有以下的内容: 1:明确的运行模式,用户态或者内核态. 2:执行的 ...