Date: Tue, 2 Jun 2009 11:10:39 -0400 From: John Baldwin <jhb@freebsd.org> To: Andrew Gallatin <gallatin@cs.duke.edu> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r193275 - in head/sys: kern sys vm Message-ID: <200906021110.40347.jhb@freebsd.org> In-Reply-To: <4A253627.4090505@cs.duke.edu> References: <200906012132.n51LWq2U092924@svn.freebsd.org> <4A253627.4090505@cs.duke.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday 02 June 2009 10:24:39 am Andrew Gallatin wrote: > John Baldwin wrote: > > Author: jhb > > Date: Mon Jun 1 21:32:52 2009 > > New Revision: 193275 > > URL: http://svn.freebsd.org/changeset/base/193275 > > > > Log: > > Add an extension to the character device interface that allows character > > device drivers to use arbitrary VM objects to satisfy individual mmap() > > requests. > > Is there an example usage of this? Was this one of the things that > Nvidia asked for? Yes, this is for Nvidia. I have a bizarr-o test device in //depot/user/jhb/pat/modules/patdev/patdev.c. It exports a single anonymous memory object for mappings that use an offset at page 0 and a OBJT_SG (new type of VM object) object that maps the local APIC for mappings that use an offset at page 1. It's d_mmap_single() routine looks like this: static int pat_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size, vm_object_t *object, int nprot) { struct patdev_softc *sc; int error; sc = dev->si_drv1; error = 0; sx_xlock(&sc->lock); switch (*offset) { case 0: /* * The first mmap() attempt with an offset of 0 creates * a new memory object with the requested size. Subsequent * mmap()'s map the same object. */ if (sc->mem == NULL) { /* * Note that this does not wire any backing * pages. I could do that later before a DMA * was started by wiring pages (even just * using the userland mapping to do that) * while the DMA was in-progress and unwiring * them later. */ sc->mem = vm_pager_allocate(OBJT_DEFAULT, NULL, size, VM_PROT_DEFAULT, 0); VM_OBJECT_LOCK(sc->mem); vm_object_clear_flag(sc->mem, OBJ_ONEMAPPING); vm_object_set_flag(sc->mem, OBJ_NOSPLIT); vm_object_set_cache_mode(sc->mem, VM_CACHE_WRITE_COMBINING); VM_OBJECT_UNLOCK(sc->mem); } vm_object_reference(sc->mem); *object = sc->mem; break; case PAGE_SIZE: /* Map the local APIC. */ vm_object_reference(sc->sgobj); *object = sc->sgobj; *offset = 0; break; default: /* Use ENODEV to fallback to d_mmap(). */ error = EINVAL; break; } sx_xunlock(&sc->lock); return (error); } The 'sgobj' object is created when the module is loaded: static int pat_attach(struct patdev_softc *sc) { vm_offset_t va; int rv; bzero(sc, sizeof(*sc)); sx_init(&sc->lock, "patdev"); sc->cdev = make_dev(&pat_devsw, 0, UID_ROOT, GID_WHEEL, 0640, "pat"); sc->cdev->si_drv1 = sc; /* Create a scatter/gather list that maps the local APIC. */ sc->sg = sglist_alloc(1, M_WAITOK); sglist_append_phys(sc->sg, lapic_paddr, LAPIC_LEN); /* Create a VM object that is backed by the scatter/gather list. */ sc->sgobj = vm_pager_allocate(OBJT_SG, sc->sg, LAPIC_LEN, VM_PROT_READ, 0); VM_OBJECT_LOCK(sc->sgobj); vm_object_set_cache_mode(sc->sgobj, VM_CACHE_UNCACHEABLE); VM_OBJECT_UNLOCK(sc->sgobj); ... } -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906021110.40347.jhb>