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

88 篇文章 19 订阅
本文详细解析了QEMU源码中virtio设备的注册过程,包括virtio_pci_probe函数的执行、register_virtio_device函数的作用,以及在Linux内核中涉及的设备初始化、设置名称、重置设备、设备添加到系统等步骤。同时,介绍了device_register函数和device_add函数在设备注册中的角色,以及如何触发用户空间的udev加载对应驱动。
摘要由CSDN通过智能技术生成

接前一篇文章:

上回书重点解析了virtio_pci_modern_probe函数。再来回顾一下其中相关的数据结构:

  • struct virtio_pci_device

struct virtio_pci_device的定义在 Linux 内核源码/drivers/ virtio /virtio_pci_common.h中,如下:

  1. /* Our device structure */
  2. struct virtio_pci_device {
  3. struct virtio_device vdev;
  4. struct pci_dev *pci_dev;
  5. union {
  6. struct virtio_pci_legacy_device ldev;
  7. struct virtio_pci_modern_device mdev;
  8. };
  9. bool is_legacy;
  10. /* Where to read and clear interrupt */
  11. u8 __iomem *isr;
  12. /* a list of queues so we can dispatch IRQs */
  13. spinlock_t lock;
  14. struct list_head virtqueues;
  15. /* array of all queues for house-keeping */
  16. struct virtio_pci_vq_info **vqs;
  17. /* MSI-X support */
  18. int msix_enabled;
  19. int intx_enabled;
  20. cpumask_var_t *msix_affinity_masks;
  21. /* Name strings for interrupts. This size should be enough,
  22. * and I'm too lazy to allocate each name separately. */
  23. char (*msix_names)[256];
  24. /* Number of available vectors */
  25. unsigned int msix_vectors;
  26. /* Vectors allocated, excluding per-vq vectors if any */
  27. unsigned int msix_used_vectors;
  28. /* Whether we have vector per vq */
  29. bool per_vq_vectors;
  30. struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev,
  31. struct virtio_pci_vq_info *info,
  32. unsigned int idx,
  33. void (*callback)(struct virtqueue *vq),
  34. const char *name,
  35. bool ctx,
  36. u16 msix_vec);
  37. void (*del_vq)(struct virtio_pci_vq_info *info);
  38. u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector);
  39. };

virtio_pci_modern_probe执行完成后,相关数据结构如下图所示:

回到virtio_pci_probe函数。在Linux内核源码/drivers/virtio/virtio_pci_common.c中,代码如下:

  1. static int virtio_pci_probe(struct pci_dev *pci_dev,
  2. const struct pci_device_id *id)
  3. {
  4. struct virtio_pci_device *vp_dev, *reg_dev = NULL;
  5. int rc;
  6. /* allocate our structure and fill it out */
  7. vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
  8. if (!vp_dev)
  9. return -ENOMEM;
  10. pci_set_drvdata(pci_dev, vp_dev);
  11. vp_dev->vdev.dev.parent = &pci_dev->dev;
  12. vp_dev->vdev.dev.release = virtio_pci_release_dev;
  13. vp_dev->pci_dev = pci_dev;
  14. INIT_LIST_HEAD(&vp_dev->virtqueues);
  15. spin_lock_init(&vp_dev->lock);
  16. /* enable the device */
  17. rc = pci_enable_device(pci_dev);
  18. if (rc)
  19. goto err_enable_device;
  20. if (force_legacy) {
  21. rc = virtio_pci_legacy_probe(vp_dev);
  22. /* Also try modern mode if we can't map BAR0 (no IO space). */
  23. if (rc == -ENODEV || rc == -ENOMEM)
  24. rc = virtio_pci_modern_probe(vp_dev);
  25. if (rc)
  26. goto err_probe;
  27. } else {
  28. rc = virtio_pci_modern_probe(vp_dev);
  29. if (rc == -ENODEV)
  30. rc = virtio_pci_legacy_probe(vp_dev);
  31. if (rc)
  32. goto err_probe;
  33. }
  34. pci_set_master(pci_dev);
  35. rc = register_virtio_device(&vp_dev->vdev);
  36. reg_dev = vp_dev;
  37. if (rc)
  38. goto err_register;
  39. return 0;
  40. err_register:
  41. if (vp_dev->is_legacy)
  42. virtio_pci_legacy_remove(vp_dev);
  43. else
  44. virtio_pci_modern_remove(vp_dev);
  45. err_probe:
  46. pci_disable_device(pci_dev);
  47. err_enable_device:
  48. if (reg_dev)
  49. put_device(&vp_dev->vdev.dev);
  50. else
  51. kfree(vp_dev);
  52. return rc;
  53. }

QEMU源码全解析 —— virtio(18) 中的内容,前文书讲到了virtio_pci_probe函数的第5步,

“(5)调用virtio_pci_legacy_probe或者virtio_pci_modern_probe函数来初始化该 PCI 设备对应的 virtio 设备。”,继续往下进行。

(6)virtio_pci_probe函数在调用virtio_pci_modern_probe函数之后,接下来会调用register_virtio_device。代码片段如下:

  1. rc = register_virtio_device(&vp_dev->vdev);
  2. reg_dev = vp_dev;
  3. if (rc)
  4. goto err_register;

register_virtio_device函数在Linux内核源码/drivers/virtio/virtio.c中,代码如下:

  1. /**
  2. * register_virtio_device - register virtio device
  3. * @dev : virtio device to be registered
  4. *
  5. * On error, the caller must call put_device on &@dev->dev (and not kfree),
  6. * as another code path may have obtained a reference to @dev.
  7. *
  8. * Returns: 0 on suceess, -error on failure
  9. */
  10. int register_virtio_device(struct virtio_device *dev)
  11. {
  12. int err;
  13. dev->dev.bus = &virtio_bus;
  14. device_initialize(&dev->dev);
  15. /* Assign a unique device index and hence name. */
  16. err = ida_alloc(&virtio_index_ida, GFP_KERNEL);
  17. if (err < 0)
  18. goto out;
  19. dev->index = err;
  20. err = dev_set_name(&dev->dev, "virtio%u", dev->index);
  21. if (err)
  22. goto out_ida_remove;
  23. err = virtio_device_of_init(dev);
  24. if (err)
  25. goto out_ida_remove;
  26. spin_lock_init(&dev->config_lock);
  27. dev->config_enabled = false;
  28. dev->config_change_pending = false;
  29. INIT_LIST_HEAD(&dev->vqs);
  30. spin_lock_init(&dev->vqs_list_lock);
  31. /* We always start by resetting the device, in case a previous
  32. * driver messed it up. This also tests that code path a little. */
  33. virtio_reset_device(dev);
  34. /* Acknowledge that we've seen the device. */
  35. virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
  36. /*
  37. * device_add() causes the bus infrastructure to look for a matching
  38. * driver.
  39. */
  40. err = device_add(&dev->dev);
  41. if (err)
  42. goto out_of_node_put;
  43. return 0;
  44. out_of_node_put:
  45. of_node_put(dev->dev.of_node);
  46. out_ida_remove:
  47. ida_free(&virtio_index_ida, dev->index);
  48. out:
  49. virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
  50. return err;
  51. }
  52. EXPORT_SYMBOL_GPL(register_virtio_device);

前文已提到,vp_dev->vdev的类型为struct virtio_device,而传给register_virtio_device函数的实参为vp_dev->vdev的地址,即&vp_dev->vdev。从函数名以及参数类型就能看出,register_virtio_device函数的作用是将一个virtio device注册到系统中。具体步骤如下:

(1)设置virtio设备的Bus为virtio_bus 。代码片段如下:

    dev->dev.bus = &virtio_bus;

virtio_bus在系统初始化的时候会注册到系统中。

