From owner-freebsd-i386@FreeBSD.ORG Tue Feb 1 09:40:11 2005 Return-Path: Delivered-To: freebsd-i386@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B725216A4CE for ; Tue, 1 Feb 2005 09:40:11 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5A8E743D46 for ; Tue, 1 Feb 2005 09:40:11 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.1/8.13.1) with ESMTP id j119eBDq042628 for ; Tue, 1 Feb 2005 09:40:11 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.1/8.13.1/Submit) id j119eBnq042626; Tue, 1 Feb 2005 09:40:11 GMT (envelope-from gnats) Resent-Date: Tue, 1 Feb 2005 09:40:11 GMT Resent-Message-Id: <200502010940.j119eBnq042626@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-i386@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Petr Lampa Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4F30716A4CF for ; Tue, 1 Feb 2005 09:32:29 +0000 (GMT) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4139243D62 for ; Tue, 1 Feb 2005 09:32:27 +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 j119WQVR072721 for ; Tue, 1 Feb 2005 09:32:26 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.13.1/8.13.1/Submit) id j119WQ8r072690; Tue, 1 Feb 2005 09:32:26 GMT (envelope-from nobody) Message-Id: <200502010932.j119WQ8r072690@www.freebsd.org> Date: Tue, 1 Feb 2005 09:32:26 GMT From: Petr Lampa To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.3 Subject: i386/76944: i386 bus_dmamap_create() bug X-BeenThere: freebsd-i386@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: I386-specific issues for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Feb 2005 09:40:11 -0000 >Number: 76944 >Category: i386 >Synopsis: i386 bus_dmamap_create() bug >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-i386 >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Feb 01 09:40:10 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Petr Lampa >Release: 5.3-STABLE >Organization: BUT FIT >Environment: FreeBSD 5.3-STABLE FreeBSD 5.3-STABLE #16: Fri Jan 28 14:26: 51 CET 2005 /usr/src/sys/i386/compile/VIDEO1 i386 >Description: Bus_dmamap_create() fails when more then MAX_BPAGES bounce pages is already allocated. The result is panic or page fault during boot. bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) { .. maxpages = MIN(MAX_BPAGES, Maxmem - atop(dmat->lowaddr)); if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 || (dmat->map_count > 0 && total_bpages < maxpages)) { int pages; ... pages = MAX(atop(dmat->maxsize), 1); At this location maxpages=512, total_bpages=513, dmat->maxsize=131072, pages=32 pages = MIN(maxpages - total_bpages, pages); Here pages=-1! if (alloc_bounce_pages(dmat, pages) < pages) if (alloc_bounce_pages(dmat, pages) < pages) error = ENOMEM; Here all kernel virtual memory is lost (or something like that), the result was spurious page fault 12 or other panic after while. I've loooked in CVS and it seems to me, that bus_dmamap_create() was not updated after introduction of bounce zones. The first test that leads to alloc_bounce_pages() is wrong in any case. >How-To-Repeat: Insert two 3Ware 9500 controllers into machine and boot. Page fault 12 results. >Fix: I've tried to fixed this and my solution works for me, but it needs some inspection. The same problem probably exists in other architectures. fix #1: change parenthesis here (I'am no sure, but the next code only add pages when there are not sufficient pages allocated, so it shouldn't be called if total_bpages>=maxpages at all): if (((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 || dmat->map_count > 0) && total_bpages < maxpages)) { fix #2: don't check total_bpages, but bounce zone's bz->total_bpages bz = dmat->bounce_zone; if (((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 || dmat->map_count > 0) && bz->total_bpages < maxpages)) { ... pages = MIN(maxpages - bz->total_bpages, pages); The whole patch is here: *** busdma_machdep.c Sat Dec 4 06:55:10 2004 --- /tmp/busdma_machdep.c Fri Jan 28 10:37:35 2005 *************** *** 393,403 **** --- 393,405 ---- /* Must bounce */ int maxpages; + struct bounce_zone *bz; if (dmat->bounce_zone == NULL) { if ((error = alloc_bounce_zone(dmat)) != 0) return (error); } + bz = dmat->bounce_zone; *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, M_NOWAIT | M_ZERO); *************** *** 415,422 **** * basis up to a sane limit. */ maxpages = MIN(MAX_BPAGES, Maxmem - atop(dmat->lowaddr)); ! if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 ! || (dmat->map_count > 0 && total_bpages < maxpages)) { int pages; if (dmat->lowaddr > bounce_lowaddr) { --- 417,424 ---- * basis up to a sane limit. */ maxpages = MIN(MAX_BPAGES, Maxmem - atop(dmat->lowaddr)); ! if (((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 ! || dmat->map_count > 0) && bz->total_bpages < maxpages) { int pages; if (dmat->lowaddr > bounce_lowaddr) { *************** *** 428,434 **** "not implemented"); } pages = MAX(atop(dmat->maxsize), 1); ! pages = MIN(maxpages - total_bpages, pages); if (alloc_bounce_pages(dmat, pages) < pages) error = ENOMEM; --- 430,436 ---- "not implemented"); } pages = MAX(atop(dmat->maxsize), 1); ! pages = MIN(maxpages - bz->total_bpages, pages); if (alloc_bounce_pages(dmat, pages) < pages) error = ENOMEM; >Release-Note: >Audit-Trail: >Unformatted: