Currently the LinuxKPI uses physical addresses to create mappings for the DMA related interfaces. These physical addresses are not true DMA addresses and hence can't be used to program a device's DMA engine in conjunction with an IOMMU. To properly supply DMA addresses for use with an IOMMU, the LinuxKPI should use the bus_dma(9) interfaces to setup and teardown the mappings.
The linux API provides an implementation of allocate/free plus map/unmap large memory regions, map/unmap a single memory region, map/unmap a scatterlist, and a dma_pool interface for a cache of smaller memory regions.
For the most part the linux allocation/mapping setup translates nicely into bus_dmamap_create() and _bus_dmamap_load_phys(). The invalidation/teardown presents more of a challenge as both bus_dmamap_unload() and bus_dmamap_destroy() need to be called for a given DMA address. To find the bus_dmamap_t associated with a given DMA address a path-compressed radix trie is used with the DMA address functioning as a key. The tree is populated with entries (struct linux_dma_obj) containing the dmamap, the DMA address and in the case of a dma_pool entry the virtual address too. A UMA cache is used for the tree's entries as well as the tree’s internal nodes.
The dma_pool supplies both allocated and mapped memory regions with characteristics specified when the pool is created. For efficiency a cache-only UMA zone is used. The items in the cache contain a DMA-able memory region and a DMA pctrie entry. The zones import and release routines allocate and free the DMA-memory with bus_dmamem_alloc() and bus_dmamem_free() as well the associated DMA tree entries (struct linux_dma_obj).