Date: Wed, 1 Mar 2006 00:54:48 GMT From: Kaustubh Patil <kpatil@vmware.com> To: freebsd-gnats-submit@FreeBSD.org Subject: amd64/93961: Problem in bounce buffer handling in sys/amd64/amd64/busdma_machdep.c: _bus_dmamap_load_buffer() Message-ID: <200603010054.k210smRw018166@www.freebsd.org> Resent-Message-ID: <200603010100.k2110KwC008276@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 93961 >Category: amd64 >Synopsis: Problem in bounce buffer handling in sys/amd64/amd64/busdma_machdep.c: _bus_dmamap_load_buffer() >Confidential: no >Severity: critical >Priority: medium >Responsible: freebsd-amd64 >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Mar 01 01:00:20 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Kaustubh Patil >Release: 5.3-64 >Organization: VMware, Inc. >Environment: >Description: A couple of us have observed this problem with 5.3-64 bit version on a high memmory machine (> 4GiB memory), but a look at the current code indicates that the bug might be present in recent branches as well. _bus_dmamap_load_buffer() first calculates the number of pages that need to be bounced. vaddr = trunc_page((vm_offset_t)buf); ---------- (1) vendaddr = (vm_offset_t)buf + buflen; while (vaddr < vendaddr) { paddr = pmap_kextract(vaddr); ---------- (2) if (run_filter(dmat, paddr) != 0) { ---------- (3) needbounce = 1; map->pagesneeded++; ---------- (4) } vaddr += PAGE_SIZE; } Consider a dma-map that is set up to indicate the need to bounce o if the address is in high memory or o if the address is not page-aligned. (1) The above code uses trunc_page() on the input virtual address. (2) This page-aligned address is passed to pmap_kextract(), which returns a page-aligned paddr ... (3) ... which is passed to run_filter(). As the paddr is page-aligned, run_filter() finds it okay as far as the page-alignment requirement is concerned. (4) The count obtained is stored in "map->pagesneeded". Later the function starts allocating bounce pages. However unlike the above code the allocation code does not align virtual addresses, so run_filter() call catches the input paddr if it is not page-aligned, then a bounce page is allocated for it using add_bounce_page() and "map->pagesneeded" is decremented. Thus this code consumes "map->pagesneeded" for a virtual address that was not initially identified for bouncing. This potentially leads to other needy pages not being bounced. In our scenario this bug caused the mpt driver to pass incorrectly truncated 32-bit addresses in the scatter-gather list, because the data buffer in the high memory (> 4Gib) was not bounced to < 4Gib memory. -- Vyacheslav Malyugin, Kaustubh Patil >How-To-Repeat: >Fix: The use of trunc_page() in the counting code seems questionable. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603010054.k210smRw018166>