I know that PCI has feature called ATS to translate virtual address to physical address, but I am not sure whether it is enabled by default in current x86 platform.
If it is, how should I generate virtual address and corresponding page table in Linux system?
This is what I guess now. First, DMA API like pci_map_* will call into intel iommu driver to setup page table and get io virtual address. Second, PCI device will use that virtual io address to start transaction, and vt-d will translate that virtual io address to physical address. Am I right about that?