如何将dma_addr_t转换为linux内核中的虚拟地址?

时间:2013-10-30 12:44:11

标签: memory-management linux-kernel linux-device-driver dma

我正在写一个PCI设备驱动程序,我需要为DMA分配一些内存, 我正在使用这个功能:

void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);

我将dma_handle传递给设备。

这个函数的返回值是我可以在内核中使用的虚拟地址,事情是我不想为每个内存分配保存这个地址。

有没有办法将物理地址dma_handle转换为我可以在内核中使用的地址? 像这些函数/宏之一:

virt_to_page(kaddr)
page_to_pfn(page)

是否有phy_to_kvirt宏/函数或任何其他方式将物理地址转换为内核虚拟地址?

感谢

1 个答案:

答案 0 :(得分:5)

不,没有,而且dma_handle不仅仅是任何物理地址。从特定设备的角度来看,它是物理地址。不同总线上的不同设备可能具有完全不同的主存储器视图。除此之外,返回的虚拟地址可以是动态映射页面,而不是与主存储器的物理映射具有固定关系。

可能在内核结构中有足够的信息将信息拼凑在某些总线和架构但不能保证并且不要指望它快 - 内核的自己的dma_free_coherent()要求你提供所有东西,虚拟地址,设备和dma_handle来完成它的工作,因为这是它可以跨架构和总线普遍工作的唯一方式。

重申:dma_handle本身毫无意义。多个设备可能具有完全相同的dma_handle,仍然指向不同的内存位置。