2015-05-01 23 views
3

Linux用户空间应用程序可以使用自己的内存用于DMA,而不被IOMMU阻止并且不使用VFIO吗?Linux用户空间DMA与iommu =无论是否为VFIO

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

官方的解决方案是使用Linux VFIO接口来管理IOMMU,但我们认为VFIO功能还不是很成熟,并且更愿意找到更简单的解决方案。

我们可以以某种方式指示IOMMU允许我们分配的物理内存使用DMA吗?这将是美好的,因为那样我们就不必指示我们的用户改变他们的内核启动参数。

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

见的细节有关的以前的问题,我们如何分配内存: mremap(2) with HugeTLB to change virtual address?

回答

1

你可以写一个简单的字符设备驱动程序来做到这一点。

内部驱动器(伪码):

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

报价“的IOMMU可以安排任何物理存储由装置访问的 地址范围内出现,它可能会导致物理 散射缓冲器看邻接装置。制作使用 IOMMU的需要使用通用DMA层; virt_to_bus达不到 任务”

“通用的DMA层尽最大努力确保所有架构上的东西 都能正常工作,但正如我们将看到的,正确的 行为需要遵守一小部分规则。”

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

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

+0

谢谢你的详细解答。这实际上并不适合我们,因为我们希望严格保持应用程序的用户空间而不依赖于新的内核模块。 –

相关问题