1/* Glue code to lib/swiotlb-xen.c */ 2 3#include <linux/dma-mapping.h> 4#include <linux/pci.h> 5#include <xen/swiotlb-xen.h> 6 7#include <asm/xen/hypervisor.h> 8#include <xen/xen.h> 9#include <asm/iommu_table.h> 10 11 12#include <asm/xen/swiotlb-xen.h> 13#ifdef CONFIG_X86_64 14#include <asm/iommu.h> 15#include <asm/dma.h> 16#endif 17#include <linux/export.h> 18 19int xen_swiotlb __read_mostly; 20 21static struct dma_map_ops xen_swiotlb_dma_ops = { 22 .mapping_error = xen_swiotlb_dma_mapping_error, 23 .alloc = xen_swiotlb_alloc_coherent, 24 .free = xen_swiotlb_free_coherent, 25 .sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu, 26 .sync_single_for_device = xen_swiotlb_sync_single_for_device, 27 .sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu, 28 .sync_sg_for_device = xen_swiotlb_sync_sg_for_device, 29 .map_sg = xen_swiotlb_map_sg_attrs, 30 .unmap_sg = xen_swiotlb_unmap_sg_attrs, 31 .map_page = xen_swiotlb_map_page, 32 .unmap_page = xen_swiotlb_unmap_page, 33 .dma_supported = xen_swiotlb_dma_supported, 34}; 35 36/* 37 * pci_xen_swiotlb_detect - set xen_swiotlb to 1 if necessary 38 * 39 * This returns non-zero if we are forced to use xen_swiotlb (by the boot 40 * option). 41 */ 42int __init pci_xen_swiotlb_detect(void) 43{ 44 45 if (!xen_pv_domain()) 46 return 0; 47 48 /* If running as PV guest, either iommu=soft, or swiotlb=force will 49 * activate this IOMMU. If running as PV privileged, activate it 50 * irregardless. 51 */ 52 if ((xen_initial_domain() || swiotlb || swiotlb_force)) 53 xen_swiotlb = 1; 54 55 /* If we are running under Xen, we MUST disable the native SWIOTLB. 56 * Don't worry about swiotlb_force flag activating the native, as 57 * the 'swiotlb' flag is the only one turning it on. */ 58 swiotlb = 0; 59 60#ifdef CONFIG_X86_64 61 /* pci_swiotlb_detect_4gb turns on native SWIOTLB if no_iommu == 0 62 * (so no iommu=X command line over-writes). 63 * Considering that PV guests do not want the *native SWIOTLB* but 64 * only Xen SWIOTLB it is not useful to us so set no_iommu=1 here. 65 */ 66 if (max_pfn > MAX_DMA32_PFN) 67 no_iommu = 1; 68#endif 69 return xen_swiotlb; 70} 71 72void __init pci_xen_swiotlb_init(void) 73{ 74 if (xen_swiotlb) { 75 xen_swiotlb_init(1, true /* early */); 76 dma_ops = &xen_swiotlb_dma_ops; 77 78#ifdef CONFIG_PCI 79 /* Make sure ACS will be enabled */ 80 pci_request_acs(); 81#endif 82 } 83} 84 85int pci_xen_swiotlb_init_late(void) 86{ 87 int rc; 88 89 if (xen_swiotlb) 90 return 0; 91 92 rc = xen_swiotlb_init(1, false /* late */); 93 if (rc) 94 return rc; 95 96 dma_ops = &xen_swiotlb_dma_ops; 97#ifdef CONFIG_PCI 98 /* Make sure ACS will be enabled */ 99 pci_request_acs(); 100#endif 101 102 return 0; 103} 104EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late); 105 106IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, 107 NULL, 108 pci_xen_swiotlb_init, 109 NULL); 110