All,
Attached is a simple patch to slightly rework the logic in
range_straddles_page_boundary(). The reason for this is to avoid a crash we are
seeing on 32-bit dom0. Basically, the contiguous_bitmap is allocated based on
max_low_pfn. However, the swiotlb code can be passed a request (in
swiotlb_map_sg) that is > 1 page (I've seen 2 pages), and is also a page
(sg->page) > max_low_pfn. If this combination happens, then you get a fatal
page fault when doing the test_bit(pfn, contiguous_bitmap). For that reason,
rework the logic in range_straddles_page_boundary so that if it gets a request >
1 page, and it's above max_low_pfn, then we force the splitting of the request.
In our testing, this seems to fix the issue.
Note that the patch is against the RHEL-5 2.6.18 code, but the patch should
apply with a little fuzz to the linux-2.6.18-xen.hg tree.
Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx>
--- linux-2.6.18.noarch/arch/i386/kernel/pci-dma-xen.c.orig 2008-10-17
16:58:03.000000000 +0200
+++ linux-2.6.18.noarch/arch/i386/kernel/pci-dma-xen.c 2008-10-17
16:58:34.000000000 +0200
@@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/version.h>
+#include <linux/bootmem.h>
#include <asm/io.h>
#include <xen/balloon.h>
#include <asm/swiotlb.h>
@@ -134,12 +135,33 @@ int range_straddles_page_boundary(paddr_
unsigned long pfn = p >> PAGE_SHIFT;
unsigned int offset = p & ~PAGE_MASK;
+ /*
+ * 1. If this request is going to stay on this page, it won't
+ * cross a page boundary
+ */
if (offset + size <= PAGE_SIZE)
return 0;
- if (test_bit(pfn, contiguous_bitmap))
- return 0;
+ /*
+ * 2. If all of the pages here are physically contiguous, we
+ * technically cross a page boundary, but that's OK
+ */
if (check_pages_physically_contiguous(pfn, offset, size))
return 0;
+ /*
+ * 3. If the above two tests failed, *and* we are a page > max_low_pfn,
+ * then we have to straddle a page boundary (we won't be in the
+ * contiguous_bitmap, and attempting to access it will cause a
+ * page fault
+ */
+ if (pfn > max_low_pfn)
+ return 1;
+ /*
+ * 4. Finally, check the contiguous bitmap for this pfn; if it's in
+ * there, we are OK.
+ */
+
+ if (test_bit(pfn, contiguous_bitmap))
+ return 0;
return 1;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|