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

[Xen-devel] SWIOMMU redundant copies?



Hi,

In current linux-2.6.18-xen.h 64-bit, it looks like we're doing
potentially large amounts of unnecessary IO bounce-buffering.

I noticed this when trying to pin down some odd behaviour concerning
changeset 15405 in xen-3.1-testing:

        http://xenbits.xensource.com/xen-3.1-testing.hg?rev/30033a637942

        # User kfraser@xxxxxxxxxxxxxxxxxxxxx
        # Date 1183985110 -3600
        # Node ID 30033a6379428f57269455f0963841743c6d5e46
        # Parent  9cdade953890a612734d97b3abc21513a1a9cf6d
        x86: dma_map_sg() must handle multi-page segments.
        Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

which adds a test when we do swiotlb_map_sg():

--- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c   Fri Sep 14 16:33:44 
2007 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c   Mon Jul 09 13:45:10 
2007 +0100
@@ -572,7 +572,9 @@ swiotlb_map_sg(struct device *hwdev, str
 
        for (i = 0; i < nelems; i++, sg++) {
                dev_addr = SG_ENT_PHYS_ADDRESS(sg);
-               if (address_needs_mapping(hwdev, dev_addr)) {
+               if (range_straddles_page_boundary(page_to_pseudophys(sg->page)
+                                                 + sg->offset, sg->length)
+                   || address_needs_mapping(hwdev, dev_addr)) {
                        buffer.page   = sg->page;

This is still present in linux-2.6.18-xen.hg's lib/swiotlb-xen.c; but it
seems to conflict with a different test that we use when we merge bios
together for multi-page disk IO, where we have

include/asm-x86_64/mach-xen/asm/io.h:
#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
#define page_to_phys(page)       (phys_to_machine(page_to_pseudophys(page)))
#define page_to_bus(page)        (phys_to_machine(page_to_pseudophys(page)))

#define bio_to_pseudophys(bio)   (page_to_pseudophys(bio_page((bio))) + \
                                  (unsigned long) bio_offset((bio)))
#define bvec_to_pseudophys(bv)   (page_to_pseudophys((bv)->bv_page) + \
                                  (unsigned long) (bv)->bv_offset)

#define BIOVEC_PHYS_MERGEABLE(vec1, vec2)       \
        (((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) && \
         ((bvec_to_pseudophys((vec1)) + (vec1)->bv_len) == \
          bvec_to_pseudophys((vec2))))

This test in io.h basically means that bios can, and will, span page
boundaries if the pages in question are both physical- and machine-
contiguous; but the range_straddles_page_boundary test does NOT check
for machine-contiguous pages (it only tests whether pages are in a
xen_create_contiguous_region() region, not whether pages happen to be
contiguous by chance in non-guaranteed-contig regions.)

So we'll create bios which span multiple pages, assuming that that's
more efficient; but then we'll force them to be copied because they span
multiple pages!

Have I missed something, or is this an oversight in the swiotlb.c patch
above?

The reason I discovered this is that including the patch seems to be
causing SWIOTLB overflows on some hardware.  Adding an extra test to
swiotlb_map_sg() to catch sg segments which are truly machine-contig and
don't need mapping, and avoid copying those, cures those symptoms for
me, but I suspect there may be other issues lurking in this area.

Cheers,
 Stephen



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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