[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] swiotlb-xen question

On Wed, 26 Mar 2014, Oleksandr Dmytryshyn wrote:
> On Wed, Mar 26, 2014 at 4:46 PM, Konrad Rzeszutek Wilk
> <konrad.wilk@xxxxxxxxxx> wrote:
> > On Wed, Mar 26, 2014 at 12:35:12PM +0200, Oleksandr Dmytryshyn wrote:
> >> Hi to all.
> >>
> >> Currently I'm using hypervisor on ARM Cortex A15 processor (DRA7xx
> >> Jacinto 6 processor). I'm using mainline xen 4.4 with some patches on
> >> top plus dom0 and domU linux kernel 3.8.
> >>
> >> I've written a hack to make a camera working on my board in dom0
> >> (drivers for camera and display system are in dom0). An user-space
> >> application in dom0 is used to test camera (it reads camera captured
> >> data and sends it to the framebuffer). In the kernel code I've implemented
> >> .mmap callback function in the swiotlb-xen.c file (like xen_swiotlb_mmap())
> >> and copied to this new callback all content from the original function
> >> 'arm_dma_mmap()' from the kernel. This function creates userspace
> >> mapping for the DMA-coherent memory. With this hack camera is working
> >> (I can see captured video on display).
> >
> > Why can't you use the v4l API? Won't that work?
> >
> Currently we are using v4l api. swiotlb-xen doesnt have mmap callback
> implemented,
> so kernel use standard function dma_common_mmap() to map memory. But this
> function doesn't work correctly. We've also tried to use arm_dma_mmap() 
> function
> instead of the dma_common_mmap() (HACK in the file
> include/asm-generic/dma-mapping-common.h only for dom0) and all is working
> in this case.

This is not a Xen specific issue.
In fact unless some of the dma pages involved could be foreign guest
pages (for example because you have a PV framebuffer frontend in a guest
sharing pages with a framebuffer backend in Dom0, and these pages are
used directly in your camera driver), swiotlb-xen shouldn't even be

The problem is that on ARM, when you call virt_to_phys on a virtual
address returned by dma_alloc_from_coherent, it doesn't return the right
physical address.
For example:

virt_address = dma_alloc_from_coherent(dev, size, dma_addr, &ret);
virt_to_phys(virt_address) != dma_addr

The issue is not that bus addresses are different from physical
addresses. The problem is that the virtual address is an ioremap address
therefore virt_to_phys and virt_to_page don't work as expected.

To fix your problem you can simply:

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 0ce39a3..052a5ed 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -248,7 +248,7 @@ int dma_common_mmap(struct device *dev, struct 
vm_area_struct *vma,
 #ifdef CONFIG_MMU
        unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
        unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-       unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
+       unsigned long pfn = dma_addr >> PAGE_SHIFT;
        unsigned long off = vma->vm_pgoff;
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

however that would cause problems on architectures for which bus
addresses are different from physical addresses.
Alternatively you could:

+       unsigned long pfn = bus_to_phys(dma_addr) >> PAGE_SHIFT;

however bus_to_phys is not defined on all architectures.
I am not sure what is the best way to fix this in common code such us

Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.