mmap_device_memory()

Updated: April 19, 2023

Map a device's physical memory into a process's address space

Synopsis:

#include <stdint.h>
#include <sys/mman.h>

void * mmap_device_memory( void * addr,
                           size_t len,
                           int prot,
                           int flags,
                           uint64_t physical );

Arguments:

addr
NULL, or a pointer to where you want to map the object in the calling process's address space.
len
The number of bytes you want to map into the caller's address space. It can't be 0.
prot
The access capabilities that you want to use for the memory region being mapped. You can use a combination of at least the following protection bits, as defined in <sys/mman.h>:
  • PROT_EXEC — the region can be executed.
    Note: To successfully use this flag:
    • Your process must have the PROCMGR_AID_PROT_EXEC ability enabled. For more information, see procmgr_ability().
  • PROT_NOCACHE — disable the caching of the region (e.g. to access dual-ported memory).
    Note:
    • Read the architecture guide for your processor; you may need to add special instructions.
    • On 32- and 64-bit ARM targets, PROT_NOCACHE causes RAM to be mapped as normal noncached, but non-RAM to be mapped as strongly ordered device memory. For finer control, see shm_ctl_special().
  • PROT_NONE — the region can't be accessed.
  • PROT_READ — the region can be read.
  • PROT_WRITE — the region can be written.
    Note: In order to simultaneously set PROT_EXEC and PROT_WRITE, your process must have the PROCMGR_AID_PROT_WRITE_AND_EXEC ability enabled (in addition to PROCMGR_AID_PROT_EXEC). For more information, see procmgr_ability().
flags
Specifies further information about handling the mapped region. You can use the following flag:
  • MAP_FIXED

This function already uses MAP_SHARED ORed with MAP_PHYS (see mmap() for a description of these flags).

physical
The physical address of the memory to map into the caller's address space.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The mmap_device_memory() function maps len bytes of a device's physical memory address into the caller's address space at the location returned by mmap_device_memory(). It's a simple wrapper for mmap():

return mmap(addr, len, prot, (flags & ~MAP_TYPE) | MAP_PHYS|MAP_SHARED, NOFD, physical);
Note: In order to map physical memory, your process must have the PROCMGR_AID_MEM_PHYS ability enabled. For more information, see procmgr_ability().

Typically, you don't need to use addr; you can just pass NULL instead. If addr isn't NULL value, whether the object is mapped depends on whether or not you set MAP_FIXED in flags:

MAP_FIXED is set
The object is mapped to the address in addr, or the function fails. If this area is already mapped, the call changes the existing mapping of the area. A memory area being mapped with MAP_FIXED is first unmapped by the system using the same memory area. See munmap() for details.
Note:
  • In order to use MAP_FIXED, your process must have the PROCMGR_AID_MAP_FIXED ability enabled. For more information, see procmgr_ability().
  • Use MAP_FIXED with caution. Not all memory models support it. In general, you should assume that you can MAP_FIXED only at an address (and size) that a call to mmap() without MAP_FIXED returned.
MAP_FIXED isn't set

The value of addr is taken as a hint as to where to map the object in the calling process's address space. The mapped area won't overlay any current mapped areas.

Refer to the MAP_BELOW description in mmap() for information on what happens if the hint in addr can't be followed.

Returns:

The address of the mapped-in object, or MAP_FAILED if an error occurs (errno is set).

Errors:

EINVAL
Invalid flags type, or len is 0.
ENOMEM
The address range requested is outside of the allowed process address range, or there wasn't enough memory to satisfy the request.
ENXIO
The address from physical for len bytes is invalid for the requested object, or MAP_FIXED was specified and addr, len, and physical are invalid for the requested object.
EPERM
The calling process doesn't have the required permission (see procmgr_ability()), or it attempted to set PROT_EXEC for a region of memory covered by an untrusted memory-mapped file.

Examples:

/* Map in the physical memory; 0xb8000 is text mode VGA video memory */
    
ptr = mmap_device_memory( 0, len, PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, 0xb8000 );
if ( ptr == MAP_FAILED ) {
    perror( "mmap_device_memory for physical address 0xb8000 failed" );
    exit( EXIT_FAILURE );
}

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes