编写设备驱动程序

DMA 隔离

有缺陷的设备可能通过总线启动错误的 DMA 传输。此类数据传输可能会损坏以前传送的正常数据。发生故障的设备可能会生成损坏的地址,该地址可能会污染甚至不属于自己的驱动器的内存。

在具有 IOMMU 的系统中,设备只能写入映射为对于 DMA 可写入的页。因此,此类页只应归一个驱动程序实例所有。不应将这些页与其他任何内核结构共享。尽管该页被映射为对于 DMA 可写入的页,但驱动程序应怀疑该页中的数据。在将页传递到驱动程序之外以及对数据进行验证之前,必须从 IOMMU 取消映射页。

可以使用 ddi_umem_alloc(9F) 来保证已分配整个对齐的页,或分配多页并忽略第一个页边界之下的内存。可以使用 ddi_ptob(9F) 确定 IOMMU 页的大小。

或者,驱动程序可以选择在处理数据之前将其复制到内存中较安全的部分。如果已执行此操作,则必须先使用 ddi_dma_sync(9F) 同步数据。

ddi_dma_sync() 的调用应在使用 DMA 向设备传送数据之前指定 SYNC_FOR_DEV,并在使用 DMA 从设备向内存传送数据之后指定 SYNC_FOR_CPU

在某些基于 PCI 且具有 IOMMU 的系统中,设备可以使用 PCI 双地址循环(64 位地址)绕过 IOMMU。此功能使设备可能损坏主内存的任何区域。设备驱动程序不得尝试使用此类模式,并应禁用此类模式。