Date: Wed, 29 Jul 2009 13:23:46 -0400 From: "Chris Harrer" <cjharrer@comcast.net> To: "'Alfred Perlstein'" <alfred@freebsd.org>, "'John Baldwin'" <jhb@freebsd.org> Cc: freebsd-drivers@freebsd.org Subject: RE: Driver development question Message-ID: <000c01ca1071$54991d70$fdcb5850$@net> In-Reply-To: <20090725035643.GT49724@elvis.mu.org> References: <002801ca06f0$b1d42af0$157c80d0$@net> <200907211743.12667.jhb@freebsd.org> <20090722000713.GZ49724@elvis.mu.org> <200907220819.05087.jhb@freebsd.org> <20090725035643.GT49724@elvis.mu.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Warning LONG message below, I figured I'd give as much information as possible to try and help me along. > On Tuesday 21 July 2009 8:07:13 pm Alfred Perlstein wrote: > > * John Baldwin <jhb@freebsd.org> [090721 14:44] wrote: > > > On Tuesday 21 July 2009 2:34:21 am Marc Loerner wrote: > > > > Am Dienstag 21 Juli 2009 00:38:56 schrieb Sam Leffler: > > > > > John Baldwin wrote: > > > > > > On Friday 17 July 2009 11:10:17 am Chris Harrer wrote: > > > > > >> Hi All, > > > > > >> > > > > > >> I'm hoping someone can point me in the right direction... I'm > > > > > >> developing a FreeBSD driver for a PCIe card. The driver controls a > > > > > >> hardware device that has DRAM and various state information on it. > I'm > > > > > >> trying to mimic functionality I have for other OS support such that > I > > > > > >> can dump memory and state information from the card to a file I > create > > > > > >> from within my driver (kernel module). > > > > > >> > > > > > >> For example, in a Linux driver I use filp_open to create the dump > file > > > > > >> (represented by fp), then use fp->f_op->write to put information > into > > > > > >> the file. > > > > > >> > > > > > >> FreeBSD doesn't have filp_* API's. I've tried searching for > example > > > > > >> drivers and googling for file API's from kernel modules to no > avail. > > > > > >> Can someone please offer some guidance as to how I might proceed > here? > > > > > >> > > > > > >> Thanks in advance and any insight would be most appreciated! > > > > > > > > > > > > You can look at sys/kern/kern_ktrace.c to see how the ktrace() > system > > > > > > call creates a file. I think in general you will wind up using > > > > > > NDINIT/namei() (to lookup the vnode for a pathname) and then > vn_open() / > > > > > > vn_rdwr() / vn_close(). > > > > > > > > > > man alq(9). > > > > > > > > > > > > > > > > > > Why not use kern_open, kern_close, kern_preadv, kern_pwritev? > > > > > > Those affect the state of the current process by opening a new file > > > descriptor, etc. That is generally bad practice for a device driver to be > > > interfering with a process' state, and it will not work for kernel > threads. > > > You can rather easily have userland open a file and then pass the file > > > descriptor to a driver which can then do operations on a file directly. > > > > If the vnode operations are annoying to wrap ones head around, one > > could have the driver defer this this to a kernel resident process > > that the driver would create on attach. > > Kernel processes don't have file descriptor tables. Hi All, I'm hoping you can provide a bit more guidance here as I'm still struggling with this and I'm running out of ideas. Again, what I want to do is, some event (interrupt from an intelligent PCIe card indicating it's "dead") will cause me to: 1) Open/create a file 2) write raw/random/non-patterned/variable sized data to the file 3) close/save the file from within my device driver. To this point, I've tried several things using vn_open, vn_open_cred, alq_open and cutting/massaging the code from alq_open with no success. I've done this from within the context of my interrupt handler as well as a timer (callout_init, callout_reset) thread as well as from a thread I create with kproc_create. In each and every instance, I get the following crash: (gdb) bt 15 #0 _mtx_lock_flags (m=0xc0, opts=0x0, file=0xffffffff80611dc0 "/src/FreeBSD/HECTOR/src/sys/kern/vfs_subr.c", line=0x847) at /src/FreeBSD/HECTOR/src/sys/kern/kern_mutex.c:195 #1 0xffffffff803c8431 in vref (vp=0x0) at /src/FreeBSD/HECTOR/src/sys/kern/vfs_subr.c:2119 #2 0xffffffff803c02de in namei (ndp=0xffffff80003bfdf2) at /src/FreeBSD/HECTOR/src/sys/kern/vfs_lookup.c:229 #3 0xffffffff803d6100 in vn_open_cred (ndp=0xffffff80003bfdf2, flagp=0xffffff8000045a2c, cmode=0x180, cred=0xffffff00014d5000, fp=0x0) at /src/FreeBSD/HECTOR/src/sys/kern/vfs_vnops.c:133 #4 0xffffffff8023497a in sxg_dump_open_file (adapter=0xffffff80003b4000) at /src/FreeBSD/HECTOR/src/sys/dev/sxg/sxg.c:5064 #5 0xffffffff8023524a in sxg_dump_thread (arg=<value optimized out>) at /src/FreeBSD/HECTOR/src/sys/dev/sxg/sxg.c:5170 #6 0xffffffff80235398 in sxg_check_for_hang_timer (arg1=<value optimized out>) at /src/FreeBSD/HECTOR/src/sys/dev/sxg/sxg.c:4956 #7 0xffffffff80350741 in softclock (arg=<value optimized out>) at /src/FreeBSD/HECTOR/src/sys/kern/kern_timeout.c:411 #8 0xffffffff80318b08 in intr_event_execute_handlers (p=<value optimized out>, ie=0xffffff00014d5600) at /src/FreeBSD/HECTOR/src/sys/kern/kern_intr.c:1146 #9 0xffffffff80319762 in ithread_loop (arg=0xffffff00014da8a0) at /src/FreeBSD/HECTOR/src/sys/kern/kern_intr.c:1159 #10 0xffffffff80316a9a in fork_exit (callout=0xffffffff803196b0 <ithread_loop>, arg=0xffffff00014da8a0, frame=0xffffff8000045c90) at /src/FreeBSD/HECTOR/src/sys/kern/kern_fork.c:829 #11 0xffffffff8054dd5e in fork_trampoline () at /src/FreeBSD/HECTOR/src/sys/amd64/amd64/exception.S:552 #12 0x0000000000000000 in ?? () The offending "SIGSEGV, Segmentation fault" is from the following code (frame 2): if (dp == NULL) { dp = fdp->fd_cdir; <----- fdp->fd_cdir = 0 VREF(dp); FILEDESC_SUNLOCK(fdp); if (ndp->ni_startdir != NULL) { vfslocked = VFS_LOCK_GIANT(ndp->ni_startdir->v_mount); vrele(ndp->ni_startdir); VFS_UNLOCK_GIANT(vfslocked); } } The *fdp structure looks like: (gdb) print *fdp $4 = { fd_ofiles = 0xffffff0001345680, fd_ofileflags = 0xffffff0001345720 "", fd_cdir = 0x0, fd_rdir = 0x0, fd_jdir = 0x0, fd_nfiles = 0x14, fd_map = 0xffffff0001345738, fd_lastfile = 0xffffffff, fd_freefile = 0x0, fd_cmask = 0x12, fd_refcnt = 0x1, fd_holdcnt = 0x1, fd_sx = { lock_object = { lo_name = 0xffffffff805fc20d "filedesc structure", lo_flags = 0x2330000, lo_data = 0x0, lo_witness = 0xffffff8000206c00 }, sx_lock = 0x11 }, fd_kqlist = { slh_first = 0x0 }, fd_holdleaderscount = 0x0, fd_holdleaderswakeup = 0x0 } In this particular instance, I created a nameidata structure via NDINIT that is: (gdb) print *ndp $2 = { ni_dirp = 0xffffff8000045a30 "/var/tmp/sxgdump", ni_segflg = UIO_SYSSPACE, ni_startdir = 0x0, ni_rootdir = 0x0, ni_topdir = 0x0, ni_dirfd = 0xffffff9c, ni_vp = 0x0, ni_dvp = 0x0, ni_pathlen = 0x11, ni_next = 0x0, ni_loopcnt = 0x0, ni_cnd = { cn_nameiop = 0x1, cn_flags = 0x520000c, cn_thread = 0xffffff00014eb390, cn_cred = 0xffffff00014d5000, cn_lkflags = 0x0, cn_pnbuf = 0xffffff000620c000 "/var/tmp/sxgdump", cn_nameptr = 0x0, cn_namelen = 0x0, cn_consume = 0x0 } } I appreciate the guidance you've given to date and I hope you can provide a few more words of wisdom to me. Thanks in advance! Chris
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?000c01ca1071$54991d70$fdcb5850$>