vfio-pci和vfio_group_fops的关联


static int __init vfio_pci_init(void)
{
    int ret;

    /* Allocate shared config space permision data used by all devices */
    ret = vfio_pci_init_perm_bits();
    if (ret)
        return ret;

    /* Register and scan for devices */
    ret = pci_register_driver(&vfio_pci_driver);
    if (ret)
        goto out_driver;

    vfio_pci_fill_ids();

    return 0;

out_driver:
    vfio_pci_uninit_perm_bits();
    return ret;
}
中有注册一个vfio_pci_driver的driver,当通过echo 0002:80:00.0 | sudo tee /sys/bus/pci/devices/0002:80:00.0/driver/unbind的时候就会调用vfio_pci_probe
static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
    struct vfio_pci_device *vdev;
    struct iommu_group *group;
    int ret;

    if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
        return -EINVAL;
//首先根据device也就是pdev->dev 找到group
    group = vfio_iommu_group_get(&pdev->dev);
    if (!group)
        return -EINVAL;
//申请一个struct vfio_pci_device *vdev;
    vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
    if (!vdev) {
        vfio_iommu_group_put(group, &pdev->dev);
        return -ENOMEM;
    }
//对vdev 赋值
    vdev->pdev = pdev;
    vdev->irq_type = VFIO_PCI_NUM_IRQS;
    mutex_init(&vdev->igate);
    spin_lock_init(&vdev->irqlock);
//将vdev 添加到group中,主要这个vdev 对应的vfio_device_ops是vfio_pci_ops
    ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
    if (ret) {
        vfio_iommu_group_put(group, &pdev->dev);
        kfree(vdev);
        return ret;
    }

    return ret;
}

int vfio_add_group_dev(struct device *dev,
               const struct vfio_device_ops *ops, void *device_data)
{
    struct iommu_group *iommu_group;
    struct vfio_group *group;
    struct vfio_device *device;
//根据dev得到设备所在的iommu_group ,这里是pci设备,则iommu_group 肯定是pcie group
    iommu_group = iommu_group_get(dev);
    if (!iommu_group)
        return -EINVAL;
//再从iommu_group 中得到vfio_group ,第一次肯定为null,因此调用vfio_create_group 新建一个vfio_group,并将group->iommu_group = iommu_group;这样下次进来的时候从iommu_group 中查找vfio_group就不为null了.

    group = vfio_group_get_from_iommu(iommu_group);
    if (!group) {
        group = vfio_create_group(iommu_group);
        if (IS_ERR(group)) {
            iommu_group_put(iommu_group);
            return PTR_ERR(group);
        }
    } else {
        /*
         * A found vfio_group already holds a reference to the
         * iommu_group.  A created vfio_group keeps the reference.
         */
        iommu_group_put(iommu_group);
    }
//从vfio_group 中找到vfio_device,第一次为null
    device = vfio_group_get_device(group, dev);
    if (device) {
        WARN(1, "Device %s already exists on group %d\n",
             dev_name(dev), iommu_group_id(iommu_group));
        vfio_device_put(device);
        vfio_group_put(group);
        return -EBUSY;
    }
//新建vfio_device 并添加到vfio_group 中
    device = vfio_group_create_device(group, dev, ops, device_data);
    if (IS_ERR(device)) {
        vfio_group_put(group);
        return PTR_ERR(device);
    }

    /*
     * Drop all but the vfio_device reference.  The vfio_device holds
     * a reference to the vfio_group, which holds a reference to the
     * iommu_group.
     */
    vfio_group_put(group);

    return 0;
}
总结一下vfio-pci 是一个pci driver,当通过echo 0002:80:00.0 | sudo tee /sys/bus/pci/devices/0002:80:00.0/driver/unbind的时候会触发vfio_pci_probe 函数,从而新建vfio_group、vfio_device。
这样在vfio_group_fops的open函数vfio_group_fops_open中就会调用
    group = vfio_group_get_from_minor(iminor(inode));
    if (!group)
        return -ENODEV;
来找到这个group。从而完成vfio-pci和vfio_group_fops的关联.

你可能感兴趣的:(Linux,源码分析)