diff options
| -rw-r--r-- | arch/arm/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/xen/swiotlb-xen.c | 22 |
2 files changed, 21 insertions, 2 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee953..24307dc85d08 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -1885,6 +1885,7 @@ config XEN | |||
| 1885 | depends on !GENERIC_ATOMIC64 | 1885 | depends on !GENERIC_ATOMIC64 |
| 1886 | select ARM_PSCI | 1886 | select ARM_PSCI |
| 1887 | select SWIOTLB_XEN | 1887 | select SWIOTLB_XEN |
| 1888 | select ARCH_DMA_ADDR_T_64BIT | ||
| 1888 | help | 1889 | help |
| 1889 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. | 1890 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. |
| 1890 | 1891 | ||
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1eac0731c349..ebd8f218a788 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
| @@ -75,14 +75,32 @@ static unsigned long xen_io_tlb_nslabs; | |||
| 75 | 75 | ||
| 76 | static u64 start_dma_addr; | 76 | static u64 start_dma_addr; |
| 77 | 77 | ||
| 78 | /* | ||
| 79 | * Both of these functions should avoid PFN_PHYS because phys_addr_t | ||
| 80 | * can be 32bit when dma_addr_t is 64bit leading to a loss in | ||
| 81 | * information if the shift is done before casting to 64bit. | ||
| 82 | */ | ||
| 78 | static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr) | 83 | static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr) |
| 79 | { | 84 | { |
| 80 | return phys_to_machine(XPADDR(paddr)).maddr; | 85 | unsigned long mfn = pfn_to_mfn(PFN_DOWN(paddr)); |
| 86 | dma_addr_t dma = (dma_addr_t)mfn << PAGE_SHIFT; | ||
| 87 | |||
| 88 | dma |= paddr & ~PAGE_MASK; | ||
| 89 | |||
| 90 | return dma; | ||
| 81 | } | 91 | } |
| 82 | 92 | ||
| 83 | static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr) | 93 | static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr) |
| 84 | { | 94 | { |
| 85 | return machine_to_phys(XMADDR(baddr)).paddr; | 95 | unsigned long pfn = mfn_to_pfn(PFN_DOWN(baddr)); |
| 96 | dma_addr_t dma = (dma_addr_t)pfn << PAGE_SHIFT; | ||
| 97 | phys_addr_t paddr = dma; | ||
| 98 | |||
| 99 | BUG_ON(paddr != dma); /* truncation has occurred, should never happen */ | ||
| 100 | |||
| 101 | paddr |= baddr & ~PAGE_MASK; | ||
| 102 | |||
| 103 | return paddr; | ||
| 86 | } | 104 | } |
| 87 | 105 | ||
| 88 | static inline dma_addr_t xen_virt_to_bus(void *address) | 106 | static inline dma_addr_t xen_virt_to_bus(void *address) |