virtio_bus在Linux内核源码/drivers/virtio/virtio.c中初始化,代码如下:

  1. static struct bus_type virtio_bus = {
  2. .name = "virtio",
  3. .match = virtio_dev_match,
  4. .dev_groups = virtio_dev_groups,
  5. .uevent = virtio_uevent,
  6. .probe = virtio_dev_probe,
  7. .remove = virtio_dev_remove,
  8. };
  9. int register_virtio_driver(struct virtio_driver *driver)
  10. {
  11. /* Catch this early. */
  12. BUG_ON(driver->feature_table_size && !driver->feature_table);
  13. driver->driver.bus = &virtio_bus;
  14. return driver_register(&driver->driver);
  15. }
  16. EXPORT_SYMBOL_GPL(register_virtio_driver);

在系统初始化的时候,通过register_virtio_driver函数注册到系统中。

(2)设置virtio设备的名字为类似"virtio0"、"virtio1"的字符串 。代码片段如下:

  1. /* Assign a unique device index and hence name. */
  2. err = ida_alloc(&virtio_index_ida, GFP_KERNEL);
  3. if (err < 0)
  4. goto out;
  5. dev->index = err;
  6. err = dev_set_name(&dev->dev, "virtio%u", dev->index);
  7. if (err)
  8. goto out_ida_remove;

dev_set_name函数在Linux内核源码/drivers/base/core.c中,代码如下:

  1. /**
  2. * dev_set_name - set a device name
  3. * @dev: device
  4. * @fmt: format string for the device's name
  5. */
  6. int dev_set_name(struct device *dev, const char *fmt, ...)
  7. {
  8. va_list vargs;
  9. int err;
  10. va_start(vargs, fmt);
  11. err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
  12. va_end(vargs);
  13. return err;
  14. }
  15. EXPORT_SYMBOL_GPL(dev_set_name);

(3)然后调用virtio_reset_device函数重置设备 。代码片段如下:

  1. /* We always start by resetting the device, in case a previous
  2. * driver messed it up. This also tests that code path a little. */
  3. virtio_reset_device(dev);

(4)最后,调用device_add函数 ,将设备注册到系统中 。代码片段如下:

  1. /*
  2. * device_add() causes the bus infrastructure to look for a matching
  3. * driver.
  4. */
  5. err = device_add(&dev->dev);
  6. if (err)
  7. goto out_of_node_put;

这里,老版本代码中是调用的是device_register函数。device_register函数跟设备驱动相关性较大,在此简单介绍一下其作用。

device_register函数在Linux内核源码/drivers/base/core.c中,代码如下:

  1. /**
  2. * device_register - register a device with the system.
  3. * @dev: pointer to the device structure
  4. *
  5. * This happens in two clean steps - initialize the device
  6. * and add it to the system. The two steps can be called
  7. * separately, but this is the easiest and most common.
  8. * I.e. you should only call the two helpers separately if
  9. * have a clearly defined need to use and refcount the device
  10. * before it is added to the hierarchy.
  11. *
  12. * For more information, see the kerneldoc for device_initialize()
  13. * and device_add().
  14. *
  15. * NOTE: _Never_ directly free @dev after calling this function, even
  16. * if it returned an error! Always use put_device() to give up the
  17. * reference initialized in this function instead.
  18. */
  19. int device_register(struct device *dev)
  20. {
  21. device_initialize(dev);
  22. return device_add(dev);
  23. }
  24. EXPORT_SYMBOL_GPL(device_register);

device_register函数向系统注册一个设备。其分为两个简单的步骤——初始化设备(device_initialize(dev))并将其添加到系统中(device_add(dev))。这两个步骤可以分别调用,但放在一起即使用device_register函数是最简单和最常见的。例如,如果有明确的需求在其添加到层级之前使用和重新计数设备,那么应该分别独立地调用这两个助手(函数)。

从此处的代码就可以知道,老版本的内核代码中确实是直接调用了device_register函数,而新版本内核代码在此处则是在register_virtio_device函数的前边先调用了device_initialize(&dev->dev),而后在这里调用了device_add(&dev->dev)。即采用了分开调用的方式。

device_register函数会调用device_add函数,将设备加到系统中,并且会发送一个uevent消息到用户空间,这个uevent消息中包含了virtio设备的vendor id、device id。 udev接收到此消息之后,会加载virtio设备对应的驱动。然后,device_add函数会调用bus_probe_device函数,最终调用到Bus的 probe 函数和设备的probe函数,也就是virtio_dev_probe函数和virtballoon_probe函数。

