接前一篇文章:

本文内容参考:

《趣谈Linux操作系统》 —— 刘超,极客时间

QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社

特此致谢!

上两回对于virtio进行了简介,并说明了其基本原理以及框架。本回开始正式结合代码讲解virtio的实现机制和细节。

virtio设备的初始化

virtio设备首先需要创建一个PCI设备,叫作virtio PCI代理设备,这个代理设备挂到PCI总线上

接着,virtio代理设备再创建一条virtio总线,这样virtio设备就可以挂到这条virtio总线上了

首先来看virtio PCI代理设备类型的定义,在QEMU源码(qemu-8.1.3)的hw/virtio/virtio-pci.c中,代码如下:

static const TypeInfo virtio_pci_bus_info = {
    .name          = TYPE_VIRTIO_PCI_BUS,
    .parent        = TYPE_VIRTIO_BUS,
    .instance_size = sizeof(VirtioPCIBusState),
    .class_size    = sizeof(VirtioPCIBusClass),
    .class_init    = virtio_pci_bus_class_init,
};

static void virtio_pci_register_types(void)
{
    /* Base types: */
    type_register_static(&virtio_pci_bus_info);
    type_register_static(&virtio_pci_info);
}

type_init(virtio_pci_register_types)

从virtio PCI代理设备的定义就可以看出,virtio PCI代理设备的父设备是一个PCI设备(.parent        = TYPE_PCI_DEVICE,),类型为VirtIOPCIClass(.class_size    = sizeof(VirtioPCIClass),),实例为virtIOPCIProxy(.instance_size = sizeof(VirtIOPCIProxy),),注意这是一个抽象设备(.abstract      = true,),因此并不能创建其实例,只能由其子类去创建

QEMU中定义了所有virtio设备的PCI代理设备,如virtio balloon PCI设备、virtio scsi PCI设备、virtio crypto PCI设备。其定义分别如下所示:

  • virtio balloon PCI设备

virtio balloon PCI设备的定义在hw/virtio/virtio-balloon-pci.c中,代码如下:

static const VirtioPCIDeviceTypeInfo virtio_balloon_pci_info = {
    .base_name             = TYPE_VIRTIO_BALLOON_PCI,
    .generic_name          = "virtio-balloon-pci",
    .transitional_name     = "virtio-balloon-pci-transitional",
    .non_transitional_name = "virtio-balloon-pci-non-transitional",
    .instance_size = sizeof(VirtIOBalloonPCI),
    .instance_init = virtio_balloon_pci_instance_init,
    .class_init    = virtio_balloon_pci_class_init,
};

static void virtio_balloon_pci_register(void)
{
    virtio_pci_types_register(&virtio_balloon_pci_info);
}

type_init(virtio_balloon_pci_register)
  • virtio scsi PCI设备

virtio scsi PCI设备的定义在hw/virtio/virtio-scsi-pci.c中,代码如下:

static const VirtioPCIDeviceTypeInfo virtio_scsi_pci_info = {
    .base_name              = TYPE_VIRTIO_SCSI_PCI,
    .generic_name           = "virtio-scsi-pci",
    .transitional_name      = "virtio-scsi-pci-transitional",
    .non_transitional_name  = "virtio-scsi-pci-non-transitional",
    .instance_size = sizeof(VirtIOSCSIPCI),
    .instance_init = virtio_scsi_pci_instance_init,
    .class_init    = virtio_scsi_pci_class_init,
};

static void virtio_scsi_pci_register(void)
{
    virtio_pci_types_register(&virtio_scsi_pci_info);
}

type_init(virtio_scsi_pci_register)
  • virtio crypto PCI设备

virtio crypto PCI设备的定义在hw/virtio/virtio-crypto-pci.c中,代码如下:

static const VirtioPCIDeviceTypeInfo virtio_crypto_pci_info = {
    .generic_name  = TYPE_VIRTIO_CRYPTO_PCI,
    .instance_size = sizeof(VirtIOCryptoPCI),
    .instance_init = virtio_crypto_initfn,
    .class_init    = virtio_crypto_pci_class_init,
};

static void virtio_crypto_pci_register_types(void)
{
    virtio_pci_types_register(&virtio_crypto_pci_info);
}
type_init(virtio_crypto_pci_register_types)

virtio设备在系统的设备树中的位置如下图所示:

QEMU源码全解析 —— virtio(3)-LMLPHP

欲知后事如何,请看下回分解。

12-12 17:23