vfio中的container 和group的操作

本文介绍了vfio用户态驱动框架的基本服务及其在QEMU中的应用。vfio提供了访问硬件设备及IOmmu的接口,并详细解释了container、group和device的概念。通过具体的代码示例展示了如何在用户态操作vfio。
vfio是一套用户态驱动框架,主要提供两种基本服务:
1):向用户态提供访问硬件设备的接口。
2):向用户态提供提供IOmmu的接口.
在用户态将vfio分为container/group/device。通过打开dev/vfio 可以得到container,通过打来/dev/vfio/X 可以得到group。通过ioctl可以得到device.
关于vfio的时候在qemu中有完整的例子,可以在hw/vfio中找到.
例如在hw/vfio/common.c 中
static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
                                  Error **errp)
{
      int ret, fd;
    
    fd = qemu_open("/dev/vfio/vfio", O_RDWR);
    if (fd < 0) {
        error_setg_errno(errp, errno, "failed to open /dev/vfio/vfio");
        ret = -errno;
        goto put_space_exit;
    }
 
    if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) ||
        ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) {
        bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU);
        struct vfio_iommu_type1_info info;

        ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
        if (ret) {
            error_setg_errno(errp, errno, "failed to set group container");
            ret = -errno;
            goto free_container_exit;
        }

        container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU;
        ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type);
        if (ret) {
            error_setg_errno(errp, errno, "failed to set iommu for container");
            ret = -errno;
            goto free_container_exit;
        }
   
}
从这个函数中可以看到,通过
fd = qemu_open("/dev/vfio/vfio", O_RDWR);得到container。文件标识符fd在kernel中关联的是
static const struct file_operations vfio_fops = {
    .owner        = THIS_MODULE,
    .open        = vfio_fops_open,
    .release    = vfio_fops_release,
    .read        = vfio_fops_read,
    .write        = vfio_fops_write,
    .unlocked_ioctl    = vfio_fops_unl_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl    = vfio_fops_compat_ioctl,
#endif
    .mmap        = vfio_fops_mmap,
};

这个从kernel中vfio.c 中的入口函数可以看到
static int __init vfio_init(void)
{

    ret = misc_register(&vfio_dev);
    if (ret) {
        pr_err("vfio: misc device register failed\n");
        return ret;
    }

    /* /dev/vfio/$GROUP */
    vfio.class = class_create(THIS_MODULE, "vfio");
    if (IS_ERR(vfio.class)) {
        ret = PTR_ERR(vfio.class);
        goto err_class;
    }

    vfio.class->devnode = vfio_devnode;

    ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK, "vfio");
    if (ret)
        goto err_alloc_chrdev;

    cdev_init(&vfio.group_cdev, &vfio_group_fops);
    ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK);
    if (ret)
        goto err_cdev_add;

    pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
    request_module_nowait("vfio_iommu_type1");
    request_module_nowait("vfio_iommu_spapr_tce");
    return 0;
}
从vfio_init 中可以看出是通过misc_register 注册了一个misc设备,且关联的file_operations是vfio_dev这样才用户空间通过qemu_open("/dev/vfio/vfio", O_RDWR) 打开这个字符设备时,就会关联到vfio_dev.
在hw/vfio/common.c 中的vfio_get_group 可以看到是通过vfio_get_group
VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp)
{
    VFIOGroup *group;
    char path[32];

    snprintf(path, sizeof(path), "/dev/vfio/%d", groupid);
    group->fd = qemu_open(path, O_RDWR);
    if (group->fd < 0) {
        error_setg_errno(errp, errno, "failed to open %s", path);
        goto free_group_exit;
    }
  }
可以看到通过打开/dev/vfio/%d 可以得到group,这在kernel中通过对应vfio_init 中的    cdev_init(&vfio.group_cdev, &vfio_group_fops);将其关联。也就是说用户态对group->fd的操作在kernel中对应的是vfio_group_fops。

同样从vfio_connect_container 可以看到iommu 设备分成两类container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU;
对应kernel中的vfio_init 中的vfio_iommu_type1.ko和vfio_iommu_spapr_tce.ko 在kernel space通过request_module_nowait 来让用户空间的modprobe来insmod这两个ko.
    request_module_nowait("vfio_iommu_type1");
    request_module_nowait("vfio_iommu_spapr_tce");



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值