Subject: Proposal to alter VM interfaces for bus.h mmap support
To: None <tech-kern@NetBSD.ORG>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-kern
Date: 09/03/1997 14:59:33
Hi folks.

As you know, one of the design considerations in the bus_dma interface
was to support mapping of DMA buffers directly into userspace.  One of
the most obvious applications here is for audio devices (we currently
use a machine-dependent kludge to support mmap methods on audio devices).
Frame grabbers are another obvious application.  High-speed, low-latency
message passing for massively parallel systems is yet another.

To accompany this, we also want a method of mmap'ing memory-like bus
space.  A good example of this would be frame buffers.  Another example
is userspace implementations of bus_space_*() methods on architectures
like the Alpha.

Unfortunately, the VM system's mmap interfaces are deficient for this.
Well, more clumsy, than anything.

Currently, a device's d_mmap entry point returns an overloaded value.
Within that value is the page frame number and some opaque information
used by some pmap's to identify the "space" in which that page frame
lives; a good example is the space identifiers used by the SPARC and
Sun 3 ports.

This makes it impossible to write machine-independent drivers that
have mmap entry points.

The bus_dmamem_mmap() (and, eventually, bus_space_mmap()) function is
provided to compute the page frame number and the opaque information
passed to the VM system.

Anyway, I'd like to clean this interface up somewhat.  I'd like to
propose the following:

	(1) Create a new machine-dependent VM type: vm_space_t.  This
	    will be used only by machine-dependent code, but values
	    will be transported through the MI VM system.  There will
	    be one magic value: VM_SPACE_MEMORY, which will be the
	    VM space value used for managed pages.

	(2) Alter the interface to pmap_enter() in the following
	    way:

void	pmap_enter_space __P((pmap_t, vm_offset_t va, vm_offset_t pa,
	    vm_space_t space, vm_prot_t prot, boolean_t wired));
#define	pmap_enter(pmap, va, pa, prot, wired) \
	pmap_enter_space((pmap), (va), (pa), VM_SPACE_MEMORY, (prot), (wired))

	    Also alter similar interfaces (e.g. pmap_map()) in the same
	    way.  This eliminates the overloading of "pa" argument.
	    (For an example of how it's overloaded, look at the Sun 3's
	    pmap_enter() function.)

	(3) Alter the d_mmap driver entry point interface in the following
	    way:

From:
	int	(*d_mmap) __P((dev_t dev, int off, int prot));
To:
	int	(*d_mmap) __P((dev_t dev, vm_offset_t off, int prot,
		    vm_offset_t *pap, vm_space_t *spacep));

	    The "int" return value is interpreted as an error code; 0
	    for success, an errno value otherwise.  The "pap" argument
	    is filled in with the physical address to pass to
	    pmap_enter_space() (also used in the fake vm_page that is
	    created).  The "spacep" argument is filled in, and merely
	    passed on by the VM system to pmap_enter_space().
	    
	    With this interface change, the Sun 3 cg2 driver's mmap
	    routine would look like this:

int
cg2mmap(dev, off, prot, pap, spacep)
	dev_t dev;
	vm_offset_t off;
	int prot;
	vm_offset_t *pap;
	vm_space_t *spacep;
{
	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];

	if (off & PGOFSET)
		panic("cg2mmap");  

	if (off >= CG2_MAPPED_SIZE)
		return (EINVAL);

	*pap = sc->sc_phys + off;
	*spacep = sc->sc_pmtype;
	return (0);
}

	    Note, I'm using the Sun 3 because it demonstrates the
	    issues well.  For machine-independent drivers, pap
	    and spacep will be filled in by bus_dmamem_mmap() and/or
	    bus_space_mmap().

	    Note that the interface to bus_dmamem_mmap() must change
	    to:

int	bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
	    int nsegs, vm_offset_t off, int prot, int flags,
	    vm_offset_t *pap, vm_space_t *spacep));
	    
	    It is expected that *spacep will always get the value
	    VM_SPACE_MEMORY in the bus_dmamem_mmap() case, but is
	    passed for consistency.

	    Note that this renders pmap_phys_address() obsolete.

Thoughts?  I'd like to address this ASAP, since there is a project here
that is going to need this relatively soon.

Jason R. Thorpe                                       thorpej@nas.nasa.gov
NASA Ames Research Center                            Home: +1 408 866 1912
NAS: M/S 258-6                                       Work: +1 415 604 0935
Moffett Field, CA 94035                             Pager: +1 415 428 6939