bus_map_resource

John Baldwin jhb at freebsd.org
Fri Apr 22 19:01:46 UTC 2016


Yet another extension I've long wanted to make to new-bus is to split out the 
part of bus_activate_resource() that establishes a valid mapping for use with 
bus_space_* (or the bus_* wrappers) from activating / detactivating.  In 
particular, making a resource "active" is orthogonal to having a mapping (e.g. 
for a PCI BAR, a resource is "active" if the appropriate IO or mem decoding 
bit is set in the device's command register.  Whether or not the CPU has a 
valid mapping for that range doesn't matter).

Secondly, there is a need to be able to specify optional parameters of 
mappings.  Some drivers may wish to only map a portion of a resource instead 
of all of it (e.g. the AGP driver wishes to only map the first page of the 
aperture instead of all of the aperture to avoid wasting a lot of KVA on 32-
bit systems).  Some drivers may wish to map a memory resource with non-default 
memory attributes (e.g. WC).

I have a strawman with an implementation on x86 to permit this.

In this model, a new RF_UNMAPPED flag is added that asks 
bus_activate_resource() to not setup the implicit mapping in 'struct 
resource'.  Instead, a driver requests explicit mappings via 
bus_map_resource() and is responsible for calling bus_unmap_resource() to tear 
them down.  A driver should allocate a 'struct resource_map' for each mapping 
(probably by putting it in its softc) and then passing a pointer to that 
object to both routines.  This structure's members are named so that you can 
use the bus_* convenience API on it the same way you can with 'struct 
resource' for the implicit mapping.

bus_map_resource() accepts an optional 'args' argument that defines optional 
properties of the mapping request.  A driver can request a mapping of a subset 
of a resource or a specific memory attribute.  The 'args' argument is defined 
as a structure headed by a size similar to the scheme Konstantin recently used 
for make_dev_s().

One use case for this is that I'd like to fix the NEW_PCIB bits in the PCI-PCI 
bridge driver to request a mapping in the subset of the resource on the 
"parent" bus for the mapping window used by a resource for a child device 
instead of passing up that child resource directly to the nexus.  The idea is 
that any bus driver that creates its own rman and resources should not be 
passing those resources up to any of its parents.

Another use case that would benefit from this are bridges that do address 
translations (such as the ThunderX Host-PCI bridge driver recently committed).  
It can allocate a resource from its parent representing the "parent" side of 
its resource window and request mappings for regions of that window 
corresponding to child resources when creating mappings of child resources.

What I'd like feedback on now is the API.  If we decide to go forward I would
also like help fixing bus drivers to use this.

Some sample code for mapping a resource that uses a WC mapping:

struct foo_softc {
	...
	struct resource *sc_regs_res;
	struct resource_map sc_regs;
	...
};

foo_attach(device_t dev)
{
	struct resource_map_request args;
	...

	sc->sc_regs_res = bus_alloc_resource(dev, ..., RF_ACTIVE |
	    RF_UNMAPPED);
	resource_init_map_request(&args, sizeof(args));
	args.memattr = VM_MEMATTR_WRITE_COMBINING;
	error = bus_map_resource(dev, SYS_RES_MEMORY, sc->regs_res,
	    &args, &sc->sc_regs);
	...
}

foo_something(struct foo_softc *sc)
{
	x = bus_read_4(&sc->sc_regs, MY_CSR);
}

foo_detach(device_t dev)
{

	bus_unmap_resource(dev, SYS_RES_MEMORY, sc->regs_res, &sc->sc_regs);
	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->regs_res),
	    sc->regs_res);
}

There is a review with the current WIP code that includes the API and an
implementation for x86.  It does not yet have manual page updates.

https://reviews.freebsd.org/D5237

-- 
John Baldwin


More information about the freebsd-arch mailing list