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;
	else
		dev->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_probe
	if (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));
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值