pci_bus_type/amba_bustype/platform_bus_type 下的driver使用smmu

来源:互联网 发布:单片机设计大赛 编辑:程序博客网 时间:2024/05/29 09:37
前面我们讲了bus_set_iommu 中以此会调用add_device->device_group->domain_alloc->attach_dev,从而会完成smmu 的初始化部分,完成这些后,driver只要调用dma的API,例如dma_alloc_coherent 就可以从buddy system的API申请memory,然后调用smmu的map函数来映射,但是这些driver只限与pci_bus_type/amba_bustype/platform_bus_type .因为只有这三个bus type调用了bus_set_iommu 接口。
#ifdef CONFIG_PCI
    if (pci_bus_type.iommu_ops != &arm_smmu_ops) {
        pci_request_acs();
        ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
        if (ret)
            return ret;
    }
#endif
#ifdef CONFIG_ARM_AMBA
    if (amba_bustype.iommu_ops != &arm_smmu_ops) {
        ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops);
        if (ret)
            return ret;
    }
#endif
    if (platform_bus_type.iommu_ops != &arm_smmu_ops) {
        ret = bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
        if (ret)
            return ret;
    }
不过好在大部分device都属于pci_bus_type/amba_bustype/platform_bus_type 。因此使用smmu很方便.

而/sys/bus 下面有很多的bus,这些bus下的driver要使用iommu的话,就需要根据iommu.h 中的api申请device/domain等
[root@centos bus]# ls
acpi         cpu       iscsi_flashnode  pci_express  spi
amba         event_source  mdio_bus        platform     usb
clockevents  gpio       mipi-dsi        pnp         usb-serial
clocksource  hid       node            scsi     virtio
container    i2c       pci            serio     workqueue
例如在drivers/vfio/vfio_iommu_type1.c 中vfio_iommu_type1_attach_group函数中,就需要先申请
domain->domain = iommu_domain_alloc(bus);
然后ret = iommu_attach_group(domain->domain, iommu_group);
再然后iommu_attach_group 等步奏使用smmu,详细代码如下:

     ret = iommu_attach_group(domain->domain, iommu_group);
1256         if (ret)
1257                 goto out_domain;
1258
1259         INIT_LIST_HEAD(&domain->group_list);
1260         list_add(&group->next, &domain->group_list);
1261
1262         if (!allow_unsafe_interrupts &&
1263             !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
1264                 pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
1265                        __func__);
1266                 ret = -EPERM;
1267                 goto out_detach;
1268         }
1269
1270         if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
1271                 domain->prot |= IOMMU_CACHE;
1272
1273         /*
1274          * Try to match an existing compatible domain.  We don't want to
1275          * preclude an IOMMU driver supporting multiple bus_types and being
1276          * able to include different bus_types in the same IOMMU domain, so
1277          * we test whether the domains use the same iommu_ops rather than
1278          * testing if they're on the same bus_type.
1279          */
1280         list_for_each_entry(d, &iommu->domain_list, next) {
1281                 if (d->domain->ops == domain->domain->ops &&
1282                     d->prot == domain->prot) {
1283                         iommu_detach_group(domain->domain, iommu_group);
1284                         if (!iommu_attach_group(d->domain, iommu_group)) {
1285                                 list_add(&group->next, &d->group_list);
1286                                 iommu_domain_free(domain->domain);
1287                                 kfree(domain);
1288                                 mutex_unlock(&iommu->lock);
1289                                 return 0;
1290                         }
1291
1292                         ret = iommu_attach_group(domain->domain, iommu_group);
1293                         if (ret)
1294                                 goto out_domain;
1295                 }
1296         }
0 0
原创粉丝点击