背景

  • Read the fucking source code! --By 鲁迅
  • A picture is worth a thousand words. --By 高尔基

说明:

  1. KVM版本:5.9.1
  2. QEMU版本:5.0.0
  3. 工具:Source Insight 3.5, Visio
  4. 文章同步在博客园:https://www.cnblogs.com/LoyenWang/

1. 概述

  • 前篇文章讲完了Qemu中如何来创建Virtio Device,本文将围绕Guest OS中的Virtio Driver来展开;

看一下Guest OS(Linux)中的Virtio框架高层架构图:

  • 核心模块为virtio和virtqueue,其他高层的驱动都是基于核心模块之上构建的;
  • 显然,本文会延续这个系列,继续分析virtio-net驱动,重心在整体流程和框架上,细节不表;
  • virtio-net,又是一个virtio设备,又是一个PCI设备,那么驱动会怎么组织呢?带着问题上路吧。

2. 数据结构

说到驱动怎么能不提linux设备驱动模型呢,感兴趣的朋友可以去看看PCI系列分析文章,简单来说就是内核创建总线用于挂载设备,总线负责设备与驱动的匹配。Linux内核创建了一个virtio bus:

  • virtio设备和virtio驱动,通过virtio_device_id来匹配,而这个都是在virtio规范中定义好的;
  • virtio_device结构中有一个struct virtio_config_ops,函数集由驱动来进行指定,用于操作具体的设备;

本文描述的virtio-net驱动,既是一个virtio设备,也是一个pci设备,在内核中通过结构体struct virtio_pci_device来组织:

  • 该结构体中维护了几个IO区域:Common, ISR, Device, Notify,用于获取virtio设备的各种信息,这个也是由virtio规范决定的;
  • 通常来说一个virtio设备,由以下几个部分组成:
    1. Device status field
    2. Feature bits
    3. Notifications
    4. Device Configuration space
    5. One or more virtqueues
  • 从结构体看,它用于充当pci设备和virtio设备的纽带,后续也会在probe函数中针对不同的部分进行对应的初始化;

以总线的匹配视角来看就是这样子的:

3. 流程分析

3.1 virtio总线创建

先看一下virtio总线的创建,virtio bus当然也算是基建了:

  • bus_register注册virtio总线,总线负责匹配,在匹配成功后调用通用的virtio_dev_probe函数;
  • 千里姻缘一线牵,当Virtio的ID号能对上时,就会触发驱动探测,所以什么时候进行设备注册呢?

3.2 virtio驱动调用流程

详细的细节,建议阅读之前PCI驱动系列的分析文章,下边罗列关键部分:

  • virtio-net设备通过挂在pci总线上,系统在PCI子系统初始化时会去枚举所有的设备,并将枚举的设备注册进系统;
  • 系统在匹配上之后,调用设备的驱动;

  • PCI设备根据Vendor ID来匹配驱动;
  • virtio规范中规定基于PCI的virtio设备,Vendor ID号为:0x1AF4,因此最终调用的驱动入口为virtio_pci_probe

  • 在probe函数中分配struct virtio_pci_device结构,前文中也提到过它负责将virtio设备和pci设备绑定到一起,最终会在两个设备驱动的probe函数中完成整体结构的初始化,也就是virtio_pci_probe完成一部分,实际的virtio设备驱动中完成一部分;
  • virtio_pci_modern_probe:该函数的内容就与virtio规范紧密相关了,简单来说,virtio设备都会按照规范填充common、device、isr、notification等功能部分,而virtio_pci_modern_probe函数通过virtio_pci_find_capability去获取对应的能力,并且通过map_capability完成IO空间的映射;
  • virtio_pci_probe中还设置了virtio_pci_config_ops操作函数集,并传递给virtio驱动,在驱动中调用这些回调函数来操作virtio设备;
  • register_virtio_device:向系统注册virtio设备,从而也就触发了virtio总线的匹配操作,最终调用virtio_dev_probe函数;
  • virtio_dev_probe函数中按照virtio规范分阶段设置不同的状态、获取virtio设备的feature等,并最终调用实际设备的驱动程序了;

At last,终于摸到本文要说的virtio-net的驱动的入口了,当然,文章也要戛然而止了。

整体执行流程及框架应该清楚了,细节就留给大家了,待续。。。

参考

https://developer.ibm.com/technologies/linux/articles/l-virtio/

Virtual I/O Device (VIRTIO) Version 1.1

欢迎关注个人公众号,不定期更新技术文章。

