svn commit: r193275 - in head/sys: kern sys vm
John Baldwin
jhb at freebsd.org
Tue Jun 2 15:11:49 UTC 2009
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
More information about the svn-src-all
mailing list