From owner-freebsd-hackers Mon Nov 2 18:34:03 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id SAA22682 for freebsd-hackers-outgoing; Mon, 2 Nov 1998 18:34:03 -0800 (PST) (envelope-from owner-freebsd-hackers@FreeBSD.ORG) Received: from heathers.stdio.com (heathers.stdio.com [199.89.192.5]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id SAA22401 for ; Mon, 2 Nov 1998 18:33:03 -0800 (PST) (envelope-from lile@stdio.com) Received: from localhost (lile@localhost) by heathers.stdio.com (8.8.8/8.8.8) with SMTP id VAA18013 for ; Mon, 2 Nov 1998 21:35:37 -0500 (EST) (envelope-from lile@heathers.stdio.com) Date: Mon, 2 Nov 1998 21:35:37 -0500 (EST) From: "Larry S. Lile" To: hackers@FreeBSD.ORG Subject: "panic: free: multiple frees" VM bug? (long) Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG I am working on a token ring driver and I cannot seem to find out why this is happening. I contigmalloc buffers for tranmsitting frames and then free them later when they have been transmitted. I have to use contigmalloc in order to get buffers below the 16M mark for dma. Anyone see what is wrong? Should I not do this? Or have I stumbled over a vm bug? It looks like a vm bug to me, but I have been wrong before. All pertinent information below... Larry Lile lile@stdio.com Please ignore the soft-updates panic, I understand that happens sometimes during a dump. panicstr: page fault panic messages: --- panic: free: multiple frees syncing disks... Fatal trap 12: page fault while in kernel mode fault virtual address = 0x30 fault code = supervisor read, page not present instruction pointer = 0x8:0xf01cdf08 stack pointer = 0x10:0xf024bf14 frame pointer = 0x10:0xf024bf18 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, def32 1, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = Idle interrupt mask = net tty bio cam trap number = 12 panic: page fault --- #0 boot (howto=260) at ../../kern/kern_shutdown.c:268 268 dumppcb.pcb_cr3 = rcr3(); (kgdb) bt #0 boot (howto=260) at ../../kern/kern_shutdown.c:268 #1 0xf014932f in panic (fmt=0xf0242de9 "page fault") at ../../kern/kern_shutdown.c:430 #2 0xf01f796d in trap_fatal (frame=0xf024bed8) at ../../i386/i386/trap.c:879 #3 0xf01f7648 in trap_pfault (frame=0xf024bed8, usermode=0) at ../../i386/i386/trap.c:772 #4 0xf01f72a7 in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = 0, tf_esi = -252868608, tf_ebp = -266027240, tf_isp = -266027264, tf_ebx = -265970844, tf_edx = -1073217472, tf_ecx = 0, tf_eax = 0, tf_trapno = 12, tf_err = 0, tf_eip = -266543352, tf_cs = 8, tf_eflags = 66182, tf_esp = -252868608, tf_ss = -266027208}) at ../../i386/i386/trap.c:396 #5 0xf01cdf08 in acquire_lock (lk=0xf0259b64) at ../../ufs/ffs/ffs_softdep.c:268 #6 0xf01d1929 in softdep_update_inodeblock (ip=0xf0ed8800, bp=0xf368ac30, waitfor=0) at ../../ufs/ffs/ffs_softdep.c:3482 #7 0xf01ccf1c in ffs_update (vp=0xf5ddc0c0, access=0xf024bfd0, modify=0xf024bfd0, waitfor=0) at ../../ufs/ffs/ffs_inode.c:109 #8 0xf01d5f59 in ffs_fsync (ap=0xf024c00c) at ../../ufs/ffs/ffs_vnops.c:252 #9 0xf01d4383 in ffs_sync (mp=0xf0e40a00, waitfor=2, cred=0xf0dd3700, p=0xf028a04c) at vnode_if.h:499 #10 0xf016b2a7 in sync (p=0xf028a04c, uap=0x0) at ../../kern/vfs_syscalls.c:527 #11 0xf0148faa in boot (howto=256) at ../../kern/kern_shutdown.c:201 #12 0xf014932f in panic (fmt=0xf023723e "free: multiple frees") at ../../kern/kern_shutdown.c:430 #13 0xf0146553 in free (addr=0xf5e62000, type=0xf0251980) at ../../kern/kern_malloc.c:334 #14 0xf01febe3 in DriverTransmitFrameCompleted (DriverHandle=0x0, FrameHandle=0xa, TransmitStatus=0) at ../../i386/isa/if_oltr.c:936 #15 0xf022b252 in ReturnCompletedBuffers () #16 0x30001 in ?? () cannot read proc at 0 (kgdb) up 14 #14 0xf01febe3 in DriverTransmitFrameCompleted (DriverHandle=0x0, FrameHandle=0xa, TransmitStatus=0) at ../../i386/isa/if_oltr.c:936 936 free(sc->tx_buffer[frame].frame->TransmitFragment[i].VirtualAddress, M_DEVBUF); (kgdb) list 931 printf("oltr%d: Unused buffer returned *boggle*\n", sc->unit); 932 } else { 933 for (i = 0; i < sc->tx_buffer[frame].frame->FragmentCount; i++) { 934 printf("oltr%d: freeing fragment %d frame %d\n", sc->unit, i, frame); 935 sc->tx_frags--; 936 free(sc->tx_buffer[frame].frame->TransmitFragment[i].VirtualAddress, M_DEVBUF); 937 } 938 } 939 940 printf("Oltr%d: %d total frags in use.\n", sc->unit, sc->tx_frags); (kgdb) I know that I have not called free on the same buffer twice by looking at the debug messages. Nov 2 21:11:43 anarchy /kernel: oltr0: output frame 0 - 1 fragments (1 fragments in use total) Nov 2 21:11:43 anarchy /kernel: iso88025_input: Packet queued. Nov 2 21:11:43 anarchy /kernel: oltr0: transmit complete frame 0 - 1 fragments (1 total fragments in use total) Nov 2 21:11:43 anarchy /kernel: oltr0: freeing fragment 0 frame 0 Nov 2 21:11:43 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:56 anarchy /kernel: oltr0: output frame 1 - 1 fragments (1 fragments in use total) Nov 2 21:11:56 anarchy /kernel: iso88025_input: Packet queued. Nov 2 21:11:56 anarchy /kernel: oltr0: transmit complete frame 1 - 1 fragments (1 total fragments in use total) Nov 2 21:11:56 anarchy /kernel: oltr0: freeing fragment 0 frame 1 Nov 2 21:11:56 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:56 anarchy /kernel: iso88025_input: Packet queued. Nov 2 21:11:56 anarchy /kernel: oltr0: output frame 2 - 2 fragments (2 fragments in use total) Nov 2 21:11:56 anarchy /kernel: oltr0: transmit complete frame 2 - 2 fragments (2 total fragments in use total) Nov 2 21:11:56 anarchy /kernel: oltr0: freeing fragment 0 frame 2 Nov 2 21:11:56 anarchy /kernel: oltr0: freeing fragment 1 frame 2 Nov 2 21:11:57 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:57 anarchy /kernel: iso88025_input: Packet queued. Nov 2 21:11:57 anarchy /kernel: oltr0: output frame 3 - 1 fragments (1 fragments in use total) Nov 2 21:11:57 anarchy /kernel: oltr0: transmit complete frame 3 - 1 fragments (1 total fragments in use total) Nov 2 21:11:57 anarchy /kernel: oltr0: freeing fragment 0 frame 3 Nov 2 21:11:57 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 4 - 2 fragments (2 fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 4 - 2 fragments (2 total fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 4 Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 4 Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:59 anarchy /kernel: iso88025_input: Packet queued. Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 5 - 2 fragments (2 fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 5 - 2 fragments (2 total fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 5 Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 5 Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 6 - 2 fragments (2 fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 6 - 2 fragments (2 total fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 6 Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 6 Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use. Nov 2 21:11:59 anarchy /kernel: iso88025_input: Packet queued. Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 7 - 2 fragments (2 fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 7 - 2 fragments (2 total fragments in use total) Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 7 Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 7 Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use. How the buffers get allocated: void * oltr_malloc(Size, Adapter) ssize_t Size; TRlldAdapterConfig_t *Adapter; { /* If the adapter needs memory below 16M for DMA then use contigmalloc */ if (Adapter->mode & TRLLD_MODE_16M) /* Adapter using ISA DMA buffer below 16M */ return(contigmalloc(Size, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, 1ul, 0x10000ul)); else return(malloc(Size, M_DEVBUF, M_NOWAIT)); } Where the frames get built: static void oltr_start(ifp) struct ifnet *ifp; { struct oltr_softc *sc = &oltr_softc[ifp->if_unit]; struct mbuf *m0, *m; struct iso88025_header *th; int len, i, j, k, rc, s; /*printf("oltr%d: oltr_start\n", sc->unit);*/ s = splimp(); /* Check to see if we have enough room to transmit */ if (sc->tx_avail <= 0) { /* No free buffers, hold off the upper layers */ /*printf("oltr%d: transmit queue full.\n", sc->unit);*/ ifp->if_flags |= IFF_OACTIVE; splx(s); return; } IF_DEQUEUE(&ifp->if_snd, m); if (m == 0) { printf("oltr%d: oltr_start NULL packet dequeued.\n", sc->unit); ifp->if_flags &= ~IFF_OACTIVE; splx(s); return; } th = mtod(m, struct iso88025_header *); th->ac = 0x10; th->fc = 0x40; /* Keep a pointer to the head of the packet */ m0 = m; i = (sc->tx_next & TX_LIST_MASK); /* Just to shorten thing up */ if (sc->tx_buffer[i].inuse) { printf("oltr%d: Transmit ring buffer blown!\n", sc->unit); oltr_stop(sc); splx(s); return; } for (len = 0, j = 0; m != 0; m = m->m_next, j++) { sc->tx_frags++; sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress = (char *)oltr_malloc(m->m_len, sc->config); if (!sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress) { printf("oltr%d: unable to allocate memory.\n", sc->unit); /* Free up the other fragments */ for (k = 0; k < j; k++) { sc->tx_frags--; free(sc->tx_buffer[i].frame->TransmitFragment[k].VirtualAddress, M_DEVBUF); } goto bad; } sc->tx_buffer[i].frame->TransmitFragment[j].PhysicalAddress = kvtop(sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAd dress); sc->tx_buffer[i].frame->TransmitFragment[j].count = m->m_len; bcopy(mtod(m, caddr_t), sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress, m->m_len); len += m->m_len; } sc->tx_buffer[i].frame->FragmentCount = j; sc->tx_buffer[i].inuse = 1; rc = TRlldTransmitFrame(sc->TRlldAdapter, (TRlldTransmit_t *)sc->tx_buffer[i].frame, (void *)sc->tx_buffer[i].index); if (rc != TRLLD_TRANSMIT_OK) { printf("oltr%d: TRlldTransmitFrame returned (%x)\n", sc->unit, rc); ifp->if_oerrors++; for (j = 0; j < sc->tx_buffer[i].frame->FragmentCount; j++) { sc->tx_frags--; free(sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress, M_DEVBUF); } sc->tx_buffer[i].inuse = 0; goto bad; } printf("oltr%d: output frame %d - %d fragments (%d fragments in use total)\n", sc->unit, i, sc->tx_buffer[i].frame->FragmentC ount, sc->tx_frags); sc->tx_next++; sc->tx_avail--; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp, m0); #endif bad: m_freem(m); splx(s); return; } Where they get freed; static void DriverCloseCompleted(DriverHandle) void *DriverHandle; { struct oltr_softc *sc = &oltr_softc[(int)DriverHandle]; /*printf("oltr%d: DriverCloseCompleted\n", sc->unit);*/ untimeout(oltr_timeout, (void *)sc->unit, sc->oltr_ch); wakeup_one((void *)sc->unit); if ((sc->hw_state != HW_CLOSING) && (sc->hw_state != HW_CLOSING2) && (sc->hw_state != HW_CLOSED)) { printf("oltr%d: adapter close complete called in wrong state (%d)\n", sc->unit, sc->hw_state); return; } sc->hw_state = HW_CLOSING2; if (sc->config->dmalevel != TRLLD_DMA_PIO) isa_dma_release(sc->config->dmalevel); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message