device_add函数也在Linux内核源码/drivers/base/core.c中,就在device_register函数上边,代码如下:

  1. /**
  2. * device_add - add device to device hierarchy.
  3. * @dev: device.
  4. *
  5. * This is part 2 of device_register(), though may be called
  6. * separately _iff_ device_initialize() has been called separately.
  7. *
  8. * This adds @dev to the kobject hierarchy via kobject_add(), adds it
  9. * to the global and sibling lists for the device, then
  10. * adds it to the other relevant subsystems of the driver model.
  11. *
  12. * Do not call this routine or device_register() more than once for
  13. * any device structure. The driver model core is not designed to work
  14. * with devices that get unregistered and then spring back to life.
  15. * (Among other things, it's very hard to guarantee that all references
  16. * to the previous incarnation of @dev have been dropped.) Allocate
  17. * and register a fresh new struct device instead.
  18. *
  19. * NOTE: _Never_ directly free @dev after calling this function, even
  20. * if it returned an error! Always use put_device() to give up your
  21. * reference instead.
  22. *
  23. * Rule of thumb is: if device_add() succeeds, you should call
  24. * device_del() when you want to get rid of it. If device_add() has
  25. * *not* succeeded, use *only* put_device() to drop the reference
  26. * count.
  27. */
  28. int device_add(struct device *dev)
  29. {
  30. struct subsys_private *sp;
  31. struct device *parent;
  32. struct kobject *kobj;
  33. struct class_interface *class_intf;
  34. int error = -EINVAL;
  35. struct kobject *glue_dir = NULL;
  36. dev = get_device(dev);
  37. if (!dev)
  38. goto done;
  39. if (!dev->p) {
  40. error = device_private_init(dev);
  41. if (error)
  42. goto done;
  43. }
  44. /*
  45. * for statically allocated devices, which should all be converted
  46. * some day, we need to initialize the name. We prevent reading back
  47. * the name, and force the use of dev_name()
  48. */
  49. if (dev->init_name) {
  50. error = dev_set_name(dev, "%s", dev->init_name);
  51. dev->init_name = NULL;
  52. }
  53. if (dev_name(dev))
  54. error = 0;
  55. /* subsystems can specify simple device enumeration */
  56. else if (dev->bus && dev->bus->dev_name)
  57. error = dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
  58. else
  59. error = -EINVAL;
  60. if (error)
  61. goto name_error;
  62. pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
  63. parent = get_device(dev->parent);
  64. kobj = get_device_parent(dev, parent);
  65. if (IS_ERR(kobj)) {
  66. error = PTR_ERR(kobj);
  67. goto parent_error;
  68. }
  69. if (kobj)
  70. dev->kobj.parent = kobj;
  71. /* use parent numa_node */
  72. if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
  73. set_dev_node(dev, dev_to_node(parent));
  74. /* first, register with generic layer. */
  75. /* we require the name to be set before, and pass NULL */
  76. error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
  77. if (error) {
  78. glue_dir = kobj;
  79. goto Error;
  80. }
  81. /* notify platform of device entry */
  82. device_platform_notify(dev);
  83. error = device_create_file(dev, &dev_attr_uevent);
  84. if (error)
  85. goto attrError;
  86. error = device_add_class_symlinks(dev);
  87. if (error)
  88. goto SymlinkError;
  89. error = device_add_attrs(dev);
  90. if (error)
  91. goto AttrsError;
  92. error = bus_add_device(dev);
  93. if (error)
  94. goto BusError;
  95. error = dpm_sysfs_add(dev);
  96. if (error)
  97. goto DPMError;
  98. device_pm_add(dev);
  99. if (MAJOR(dev->devt)) {
  100. error = device_create_file(dev, &dev_attr_dev);
  101. if (error)
  102. goto DevAttrError;
  103. error = device_create_sys_dev_entry(dev);
  104. if (error)
  105. goto SysEntryError;
  106. devtmpfs_create_node(dev);
  107. }
  108. /* Notify clients of device addition. This call must come
  109. * after dpm_sysfs_add() and before kobject_uevent().
  110. */
  111. bus_notify(dev, BUS_NOTIFY_ADD_DEVICE);
  112. kobject_uevent(&dev->kobj, KOBJ_ADD);
  113. /*
  114. * Check if any of the other devices (consumers) have been waiting for
  115. * this device (supplier) to be added so that they can create a device
  116. * link to it.
  117. *
  118. * This needs to happen after device_pm_add() because device_link_add()
  119. * requires the supplier be registered before it's called.
  120. *
  121. * But this also needs to happen before bus_probe_device() to make sure
  122. * waiting consumers can link to it before the driver is bound to the
  123. * device and the driver sync_state callback is called for this device.
  124. */
  125. if (dev->fwnode && !dev->fwnode->dev) {
  126. dev->fwnode->dev = dev;
  127. fw_devlink_link_device(dev);
  128. }
  129. bus_probe_device(dev);
  130. /*
  131. * If all driver registration is done and a newly added device doesn't
  132. * match with any driver, don't block its consumers from probing in
  133. * case the consumer device is able to operate without this supplier.
  134. */
  135. if (dev->fwnode && fw_devlink_drv_reg_done && !dev->can_match)
  136. fw_devlink_unblock_consumers(dev);
  137. if (parent)
  138. klist_add_tail(&dev->p->knode_parent,
  139. &parent->p->klist_children);
  140. sp = class_to_subsys(dev->class);
  141. if (sp) {
  142. mutex_lock(&sp->mutex);
  143. /* tie the class to the device */
  144. klist_add_tail(&dev->p->knode_class, &sp->klist_devices);
  145. /* notify any interfaces that the device is here */
  146. list_for_each_entry(class_intf, &sp->interfaces, node)
  147. if (class_intf->add_dev)
  148. class_intf->add_dev(dev);
  149. mutex_unlock(&sp->mutex);
  150. subsys_put(sp);
  151. }
  152. done:
  153. put_device(dev);
  154. return error;
  155. SysEntryError:
  156. if (MAJOR(dev->devt))
  157. device_remove_file(dev, &dev_attr_dev);
  158. DevAttrError:
  159. device_pm_remove(dev);
  160. dpm_sysfs_remove(dev);
  161. DPMError:
  162. dev->driver = NULL;
  163. bus_remove_device(dev);
  164. BusError:
  165. device_remove_attrs(dev);
  166. AttrsError:
  167. device_remove_class_symlinks(dev);
  168. SymlinkError:
  169. device_remove_file(dev, &dev_attr_uevent);
  170. attrError:
  171. device_platform_notify_remove(dev);
  172. kobject_uevent(&dev->kobj, KOBJ_REMOVE);
  173. glue_dir = get_glue_dir(dev);
  174. kobject_del(&dev->kobj);
  175. Error:
  176. cleanup_glue_dir(dev, glue_dir);
  177. parent_error:
  178. put_device(parent);
  179. name_error:
  180. kfree(dev->p);
  181. dev->p = NULL;
  182. goto done;
  183. }
  184. EXPORT_SYMBOL_GPL(device_add);

其中的代码片段:

  1. /* Notify clients of device addition. This call must come
  2. * after dpm_sysfs_add() and before kobject_uevent().
  3. */
  4. bus_notify(dev, BUS_NOTIFY_ADD_DEVICE);
  5. kobject_uevent(&dev->kobj, KOBJ_ADD);

    bus_probe_device(dev);

就是上边所讲到的:

device_register函数会调用device_add函数,将设备加到系统中,并且会发送一个uevent消息到用户空间,这个uevent消息中包含了virtio设备的vendor id、device id。 udev接收到此消息之后,会加载virtio设备对应的驱动。

然后,device_add函数会调用bus_probe_device函数,最终调用到Bus的probe函数和设备的probe函数,也就是virtio_dev_probe函数和virtballoon_probe函数。

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

举报

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