From 69908907b02efee31377af0cefbcd5a3ba66334a Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 9 Oct 2013 16:56:32 +0000 Subject: xen: make xen_create_contiguous_region return the dma address Modify xen_create_contiguous_region to return the dma address of the newly contiguous buffer. Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel Changes in v4: - use virt_to_machine instead of virt_to_bus. --- include/xen/xen-ops.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/xen') diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index d6fe062cad6..9ef704d3a9d 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h @@ -20,7 +20,8 @@ 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); + unsigned int address_bits, + dma_addr_t *dma_handle); void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); -- cgit v1.2.3-70-g09d2 From eb1ddc00b81cb8cb23891b6c7c5fbfaea29f3c73 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 9 Oct 2013 16:56:33 +0000 Subject: swiotlb-xen: introduce xen_swiotlb_set_dma_mask Implement xen_swiotlb_set_dma_mask, use it for set_dma_mask on arm. Signed-off-by: Stefano Stabellini --- arch/arm/xen/mm.c | 1 + drivers/xen/swiotlb-xen.c | 12 ++++++++++++ include/xen/swiotlb-xen.h | 2 ++ 3 files changed, 15 insertions(+) (limited to 'include/xen') diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c index d56b8c6e4fb..0d69b874d24 100644 --- a/arch/arm/xen/mm.c +++ b/arch/arm/xen/mm.c @@ -51,6 +51,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = { .map_page = xen_swiotlb_map_page, .unmap_page = xen_swiotlb_unmap_page, .dma_supported = xen_swiotlb_dma_supported, + .set_dma_mask = xen_swiotlb_set_dma_mask, }; int __init xen_mm_init(void) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index f0fc1a4f565..d8ef0bf577d 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -608,3 +608,15 @@ xen_swiotlb_dma_supported(struct device *hwdev, u64 mask) return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask; } EXPORT_SYMBOL_GPL(xen_swiotlb_dma_supported); + +int +xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask) +{ + if (!dev->dma_mask || !xen_swiotlb_dma_supported(dev, dma_mask)) + return -EIO; + + *dev->dma_mask = dma_mask; + + return 0; +} +EXPORT_SYMBOL_GPL(xen_swiotlb_set_dma_mask); diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index de8bcc641c4..7b644650d96 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h @@ -55,4 +55,6 @@ xen_swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr); extern int xen_swiotlb_dma_supported(struct device *hwdev, u64 mask); +extern int +xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask); #endif /* __LINUX_SWIOTLB_XEN_H */ -- cgit v1.2.3-70-g09d2 From 1b65c4e5a9af1a1c61e792e2d0ed481e0c1f21a9 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 10 Oct 2013 13:41:10 +0000 Subject: swiotlb-xen: use xen_alloc/free_coherent_pages Use xen_alloc_coherent_pages and xen_free_coherent_pages to allocate or free coherent pages. We need to be careful handling the pointer returned by xen_alloc_coherent_pages, because on ARM the pointer is not equal to phys_to_virt(*dma_handle). In fact virt_to_phys only works for kernel direct mapped RAM memory. In ARM case the pointer could be an ioremap address, therefore passing it to virt_to_phys would give you another physical address that doesn't correspond to it. Make xen_create_contiguous_region take a phys_addr_t as start parameter to avoid the virt_to_phys calls which would be incorrect. Changes in v6: - remove extra spaces. Signed-off-by: Stefano Stabellini Reviewed-by: Konrad Rzeszutek Wilk --- arch/arm/xen/mm.c | 6 +++--- arch/x86/xen/mmu.c | 7 +++++-- drivers/xen/swiotlb-xen.c | 31 +++++++++++++++++++++---------- include/xen/xen-ops.h | 4 ++-- 4 files changed, 31 insertions(+), 17 deletions(-) (limited to 'include/xen') diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c index 0d69b874d24..b0e77de9914 100644 --- a/arch/arm/xen/mm.c +++ b/arch/arm/xen/mm.c @@ -16,7 +16,7 @@ #include #include -int xen_create_contiguous_region(unsigned long vstart, unsigned int order, +int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, unsigned int address_bits, dma_addr_t *dma_handle) { @@ -24,12 +24,12 @@ int xen_create_contiguous_region(unsigned long vstart, unsigned int order, return -EINVAL; /* we assume that dom0 is mapped 1:1 for now */ - *dma_handle = virt_to_phys(pstart); + *dma_handle = pstart; return 0; } EXPORT_SYMBOL_GPL(xen_create_contiguous_region); -void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) +void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) { return; } diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6c34d7c03d5..883088368ff 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -2328,13 +2328,14 @@ static int xen_exchange_memory(unsigned long extents_in, unsigned int order_in, return success; } -int xen_create_contiguous_region(unsigned long vstart, unsigned int order, +int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, unsigned int address_bits, dma_addr_t *dma_handle) { unsigned long *in_frames = discontig_frames, out_frame; unsigned long flags; int success; + unsigned long vstart = (unsigned long)phys_to_virt(pstart); /* * Currently an auto-translated guest will not perform I/O, nor will @@ -2374,11 +2375,12 @@ int xen_create_contiguous_region(unsigned long vstart, unsigned int order, } EXPORT_SYMBOL_GPL(xen_create_contiguous_region); -void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) +void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) { unsigned long *out_frames = discontig_frames, in_frame; unsigned long flags; int success; + unsigned long vstart; if (xen_feature(XENFEAT_auto_translated_physmap)) return; @@ -2386,6 +2388,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) if (unlikely(order > MAX_CONTIG_ORDER)) return; + vstart = (unsigned long)phys_to_virt(pstart); memset((void *) vstart, 0, PAGE_SIZE << order); spin_lock_irqsave(&xen_reservation_lock, flags); diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index d8ef0bf577d..189b8db5c98 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -43,6 +43,7 @@ #include #include #include +#include /* * Used to do a quick range check in swiotlb_tbl_unmap_single and * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this @@ -142,6 +143,7 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) int i, rc; int dma_bits; dma_addr_t dma_handle; + phys_addr_t p = virt_to_phys(buf); dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT; @@ -151,7 +153,7 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) do { rc = xen_create_contiguous_region( - (unsigned long)buf + (i << IO_TLB_SHIFT), + p + (i << IO_TLB_SHIFT), get_order(slabs << IO_TLB_SHIFT), dma_bits, &dma_handle); } while (rc && dma_bits++ < max_dma_bits); @@ -279,7 +281,6 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, void *ret; int order = get_order(size); u64 dma_mask = DMA_BIT_MASK(32); - unsigned long vstart; phys_addr_t phys; dma_addr_t dev_addr; @@ -294,8 +295,12 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, if (dma_alloc_from_coherent(hwdev, size, dma_handle, &ret)) return ret; - vstart = __get_free_pages(flags, order); - ret = (void *)vstart; + /* On ARM this function returns an ioremap'ped virtual address for + * which virt_to_phys doesn't return the corresponding physical + * address. In fact on ARM virt_to_phys only works for kernel direct + * mapped RAM memory. Also see comment below. + */ + ret = xen_alloc_coherent_pages(hwdev, size, dma_handle, flags, attrs); if (!ret) return ret; @@ -303,15 +308,19 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, if (hwdev && hwdev->coherent_dma_mask) dma_mask = dma_alloc_coherent_mask(hwdev, flags); - phys = virt_to_phys(ret); + /* At this point dma_handle is the physical address, next we are + * going to set it to the machine address. + * Do not use virt_to_phys(ret) because on ARM it doesn't correspond + * to *dma_handle. */ + phys = *dma_handle; dev_addr = xen_phys_to_bus(phys); if (((dev_addr + size - 1 <= dma_mask)) && !range_straddles_page_boundary(phys, size)) *dma_handle = dev_addr; else { - if (xen_create_contiguous_region(vstart, order, + if (xen_create_contiguous_region(phys, order, fls64(dma_mask), dma_handle) != 0) { - free_pages(vstart, order); + xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs); return NULL; } } @@ -334,13 +343,15 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, if (hwdev && hwdev->coherent_dma_mask) dma_mask = hwdev->coherent_dma_mask; - phys = virt_to_phys(vaddr); + /* do not use virt_to_phys because on ARM it doesn't return you the + * physical address */ + phys = xen_bus_to_phys(dev_addr); if (((dev_addr + size - 1 > dma_mask)) || range_straddles_page_boundary(phys, size)) - xen_destroy_contiguous_region((unsigned long)vaddr, order); + xen_destroy_contiguous_region(phys, order); - free_pages((unsigned long)vaddr, order); + xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs); } EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent); diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 9ef704d3a9d..fb2ea8f2655 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h @@ -19,11 +19,11 @@ void xen_arch_resume(void); int xen_setup_shutdown_event(void); extern unsigned long *xen_contiguous_bitmap; -int xen_create_contiguous_region(unsigned long vstart, unsigned int order, +int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, unsigned int address_bits, dma_addr_t *dma_handle); -void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); +void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order); struct vm_area_struct; int xen_remap_domain_mfn_range(struct vm_area_struct *vma, -- cgit v1.2.3-70-g09d2 From 8deb3eb1461e4cb136c88d03ec5a6729ccf2f933 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 25 Oct 2013 16:26:02 -0400 Subject: xen/mcfg: Call PHYSDEVOP_pci_mmcfg_reserved for MCFG areas. The PCI MMCONFIG area is usually reserved via the E820 so the Xen hypervisor is aware of these regions. But they can also be enumerated in the ACPI DSDT which means the hypervisor won't know of them until the initial domain informs it of via PHYSDEVOP_pci_mmcfg_reserved. This is what this patch does for all of the MCFG regions that the initial domain is aware of (E820 enumerated and ACPI). Reported-by: Santosh Jodh CC: Jan Beulich Reviewed-by: Boris Ostrovsky CC: David Vrabel CC: Mukesh Rathor Signed-off-by: Konrad Rzeszutek Wilk [v1: Redid it a bit] [v2: Dropped the P2M 1-1 setting] [v3: Check for Xen in-case we are running under baremetal] [v4: Wrap with CONFIG_PCI_MMCONFIG] --- drivers/xen/pci.c | 47 +++++++++++++++++++++++++++++++++++++++++ include/xen/interface/physdev.h | 11 ++++++++++ 2 files changed, 58 insertions(+) (limited to 'include/xen') diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c index 18fff88254e..d15f6e80479 100644 --- a/drivers/xen/pci.c +++ b/drivers/xen/pci.c @@ -26,6 +26,7 @@ #include #include #include "../pci/pci.h" +#include static bool __read_mostly pci_seg_supported = true; @@ -192,3 +193,49 @@ static int __init register_xen_pci_notifier(void) } arch_initcall(register_xen_pci_notifier); + +#ifdef CONFIG_PCI_MMCONFIG +static int __init xen_mcfg_late(void) +{ + struct pci_mmcfg_region *cfg; + int rc; + + if (!xen_initial_domain()) + return 0; + + if ((pci_probe & PCI_PROBE_MMCONF) == 0) + return 0; + + if (list_empty(&pci_mmcfg_list)) + return 0; + + /* Check whether they are in the right area. */ + list_for_each_entry(cfg, &pci_mmcfg_list, list) { + struct physdev_pci_mmcfg_reserved r; + + r.address = cfg->address; + r.segment = cfg->segment; + r.start_bus = cfg->start_bus; + r.end_bus = cfg->end_bus; + r.flags = XEN_PCI_MMCFG_RESERVED; + + rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r); + switch (rc) { + case 0: + case -ENOSYS: + continue; + + default: + pr_warn("Failed to report MMCONFIG reservation" + " state for %s to hypervisor" + " (%d)\n", + cfg->name, rc); + } + } + return 0; +} +/* + * Needs to be done after acpi_init which are subsys_initcall. + */ +subsys_initcall_sync(xen_mcfg_late); +#endif diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 7000bb1f6e9..42721d13a10 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -231,6 +231,17 @@ struct physdev_get_free_pirq { #define XEN_PCI_DEV_VIRTFN 0x2 #define XEN_PCI_DEV_PXM 0x4 +#define XEN_PCI_MMCFG_RESERVED 0x1 + +#define PHYSDEVOP_pci_mmcfg_reserved 24 +struct physdev_pci_mmcfg_reserved { + uint64_t address; + uint16_t segment; + uint8_t start_bus; + uint8_t end_bus; + uint32_t flags; +}; + #define PHYSDEVOP_pci_device_add 25 struct physdev_pci_device_add { /* IN */ -- cgit v1.2.3-70-g09d2 From 6fe19278ffebdd57e5c5ec10275e6d423404364e Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 4 Nov 2013 17:54:27 +0000 Subject: swiotlb-xen: missing include dma-direction.h Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk --- include/xen/swiotlb-xen.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/xen') diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index de8bcc641c4..4d81cccf109 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h @@ -1,6 +1,7 @@ #ifndef __LINUX_SWIOTLB_XEN_H #define __LINUX_SWIOTLB_XEN_H +#include #include extern int xen_swiotlb_init(int verbose, bool early); -- cgit v1.2.3-70-g09d2