QEMU源码全解析 —— virtio(7)

88 篇文章 19 订阅
本文详细解析了QEMU中VirtioPCIClass的realize函数流程,从virtio_pci_class_init开始,探讨了device_class_set_parent_realize如何改变realize函数的调用顺序,确保virtio_pci_dc_realize先执行,然后是pci_qdev_realize。此外,还介绍了virtio balloon PCI代理设备的初始化过程及其realize函数的设置。
摘要由CSDN通过智能技术生成

接前一篇文章:

本回分析在VirtioPCI Class类 还没有初始化时的realize函数。如下表所示:

DeviceClass pci_qdev_realize
PCIDeviceClass pci_default_realize

VirtioPCIClass类的相关定义是在所有 virtio PCI代理设备的父设备TYPE_VIRTIO_PCI中进行的,其中的类初始化函数是virtio_pci_class_init,其在hw/virtio/virtio-pci.c中,代码如下:

  1. static void virtio_pci_class_init(ObjectClass *klass, void *data)
  2. {
  3. DeviceClass *dc = DEVICE_CLASS(klass);
  4. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  5. VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
  6. ResettableClass *rc = RESETTABLE_CLASS(klass);
  7. device_class_set_props(dc, virtio_pci_properties);
  8. k->realize = virtio_pci_realize;
  9. k->exit = virtio_pci_exit;
  10. k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
  11. k->revision = VIRTIO_PCI_ABI_VERSION;
  12. k->class_id = PCI_CLASS_OTHERS;
  13. device_class_set_parent_realize(dc, virtio_pci_dc_realize,
  14. &vpciklass->parent_dc_realize);
  15. rc->phases.hold = virtio_pci_bus_reset_hold;
  16. }
  17. static const TypeInfo virtio_pci_info = {
  18. .name = TYPE_VIRTIO_PCI,
  19. .parent = TYPE_PCI_DEVICE,
  20. .instance_size = sizeof(VirtIOPCIProxy),
  21. .class_init = virtio_pci_class_init,
  22. .class_size = sizeof(VirtioPCIClass),
  23. .abstract = true,
  24. };

如上一回所讲,virtio_pci_class_init函数首先把PCIDeviceClass->realize函数(指针)替换成了自己的virtio_pci_realize函数。

    k->realize = virtio_pci_realize;

接下来较为关键的一句是:

  1. device_class_set_parent_realize(dc, virtio_pci_dc_realize,
  2. &vpciklass->parent_dc_realize);

device_class_set_parent_realize函数在hw/core/qdev.c中,代码如下:

  1. void device_class_set_parent_realize(DeviceClass *dc,
  2. DeviceRealize dev_realize,
  3. DeviceRealize *parent_realize)
  4. {
  5. *parent_realize = dc->realize;
  6. dc->realize = dev_realize;
  7. }

device_class_set_parent函数上下文先将vpciklass->parent_dc_realize设置成了dc->realize,这个值是pci_qdev_realize。在hw/pci/pci.c的pci_device_class_init函数中,如下所示(见上一回):

  1. static void pci_device_class_init(ObjectClass *klass, void *data)
  2. {
  3. DeviceClass *k = DEVICE_CLASS(klass);
  4. k->realize = pci_qdev_realize;
  5. k->unrealize = pci_qdev_unrealize;
  6. k->bus_type = TYPE_PCI_BUS;
  7. device_class_set_props(k, pci_props);
  8. }

然后将dc->realize设置成了virtio_pci_dc_realize(通过中间变量dev_realize)。

通常来说, 父类的realize函数会调用子类的realize函数 ,如DeviceClass->realize(pci_qdev_realize)会调用PCIDeviceClass->realize回调,而PCIDeviceClass->realize回调又可以调用子类型的realize函数。但是这两条语句改变了这个顺序。在这里,dc->realize被设置成了virtio_pci_dc_realize,由于DeviceClass->realize即dc->realize所指向的函数会先被执行,因此virtio_pci_dc_realize函数会最先执行,然后将原来的dc->realize即pci_qdev_realize函数保存到VirtioPCIClass->parent_dc_realize函数中。见上边的片段:

  1. device_class_set_parent_realize(dc, virtio_pci_dc_realize,
  2. &vpciklass->parent_dc_realize);
  1. void device_class_set_parent_realize(DeviceClass *dc,
  2. DeviceRealize dev_realize,
  3. DeviceRealize *parent_realize)
  4. {
  5. *parent_realize = dc->realize;
  6. dc->realize = dev_realize;
  7. }

通常在设备具现化过程中,子类型的realize函数需要先做某些事情的时候会使用这种方法。

回到virtio balloon PCI代理设备类型的 初始化 函数virtio_balloon_pci_class_init(),在hw/virtio/virtio-balloon-pci.c中,代码如下:

  1. static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
  2. {
  3. DeviceClass *dc = DEVICE_CLASS(klass);
  4. VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
  5. PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
  6. k->realize = virtio_balloon_pci_realize;
  7. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  8. pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
  9. pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
  10. pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
  11. pcidev_k->class_id = PCI_CLASS_OTHERS;
  12. }

可以看到,其中设置了VirtioPCIClass->realize函数指针指向virtio_balloon_pci_realize()。

综上所述,virtio balloon相关类所涉及的realize函数如下表所示:

realize函数 parent_dc_realize函数
DeviceClass virtio_pci_dc_realize
PCIDeviceClass virtio_pci_realize
VirtioPCIClass virtio_balloon_pci_realize pci_qdev_realize

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

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他