Writing Device Drivers

Exporting Kernel Memory to Applications

devmap_umem_setup(9F) is provided to export kernel memory to user applications. devmap_umem_setup(9F) must be called from the driver's devmap(9E) entry point:

int devmap_umem_setup(devmap_cookie_t handle, dev_info_t *dip,
    struct devmap_callback_ctl *callbackops, ddi_umem_cookie_t cookie,
    offset_t koff, size_t len, uint_t maxprot, uint_t flags,
    ddi_device_acc_attr_t *accattrp);
handle

Opaque structure used to describe the mapping

dip

Pointer to the device's dev_info structure.

callbackops

Pointer to a devmap_callback_ctl(9S) structure

cookie

Kernel memory cookie returned by ddi_umem_alloc(9F)

koff

Offset into the kernel memory specified by cookie

len

Length in bytes that is exported

maxprot

Specifies the maximum protection possible for the exported mapping

flags

Must be set to DEVMAP_DEFAULTS

accattrp

Pointer to a ddi_device_acc_attr(9S) structure

handle is a device-mapping handle that the system uses to identify the mapping. It is passed in by the devmap(9E) entry point. dip is a pointer to the device's dev_info structure. callbackops allows the driver to be notified of user events on the mapping. Most drivers set callbackops to NULL when kernel memory is exported.

koff and len specify a range within the kernel memory allocated by ddi_umem_alloc(9F). This range will be made accessible to the user's application mapping at the offset passed in by the devmap(9E) entry point. Usually the driver will pass the devmap(9E) offset directly to devmap_umem_setup(9F). The return address of mmap(2) will then map to the kernel address returned by ddi_umem_alloc(9F). koff and len must be page aligned.

maxprot enables the driver to specify different protections for different regions within the exported kernel memory. For example, one region might not allow write access by only setting PROT_READ and PROT_USER.

Example 12-3 shows how to export kernel memory to an application. The driver first checks if the requested mapping falls within the allocated kernel memory region. If a 64-bit driver receives a mapping request from a 32-bit application, the request is redirected to the second page of the kernel memory area. This ensures that only applications compiled to the same data model will share the same page.


Example 12-3 devmap_umem_setup(9F) Routine

static int
xxdevmap(dev_t dev, devmap_cookie_t handle, offset_t off, size_t len,
    size_t *maplen, uint_t model)
{
        struct xxstate *xsp;
        int    error;

        /* round up len to a multiple of a page size */
        len = ptob(btopr(len));
        /* check if the requested range is ok */
        if (off + len > ptob(1))
                return (ENXIO);
        xsp = ddi_get_soft_state(statep, getminor(dev));
        if (xsp == NULL)
                return (ENXIO);
    
        #ifdef  _MULTI_DATAMODEL
        if (ddi_model_convert_from(model) == DDI_MODEL_ILP32) {
                /* request from 32-bit application. Skip first page */
                off += ptob(1);
        }
        #endif  /* _MULTI_DATAMODEL */
        /* export the memory to the application */
        error = devmap_umem_setup(handle, xsp->dip, NULL, xsp->ucookie,
            off, len, PROT_ALL, DEVMAP_DEFAULTS, NULL);
        *maplen = len;
        return (error);
}