virtio 学习随笔 —— 四、virtio设备发现以及枚举

四、virtio设备发现以及枚举

Linux Kernel: v2.6.15

virtio总线

virtio总线是一个虚拟总线,物理上并不存在,该总线为virtio设备提供统一的管理、探测、注册以及匹配的抽象层,所有的virtio设备都会通过这个总线进行设备匹配与驱动绑定。

virtio bus + virtio device的抽象是为了统一设备模型、简化设备驱动的编写而设计的。这是因为每种设备都有自己的寄存器定义、初始化流程和DMA控制逻辑等,不同设备之间的差异巨大, 因此驱动程序千差万别,维护成本高,缺乏可复用性。virtio通过定义一套统一的通信机制和驱动框架简化这个设备控制逻辑。

virtio bus是一个统一的“虚拟总线抽象”,无论底层设备是接入到PCI总线还是其他总线,都可以通过实现virtio标准挂载到virtio bus。

【上面的内容太抽象,如果不理解可以直接看下面】

【系统总线层 - 平台相关总线】
+----------------+   +----------------+   +----------------+
|    PCI bus     |   |   MMIO bus     |   |    CCW bus     |
+-------+--------+   +--------+-------+   +--------+-------+
        |                     |                    |
        v                     v                    v

【Transport 层 - virtio 传输层驱动】
+---------------+   +---------------+   +----------------+
|  virtio-pci   |   |  virtio-mmio  |   |  virtio-ccw     |
+-------+-------+   +-------+-------+   +--------+--------+
        |                    |                    |
        |   创建并注册        |      virtio_device  |
        +----------+----------+---------+----------+
                   |                    |
                   v                    v

【virtio 总线层 - 抽象统一的 virtio bus】
                +----------------------------+
                |        virtio bus          |
                +-------------+--------------+
                              |
              匹配 virtio_device 和 virtio_driver
                              |
                              v

【virtio 驱动层 - 功能驱动】
+-------------------+   +-------------------+   +-------------------+
|   virtio_blk      |   |   virtio_net      |   |   virtio_console  |
+-------------------+   +-------------------+   +-------------------+

以通过PCI总线连接的virtio-net设备注册与驱动绑定流程为例

  1. PCI 总线初始化:系统启动时,PCI 子系统会枚举总线上的所有设备,并根据 Vendor/Device ID 识别出 Virtio 设备
  2. virtio-pci 驱动探测:当 PCI 总线枚举到 Virtio 设备并与 virtio-pci 驱动的 id_table 匹配时,会调用驱动的回调函数 virtio_pci_probe。在该函数中,通过 register_virtio_device() 将 Virtio 设备注册到 virtio 总线
  3. 设备与驱动的匹配与绑定register_virtio_device() 内部调用 device_add(),触发 virtio 总线的设备枚举机制。总线会查找所有已注册的 virtio 驱动(如 virtio-net),如果驱动的 id_table 能与设备匹配,则调用总线的 probe 回调(即 virtio_dev_probe),完成 Virtio 特性协商和设备初始化

virtio-pcivirtio-mmio 驱动作为桥梁,负责将底层硬件平台(如 PCI 或 MMIO 设备)包装成统一的 virtio_device,并接入 virtio 总线(virtio_bus)。这样,上层的 virtio 驱动(如 virtio-net、virtio-blk 等)就可以通过统一的接口与不同类型的底层设备进行交互,实现虚拟化设备的标准化管理和驱动绑定。

Virtio-PCI设备枚举及驱动绑定全流程

/* 1. PCI总线枚举阶段 */
pci_scan_bus() // 扫描PCI总线
  → pci_scan_slot()
    → pci_scan_device()
      → pci_device_add()
        → device_register(&dev->dev) // 注册PCI设备

/* 2. PCI设备与驱动匹配 */
virtio_pci_driver.probe = virtio_pci_probe // drivers/virtio/virtio_pci_common.c:487
  → when PCI device matches:
    vp_dev = kzalloc(sizeof(*vp_dev)) // 分配virtio_pci_device
    pci_set_drvdata(pci_dev, vp_dev)
    
    /* 3. 注册virtio设备 */
    register_virtio_device(&vp_dev->vdev)
      → device_initialize(&dev->dev) // 初始化设备
      → device_add(&dev->dev)       // 加入设备模型
        → bus_add_device(dev)      // 添加到virtio总线
        → bus_probe_device(dev)    // 触发探测
          → device_initial_probe(dev)
            → __device_attach(dev, false)
              → bus_for_each_drv(dev->bus, __device_attach_driver)
                → for_each_driver_on_bus:
                  /* 4. 驱动匹配检查 */
                  driver_match_device(drv, dev) // virtio_dev_match()
                  if matched:
                    driver_probe_device(drv, dev)
                      → really_probe(dev, drv)
                        → dev->bus->probe(dev) // virtio_dev_probe()
                          /* 5. 调用具体驱动probe */
                          drv->probe(dev) // virtnet_probe() for virtio-net

/* 6. 网络设备初始化 */
virtnet_probe(struct virtio_device *vdev) // drivers/net/virtio_net.c

posted @ 2025-08-26 10:34  Groot_Liu  阅读(19)  评论(0)    收藏  举报