Date: Mon, 20 Aug 2001 17:05:14 -0700 (PDT) From: Joe DiMartino <joe@mirapoint.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/29915: kernel panics on interaction with mlock and mmap Message-ID: <200108210005.f7L05ES84446@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 29915 >Category: kern >Synopsis: kernel panics on interaction with mlock and mmap >Confidential: no >Severity: non-critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Aug 20 17:10:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Joe DiMartino >Release: 4.1-RELEASE >Organization: Mirapoint, Inc. >Environment: FreeBSD w-joe.pdx.mirapoint.com 4.1-RELEASE FreeBSD 4.1-RELEASE #0: Fri Jan 12 09:50:01 PST 2001 (no fixes present in 4.3-RELEASE) >Description: There appears to be a bad interaction between mmap'ed kernel addresses and mlock() that causes a VM panic upon exit. panic: vm_page_unwire: invalid wire count: 0 Program received signal SIGTRAP, Trace/breakpoint trap. Debugger (msg=0xc023165b "panic") at /usr/src/sys/i386/i386/db_interface.c:332 332 cndebugoff(); (kgdb) bt #0 Debugger (msg=0xc023165b "panic") at /usr/src/sys/i386/i386/db_interface.c:332 #1 0xc016601a in panic ( fmt=0xc0241600 "vm_page_unwire: invalid wire count: %d\n") at /usr/src/sys/kern/kern_shutdown.c:552 #2 0xc01e61df in vm_page_unwire (m=0xc04335c0, activate=1) at /usr/src/sys/vm/vm_page.c:1219 #3 0xc01de65c in vm_fault_unwire (map=0xd1669fc0, start=672096256, end=672100352) at /usr/src/sys/vm/vm_fault.c:981 #4 0xc01e11b0 in vm_map_entry_unwire (map=0xd1669fc0, entry=0xd1be1840) at /usr/src/sys/vm/vm_map.c:1713 #5 0xc01e12d2 in vm_map_delete (map=0xd1669fc0, start=0, end=3217031168) at /usr/src/sys/vm/vm_map.c:1803 #6 0xc01e1409 in vm_map_remove (map=0xd1669fc0, start=0, end=3217031168) at /usr/src/sys/vm/vm_map.c:1859 #7 0xc015e421 in exit1 (p=0xd1ba6300, rv=0) at /usr/src/sys/kern/kern_exit.c:216 #8 0xc015e1f9 in exit (p=0xd1ba6300, uap=0xd1c08f80) at /usr/src/sys/kern/kern_exit.c:103 #9 0xc0219a22 in syscall2 (frame={tf_fs = -1078001617, tf_es = -1078001617, tf_ds = -1078001617, tf_edi = 0, tf_esi = -1, tf_ebp = -1077937156, tf_isp = -775909420, tf_ebx = 672019876, tf_edx = 672019488, tf_ecx = -1077937224, tf_eax = 1, tf_trapno = 8, tf_err = 2, tf_eip = 671729148, tf_cs = 31, tf_eflags = 647, tf_esp = -1077937200, tf_ss = 47}) at /usr/src/sys/i386/i386/trap.c:1253 #10 0xc020b115 in Xint0x80_syscall () >How-To-Repeat: The following program will display this behaviour every time it is run. It does an nlist to extract the kernel virtual address for "boottime", mmap()'s that into the process address space and then mlock()'s the entire address space (including the mmap region). It panics on exit (see stack trace in Full Description). Of course, you have to have read permission on /dev/kmem. [I know I'm not supposed to submit code as plain text, but there was nowhere in the problem report form to submit a tarball.] --------- Begin source ---------- #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/time.h> #include <sys/sysctl.h> #include <sys/ticksinfo.h> #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/ipc.h> #include <paths.h> #include <nlist.h> #include <errno.h> typedef struct timeval timeval_t; static void mlock_as(void); static timeval_t getboottime(void); struct nlist timeaddr_nl[] = { { "boottime" }, { "" }, }; int main(int argc, char *argv[]) { timeval_t time1, time2; time1 = getboottime(); /* * lock all existing pages of user virtual space into memory. */ mlock_as(); time2 = getboottime(); printf("It took %ld:%03ld seconds to lock pages.\n", time2.tv_sec - time1.tv_sec, time2.tv_usec - time1.tv_usec); exit(0); } /* * void * mlock_as(void) * Lock all pages presently in existence in the address space of the * calling process into memory, such that we are immune to page-faults. */ static void mlock_as(void) { void *addr; size_t pagesize; char pagestate; size_t npages; pagesize = getpagesize(); npages = 0; addr = (void *)0; do { if (mincore(addr, pagesize, &pagestate) == -1 && errno == EINVAL) { /* We reached the end of user virtual space */ break; } (void)mlock(addr, pagesize); addr += pagesize; } while (addr != (void *)0); /* safety check for addr wrap */ } static volatile timeval_t *kboottime = 0; static timeval_t getboottime(void) { timeval_t now; if (kboottime == 0) { int nl; int kfd; off_t kbootaddr; printf("bootfile is: '%s'\n", getbootfile()); if ((nl = nlist(getbootfile(), timeaddr_nl)) == -1) { (void) perror("nlist failed"); exit(errno); } kbootaddr = (off_t)timeaddr_nl[0].n_value; printf("boottime addr is: 0x%qx\n", kbootaddr); /* * Map the kernel boottime into this processes address * space to avoid the syscall overhead for repeated use. */ kfd = open("/dev/kmem", O_RDONLY); kboottime = (timeval_t *)mmap((void *)NULL, sizeof(*kboottime), PROT_READ, MAP_NOCORE, kfd, kbootaddr); (void) close(kfd); if (kboottime == MAP_FAILED) { (void) perror("Cannot map kernel boottime"); fflush(stderr); exit(errno); } } now = *kboottime; return(now); } --------- End source ---------- >Fix: >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108210005.f7L05ES84446>