[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Work aroudn swiotlb issue where a read-only host buffer is
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID b92ca87a2403d465e4d1087f8a7a43223b21bed8 # Parent 1509521c824efbae25bb953a2e2a49ab3f7fe7f4 Work aroudn swiotlb issue where a read-only host buffer is mapped for DMA_BIDIRECTIONAL streaming access by certain low-level drivers. This causes an unnecessary copy to the host buffer that previously caused a fatal kernel page fault. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r 1509521c824e -r b92ca87a2403 linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Fri Dec 16 23:28:27 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Fri Dec 16 23:43:00 2005 @@ -24,6 +24,7 @@ #include <asm/io.h> #include <asm/pci.h> #include <asm/dma.h> +#include <asm/uaccess.h> #include <asm-xen/xen-public/memory.h> #define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1))) @@ -201,6 +202,12 @@ printk(KERN_INFO "Software IO TLB disabled\n"); } +/* + * We use __copy_to_user to transfer to the host buffer because the buffer + * may be mapped read-only (e.g, in blkback driver) but lower-level + * drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an + * unnecessary copy from the aperture to the host buffer, and a page fault. + */ static void __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir) { @@ -214,9 +221,11 @@ kmp = kmap_atomic(buffer.page, KM_SWIOTLB); dev = dma_addr + size - len; host = kmp + buffer.offset; - memcpy((dir == DMA_FROM_DEVICE) ? host : dev, - (dir == DMA_FROM_DEVICE) ? dev : host, - bytes); + if (dir == DMA_FROM_DEVICE) { + if (__copy_to_user(host, dev, bytes)) + return; /* inaccessible */ + } else + memcpy(dev, host, bytes); kunmap_atomic(kmp, KM_SWIOTLB); len -= bytes; buffer.page++; @@ -225,9 +234,10 @@ } else { char *host = (char *)phys_to_virt( page_to_pseudophys(buffer.page)) + buffer.offset; - if (dir == DMA_FROM_DEVICE) - memcpy(host, dma_addr, size); - else if (dir == DMA_TO_DEVICE) + if (dir == DMA_FROM_DEVICE) { + if (__copy_to_user(host, dma_addr, size)) + return; /* inaccessible */ + } else if (dir == DMA_TO_DEVICE) memcpy(dma_addr, host, size); } } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |