我有一个PCI设备驱动程序,目前使用dma_map_page
将用户空间地址映射到dma_map_page
地址。 这工作正常,但我试图移植到iommu api,以获得使用组和域给一些好处。
当前代码:这工作正常
ret = get_user_pages_fast(user_addr, one_page, flags, page); dma_addr = dma_map_page(dev, off, size, *page, DMA_BIDIRECTIONAL);
IOMMU代码:这不起作用
ret = get_user_pages_fast(...); pfn = page_to_pfn(*page); group = iommu_group_get(dev); domain = iommu_domain_alloc(dev->bus); iommu_attach_device(domain, dev); iommu_attach_group(domain, group); iommu_map(domain, iova, pfn << PAGE_SHIFT, size, IOMMU_READ|IOMMU_WRITE);
所有function都成功返回,但是当我将Iova传递给设备时,设备无法使用它。 有没有人曾与iommu之前,知道我的问题在哪里,或者我可以看看? 我在任何地方都找不到Linux上的iommu实现。
编辑 :dmesg中有一些条目我第一次错过了:
DEBUG: phys addr 0x7738de000 DEBUG: iova 0xdeadb000 DMAR: DRHD: handling fault status reg 2 DMAR: DMAR:[DMA Read] Request device [50:00.0] fault addr 1fdaee4000 DMAR:[fault reason 06] PTE Read access is not set
这样的操作是有特权的,因为它正在访问页表或者可能是任务结构中维护的数据结构。
请检查虚拟机管理程序如何执行此操作或虚拟机处理此类调用。 可能有一些驱动程序接口通过虚拟机管理程序从来宾操作系统设置IOMMU分页单元。
管理程序也在特权模式下执行。