Writing Device Drivers

DMA Isolation

A defective PCI device might initiate an improper DMA transfer over the bus. This data transfer could corrupt good data previously delivered. A device that fails might generate a corrupt address that can contaminate memory not even belonging to this driver.

In systems with an IOMMU, a device can write only to pages mapped as writable for DMA. It is therefore important that DMA writes data only into pages that are owned by that driver instance and not shared with any other kernel structure. While the page in question is mapped as writable for DMA, the driver should be suspicious of data in that page, and the page must be unmapped from the IOMMU before it is passed beyond the driver, or before any validation of the data.

To guarantee that a whole aligned page is allocated, ddi_umem_alloc(9F) can be used, or multiple pages allocated and the memory below the first page boundary ignored. The size of an IOMMU page can be found using ddi_ptob(9F).

Alternatively, the driver can choose to copy the data into a safe part of memory before processing it. If this is done, the data must first be synchronized using ddi_dma_sync(9F).

Calls to ddi_dma_sync(9F) should specify SYNC_FOR_DEV before using DMA to transfer data to a device, and SYNC_FOR_CPU after using DMA to transfer data from the device to memory.

Some PCI devices are able to use dual address cycles (64-bit addresses) to avoid the IOMMU. This gives the device the potential to corrupt any region of main memory. Hardened device drivers must not attempt to use such a mode and should disable it.