aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-14 23:34:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-14 23:34:37 -0500
commiteda670c626a4f53eb8ac5f20d8c10d3f0b54c583 (patch)
treee8b31fdeddd520b0fc56483f0a33c0501ee3b692
parentb746f9c7941f227ad582b4f0bc981f3adcbc46b2 (diff)
parent18c51e1a3fabb455ff1f5cd610097d89f577b8f7 (diff)
Merge tag 'stable/for-linus-3.13-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull Xen updates from Konrad Rzeszutek Wilk: "This has tons of fixes and two major features which are concentrated around the Xen SWIOTLB library. The short <blurb> is that the tracing facility (just one function) has been added to SWIOTLB to make it easier to track I/O progress. Additionally under Xen and ARM (32 & 64) the Xen-SWIOTLB driver "is used to translate physical to machine and machine to physical addresses of foreign[guest] pages for DMA operations" (Stefano) when booting under hardware without proper IOMMU. There are also bug-fixes, cleanups, compile warning fixes, etc. The commit times for some of the commits is a bit fresh - that is b/c we wanted to make sure we have the Ack's from the ARM folks - which with the string of back-to-back conferences took a bit of time. Rest assured - the code has been stewing in #linux-next for some time. Features: - SWIOTLB has tracing added when doing bounce buffer. - Xen ARM/ARM64 can use Xen-SWIOTLB. This work allows Linux to safely program real devices for DMA operations when running as a guest on Xen on ARM, without IOMMU support. [*1] - xen_raw_printk works with PVHVM guests if needed. Bug-fixes: - Make memory ballooning work under HVM with large MMIO region. - Inform hypervisor of MCFG regions found in ACPI DSDT. - Remove deprecated IRQF_DISABLED. - Remove deprecated __cpuinit. [*1]: "On arm and arm64 all Xen guests, including dom0, run with second stage translation enabled. As a consequence when dom0 programs a device for a DMA operation is going to use (pseudo) physical addresses instead machine addresses. This work introduces two trees to track physical to machine and machine to physical mappings of foreign pages. Local pages are assumed mapped 1:1 (physical address == machine address). It enables the SWIOTLB-Xen driver on ARM and ARM64, so that Linux can translate physical addresses to machine addresses for dma operations when necessary. " (Stefano)" * tag 'stable/for-linus-3.13-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: (32 commits) xen/arm: pfn_to_mfn and mfn_to_pfn return the argument if nothing is in the p2m arm,arm64/include/asm/io.h: define struct bio_vec swiotlb-xen: missing include dma-direction.h pci-swiotlb-xen: call pci_request_acs only ifdef CONFIG_PCI arm: make SWIOTLB available xen: delete new instances of added __cpuinit xen/balloon: Set balloon's initial state to number of existing RAM pages xen/mcfg: Call PHYSDEVOP_pci_mmcfg_reserved for MCFG areas. xen: remove deprecated IRQF_DISABLED x86/xen: remove deprecated IRQF_DISABLED swiotlb-xen: fix error code returned by xen_swiotlb_map_sg_attrs swiotlb-xen: static inline xen_phys_to_bus, xen_bus_to_phys, xen_virt_to_bus and range_straddles_page_boundary grant-table: call set_phys_to_machine after mapping grant refs arm,arm64: do not always merge biovec if we are running on Xen swiotlb: print a warning when the swiotlb is full swiotlb-xen: use xen_dma_map/unmap_page, xen_dma_sync_single_for_cpu/device xen: introduce xen_dma_map/unmap_page and xen_dma_sync_single_for_cpu/device tracing/events: Fix swiotlb tracepoint creation swiotlb-xen: use xen_alloc/free_coherent_pages xen: introduce xen_alloc/free_coherent_pages ...
-rw-r--r--arch/arm/Kconfig7
-rw-r--r--arch/arm/include/asm/dma-mapping.h46
-rw-r--r--arch/arm/include/asm/io.h9
-rw-r--r--arch/arm/include/asm/xen/hypervisor.h2
-rw-r--r--arch/arm/include/asm/xen/page-coherent.h50
-rw-r--r--arch/arm/include/asm/xen/page.h44
-rw-r--r--arch/arm/xen/Makefile2
-rw-r--r--arch/arm/xen/mm.c65
-rw-r--r--arch/arm/xen/p2m.c208
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/include/asm/dma-mapping.h14
-rw-r--r--arch/arm64/include/asm/io.h10
-rw-r--r--arch/arm64/include/asm/xen/page-coherent.h47
-rw-r--r--arch/arm64/xen/Makefile2
-rw-r--r--arch/ia64/include/asm/xen/page-coherent.h38
-rw-r--r--arch/x86/include/asm/xen/page-coherent.h38
-rw-r--r--arch/x86/xen/mmu.c15
-rw-r--r--arch/x86/xen/p2m.c6
-rw-r--r--arch/x86/xen/pci-swiotlb-xen.c4
-rw-r--r--arch/x86/xen/setup.c2
-rw-r--r--arch/x86/xen/smp.c10
-rw-r--r--arch/x86/xen/spinlock.c2
-rw-r--r--arch/x86/xen/time.c3
-rw-r--r--drivers/tty/hvc/hvc_xen.c19
-rw-r--r--drivers/xen/Kconfig1
-rw-r--r--drivers/xen/balloon.c6
-rw-r--r--drivers/xen/evtchn.c2
-rw-r--r--drivers/xen/grant-table.c19
-rw-r--r--drivers/xen/pci.c47
-rw-r--r--drivers/xen/platform-pci.c2
-rw-r--r--drivers/xen/swiotlb-xen.c119
-rw-r--r--include/trace/events/swiotlb.h46
-rw-r--r--include/xen/interface/physdev.h11
-rw-r--r--include/xen/swiotlb-xen.h3
-rw-r--r--include/xen/xen-ops.h7
-rw-r--r--lib/swiotlb.c6
36 files changed, 846 insertions, 67 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 00c1ff45a158..e089e622be79 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1862,6 +1862,12 @@ config CC_STACKPROTECTOR
1862 neutralized via a kernel panic. 1862 neutralized via a kernel panic.
1863 This feature requires gcc version 4.2 or above. 1863 This feature requires gcc version 4.2 or above.
1864 1864
1865config SWIOTLB
1866 def_bool y
1867
1868config IOMMU_HELPER
1869 def_bool SWIOTLB
1870
1865config XEN_DOM0 1871config XEN_DOM0
1866 def_bool y 1872 def_bool y
1867 depends on XEN 1873 depends on XEN
@@ -1872,6 +1878,7 @@ config XEN
1872 depends on CPU_V7 && !CPU_V6 1878 depends on CPU_V7 && !CPU_V6
1873 depends on !GENERIC_ATOMIC64 1879 depends on !GENERIC_ATOMIC64
1874 select ARM_PSCI 1880 select ARM_PSCI
1881 select SWIOTLB_XEN
1875 help 1882 help
1876 Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. 1883 Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
1877 1884
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 863cd84eb1a2..e701a4d9aa59 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -11,17 +11,28 @@
11#include <asm-generic/dma-coherent.h> 11#include <asm-generic/dma-coherent.h>
12#include <asm/memory.h> 12#include <asm/memory.h>
13 13
14#include <xen/xen.h>
15#include <asm/xen/hypervisor.h>
16
14#define DMA_ERROR_CODE (~0) 17#define DMA_ERROR_CODE (~0)
15extern struct dma_map_ops arm_dma_ops; 18extern struct dma_map_ops arm_dma_ops;
16extern struct dma_map_ops arm_coherent_dma_ops; 19extern struct dma_map_ops arm_coherent_dma_ops;
17 20
18static inline struct dma_map_ops *get_dma_ops(struct device *dev) 21static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
19{ 22{
20 if (dev && dev->archdata.dma_ops) 23 if (dev && dev->archdata.dma_ops)
21 return dev->archdata.dma_ops; 24 return dev->archdata.dma_ops;
22 return &arm_dma_ops; 25 return &arm_dma_ops;
23} 26}
24 27
28static inline struct dma_map_ops *get_dma_ops(struct device *dev)
29{
30 if (xen_initial_domain())
31 return xen_dma_ops;
32 else
33 return __generic_dma_ops(dev);
34}
35
25static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) 36static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
26{ 37{
27 BUG_ON(!dev); 38 BUG_ON(!dev);
@@ -94,6 +105,39 @@ static inline unsigned long dma_max_pfn(struct device *dev)
94} 105}
95#define dma_max_pfn(dev) dma_max_pfn(dev) 106#define dma_max_pfn(dev) dma_max_pfn(dev)
96 107
108static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
109{
110 unsigned int offset = paddr & ~PAGE_MASK;
111 return pfn_to_dma(dev, __phys_to_pfn(paddr)) + offset;
112}
113
114static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
115{
116 unsigned int offset = dev_addr & ~PAGE_MASK;
117 return __pfn_to_phys(dma_to_pfn(dev, dev_addr)) + offset;
118}
119
120static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
121{
122 u64 limit, mask;
123
124 if (!dev->dma_mask)
125 return 0;
126
127 mask = *dev->dma_mask;
128
129 limit = (mask + 1) & ~mask;
130 if (limit && size > limit)
131 return 0;
132
133 if ((addr | (addr + size - 1)) & ~mask)
134 return 0;
135
136 return 1;
137}
138
139static inline void dma_mark_clean(void *addr, size_t size) { }
140
97/* 141/*
98 * DMA errors are defined by all-bits-set in the DMA address. 142 * DMA errors are defined by all-bits-set in the DMA address.
99 */ 143 */
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index d070741b2b37..3c597c222ef2 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -24,9 +24,11 @@
24#ifdef __KERNEL__ 24#ifdef __KERNEL__
25 25
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/blk_types.h>
27#include <asm/byteorder.h> 28#include <asm/byteorder.h>
28#include <asm/memory.h> 29#include <asm/memory.h>
29#include <asm-generic/pci_iomap.h> 30#include <asm-generic/pci_iomap.h>
31#include <xen/xen.h>
30 32
31/* 33/*
32 * ISA I/O bus memory addresses are 1:1 with the physical address. 34 * ISA I/O bus memory addresses are 1:1 with the physical address.
@@ -372,6 +374,13 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
372#define BIOVEC_MERGEABLE(vec1, vec2) \ 374#define BIOVEC_MERGEABLE(vec1, vec2) \
373 ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) 375 ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
374 376
377struct bio_vec;
378extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
379 const struct bio_vec *vec2);
380#define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
381 (__BIOVEC_PHYS_MERGEABLE(vec1, vec2) && \
382 (!xen_domain() || xen_biovec_phys_mergeable(vec1, vec2)))
383
375#ifdef CONFIG_MMU 384#ifdef CONFIG_MMU
376#define ARCH_HAS_VALID_PHYS_ADDR_RANGE 385#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
377extern int valid_phys_addr_range(phys_addr_t addr, size_t size); 386extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
diff --git a/arch/arm/include/asm/xen/hypervisor.h b/arch/arm/include/asm/xen/hypervisor.h
index d7ab99a0c9eb..1317ee40f4df 100644
--- a/arch/arm/include/asm/xen/hypervisor.h
+++ b/arch/arm/include/asm/xen/hypervisor.h
@@ -16,4 +16,6 @@ static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
16 return PARAVIRT_LAZY_NONE; 16 return PARAVIRT_LAZY_NONE;
17} 17}
18 18
19extern struct dma_map_ops *xen_dma_ops;
20
19#endif /* _ASM_ARM_XEN_HYPERVISOR_H */ 21#endif /* _ASM_ARM_XEN_HYPERVISOR_H */
diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h
new file mode 100644
index 000000000000..1109017499e5
--- /dev/null
+++ b/arch/arm/include/asm/xen/page-coherent.h
@@ -0,0 +1,50 @@
1#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
2#define _ASM_ARM_XEN_PAGE_COHERENT_H
3
4#include <asm/page.h>
5#include <linux/dma-attrs.h>
6#include <linux/dma-mapping.h>
7
8static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
9 dma_addr_t *dma_handle, gfp_t flags,
10 struct dma_attrs *attrs)
11{
12 return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
13}
14
15static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
16 void *cpu_addr, dma_addr_t dma_handle,
17 struct dma_attrs *attrs)
18{
19 __generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
20}
21
22static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
23 unsigned long offset, size_t size, enum dma_data_direction dir,
24 struct dma_attrs *attrs)
25{
26 __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
27}
28
29static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
30 size_t size, enum dma_data_direction dir,
31 struct dma_attrs *attrs)
32{
33 if (__generic_dma_ops(hwdev)->unmap_page)
34 __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
35}
36
37static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
38 dma_addr_t handle, size_t size, enum dma_data_direction dir)
39{
40 if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
41 __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
42}
43
44static inline void xen_dma_sync_single_for_device(struct device *hwdev,
45 dma_addr_t handle, size_t size, enum dma_data_direction dir)
46{
47 if (__generic_dma_ops(hwdev)->sync_single_for_device)
48 __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
49}
50#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h
index 359a7b50b158..75579a9d6f76 100644
--- a/arch/arm/include/asm/xen/page.h
+++ b/arch/arm/include/asm/xen/page.h
@@ -6,12 +6,12 @@
6 6
7#include <linux/pfn.h> 7#include <linux/pfn.h>
8#include <linux/types.h> 8#include <linux/types.h>
9#include <linux/dma-mapping.h>
9 10
11#include <xen/xen.h>
10#include <xen/interface/grant_table.h> 12#include <xen/interface/grant_table.h>
11 13
12#define pfn_to_mfn(pfn) (pfn)
13#define phys_to_machine_mapping_valid(pfn) (1) 14#define phys_to_machine_mapping_valid(pfn) (1)
14#define mfn_to_pfn(mfn) (mfn)
15#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) 15#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
16 16
17#define pte_mfn pte_pfn 17#define pte_mfn pte_pfn
@@ -32,6 +32,38 @@ typedef struct xpaddr {
32 32
33#define INVALID_P2M_ENTRY (~0UL) 33#define INVALID_P2M_ENTRY (~0UL)
34 34
35unsigned long __pfn_to_mfn(unsigned long pfn);
36unsigned long __mfn_to_pfn(unsigned long mfn);
37extern struct rb_root phys_to_mach;
38
39static inline unsigned long pfn_to_mfn(unsigned long pfn)
40{
41 unsigned long mfn;
42
43 if (phys_to_mach.rb_node != NULL) {
44 mfn = __pfn_to_mfn(pfn);
45 if (mfn != INVALID_P2M_ENTRY)
46 return mfn;
47 }
48
49 return pfn;
50}
51
52static inline unsigned long mfn_to_pfn(unsigned long mfn)
53{
54 unsigned long pfn;
55
56 if (phys_to_mach.rb_node != NULL) {
57 pfn = __mfn_to_pfn(mfn);
58 if (pfn != INVALID_P2M_ENTRY)
59 return pfn;
60 }
61
62 return mfn;
63}
64
65#define mfn_to_local_pfn(mfn) mfn_to_pfn(mfn)
66
35static inline xmaddr_t phys_to_machine(xpaddr_t phys) 67static inline xmaddr_t phys_to_machine(xpaddr_t phys)
36{ 68{
37 unsigned offset = phys.paddr & ~PAGE_MASK; 69 unsigned offset = phys.paddr & ~PAGE_MASK;
@@ -76,11 +108,9 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte)
76 return 0; 108 return 0;
77} 109}
78 110
79static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) 111bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
80{ 112bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn,
81 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 113 unsigned long nr_pages);
82 return true;
83}
84 114
85static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) 115static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
86{ 116{
diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
index 43841033afd3..12969523414c 100644
--- a/arch/arm/xen/Makefile
+++ b/arch/arm/xen/Makefile
@@ -1 +1 @@
obj-y := enlighten.o hypercall.o grant-table.o obj-y := enlighten.o hypercall.o grant-table.o p2m.o mm.o
diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
new file mode 100644
index 000000000000..b0e77de99148
--- /dev/null
+++ b/arch/arm/xen/mm.c
@@ -0,0 +1,65 @@
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
19int xen_create_contiguous_region(phys_addr_t pstart, 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 = pstart;
28 return 0;
29}
30EXPORT_SYMBOL_GPL(xen_create_contiguous_region);
31
32void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
33{
34 return;
35}
36EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
37
38struct dma_map_ops *xen_dma_ops;
39EXPORT_SYMBOL_GPL(xen_dma_ops);
40
41static 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 .set_dma_mask = xen_swiotlb_set_dma_mask,
55};
56
57int __init xen_mm_init(void)
58{
59 if (!xen_initial_domain())
60 return 0;
61 xen_swiotlb_init(1, false);
62 xen_dma_ops = &xen_swiotlb_dma_ops;
63 return 0;
64}
65arch_initcall(xen_mm_init);
diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c
new file mode 100644
index 000000000000..23732cdff551
--- /dev/null
+++ b/arch/arm/xen/p2m.c
@@ -0,0 +1,208 @@
1#include <linux/bootmem.h>
2#include <linux/gfp.h>
3#include <linux/export.h>
4#include <linux/rwlock.h>
5#include <linux/slab.h>
6#include <linux/types.h>
7#include <linux/dma-mapping.h>
8#include <linux/vmalloc.h>
9#include <linux/swiotlb.h>
10
11#include <xen/xen.h>
12#include <xen/interface/memory.h>
13#include <xen/swiotlb-xen.h>
14
15#include <asm/cacheflush.h>
16#include <asm/xen/page.h>
17#include <asm/xen/hypercall.h>
18#include <asm/xen/interface.h>
19
20struct xen_p2m_entry {
21 unsigned long pfn;
22 unsigned long mfn;
23 unsigned long nr_pages;
24 struct rb_node rbnode_mach;
25 struct rb_node rbnode_phys;
26};
27
28rwlock_t p2m_lock;
29struct rb_root phys_to_mach = RB_ROOT;
30static struct rb_root mach_to_phys = RB_ROOT;
31
32static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
33{
34 struct rb_node **link = &phys_to_mach.rb_node;
35 struct rb_node *parent = NULL;
36 struct xen_p2m_entry *entry;
37 int rc = 0;
38
39 while (*link) {
40 parent = *link;
41 entry = rb_entry(parent, struct xen_p2m_entry, rbnode_phys);
42
43 if (new->mfn == entry->mfn)
44 goto err_out;
45 if (new->pfn == entry->pfn)
46 goto err_out;
47
48 if (new->pfn < entry->pfn)
49 link = &(*link)->rb_left;
50 else
51 link = &(*link)->rb_right;
52 }
53 rb_link_node(&new->rbnode_phys, parent, link);
54 rb_insert_color(&new->rbnode_phys, &phys_to_mach);
55 goto out;
56
57err_out:
58 rc = -EINVAL;
59 pr_warn("%s: cannot add pfn=%pa -> mfn=%pa: pfn=%pa -> mfn=%pa already exists\n",
60 __func__, &new->pfn, &new->mfn, &entry->pfn, &entry->mfn);
61out:
62 return rc;
63}
64
65unsigned long __pfn_to_mfn(unsigned long pfn)
66{
67 struct rb_node *n = phys_to_mach.rb_node;
68 struct xen_p2m_entry *entry;
69 unsigned long irqflags;
70
71 read_lock_irqsave(&p2m_lock, irqflags);
72 while (n) {
73 entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
74 if (entry->pfn <= pfn &&
75 entry->pfn + entry->nr_pages > pfn) {
76 read_unlock_irqrestore(&p2m_lock, irqflags);
77 return entry->mfn + (pfn - entry->pfn);
78 }
79 if (pfn < entry->pfn)
80 n = n->rb_left;
81 else
82 n = n->rb_right;
83 }
84 read_unlock_irqrestore(&p2m_lock, irqflags);
85
86 return INVALID_P2M_ENTRY;
87}
88EXPORT_SYMBOL_GPL(__pfn_to_mfn);
89
90static int xen_add_mach_to_phys_entry(struct xen_p2m_entry *new)
91{
92 struct rb_node **link = &mach_to_phys.rb_node;
93 struct rb_node *parent = NULL;
94 struct xen_p2m_entry *entry;
95 int rc = 0;
96
97 while (*link) {
98 parent = *link;
99 entry = rb_entry(parent, struct xen_p2m_entry, rbnode_mach);
100
101 if (new->mfn == entry->mfn)
102 goto err_out;
103 if (new->pfn == entry->pfn)
104 goto err_out;
105
106 if (new->mfn < entry->mfn)
107 link = &(*link)->rb_left;
108 else
109 link = &(*link)->rb_right;
110 }
111 rb_link_node(&new->rbnode_mach, parent, link);
112 rb_insert_color(&new->rbnode_mach, &mach_to_phys);
113 goto out;
114
115err_out:
116 rc = -EINVAL;
117 pr_warn("%s: cannot add pfn=%pa -> mfn=%pa: pfn=%pa -> mfn=%pa already exists\n",
118 __func__, &new->pfn, &new->mfn, &entry->pfn, &entry->mfn);
119out:
120 return rc;
121}
122
123unsigned long __mfn_to_pfn(unsigned long mfn)
124{
125 struct rb_node *n = mach_to_phys.rb_node;
126 struct xen_p2m_entry *entry;
127 unsigned long irqflags;
128
129 read_lock_irqsave(&p2m_lock, irqflags);
130 while (n) {
131 entry = rb_entry(n, struct xen_p2m_entry, rbnode_mach);
132 if (entry->mfn <= mfn &&
133 entry->mfn + entry->nr_pages > mfn) {
134 read_unlock_irqrestore(&p2m_lock, irqflags);
135 return entry->pfn + (mfn - entry->mfn);
136 }
137 if (mfn < entry->mfn)
138 n = n->rb_left;
139 else
140 n = n->rb_right;
141 }
142 read_unlock_irqrestore(&p2m_lock, irqflags);
143
144 return INVALID_P2M_ENTRY;
145}
146EXPORT_SYMBOL_GPL(__mfn_to_pfn);
147
148bool __set_phys_to_machine_multi(unsigned long pfn,
149 unsigned long mfn, unsigned long nr_pages)
150{
151 int rc;
152 unsigned long irqflags;
153 struct xen_p2m_entry *p2m_entry;
154 struct rb_node *n = phys_to_mach.rb_node;
155
156 if (mfn == INVALID_P2M_ENTRY) {
157 write_lock_irqsave(&p2m_lock, irqflags);
158 while (n) {
159 p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
160 if (p2m_entry->pfn <= pfn &&
161 p2m_entry->pfn + p2m_entry->nr_pages > pfn) {
162 rb_erase(&p2m_entry->rbnode_mach, &mach_to_phys);
163 rb_erase(&p2m_entry->rbnode_phys, &phys_to_mach);
164 write_unlock_irqrestore(&p2m_lock, irqflags);
165 kfree(p2m_entry);
166 return true;
167 }
168 if (pfn < p2m_entry->pfn)
169 n = n->rb_left;
170 else
171 n = n->rb_right;
172 }
173 write_unlock_irqrestore(&p2m_lock, irqflags);
174 return true;
175 }
176
177 p2m_entry = kzalloc(sizeof(struct xen_p2m_entry), GFP_NOWAIT);
178 if (!p2m_entry) {
179 pr_warn("cannot allocate xen_p2m_entry\n");
180 return false;
181 }
182 p2m_entry->pfn = pfn;
183 p2m_entry->nr_pages = nr_pages;
184 p2m_entry->mfn = mfn;
185
186 write_lock_irqsave(&p2m_lock, irqflags);
187 if ((rc = xen_add_phys_to_mach_entry(p2m_entry) < 0) ||
188 (rc = xen_add_mach_to_phys_entry(p2m_entry) < 0)) {
189 write_unlock_irqrestore(&p2m_lock, irqflags);
190 return false;
191 }
192 write_unlock_irqrestore(&p2m_lock, irqflags);
193 return true;
194}
195EXPORT_SYMBOL_GPL(__set_phys_to_machine_multi);
196
197bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
198{
199 return __set_phys_to_machine_multi(pfn, mfn, 1);
200}
201EXPORT_SYMBOL_GPL(__set_phys_to_machine);
202
203int p2m_init(void)
204{
205 rwlock_init(&p2m_lock);
206 return 0;
207}
208arch_initcall(p2m_init);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9714fe0403b7..88c8b6c1341a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -220,6 +220,7 @@ config XEN_DOM0
220config XEN 220config XEN
221 bool "Xen guest support on ARM64 (EXPERIMENTAL)" 221 bool "Xen guest support on ARM64 (EXPERIMENTAL)"
222 depends on ARM64 && OF 222 depends on ARM64 && OF
223 select SWIOTLB_XEN
223 help 224 help
224 Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64. 225 Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64.
225 226
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index 8d1810001aef..fd0c0c0e447a 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -23,11 +23,15 @@
23 23
24#include <asm-generic/dma-coherent.h> 24#include <asm-generic/dma-coherent.h>
25 25
26#include <xen/xen.h>
27#include <asm/xen/hypervisor.h>
28
26#define ARCH_HAS_DMA_GET_REQUIRED_MASK 29#define ARCH_HAS_DMA_GET_REQUIRED_MASK
27 30
31#define DMA_ERROR_CODE (~(dma_addr_t)0)
28extern struct dma_map_ops *dma_ops; 32extern struct dma_map_ops *dma_ops;
29 33
30static inline struct dma_map_ops *get_dma_ops(struct device *dev) 34static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
31{ 35{
32 if (unlikely(!dev) || !dev->archdata.dma_ops) 36 if (unlikely(!dev) || !dev->archdata.dma_ops)
33 return dma_ops; 37 return dma_ops;
@@ -35,6 +39,14 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
35 return dev->archdata.dma_ops; 39 return dev->archdata.dma_ops;
36} 40}
37 41
42static inline struct dma_map_ops *get_dma_ops(struct device *dev)
43{
44 if (xen_initial_domain())
45 return xen_dma_ops;
46 else
47 return __generic_dma_ops(dev);
48}
49
38#include <asm-generic/dma-mapping-common.h> 50#include <asm-generic/dma-mapping-common.h>
39 51
40static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) 52static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index b56e5b5df881..4cc813eddacb 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -22,11 +22,14 @@
22#ifdef __KERNEL__ 22#ifdef __KERNEL__
23 23
24#include <linux/types.h> 24#include <linux/types.h>
25#include <linux/blk_types.h>
25 26
26#include <asm/byteorder.h> 27#include <asm/byteorder.h>
27#include <asm/barrier.h> 28#include <asm/barrier.h>
28#include <asm/pgtable.h> 29#include <asm/pgtable.h>
29 30
31#include <xen/xen.h>
32
30/* 33/*
31 * Generic IO read/write. These perform native-endian accesses. 34 * Generic IO read/write. These perform native-endian accesses.
32 */ 35 */
@@ -263,5 +266,12 @@ extern int devmem_is_allowed(unsigned long pfn);
263 */ 266 */
264#define xlate_dev_kmem_ptr(p) p 267#define xlate_dev_kmem_ptr(p) p
265 268
269struct bio_vec;
270extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
271 const struct bio_vec *vec2);
272#define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
273 (__BIOVEC_PHYS_MERGEABLE(vec1, vec2) && \
274 (!xen_domain() || xen_biovec_phys_mergeable(vec1, vec2)))
275
266#endif /* __KERNEL__ */ 276#endif /* __KERNEL__ */
267#endif /* __ASM_IO_H */ 277#endif /* __ASM_IO_H */
diff --git a/arch/arm64/include/asm/xen/page-coherent.h b/arch/arm64/include/asm/xen/page-coherent.h
new file mode 100644
index 000000000000..2820f1a6eebe
--- /dev/null
+++ b/arch/arm64/include/asm/xen/page-coherent.h
@@ -0,0 +1,47 @@
1#ifndef _ASM_ARM64_XEN_PAGE_COHERENT_H
2#define _ASM_ARM64_XEN_PAGE_COHERENT_H
3
4#include <asm/page.h>
5#include <linux/dma-attrs.h>
6#include <linux/dma-mapping.h>
7
8static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
9 dma_addr_t *dma_handle, gfp_t flags,
10 struct dma_attrs *attrs)
11{
12 return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
13}
14
15static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
16 void *cpu_addr, dma_addr_t dma_handle,
17 struct dma_attrs *attrs)
18{
19 __generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
20}
21
22static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
23 unsigned long offset, size_t size, enum dma_data_direction dir,
24 struct dma_attrs *attrs)
25{
26 __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
27}
28
29static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
30 size_t size, enum dma_data_direction dir,
31 struct dma_attrs *attrs)
32{
33 __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
34}
35
36static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
37 dma_addr_t handle, size_t size, enum dma_data_direction dir)
38{
39 __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
40}
41
42static inline void xen_dma_sync_single_for_device(struct device *hwdev,
43 dma_addr_t handle, size_t size, enum dma_data_direction dir)
44{
45 __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
46}
47#endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
diff --git a/arch/arm64/xen/Makefile b/arch/arm64/xen/Makefile
index be240404ba96..74a8d87e542b 100644
--- a/arch/arm64/xen/Makefile
+++ b/arch/arm64/xen/Makefile
@@ -1,2 +1,2 @@
1xen-arm-y += $(addprefix ../../arm/xen/, enlighten.o grant-table.o) 1xen-arm-y += $(addprefix ../../arm/xen/, enlighten.o grant-table.o p2m.o mm.o)
2obj-y := xen-arm.o hypercall.o 2obj-y := xen-arm.o hypercall.o
diff --git a/arch/ia64/include/asm/xen/page-coherent.h b/arch/ia64/include/asm/xen/page-coherent.h
new file mode 100644
index 000000000000..96e42f97fa1f
--- /dev/null
+++ b/arch/ia64/include/asm/xen/page-coherent.h
@@ -0,0 +1,38 @@
1#ifndef _ASM_IA64_XEN_PAGE_COHERENT_H
2#define _ASM_IA64_XEN_PAGE_COHERENT_H
3
4#include <asm/page.h>
5#include <linux/dma-attrs.h>
6#include <linux/dma-mapping.h>
7
8static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
9 dma_addr_t *dma_handle, gfp_t flags,
10 struct dma_attrs *attrs)
11{
12 void *vstart = (void*)__get_free_pages(flags, get_order(size));
13 *dma_handle = virt_to_phys(vstart);
14 return vstart;
15}
16
17static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
18 void *cpu_addr, dma_addr_t dma_handle,
19 struct dma_attrs *attrs)
20{
21 free_pages((unsigned long) cpu_addr, get_order(size));
22}
23
24static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
25 unsigned long offset, size_t size, enum dma_data_direction dir,
26 struct dma_attrs *attrs) { }
27
28static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
29 size_t size, enum dma_data_direction dir,
30 struct dma_attrs *attrs) { }
31
32static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
33 dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
34
35static inline void xen_dma_sync_single_for_device(struct device *hwdev,
36 dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
37
38#endif /* _ASM_IA64_XEN_PAGE_COHERENT_H */
diff --git a/arch/x86/include/asm/xen/page-coherent.h b/arch/x86/include/asm/xen/page-coherent.h
new file mode 100644
index 000000000000..7f02fe4e2c7b
--- /dev/null
+++ b/arch/x86/include/asm/xen/page-coherent.h
@@ -0,0 +1,38 @@
1#ifndef _ASM_X86_XEN_PAGE_COHERENT_H
2#define _ASM_X86_XEN_PAGE_COHERENT_H
3
4#include <asm/page.h>
5#include <linux/dma-attrs.h>
6#include <linux/dma-mapping.h>
7
8static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
9 dma_addr_t *dma_handle, gfp_t flags,
10 struct dma_attrs *attrs)
11{
12 void *vstart = (void*)__get_free_pages(flags, get_order(size));
13 *dma_handle = virt_to_phys(vstart);
14 return vstart;
15}
16
17static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
18 void *cpu_addr, dma_addr_t dma_handle,
19 struct dma_attrs *attrs)
20{
21 free_pages((unsigned long) cpu_addr, get_order(size));
22}
23
24static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
25 unsigned long offset, size_t size, enum dma_data_direction dir,
26 struct dma_attrs *attrs) { }
27
28static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
29 size_t size, enum dma_data_direction dir,
30 struct dma_attrs *attrs) { }
31
32static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
33 dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
34
35static inline void xen_dma_sync_single_for_device(struct device *hwdev,
36 dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
37
38#endif /* _ASM_X86_XEN_PAGE_COHERENT_H */
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 49c962fe7e62..ce563be09cc1 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -468,8 +468,8 @@ PV_CALLEE_SAVE_REGS_THUNK(xen_pgd_val);
468 * 3 PCD PWT UC UC UC 468 * 3 PCD PWT UC UC UC
469 * 4 PAT WB WC WB 469 * 4 PAT WB WC WB
470 * 5 PAT PWT WC WP WT 470 * 5 PAT PWT WC WP WT
471 * 6 PAT PCD UC- UC UC- 471 * 6 PAT PCD UC- rsv UC-
472 * 7 PAT PCD PWT UC UC UC 472 * 7 PAT PCD PWT UC rsv UC
473 */ 473 */
474 474
475void xen_set_pat(u64 pat) 475void xen_set_pat(u64 pat)
@@ -2328,12 +2328,14 @@ static int xen_exchange_memory(unsigned long extents_in, unsigned int order_in,
2328 return success; 2328 return success;
2329} 2329}
2330 2330
2331int xen_create_contiguous_region(unsigned long vstart, unsigned int order, 2331int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
2332 unsigned int address_bits) 2332 unsigned int address_bits,
2333 dma_addr_t *dma_handle)
2333{ 2334{
2334 unsigned long *in_frames = discontig_frames, out_frame; 2335 unsigned long *in_frames = discontig_frames, out_frame;
2335 unsigned long flags; 2336 unsigned long flags;
2336 int success; 2337 int success;
2338 unsigned long vstart = (unsigned long)phys_to_virt(pstart);
2337 2339
2338 /* 2340 /*
2339 * Currently an auto-translated guest will not perform I/O, nor will 2341 * Currently an auto-translated guest will not perform I/O, nor will
@@ -2368,15 +2370,17 @@ int xen_create_contiguous_region(unsigned long vstart, unsigned int order,
2368 2370
2369 spin_unlock_irqrestore(&xen_reservation_lock, flags); 2371 spin_unlock_irqrestore(&xen_reservation_lock, flags);
2370 2372
2373 *dma_handle = virt_to_machine(vstart).maddr;
2371 return success ? 0 : -ENOMEM; 2374 return success ? 0 : -ENOMEM;
2372} 2375}
2373EXPORT_SYMBOL_GPL(xen_create_contiguous_region); 2376EXPORT_SYMBOL_GPL(xen_create_contiguous_region);
2374 2377
2375void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) 2378void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
2376{ 2379{
2377 unsigned long *out_frames = discontig_frames, in_frame; 2380 unsigned long *out_frames = discontig_frames, in_frame;
2378 unsigned long flags; 2381 unsigned long flags;
2379 int success; 2382 int success;
2383 unsigned long vstart;
2380 2384
2381 if (xen_feature(XENFEAT_auto_translated_physmap)) 2385 if (xen_feature(XENFEAT_auto_translated_physmap))
2382 return; 2386 return;
@@ -2384,6 +2388,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
2384 if (unlikely(order > MAX_CONTIG_ORDER)) 2388 if (unlikely(order > MAX_CONTIG_ORDER))
2385 return; 2389 return;
2386 2390
2391 vstart = (unsigned long)phys_to_virt(pstart);
2387 memset((void *) vstart, 0, PAGE_SIZE << order); 2392 memset((void *) vstart, 0, PAGE_SIZE << order);
2388 2393
2389 spin_lock_irqsave(&xen_reservation_lock, flags); 2394 spin_lock_irqsave(&xen_reservation_lock, flags);
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index a61c7d5811be..2ae8699e8767 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -799,10 +799,10 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
799{ 799{
800 unsigned topidx, mididx, idx; 800 unsigned topidx, mididx, idx;
801 801
802 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { 802 /* don't track P2M changes in autotranslate guests */
803 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 803 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
804 return true; 804 return true;
805 } 805
806 if (unlikely(pfn >= MAX_P2M_PFN)) { 806 if (unlikely(pfn >= MAX_P2M_PFN)) {
807 BUG_ON(mfn != INVALID_P2M_ENTRY); 807 BUG_ON(mfn != INVALID_P2M_ENTRY);
808 return true; 808 return true;
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
index 969570491c39..0e98e5d241d0 100644
--- a/arch/x86/xen/pci-swiotlb-xen.c
+++ b/arch/x86/xen/pci-swiotlb-xen.c
@@ -75,8 +75,10 @@ void __init pci_xen_swiotlb_init(void)
75 xen_swiotlb_init(1, true /* early */); 75 xen_swiotlb_init(1, true /* early */);
76 dma_ops = &xen_swiotlb_dma_ops; 76 dma_ops = &xen_swiotlb_dma_ops;
77 77
78#ifdef CONFIG_PCI
78 /* Make sure ACS will be enabled */ 79 /* Make sure ACS will be enabled */
79 pci_request_acs(); 80 pci_request_acs();
81#endif
80 } 82 }
81} 83}
82 84
@@ -92,8 +94,10 @@ int pci_xen_swiotlb_init_late(void)
92 return rc; 94 return rc;
93 95
94 dma_ops = &xen_swiotlb_dma_ops; 96 dma_ops = &xen_swiotlb_dma_ops;
97#ifdef CONFIG_PCI
95 /* Make sure ACS will be enabled */ 98 /* Make sure ACS will be enabled */
96 pci_request_acs(); 99 pci_request_acs();
100#endif
97 101
98 return 0; 102 return 0;
99} 103}
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 09f3059cb00b..68c054f59de6 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -556,7 +556,7 @@ void xen_enable_syscall(void)
556 } 556 }
557#endif /* CONFIG_X86_64 */ 557#endif /* CONFIG_X86_64 */
558} 558}
559void __cpuinit xen_enable_nmi(void) 559void xen_enable_nmi(void)
560{ 560{
561#ifdef CONFIG_X86_64 561#ifdef CONFIG_X86_64
562 if (register_callback(CALLBACKTYPE_nmi, nmi)) 562 if (register_callback(CALLBACKTYPE_nmi, nmi))
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 31d04758b76f..c36b325abd83 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -149,7 +149,7 @@ static int xen_smp_intr_init(unsigned int cpu)
149 rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, 149 rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
150 cpu, 150 cpu,
151 xen_reschedule_interrupt, 151 xen_reschedule_interrupt,
152 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 152 IRQF_PERCPU|IRQF_NOBALANCING,
153 resched_name, 153 resched_name,
154 NULL); 154 NULL);
155 if (rc < 0) 155 if (rc < 0)
@@ -161,7 +161,7 @@ static int xen_smp_intr_init(unsigned int cpu)
161 rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, 161 rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
162 cpu, 162 cpu,
163 xen_call_function_interrupt, 163 xen_call_function_interrupt,
164 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 164 IRQF_PERCPU|IRQF_NOBALANCING,
165 callfunc_name, 165 callfunc_name,
166 NULL); 166 NULL);
167 if (rc < 0) 167 if (rc < 0)
@@ -171,7 +171,7 @@ static int xen_smp_intr_init(unsigned int cpu)
171 171
172 debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); 172 debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
173 rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, 173 rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
174 IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING, 174 IRQF_PERCPU | IRQF_NOBALANCING,
175 debug_name, NULL); 175 debug_name, NULL);
176 if (rc < 0) 176 if (rc < 0)
177 goto fail; 177 goto fail;
@@ -182,7 +182,7 @@ static int xen_smp_intr_init(unsigned int cpu)
182 rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, 182 rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
183 cpu, 183 cpu,
184 xen_call_function_single_interrupt, 184 xen_call_function_single_interrupt,
185 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 185 IRQF_PERCPU|IRQF_NOBALANCING,
186 callfunc_name, 186 callfunc_name,
187 NULL); 187 NULL);
188 if (rc < 0) 188 if (rc < 0)
@@ -201,7 +201,7 @@ static int xen_smp_intr_init(unsigned int cpu)
201 rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, 201 rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
202 cpu, 202 cpu,
203 xen_irq_work_interrupt, 203 xen_irq_work_interrupt,
204 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 204 IRQF_PERCPU|IRQF_NOBALANCING,
205 callfunc_name, 205 callfunc_name,
206 NULL); 206 NULL);
207 if (rc < 0) 207 if (rc < 0)
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index be6b86078957..0e36cde12f7e 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -234,7 +234,7 @@ void xen_init_lock_cpu(int cpu)
234 irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, 234 irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
235 cpu, 235 cpu,
236 dummy_handler, 236 dummy_handler,
237 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 237 IRQF_PERCPU|IRQF_NOBALANCING,
238 name, 238 name,
239 NULL); 239 NULL);
240 240
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index ee365895b06b..12a1ca707b94 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -443,8 +443,7 @@ void xen_setup_timer(int cpu)
443 name = "<timer kasprintf failed>"; 443 name = "<timer kasprintf failed>";
444 444
445 irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, 445 irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
446 IRQF_DISABLED|IRQF_PERCPU| 446 IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER|
447 IRQF_NOBALANCING|IRQF_TIMER|
448 IRQF_FORCE_RESUME, 447 IRQF_FORCE_RESUME,
449 name, NULL); 448 name, NULL);
450 449
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index c193af6a628f..636c9baad7a5 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -183,7 +183,7 @@ static int dom0_write_console(uint32_t vtermno, const char *str, int len)
183{ 183{
184 int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str); 184 int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
185 if (rc < 0) 185 if (rc < 0)
186 return 0; 186 return rc;
187 187
188 return len; 188 return len;
189} 189}
@@ -642,7 +642,22 @@ struct console xenboot_console = {
642 642
643void xen_raw_console_write(const char *str) 643void xen_raw_console_write(const char *str)
644{ 644{
645 dom0_write_console(0, str, strlen(str)); 645 ssize_t len = strlen(str);
646 int rc = 0;
647
648 if (xen_domain()) {
649 rc = dom0_write_console(0, str, len);
650#ifdef CONFIG_X86
651 if (rc == -ENOSYS && xen_hvm_domain())
652 goto outb_print;
653
654 } else if (xen_cpuid_base()) {
655 int i;
656outb_print:
657 for (i = 0; i < len; i++)
658 outb(str[i], 0xe9);
659#endif
660 }
646} 661}
647 662
648void xen_raw_printk(const char *fmt, ...) 663void xen_raw_printk(const char *fmt, ...)
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 23eae5cb69c2..c794ea182140 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -140,7 +140,6 @@ config XEN_GRANT_DEV_ALLOC
140 140
141config SWIOTLB_XEN 141config SWIOTLB_XEN
142 def_bool y 142 def_bool y
143 depends on PCI && X86
144 select SWIOTLB 143 select SWIOTLB
145 144
146config XEN_TMEM 145config XEN_TMEM
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index b232908a6192..55ea73f7c70b 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -596,7 +596,7 @@ static void __init balloon_add_region(unsigned long start_pfn,
596 } 596 }
597} 597}
598 598
599static int __cpuinit balloon_cpu_notify(struct notifier_block *self, 599static int balloon_cpu_notify(struct notifier_block *self,
600 unsigned long action, void *hcpu) 600 unsigned long action, void *hcpu)
601{ 601{
602 int cpu = (long)hcpu; 602 int cpu = (long)hcpu;
@@ -616,7 +616,7 @@ static int __cpuinit balloon_cpu_notify(struct notifier_block *self,
616 return NOTIFY_OK; 616 return NOTIFY_OK;
617} 617}
618 618
619static struct notifier_block balloon_cpu_notifier __cpuinitdata = { 619static struct notifier_block balloon_cpu_notifier = {
620 .notifier_call = balloon_cpu_notify, 620 .notifier_call = balloon_cpu_notify,
621}; 621};
622 622
@@ -641,7 +641,7 @@ static int __init balloon_init(void)
641 641
642 balloon_stats.current_pages = xen_pv_domain() 642 balloon_stats.current_pages = xen_pv_domain()
643 ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn) 643 ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn)
644 : max_pfn; 644 : get_num_physpages();
645 balloon_stats.target_pages = balloon_stats.current_pages; 645 balloon_stats.target_pages = balloon_stats.current_pages;
646 balloon_stats.balloon_low = 0; 646 balloon_stats.balloon_low = 0;
647 balloon_stats.balloon_high = 0; 647 balloon_stats.balloon_high = 0;
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index 8b3a69a06c39..5de2063e16d3 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -305,7 +305,7 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port)
305 if (rc < 0) 305 if (rc < 0)
306 goto err; 306 goto err;
307 307
308 rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, IRQF_DISABLED, 308 rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, 0,
309 u->name, evtchn); 309 u->name, evtchn);
310 if (rc < 0) 310 if (rc < 0)
311 goto err; 311 goto err;
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index c4d2298893b1..62ccf5424ba8 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -49,6 +49,7 @@
49#include <xen/grant_table.h> 49#include <xen/grant_table.h>
50#include <xen/interface/memory.h> 50#include <xen/interface/memory.h>
51#include <xen/hvc-console.h> 51#include <xen/hvc-console.h>
52#include <xen/swiotlb-xen.h>
52#include <asm/xen/hypercall.h> 53#include <asm/xen/hypercall.h>
53#include <asm/xen/interface.h> 54#include <asm/xen/interface.h>
54 55
@@ -898,8 +899,16 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
898 gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, 899 gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
899 &map_ops[i].status, __func__); 900 &map_ops[i].status, __func__);
900 901
901 if (xen_feature(XENFEAT_auto_translated_physmap)) 902 /* this is basically a nop on x86 */
903 if (xen_feature(XENFEAT_auto_translated_physmap)) {
904 for (i = 0; i < count; i++) {
905 if (map_ops[i].status)
906 continue;
907 set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
908 map_ops[i].dev_bus_addr >> PAGE_SHIFT);
909 }
902 return ret; 910 return ret;
911 }
903 912
904 if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { 913 if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
905 arch_enter_lazy_mmu_mode(); 914 arch_enter_lazy_mmu_mode();
@@ -942,8 +951,14 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
942 if (ret) 951 if (ret)
943 return ret; 952 return ret;
944 953
945 if (xen_feature(XENFEAT_auto_translated_physmap)) 954 /* this is basically a nop on x86 */
955 if (xen_feature(XENFEAT_auto_translated_physmap)) {
956 for (i = 0; i < count; i++) {
957 set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
958 INVALID_P2M_ENTRY);
959 }
946 return ret; 960 return ret;
961 }
947 962
948 if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { 963 if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
949 arch_enter_lazy_mmu_mode(); 964 arch_enter_lazy_mmu_mode();
diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c
index 18fff88254eb..d15f6e80479f 100644
--- a/drivers/xen/pci.c
+++ b/drivers/xen/pci.c
@@ -26,6 +26,7 @@
26#include <asm/xen/hypervisor.h> 26#include <asm/xen/hypervisor.h>
27#include <asm/xen/hypercall.h> 27#include <asm/xen/hypercall.h>
28#include "../pci/pci.h" 28#include "../pci/pci.h"
29#include <asm/pci_x86.h>
29 30
30static bool __read_mostly pci_seg_supported = true; 31static bool __read_mostly pci_seg_supported = true;
31 32
@@ -192,3 +193,49 @@ static int __init register_xen_pci_notifier(void)
192} 193}
193 194
194arch_initcall(register_xen_pci_notifier); 195arch_initcall(register_xen_pci_notifier);
196
197#ifdef CONFIG_PCI_MMCONFIG
198static int __init xen_mcfg_late(void)
199{
200 struct pci_mmcfg_region *cfg;
201 int rc;
202
203 if (!xen_initial_domain())
204 return 0;
205
206 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
207 return 0;
208
209 if (list_empty(&pci_mmcfg_list))
210 return 0;
211
212 /* Check whether they are in the right area. */
213 list_for_each_entry(cfg, &pci_mmcfg_list, list) {
214 struct physdev_pci_mmcfg_reserved r;
215
216 r.address = cfg->address;
217 r.segment = cfg->segment;
218 r.start_bus = cfg->start_bus;
219 r.end_bus = cfg->end_bus;
220 r.flags = XEN_PCI_MMCFG_RESERVED;
221
222 rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r);
223 switch (rc) {
224 case 0:
225 case -ENOSYS:
226 continue;
227
228 default:
229 pr_warn("Failed to report MMCONFIG reservation"
230 " state for %s to hypervisor"
231 " (%d)\n",
232 cfg->name, rc);
233 }
234 }
235 return 0;
236}
237/*
238 * Needs to be done after acpi_init which are subsys_initcall.
239 */
240subsys_initcall_sync(xen_mcfg_late);
241#endif
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index 99db9e1eb8ba..2f3528e93cb9 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -84,7 +84,7 @@ static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
84static int xen_allocate_irq(struct pci_dev *pdev) 84static int xen_allocate_irq(struct pci_dev *pdev)
85{ 85{
86 return request_irq(pdev->irq, do_hvm_evtchn_intr, 86 return request_irq(pdev->irq, do_hvm_evtchn_intr,
87 IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, 87 IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
88 "xen-platform-pci", pdev); 88 "xen-platform-pci", pdev);
89} 89}
90 90
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 1b2277c311d2..a224bc74b6b9 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -42,12 +42,31 @@
42#include <xen/page.h> 42#include <xen/page.h>
43#include <xen/xen-ops.h> 43#include <xen/xen-ops.h>
44#include <xen/hvc-console.h> 44#include <xen/hvc-console.h>
45
46#include <asm/dma-mapping.h>
47#include <asm/xen/page-coherent.h>
48
49#include <trace/events/swiotlb.h>
45/* 50/*
46 * Used to do a quick range check in swiotlb_tbl_unmap_single and 51 * Used to do a quick range check in swiotlb_tbl_unmap_single and
47 * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this 52 * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
48 * API. 53 * API.
49 */ 54 */
50 55
56#ifndef CONFIG_X86
57static unsigned long dma_alloc_coherent_mask(struct device *dev,
58 gfp_t gfp)
59{
60 unsigned long dma_mask = 0;
61
62 dma_mask = dev->coherent_dma_mask;
63 if (!dma_mask)
64 dma_mask = (gfp & GFP_DMA) ? DMA_BIT_MASK(24) : DMA_BIT_MASK(32);
65
66 return dma_mask;
67}
68#endif
69
51static char *xen_io_tlb_start, *xen_io_tlb_end; 70static char *xen_io_tlb_start, *xen_io_tlb_end;
52static unsigned long xen_io_tlb_nslabs; 71static unsigned long xen_io_tlb_nslabs;
53/* 72/*
@@ -56,17 +75,17 @@ static unsigned long xen_io_tlb_nslabs;
56 75
57static u64 start_dma_addr; 76static u64 start_dma_addr;
58 77
59static dma_addr_t xen_phys_to_bus(phys_addr_t paddr) 78static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr)
60{ 79{
61 return phys_to_machine(XPADDR(paddr)).maddr; 80 return phys_to_machine(XPADDR(paddr)).maddr;
62} 81}
63 82
64static phys_addr_t xen_bus_to_phys(dma_addr_t baddr) 83static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr)
65{ 84{
66 return machine_to_phys(XMADDR(baddr)).paddr; 85 return machine_to_phys(XMADDR(baddr)).paddr;
67} 86}
68 87
69static dma_addr_t xen_virt_to_bus(void *address) 88static inline dma_addr_t xen_virt_to_bus(void *address)
70{ 89{
71 return xen_phys_to_bus(virt_to_phys(address)); 90 return xen_phys_to_bus(virt_to_phys(address));
72} 91}
@@ -89,7 +108,7 @@ static int check_pages_physically_contiguous(unsigned long pfn,
89 return 1; 108 return 1;
90} 109}
91 110
92static int range_straddles_page_boundary(phys_addr_t p, size_t size) 111static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
93{ 112{
94 unsigned long pfn = PFN_DOWN(p); 113 unsigned long pfn = PFN_DOWN(p);
95 unsigned int offset = p & ~PAGE_MASK; 114 unsigned int offset = p & ~PAGE_MASK;
@@ -126,6 +145,8 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs)
126{ 145{
127 int i, rc; 146 int i, rc;
128 int dma_bits; 147 int dma_bits;
148 dma_addr_t dma_handle;
149 phys_addr_t p = virt_to_phys(buf);
129 150
130 dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT; 151 dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
131 152
@@ -135,9 +156,9 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs)
135 156
136 do { 157 do {
137 rc = xen_create_contiguous_region( 158 rc = xen_create_contiguous_region(
138 (unsigned long)buf + (i << IO_TLB_SHIFT), 159 p + (i << IO_TLB_SHIFT),
139 get_order(slabs << IO_TLB_SHIFT), 160 get_order(slabs << IO_TLB_SHIFT),
140 dma_bits); 161 dma_bits, &dma_handle);
141 } while (rc && dma_bits++ < max_dma_bits); 162 } while (rc && dma_bits++ < max_dma_bits);
142 if (rc) 163 if (rc)
143 return rc; 164 return rc;
@@ -263,7 +284,6 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
263 void *ret; 284 void *ret;
264 int order = get_order(size); 285 int order = get_order(size);
265 u64 dma_mask = DMA_BIT_MASK(32); 286 u64 dma_mask = DMA_BIT_MASK(32);
266 unsigned long vstart;
267 phys_addr_t phys; 287 phys_addr_t phys;
268 dma_addr_t dev_addr; 288 dma_addr_t dev_addr;
269 289
@@ -278,8 +298,12 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
278 if (dma_alloc_from_coherent(hwdev, size, dma_handle, &ret)) 298 if (dma_alloc_from_coherent(hwdev, size, dma_handle, &ret))
279 return ret; 299 return ret;
280 300
281 vstart = __get_free_pages(flags, order); 301 /* On ARM this function returns an ioremap'ped virtual address for
282 ret = (void *)vstart; 302 * which virt_to_phys doesn't return the corresponding physical
303 * address. In fact on ARM virt_to_phys only works for kernel direct
304 * mapped RAM memory. Also see comment below.
305 */
306 ret = xen_alloc_coherent_pages(hwdev, size, dma_handle, flags, attrs);
283 307
284 if (!ret) 308 if (!ret)
285 return ret; 309 return ret;
@@ -287,18 +311,21 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
287 if (hwdev && hwdev->coherent_dma_mask) 311 if (hwdev && hwdev->coherent_dma_mask)
288 dma_mask = dma_alloc_coherent_mask(hwdev, flags); 312 dma_mask = dma_alloc_coherent_mask(hwdev, flags);
289 313
290 phys = virt_to_phys(ret); 314 /* At this point dma_handle is the physical address, next we are
315 * going to set it to the machine address.
316 * Do not use virt_to_phys(ret) because on ARM it doesn't correspond
317 * to *dma_handle. */
318 phys = *dma_handle;
291 dev_addr = xen_phys_to_bus(phys); 319 dev_addr = xen_phys_to_bus(phys);
292 if (((dev_addr + size - 1 <= dma_mask)) && 320 if (((dev_addr + size - 1 <= dma_mask)) &&
293 !range_straddles_page_boundary(phys, size)) 321 !range_straddles_page_boundary(phys, size))
294 *dma_handle = dev_addr; 322 *dma_handle = dev_addr;
295 else { 323 else {
296 if (xen_create_contiguous_region(vstart, order, 324 if (xen_create_contiguous_region(phys, order,
297 fls64(dma_mask)) != 0) { 325 fls64(dma_mask), dma_handle) != 0) {
298 free_pages(vstart, order); 326 xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs);
299 return NULL; 327 return NULL;
300 } 328 }
301 *dma_handle = virt_to_machine(ret).maddr;
302 } 329 }
303 memset(ret, 0, size); 330 memset(ret, 0, size);
304 return ret; 331 return ret;
@@ -319,13 +346,15 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
319 if (hwdev && hwdev->coherent_dma_mask) 346 if (hwdev && hwdev->coherent_dma_mask)
320 dma_mask = hwdev->coherent_dma_mask; 347 dma_mask = hwdev->coherent_dma_mask;
321 348
322 phys = virt_to_phys(vaddr); 349 /* do not use virt_to_phys because on ARM it doesn't return you the
350 * physical address */
351 phys = xen_bus_to_phys(dev_addr);
323 352
324 if (((dev_addr + size - 1 > dma_mask)) || 353 if (((dev_addr + size - 1 > dma_mask)) ||
325 range_straddles_page_boundary(phys, size)) 354 range_straddles_page_boundary(phys, size))
326 xen_destroy_contiguous_region((unsigned long)vaddr, order); 355 xen_destroy_contiguous_region(phys, order);
327 356
328 free_pages((unsigned long)vaddr, order); 357 xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs);
329} 358}
330EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent); 359EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent);
331 360
@@ -352,16 +381,25 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
352 * buffering it. 381 * buffering it.
353 */ 382 */
354 if (dma_capable(dev, dev_addr, size) && 383 if (dma_capable(dev, dev_addr, size) &&
355 !range_straddles_page_boundary(phys, size) && !swiotlb_force) 384 !range_straddles_page_boundary(phys, size) && !swiotlb_force) {
385 /* we are not interested in the dma_addr returned by
386 * xen_dma_map_page, only in the potential cache flushes executed
387 * by the function. */
388 xen_dma_map_page(dev, page, offset, size, dir, attrs);
356 return dev_addr; 389 return dev_addr;
390 }
357 391
358 /* 392 /*
359 * Oh well, have to allocate and map a bounce buffer. 393 * Oh well, have to allocate and map a bounce buffer.
360 */ 394 */
395 trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
396
361 map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir); 397 map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir);
362 if (map == SWIOTLB_MAP_ERROR) 398 if (map == SWIOTLB_MAP_ERROR)
363 return DMA_ERROR_CODE; 399 return DMA_ERROR_CODE;
364 400
401 xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT),
402 map & ~PAGE_MASK, size, dir, attrs);
365 dev_addr = xen_phys_to_bus(map); 403 dev_addr = xen_phys_to_bus(map);
366 404
367 /* 405 /*
@@ -384,12 +422,15 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
384 * whatever the device wrote there. 422 * whatever the device wrote there.
385 */ 423 */
386static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr, 424static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
387 size_t size, enum dma_data_direction dir) 425 size_t size, enum dma_data_direction dir,
426 struct dma_attrs *attrs)
388{ 427{
389 phys_addr_t paddr = xen_bus_to_phys(dev_addr); 428 phys_addr_t paddr = xen_bus_to_phys(dev_addr);
390 429
391 BUG_ON(dir == DMA_NONE); 430 BUG_ON(dir == DMA_NONE);
392 431
432 xen_dma_unmap_page(hwdev, paddr, size, dir, attrs);
433
393 /* NOTE: We use dev_addr here, not paddr! */ 434 /* NOTE: We use dev_addr here, not paddr! */
394 if (is_xen_swiotlb_buffer(dev_addr)) { 435 if (is_xen_swiotlb_buffer(dev_addr)) {
395 swiotlb_tbl_unmap_single(hwdev, paddr, size, dir); 436 swiotlb_tbl_unmap_single(hwdev, paddr, size, dir);
@@ -412,7 +453,7 @@ void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
412 size_t size, enum dma_data_direction dir, 453 size_t size, enum dma_data_direction dir,
413 struct dma_attrs *attrs) 454 struct dma_attrs *attrs)
414{ 455{
415 xen_unmap_single(hwdev, dev_addr, size, dir); 456 xen_unmap_single(hwdev, dev_addr, size, dir, attrs);
416} 457}
417EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_page); 458EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_page);
418 459
@@ -435,11 +476,15 @@ xen_swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
435 476
436 BUG_ON(dir == DMA_NONE); 477 BUG_ON(dir == DMA_NONE);
437 478
479 if (target == SYNC_FOR_CPU)
480 xen_dma_sync_single_for_cpu(hwdev, paddr, size, dir);
481
438 /* NOTE: We use dev_addr here, not paddr! */ 482 /* NOTE: We use dev_addr here, not paddr! */
439 if (is_xen_swiotlb_buffer(dev_addr)) { 483 if (is_xen_swiotlb_buffer(dev_addr))
440 swiotlb_tbl_sync_single(hwdev, paddr, size, dir, target); 484 swiotlb_tbl_sync_single(hwdev, paddr, size, dir, target);
441 return; 485
442 } 486 if (target == SYNC_FOR_DEVICE)
487 xen_dma_sync_single_for_cpu(hwdev, paddr, size, dir);
443 488
444 if (dir != DMA_FROM_DEVICE) 489 if (dir != DMA_FROM_DEVICE)
445 return; 490 return;
@@ -502,16 +547,26 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
502 sg->length, 547 sg->length,
503 dir); 548 dir);
504 if (map == SWIOTLB_MAP_ERROR) { 549 if (map == SWIOTLB_MAP_ERROR) {
550 dev_warn(hwdev, "swiotlb buffer is full\n");
505 /* Don't panic here, we expect map_sg users 551 /* Don't panic here, we expect map_sg users
506 to do proper error handling. */ 552 to do proper error handling. */
507 xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir, 553 xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
508 attrs); 554 attrs);
509 sg_dma_len(sgl) = 0; 555 sg_dma_len(sgl) = 0;
510 return DMA_ERROR_CODE; 556 return 0;
511 } 557 }
512 sg->dma_address = xen_phys_to_bus(map); 558 sg->dma_address = xen_phys_to_bus(map);
513 } else 559 } else {
560 /* we are not interested in the dma_addr returned by
561 * xen_dma_map_page, only in the potential cache flushes executed
562 * by the function. */
563 xen_dma_map_page(hwdev, pfn_to_page(paddr >> PAGE_SHIFT),
564 paddr & ~PAGE_MASK,
565 sg->length,
566 dir,
567 attrs);
514 sg->dma_address = dev_addr; 568 sg->dma_address = dev_addr;
569 }
515 sg_dma_len(sg) = sg->length; 570 sg_dma_len(sg) = sg->length;
516 } 571 }
517 return nelems; 572 return nelems;
@@ -533,7 +588,7 @@ xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
533 BUG_ON(dir == DMA_NONE); 588 BUG_ON(dir == DMA_NONE);
534 589
535 for_each_sg(sgl, sg, nelems, i) 590 for_each_sg(sgl, sg, nelems, i)
536 xen_unmap_single(hwdev, sg->dma_address, sg_dma_len(sg), dir); 591 xen_unmap_single(hwdev, sg->dma_address, sg_dma_len(sg), dir, attrs);
537 592
538} 593}
539EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); 594EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs);
@@ -593,3 +648,15 @@ xen_swiotlb_dma_supported(struct device *hwdev, u64 mask)
593 return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask; 648 return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask;
594} 649}
595EXPORT_SYMBOL_GPL(xen_swiotlb_dma_supported); 650EXPORT_SYMBOL_GPL(xen_swiotlb_dma_supported);
651
652int
653xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask)
654{
655 if (!dev->dma_mask || !xen_swiotlb_dma_supported(dev, dma_mask))
656 return -EIO;
657
658 *dev->dma_mask = dma_mask;
659
660 return 0;
661}
662EXPORT_SYMBOL_GPL(xen_swiotlb_set_dma_mask);
diff --git a/include/trace/events/swiotlb.h b/include/trace/events/swiotlb.h
new file mode 100644
index 000000000000..7ea4c5e7c448
--- /dev/null
+++ b/include/trace/events/swiotlb.h
@@ -0,0 +1,46 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM swiotlb
3
4#if !defined(_TRACE_SWIOTLB_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_SWIOTLB_H
6
7#include <linux/tracepoint.h>
8
9TRACE_EVENT(swiotlb_bounced,
10
11 TP_PROTO(struct device *dev,
12 dma_addr_t dev_addr,
13 size_t size,
14 int swiotlb_force),
15
16 TP_ARGS(dev, dev_addr, size, swiotlb_force),
17
18 TP_STRUCT__entry(
19 __string( dev_name, dev_name(dev) )
20 __field( u64, dma_mask )
21 __field( dma_addr_t, dev_addr )
22 __field( size_t, size )
23 __field( int, swiotlb_force )
24 ),
25
26 TP_fast_assign(
27 __assign_str(dev_name, dev_name(dev));
28 __entry->dma_mask = (dev->dma_mask ? *dev->dma_mask : 0);
29 __entry->dev_addr = dev_addr;
30 __entry->size = size;
31 __entry->swiotlb_force = swiotlb_force;
32 ),
33
34 TP_printk("dev_name: %s dma_mask=%llx dev_addr=%llx "
35 "size=%zu %s",
36 __get_str(dev_name),
37 __entry->dma_mask,
38 (unsigned long long)__entry->dev_addr,
39 __entry->size,
40 __entry->swiotlb_force ? "swiotlb_force" : "" )
41);
42
43#endif /* _TRACE_SWIOTLB_H */
44
45/* This part must be outside protection */
46#include <trace/define_trace.h>
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
index 7000bb1f6e96..42721d13a106 100644
--- a/include/xen/interface/physdev.h
+++ b/include/xen/interface/physdev.h
@@ -231,6 +231,17 @@ struct physdev_get_free_pirq {
231#define XEN_PCI_DEV_VIRTFN 0x2 231#define XEN_PCI_DEV_VIRTFN 0x2
232#define XEN_PCI_DEV_PXM 0x4 232#define XEN_PCI_DEV_PXM 0x4
233 233
234#define XEN_PCI_MMCFG_RESERVED 0x1
235
236#define PHYSDEVOP_pci_mmcfg_reserved 24
237struct physdev_pci_mmcfg_reserved {
238 uint64_t address;
239 uint16_t segment;
240 uint8_t start_bus;
241 uint8_t end_bus;
242 uint32_t flags;
243};
244
234#define PHYSDEVOP_pci_device_add 25 245#define PHYSDEVOP_pci_device_add 25
235struct physdev_pci_device_add { 246struct physdev_pci_device_add {
236 /* IN */ 247 /* IN */
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
index de8bcc641c49..8b2eb93ae8ba 100644
--- a/include/xen/swiotlb-xen.h
+++ b/include/xen/swiotlb-xen.h
@@ -1,6 +1,7 @@
1#ifndef __LINUX_SWIOTLB_XEN_H 1#ifndef __LINUX_SWIOTLB_XEN_H
2#define __LINUX_SWIOTLB_XEN_H 2#define __LINUX_SWIOTLB_XEN_H
3 3
4#include <linux/dma-direction.h>
4#include <linux/swiotlb.h> 5#include <linux/swiotlb.h>
5 6
6extern int xen_swiotlb_init(int verbose, bool early); 7extern int xen_swiotlb_init(int verbose, bool early);
@@ -55,4 +56,6 @@ xen_swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
55extern int 56extern int
56xen_swiotlb_dma_supported(struct device *hwdev, u64 mask); 57xen_swiotlb_dma_supported(struct device *hwdev, u64 mask);
57 58
59extern int
60xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask);
58#endif /* __LINUX_SWIOTLB_XEN_H */ 61#endif /* __LINUX_SWIOTLB_XEN_H */
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index d6fe062cad6b..fb2ea8f26552 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -19,10 +19,11 @@ void xen_arch_resume(void);
19int xen_setup_shutdown_event(void); 19int xen_setup_shutdown_event(void);
20 20
21extern unsigned long *xen_contiguous_bitmap; 21extern unsigned long *xen_contiguous_bitmap;
22int xen_create_contiguous_region(unsigned long vstart, unsigned int order, 22int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
23 unsigned int address_bits); 23 unsigned int address_bits,
24 dma_addr_t *dma_handle);
24 25
25void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); 26void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order);
26 27
27struct vm_area_struct; 28struct vm_area_struct;
28int xen_remap_domain_mfn_range(struct vm_area_struct *vma, 29int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 4e8686c7e5a4..e4399fa65ad6 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -38,6 +38,9 @@
38#include <linux/bootmem.h> 38#include <linux/bootmem.h>
39#include <linux/iommu-helper.h> 39#include <linux/iommu-helper.h>
40 40
41#define CREATE_TRACE_POINTS
42#include <trace/events/swiotlb.h>
43
41#define OFFSET(val,align) ((unsigned long) \ 44#define OFFSET(val,align) ((unsigned long) \
42 ( (val) & ( (align) - 1))) 45 ( (val) & ( (align) - 1)))
43 46
@@ -502,6 +505,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
502 505
503not_found: 506not_found:
504 spin_unlock_irqrestore(&io_tlb_lock, flags); 507 spin_unlock_irqrestore(&io_tlb_lock, flags);
508 dev_warn(hwdev, "swiotlb buffer is full\n");
505 return SWIOTLB_MAP_ERROR; 509 return SWIOTLB_MAP_ERROR;
506found: 510found:
507 spin_unlock_irqrestore(&io_tlb_lock, flags); 511 spin_unlock_irqrestore(&io_tlb_lock, flags);
@@ -726,6 +730,8 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
726 if (dma_capable(dev, dev_addr, size) && !swiotlb_force) 730 if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
727 return dev_addr; 731 return dev_addr;
728 732
733 trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
734
729 /* Oh well, have to allocate and map a bounce buffer. */ 735 /* Oh well, have to allocate and map a bounce buffer. */
730 map = map_single(dev, phys, size, dir); 736 map = map_single(dev, phys, size, dir);
731 if (map == SWIOTLB_MAP_ERROR) { 737 if (map == SWIOTLB_MAP_ERROR) {