From owner-freebsd-amd64@FreeBSD.ORG Wed Mar 1 01:00:22 2006 Return-Path: X-Original-To: freebsd-amd64@hub.freebsd.org Delivered-To: freebsd-amd64@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 09EF016A420 for ; Wed, 1 Mar 2006 01:00:22 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id BF94643D48 for ; Wed, 1 Mar 2006 01:00:20 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k2110KKb008277 for ; Wed, 1 Mar 2006 01:00:20 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k2110KwC008276; Wed, 1 Mar 2006 01:00:20 GMT (envelope-from gnats) Resent-Date: Wed, 1 Mar 2006 01:00:20 GMT Resent-Message-Id: <200603010100.k2110KwC008276@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-amd64@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Kaustubh Patil Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4987F16A420 for ; Wed, 1 Mar 2006 00:54:49 +0000 (GMT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id C96F543D46 for ; Wed, 1 Mar 2006 00:54:48 +0000 (GMT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k210sm8O018167 for ; Wed, 1 Mar 2006 00:54:48 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.13.1/8.13.1/Submit) id k210smRw018166; Wed, 1 Mar 2006 00:54:48 GMT (envelope-from nobody) Message-Id: <200603010054.k210smRw018166@www.freebsd.org> Date: Wed, 1 Mar 2006 00:54:48 GMT From: Kaustubh Patil To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.3 Cc: Subject: amd64/93961: Problem in bounce buffer handling in sys/amd64/amd64/busdma_machdep.c: _bus_dmamap_load_buffer() X-BeenThere: freebsd-amd64@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting FreeBSD to the AMD64 platform List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Mar 2006 01:00:22 -0000 >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: