本文主要是介绍virtio设备状态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
spec描述
驱动初始化探测的大致过程:
virtio_pci_probe->pci_enable_device->virtio_pci_modern_probe->register_virtio_device->virtio_dev_probe
virtio_pci_modern_probe->设置回调vp_config_vector->设置回调setup_vq
drivers/virtio/virtio_pci_common.c
virtblk_probe->init_vq(virtio_blk.c)->virtio_find_vqs->find_vqs->vp_modern_find_vqs->vp_find_vqs->vp_find_vqs_msix->vp_request_msix_vectors->vp_setup_vq->setup_vq->request_irq->vring_interrupt
virtnet_probe->init_vqs->virtnet_find_vqs->find_vqs->同上
例如virtio_net驱动中用于初始化queue,创建网络设备并初始化一些必要的数据结构
当后端模拟出virtio_net设备后,驱动扫描到virtio设备,然后调用virtio_pci_driver中virtio_pci_probe函数完成pci设备的启动。
注册一条virtio_bus,同时在virtio总线进行注册设备。当virtio总线进行注册设备register_virtio_device,设置virtio总线后将调用virtio总线的probe函数:virtio_dev_probe。
该函数遍历驱动,找到支持驱动关联到该设备并且调用
virtio_driver probe,virtnet_probe函数
static int virtio_dev_probe(struct device *_d)
{int err, i;struct virtio_device *dev = dev_to_virtio(_d);struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);u64 device_features;u64 driver_features;u64 driver_features_legacy;/* We have a driver! */virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);//置位状态,知道是什么驱动/* Figure out what features the device supports. * 回调函数vp_get_features->vp_modern_get_features* vp_modern_get_features 中会和后端设备协商feature*/device_features = dev->config->get_features(dev);/* Figure out what features the driver supports. */driver_features = 0;for (i = 0; i < drv->feature_table_size; i++) {unsigned int f = drv->feature_table[i];BUG_ON(f >= 64);driver_features |= (1ULL << f);}/* Some drivers have a separate feature table for virtio v1.0 */if (drv->feature_table_legacy) {driver_features_legacy = 0;for (i = 0; i < drv->feature_table_size_legacy; i++) {unsigned int f = drv->feature_table_legacy[i];BUG_ON(f >= 64);driver_features_legacy |= (1ULL << f);}} else {driver_features_legacy = driver_features;}if (device_features & (1ULL << VIRTIO_F_VERSION_1))dev->features = driver_features & device_features;elsedev->features = driver_features_legacy & device_features;/* Transport features always preserved to pass to finalize_features. */for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)if (device_features & (1ULL << i))__virtio_set_bit(dev, i);if (drv->validate) {err = drv->validate(dev);if (err)goto err;}// 协商结果,成功会置位VIRTIO_CONFIG_S_FEATURES_OK,表示前后端协商成功err = virtio_finalize_features(dev);if (err)goto err;err = drv->probe(dev); //virtio_drive回调函数 virtnet_probe 或者 virtblk_probeif (err)goto err;/* If probe didn't do it, mark device DRIVER_OK ourselves. */if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK))virtio_device_ready(dev);if (drv->scan)drv->scan(dev);virtio_config_enable(dev);return 0;
err:virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);return err;}
下面分别描述探测过程中几个状态的前端发生过程。
VIRTIO_CONFIG_S_ACKNOWLEDGE
前端:
virtio_pci_probe ->register_virtio_device
->virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);//通知后端已发现此virtio设备
后端
todo
VIRTIO_CONFIG_S_DRIVER
virtio_dev_probe->virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER)
VIRTIO_CONFIG_S_FEATURES_OK
virtio_dev_probe->>virtio_finalize_features
virtio_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK);
VIRTIO_CONFIG_S_DRIVER_OK
virtio_dev_probe->virtio_device_ready-
dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
后端:(以qemu为例)
hw/virtio/virtio-pci.c: virtio_pci_bus_class_init->virtio_pci_device_plugged->
virtio_pci_modern_regions_init->virtio_pci_common_write->
case VIRTIO_PCI_COMMON_STATUS:if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {virtio_pci_stop_ioeventfd(proxy);}virtio_set_status(vdev, val & 0xFF);if (val & VIRTIO_CONFIG_S_DRIVER_OK) {virtio_pci_start_ioeventfd(proxy);//启动ioeventfd}if (vdev->status == 0) {virtio_pci_reset(DEVICE(proxy));}
这篇关于virtio设备状态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!