Linux用户空间应用程序是否可以将自己的内存用于DMA,而不会被IOMMU阻塞并且不使用VFIO?

当禁用iommu(intel_iommu = off)或处于直通模式(intel_iommu = passthrough)时,我们的应用程序运行良好。但是,当启用IOMMU(intel_iommu = on)时,它不起作用,因为DMA不允许我们在用户空间中分配的内存。

官方的解决方案是使用Linux VFIO接口(interface)来管理IOMMU,但是我们认为VFIO功能还不是很成熟,因此希望找到一个更简单的解决方案。

我们可以以某种方式指示IOMMU允许DMA用于已分配的物理内存吗?那样太好了,因为这样我们就不必指示我们的用户更改其内核引导参数。

如果有一个基于VFIO的简单可靠的解决方案,那也将很有趣。

有关我们如何分配内存的详细信息,请参见前面的相关问题:
mremap(2) with HugeTLB to change virtual address?

最佳答案

您可以编写一个简单的char设备驱动程序来执行此操作。

内部驱动程序(伪代码):

static ssize_t device_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
{
    struct page *page;
    dma_addr_t DmaBusAddress;

    copy_from_user(addrstr, buf, sizeof(addrstr));

    uaddr = simple_strtoul(addrstr, NULL, 0);

    /* Get page structure which describes your user space
       memory area
    */
    res = get_user_pages(...,uaddr,...&page);

    /* (optional)Get the kernel virtual address for your user space page
    */
    kernel_virtual_address = kmap(page);

    DmaBusAddress = dma_map_page(...,page)

    /*
    or the function below if you use address instead of page

    DmaBusAddress  = dma_map_single(...kernel_virtual_address,count...);

    */

    dev->dma_dir = DMA_TO_DEVICE;/* Write operation */
    dev->dma_size = count;
    dev->dma_addr = DmaBusAddress;

    /* Assume you have already memory map your DMA controller's I/O space
      with remap_pfn_range() */

    writeRegister(DMA_ADDRESS,dev->dma_addr);
    ........................

    writeRegister(START_DMA_TRANSFER,1); /* enable DMA controller */

}

上面的代码显示了如何使用通用DMA层。

引用ldd3







“内存映射和DMA”一章可能回答您所有的问题。

这是链接:
http://free-electrons.com/doc/books/ldd3.pdf

关于c - 具有iommu = on且不具有VFIO的Linux用户空间DMA,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29985296/

10-12 21:03