【原创】Linux虚拟化KVM-Qemu分析(十)之virtio驱动的更多相关文章

  1. KVM下windows虚拟机使用virtio驱动

    KVM下windows虚拟机默认disk使用的是Qemu IDE硬盘,网卡默认是rtl8139网卡.为了使kvm主机在相同的配置下,有更好的效率,可以将网卡和磁盘替换成virtio的驱动. windo ...

  2. KVM/QEMU桥接网络设置及kvm资料

    KVM/QEMU桥接网络设置 配置kvm的网络有2种方法.其一,默认方式为用户模式网络(Usermode Networking),数据包由NAT方式通过主机的接口进行传送.其二,使用桥接方式(Brid ...

  3. KVM/QEMU/qemu-kvm/libvirt 概念全解

    目录 目录 前言 KVM QEMU KVM 与 QEMU qemu-kvm Libvirt Libvirt 在 OpenStack 中的应用 前言 如果是刚开始接触虚拟机技术的话, 对上述的概念肯定会 ...

  4. 【原创】Linux虚拟化KVM-Qemu分析(三)之KVM源码(1)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  5. 【原创】Linux虚拟化KVM-Qemu分析(一)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  6. 【原创】Linux虚拟化KVM-Qemu分析(四)之CPU虚拟化(2)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  7. 【原创】Linux虚拟化KVM-Qemu分析(五)之内存虚拟化

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  8. 【原创】Linux虚拟化KVM-Qemu分析(八)之virtio初探

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  9. Linux虚拟化技术KVM、QEMU与libvirt的关系(转)

    说明:个人理解,KVM是内核虚拟化技术,而内核是不能使用在界面上使用的,那么此时QEMU提供了用户级别的使用界面,相互辅助.当然,单独使用QEMU也是可以实现一整套虚拟机,不过QEMU+KVM基本是标 ...

随机推荐

  1. Arduino字符串笔记

    Arduino里的字符串笔记 1 字符串转数字 String To Int /* 使用String.toInt()将字符串转为数字示例 */ String inString = "" ...

  2. Pytest(11)allure报告

    前言 allure是一个report框架,支持java的Junit/testng等框架,当然也可以支持python的pytest框架,也可以集成到Jenkins上展示高大上的报告界面. mac环境: ...

  3. 聊聊elasticsearch7.8的模板和动态映射

    最近想写一篇es的索引的一个设计,由于设计的东西特别多,当然,elasticsearch的模板和动态映射也是其中的一个设计点,所以干脆先来聊聊索引的模板和动态映射,模板,听这个名字就相当于一些公共可用 ...

  4. C# 如何复制(拷贝)Label控件上的文本【新方法】

    Label控件在目前是无法直接调用成员函数来复制其文本内容.其实网络上有很多热心程序员网民解答过这个问题,百度上也可以搜索到,不过大多数人建议使用 TextBox 并把边框调整为不可见(运行时文本框看 ...

  5. hdu5637 Transform (bfs+预处理)

    Problem Description A list of n integers are given. For an integer x you can do the following operat ...

  6. codeforces 86D D. Powerful array

    An array of positive integers a1, a2, ..., an is given. Let us consider its arbitrary subarray al, a ...

  7. Educational Codeforces Round 91 (Rated for Div. 2) A. Three Indices (模拟)

    题意:有一长度为\(n\)的序列,问是否能找到\(a_{i}<a_{j},a_{j}>a_{k},(i<j<k)\),如果满足,输出其位置. 题解:直接暴力两头找即可,最坏复杂 ...

  8. 4.Direct交换机之使用指定routingkey完成日志记录场景

    标题 : 4.Direct交换机之使用指定routingkey完成日志记录场景 目录 : RabbitMQ 序号 : 4 const string logOthersQueueName = " ...

  9. POJ 1625 Censored!(AC自动机 + DP + 大数 + 拓展ASCII处理)题解

    题意:给出n个字符,p个病毒串,要你求出长度为m的不包含病毒串的主串的个数 思路:不给取模最恶劣情况$50^{50}$,所以用高精度板子.因为m比较小,可以直接用DP写. 因为给你的串的字符包含拓展A ...

  10. Java 对象的哈希值是每次 hashCode() 方法调用重计算么?

    对于没有覆盖hashCode()方法的对象 如果没有覆盖 hashCode() 方法,那么哈希值为底层 JDK C++ 源码实现,实例每次调用hashcode()方法,只有第一次计算哈希值,之后哈希值 ...