Commit 26f0cf91 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'stable/xen-swiotlb-0.8.6' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen

* 'stable/xen-swiotlb-0.8.6' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  x86: Detect whether we should use Xen SWIOTLB.
  pci-swiotlb-xen: Add glue code to setup dma_ops utilizing xen_swiotlb_* functions.
  swiotlb-xen: SWIOTLB library for Xen PV guest with PCI passthrough.
  xen/mmu: inhibit vmap aliases rather than trying to clear them out
  vmap: add flag to allow lazy unmap to be disabled at runtime
  xen: Add xen_create_contiguous_region
  xen: Rename the balloon lock
  xen: Allow unprivileged Xen domains to create iomap pages
  xen: use _PAGE_IOMAP in ioremap to do machine mappings

Fix up trivial conflicts (adding both xen swiotlb and xen pci platform
driver setup close to each other) in drivers/xen/{Kconfig,Makefile} and
include/xen/xen-ops.h
parents d862b13b fe96eb40
...@@ -112,13 +112,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine) ...@@ -112,13 +112,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine)
*/ */
static inline unsigned long mfn_to_local_pfn(unsigned long mfn) static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
{ {
extern unsigned long max_mapnr;
unsigned long pfn = mfn_to_pfn(mfn); unsigned long pfn = mfn_to_pfn(mfn);
if ((pfn < max_mapnr) if (get_phys_to_machine(pfn) != mfn)
&& !xen_feature(XENFEAT_auto_translated_physmap) return -1; /* force !pfn_valid() */
&& (get_phys_to_machine(pfn) != mfn))
return max_mapnr; /* force !pfn_valid() */
/* XXX fixme; not true with sparsemem */
return pfn; return pfn;
} }
......
#ifndef _ASM_X86_SWIOTLB_XEN_H
#define _ASM_X86_SWIOTLB_XEN_H
#ifdef CONFIG_SWIOTLB_XEN
extern int xen_swiotlb;
extern int __init pci_xen_swiotlb_detect(void);
extern void __init pci_xen_swiotlb_init(void);
#else
#define xen_swiotlb (0)
static inline int __init pci_xen_swiotlb_detect(void) { return 0; }
static inline void __init pci_xen_swiotlb_init(void) { }
#endif
#endif /* _ASM_X86_SWIOTLB_XEN_H */
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <asm/calgary.h> #include <asm/calgary.h>
#include <asm/amd_iommu.h> #include <asm/amd_iommu.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
#include <asm/xen/swiotlb-xen.h>
static int forbid_dac __read_mostly; static int forbid_dac __read_mostly;
...@@ -132,7 +133,7 @@ void __init pci_iommu_alloc(void) ...@@ -132,7 +133,7 @@ void __init pci_iommu_alloc(void)
/* free the range so iommu could get some range less than 4G */ /* free the range so iommu could get some range less than 4G */
dma32_free_bootmem(); dma32_free_bootmem();
if (pci_swiotlb_detect()) if (pci_xen_swiotlb_detect() || pci_swiotlb_detect())
goto out; goto out;
gart_iommu_hole_init(); gart_iommu_hole_init();
...@@ -144,6 +145,8 @@ void __init pci_iommu_alloc(void) ...@@ -144,6 +145,8 @@ void __init pci_iommu_alloc(void)
/* needs to be called after gart_iommu_hole_init */ /* needs to be called after gart_iommu_hole_init */
amd_iommu_detect(); amd_iommu_detect();
out: out:
pci_xen_swiotlb_init();
pci_swiotlb_init(); pci_swiotlb_init();
} }
...@@ -296,7 +299,7 @@ static int __init pci_iommu_init(void) ...@@ -296,7 +299,7 @@ static int __init pci_iommu_init(void)
#endif #endif
x86_init.iommu.iommu_init(); x86_init.iommu.iommu_init();
if (swiotlb) { if (swiotlb || xen_swiotlb) {
printk(KERN_INFO "PCI-DMA: " printk(KERN_INFO "PCI-DMA: "
"Using software bounce buffering for IO (SWIOTLB)\n"); "Using software bounce buffering for IO (SWIOTLB)\n");
swiotlb_print_info(); swiotlb_print_info();
......
...@@ -18,3 +18,4 @@ obj-$(CONFIG_SMP) += smp.o ...@@ -18,3 +18,4 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
...@@ -1172,6 +1172,10 @@ asmlinkage void __init xen_start_kernel(void) ...@@ -1172,6 +1172,10 @@ asmlinkage void __init xen_start_kernel(void)
pgd = (pgd_t *)xen_start_info->pt_base; pgd = (pgd_t *)xen_start_info->pt_base;
if (!xen_initial_domain())
__supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
__supported_pte_mask |= _PAGE_IOMAP;
/* Don't do the full vcpu_info placement stuff until we have a /* Don't do the full vcpu_info placement stuff until we have a
possible map and a non-dummy shared_info. */ possible map and a non-dummy shared_info. */
per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
......
This diff is collapsed.
/* Glue code to lib/swiotlb-xen.c */
#include <linux/dma-mapping.h>
#include <xen/swiotlb-xen.h>
#include <asm/xen/hypervisor.h>
#include <xen/xen.h>
int xen_swiotlb __read_mostly;
static struct dma_map_ops xen_swiotlb_dma_ops = {
.mapping_error = xen_swiotlb_dma_mapping_error,
.alloc_coherent = xen_swiotlb_alloc_coherent,
.free_coherent = xen_swiotlb_free_coherent,
.sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
.sync_single_for_device = xen_swiotlb_sync_single_for_device,
.sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu,
.sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
.map_sg = xen_swiotlb_map_sg_attrs,
.unmap_sg = xen_swiotlb_unmap_sg_attrs,
.map_page = xen_swiotlb_map_page,
.unmap_page = xen_swiotlb_unmap_page,
.dma_supported = xen_swiotlb_dma_supported,
};
/*
* pci_xen_swiotlb_detect - set xen_swiotlb to 1 if necessary
*
* This returns non-zero if we are forced to use xen_swiotlb (by the boot
* option).
*/
int __init pci_xen_swiotlb_detect(void)
{
/* If running as PV guest, either iommu=soft, or swiotlb=force will
* activate this IOMMU. If running as PV privileged, activate it
* irregardlesss.
*/
if ((xen_initial_domain() || swiotlb || swiotlb_force) &&
(xen_pv_domain()))
xen_swiotlb = 1;
/* If we are running under Xen, we MUST disable the native SWIOTLB.
* Don't worry about swiotlb_force flag activating the native, as
* the 'swiotlb' flag is the only one turning it on. */
if (xen_pv_domain())
swiotlb = 0;
return xen_swiotlb;
}
void __init pci_xen_swiotlb_init(void)
{
if (xen_swiotlb) {
xen_swiotlb_init(1);
dma_ops = &xen_swiotlb_dma_ops;
}
}
...@@ -71,4 +71,9 @@ config XEN_PLATFORM_PCI ...@@ -71,4 +71,9 @@ config XEN_PLATFORM_PCI
initializing xenbus and grant_table when running in a Xen HVM initializing xenbus and grant_table when running in a Xen HVM
domain. As a consequence this driver is required to run any Xen PV domain. As a consequence this driver is required to run any Xen PV
frontend on Xen HVM. frontend on Xen HVM.
config SWIOTLB_XEN
def_bool y
depends on SWIOTLB
endmenu endmenu
...@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o ...@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o
obj-$(CONFIG_XENFS) += xenfs/ obj-$(CONFIG_XENFS) += xenfs/
obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o
obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o
...@@ -85,13 +85,6 @@ static struct sys_device balloon_sysdev; ...@@ -85,13 +85,6 @@ static struct sys_device balloon_sysdev;
static int register_balloon(struct sys_device *sysdev); static int register_balloon(struct sys_device *sysdev);
/*
* Protects atomic reservation decrease/increase against concurrent increases.
* Also protects non-atomic updates of current_pages and driver_pages, and
* balloon lists.
*/
static DEFINE_SPINLOCK(balloon_lock);
static struct balloon_stats balloon_stats; static struct balloon_stats balloon_stats;
/* We increase/decrease in batches which fit in a page */ /* We increase/decrease in batches which fit in a page */
...@@ -210,7 +203,7 @@ static int increase_reservation(unsigned long nr_pages) ...@@ -210,7 +203,7 @@ static int increase_reservation(unsigned long nr_pages)
if (nr_pages > ARRAY_SIZE(frame_list)) if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list); nr_pages = ARRAY_SIZE(frame_list);
spin_lock_irqsave(&balloon_lock, flags); spin_lock_irqsave(&xen_reservation_lock, flags);
page = balloon_first_page(); page = balloon_first_page();
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
...@@ -254,7 +247,7 @@ static int increase_reservation(unsigned long nr_pages) ...@@ -254,7 +247,7 @@ static int increase_reservation(unsigned long nr_pages)
balloon_stats.current_pages += rc; balloon_stats.current_pages += rc;
out: out:
spin_unlock_irqrestore(&balloon_lock, flags); spin_unlock_irqrestore(&xen_reservation_lock, flags);
return rc < 0 ? rc : rc != nr_pages; return rc < 0 ? rc : rc != nr_pages;
} }
...@@ -299,7 +292,7 @@ static int decrease_reservation(unsigned long nr_pages) ...@@ -299,7 +292,7 @@ static int decrease_reservation(unsigned long nr_pages)
kmap_flush_unused(); kmap_flush_unused();
flush_tlb_all(); flush_tlb_all();
spin_lock_irqsave(&balloon_lock, flags); spin_lock_irqsave(&xen_reservation_lock, flags);
/* No more mappings: invalidate P2M and add to balloon. */ /* No more mappings: invalidate P2M and add to balloon. */
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
...@@ -315,7 +308,7 @@ static int decrease_reservation(unsigned long nr_pages) ...@@ -315,7 +308,7 @@ static int decrease_reservation(unsigned long nr_pages)
balloon_stats.current_pages -= nr_pages; balloon_stats.current_pages -= nr_pages;
spin_unlock_irqrestore(&balloon_lock, flags); spin_unlock_irqrestore(&xen_reservation_lock, flags);
return need_sleep; return need_sleep;
} }
......
This diff is collapsed.
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
struct vm_area_struct; /* vma defining user mapping in mm_types.h */ struct vm_area_struct; /* vma defining user mapping in mm_types.h */
extern bool vmap_lazy_unmap;
/* bits in flags of vmalloc's vm_struct below */ /* bits in flags of vmalloc's vm_struct below */
#define VM_IOREMAP 0x00000001 /* ioremap() and friends */ #define VM_IOREMAP 0x00000001 /* ioremap() and friends */
#define VM_ALLOC 0x00000002 /* vmalloc() */ #define VM_ALLOC 0x00000002 /* vmalloc() */
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#ifndef __XEN_PUBLIC_MEMORY_H__ #ifndef __XEN_PUBLIC_MEMORY_H__
#define __XEN_PUBLIC_MEMORY_H__ #define __XEN_PUBLIC_MEMORY_H__
#include <linux/spinlock.h>
/* /*
* Increase or decrease the specified domain's memory reservation. Returns a * Increase or decrease the specified domain's memory reservation. Returns a
* -ve errcode on failure, or the # extents successfully allocated or freed. * -ve errcode on failure, or the # extents successfully allocated or freed.
...@@ -52,6 +54,48 @@ struct xen_memory_reservation { ...@@ -52,6 +54,48 @@ struct xen_memory_reservation {
}; };
DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation); DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
/*
* An atomic exchange of memory pages. If return code is zero then
* @out.extent_list provides GMFNs of the newly-allocated memory.
* Returns zero on complete success, otherwise a negative error code.
* On complete success then always @nr_exchanged == @in.nr_extents.
* On partial success @nr_exchanged indicates how much work was done.
*/
#define XENMEM_exchange 11
struct xen_memory_exchange {
/*
* [IN] Details of memory extents to be exchanged (GMFN bases).
* Note that @in.address_bits is ignored and unused.
*/
struct xen_memory_reservation in;
/*
* [IN/OUT] Details of new memory extents.
* We require that:
* 1. @in.domid == @out.domid
* 2. @in.nr_extents << @in.extent_order ==
* @out.nr_extents << @out.extent_order
* 3. @in.extent_start and @out.extent_start lists must not overlap
* 4. @out.extent_start lists GPFN bases to be populated
* 5. @out.extent_start is overwritten with allocated GMFN bases
*/
struct xen_memory_reservation out;
/*
* [OUT] Number of input extents that were successfully exchanged:
* 1. The first @nr_exchanged input extents were successfully
* deallocated.
* 2. The corresponding first entries in the output extent list correctly
* indicate the GMFNs that were successfully exchanged.
* 3. All other input and output extents are untouched.
* 4. If not all input exents are exchanged then the return code of this
* command will be non-zero.
* 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
*/
unsigned long nr_exchanged;
};
DEFINE_GUEST_HANDLE_STRUCT(xen_memory_exchange);
/* /*
* Returns the maximum machine frame number of mapped RAM in this system. * Returns the maximum machine frame number of mapped RAM in this system.
* This command always succeeds (it never returns an error code). * This command always succeeds (it never returns an error code).
...@@ -142,4 +186,10 @@ struct xen_translate_gpfn_list { ...@@ -142,4 +186,10 @@ struct xen_translate_gpfn_list {
}; };
DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list); DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
/*
* Prevent the balloon driver from changing the memory reservation
* during a driver critical region.
*/
extern spinlock_t xen_reservation_lock;
#endif /* __XEN_PUBLIC_MEMORY_H__ */ #endif /* __XEN_PUBLIC_MEMORY_H__ */
#ifndef __LINUX_SWIOTLB_XEN_H
#define __LINUX_SWIOTLB_XEN_H
#include <linux/swiotlb.h>
extern void xen_swiotlb_init(int verbose);
extern void
*xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags);
extern void
xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
struct dma_attrs *attrs);
extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs);
/*
extern int
xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
enum dma_data_direction dir);
extern void
xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
enum dma_data_direction dir);
*/
extern int
xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
struct dma_attrs *attrs);
extern void
xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
struct dma_attrs *attrs);
extern void
xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir);
extern void
xen_swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
int nelems, enum dma_data_direction dir);
extern void
xen_swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir);
extern void
xen_swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
int nelems, enum dma_data_direction dir);
extern int
xen_swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
extern int
xen_swiotlb_dma_supported(struct device *hwdev, u64 mask);
#endif /* __LINUX_SWIOTLB_XEN_H */
...@@ -17,4 +17,10 @@ void xen_arch_resume(void); ...@@ -17,4 +17,10 @@ void xen_arch_resume(void);
int xen_setup_shutdown_event(void); int xen_setup_shutdown_event(void);
extern unsigned long *xen_contiguous_bitmap;
int xen_create_contiguous_region(unsigned long vstart, unsigned int order,
unsigned int address_bits);
void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
#endif /* INCLUDE_XEN_OPS_H */ #endif /* INCLUDE_XEN_OPS_H */
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/shmparam.h> #include <asm/shmparam.h>
bool vmap_lazy_unmap __read_mostly = true;
/*** Page table manipulation functions ***/ /*** Page table manipulation functions ***/
...@@ -502,6 +503,9 @@ static unsigned long lazy_max_pages(void) ...@@ -502,6 +503,9 @@ static unsigned long lazy_max_pages(void)
{ {
unsigned int log; unsigned int log;
if (!vmap_lazy_unmap)
return 0;
log = fls(num_online_cpus()); log = fls(num_online_cpus());
return log * (32UL * 1024 * 1024 / PAGE_SIZE); return log * (32UL * 1024 * 1024 / PAGE_SIZE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment