Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen/arm,arm64: enable SWIOTLB_XEN

Xen on arm and arm64 needs SWIOTLB_XEN: when running on Xen we need to
program the hardware with mfns rather than pfns for dma addresses.
Remove SWIOTLB_XEN dependency on X86 and PCI and make XEN select
SWIOTLB_XEN on arm and arm64.

At the moment always rely on swiotlb-xen, but when Xen starts supporting
hardware IOMMUs we'll be able to avoid it conditionally on the presence
of an IOMMU on the platform.

Implement xen_create_contiguous_region on arm and arm64: for the moment
we assume that dom0 has been mapped 1:1 (physical addresses == machine
addresses) therefore we don't need to call XENMEM_exchange. Simply
return the physical address as dma address.

Initialize the xen-swiotlb from xen_early_init (before the native
dma_ops are initialized), set xen_dma_ops to &xen_swiotlb_dma_ops.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>


Changes in v8:
- assume dom0 is mapped 1:1, no need to call XENMEM_exchange.

Changes in v7:
- call __set_phys_to_machine_multi from xen_create_contiguous_region and
xen_destroy_contiguous_region to update the P2M;
- don't call XENMEM_unpin, it has been removed;
- call XENMEM_exchange instead of XENMEM_exchange_and_pin;
- set nr_exchanged to 0 before calling the hypercall.

Changes in v6:
- introduce and export xen_dma_ops;
- call xen_mm_init from as arch_initcall.

Changes in v4:
- remove redefinition of DMA_ERROR_CODE;
- update the code to use XENMEM_exchange_and_pin and XENMEM_unpin;
- add a note about hardware IOMMU in the commit message.

Changes in v3:
- code style changes;
- warn on XENMEM_put_dma_buf failures.

+86 -3
+1
arch/arm/Kconfig
··· 1888 1888 depends on CPU_V7 && !CPU_V6 1889 1889 depends on !GENERIC_ATOMIC64 1890 1890 select ARM_PSCI 1891 + select SWIOTLB_XEN 1891 1892 help 1892 1893 Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. 1893 1894
+2
arch/arm/include/asm/xen/hypervisor.h
··· 16 16 return PARAVIRT_LAZY_NONE; 17 17 } 18 18 19 + extern struct dma_map_ops *xen_dma_ops; 20 + 19 21 #endif /* _ASM_ARM_XEN_HYPERVISOR_H */
+1
arch/arm/include/asm/xen/page.h
··· 6 6 7 7 #include <linux/pfn.h> 8 8 #include <linux/types.h> 9 + #include <linux/dma-mapping.h> 9 10 10 11 #include <xen/xen.h> 11 12 #include <xen/interface/grant_table.h>
+1 -1
arch/arm/xen/Makefile
··· 1 - obj-y := enlighten.o hypercall.o grant-table.o p2m.o 1 + obj-y := enlighten.o hypercall.o grant-table.o p2m.o mm.o
+64
arch/arm/xen/mm.c
··· 1 + #include <linux/bootmem.h> 2 + #include <linux/gfp.h> 3 + #include <linux/export.h> 4 + #include <linux/slab.h> 5 + #include <linux/types.h> 6 + #include <linux/dma-mapping.h> 7 + #include <linux/vmalloc.h> 8 + #include <linux/swiotlb.h> 9 + 10 + #include <xen/xen.h> 11 + #include <xen/interface/memory.h> 12 + #include <xen/swiotlb-xen.h> 13 + 14 + #include <asm/cacheflush.h> 15 + #include <asm/xen/page.h> 16 + #include <asm/xen/hypercall.h> 17 + #include <asm/xen/interface.h> 18 + 19 + int xen_create_contiguous_region(unsigned long vstart, unsigned int order, 20 + unsigned int address_bits, 21 + dma_addr_t *dma_handle) 22 + { 23 + if (!xen_initial_domain()) 24 + return -EINVAL; 25 + 26 + /* we assume that dom0 is mapped 1:1 for now */ 27 + *dma_handle = virt_to_phys(pstart); 28 + return 0; 29 + } 30 + EXPORT_SYMBOL_GPL(xen_create_contiguous_region); 31 + 32 + void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) 33 + { 34 + return; 35 + } 36 + EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region); 37 + 38 + struct dma_map_ops *xen_dma_ops; 39 + EXPORT_SYMBOL_GPL(xen_dma_ops); 40 + 41 + static struct dma_map_ops xen_swiotlb_dma_ops = { 42 + .mapping_error = xen_swiotlb_dma_mapping_error, 43 + .alloc = xen_swiotlb_alloc_coherent, 44 + .free = xen_swiotlb_free_coherent, 45 + .sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu, 46 + .sync_single_for_device = xen_swiotlb_sync_single_for_device, 47 + .sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu, 48 + .sync_sg_for_device = xen_swiotlb_sync_sg_for_device, 49 + .map_sg = xen_swiotlb_map_sg_attrs, 50 + .unmap_sg = xen_swiotlb_unmap_sg_attrs, 51 + .map_page = xen_swiotlb_map_page, 52 + .unmap_page = xen_swiotlb_unmap_page, 53 + .dma_supported = xen_swiotlb_dma_supported, 54 + }; 55 + 56 + int __init xen_mm_init(void) 57 + { 58 + if (!xen_initial_domain()) 59 + return 0; 60 + xen_swiotlb_init(1, false); 61 + xen_dma_ops = &xen_swiotlb_dma_ops; 62 + return 0; 63 + } 64 + arch_initcall(xen_mm_init);
+1
arch/arm64/Kconfig
··· 211 211 config XEN 212 212 bool "Xen guest support on ARM64 (EXPERIMENTAL)" 213 213 depends on ARM64 && OF 214 + select SWIOTLB_XEN 214 215 help 215 216 Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64. 216 217
+1 -1
arch/arm64/xen/Makefile
··· 1 - xen-arm-y += $(addprefix ../../arm/xen/, enlighten.o grant-table.o p2m.o) 1 + xen-arm-y += $(addprefix ../../arm/xen/, enlighten.o grant-table.o p2m.o mm.o) 2 2 obj-y := xen-arm.o hypercall.o
-1
drivers/xen/Kconfig
··· 140 140 141 141 config SWIOTLB_XEN 142 142 def_bool y 143 - depends on PCI && X86 144 143 select SWIOTLB 145 144 146 145 config XEN_TMEM
+15
drivers/xen/swiotlb-xen.c
··· 42 42 #include <xen/page.h> 43 43 #include <xen/xen-ops.h> 44 44 #include <xen/hvc-console.h> 45 + #include <asm/dma-mapping.h> 45 46 /* 46 47 * Used to do a quick range check in swiotlb_tbl_unmap_single and 47 48 * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this 48 49 * API. 49 50 */ 51 + 52 + #ifndef CONFIG_X86 53 + static unsigned long dma_alloc_coherent_mask(struct device *dev, 54 + gfp_t gfp) 55 + { 56 + unsigned long dma_mask = 0; 57 + 58 + dma_mask = dev->coherent_dma_mask; 59 + if (!dma_mask) 60 + dma_mask = (gfp & GFP_DMA) ? DMA_BIT_MASK(24) : DMA_BIT_MASK(32); 61 + 62 + return dma_mask; 63 + } 64 + #endif 50 65 51 66 static char *xen_io_tlb_start, *xen_io_tlb_end; 52 67 static unsigned long xen_io_tlb_nslabs;