Virtual Memory Address Region

NAME

vm_address_region - A contiguous region of a virtual memory address space

SYNOPSIS

Virtual Memory Address Regions (VMARs) represent contiguous parts of a virtual address space.

DESCRIPTION

VMARs are used by the kernel and user space to represent the allocation of an address space.

Every process starts with a single VMAR (the root VMAR) that spans the entire address space (see process_create). Each VMAR can be logically divided up into any number of non-overlapping parts, each representing a child VMARs, a virtual memory mapping, or a gap. Child VMARs are created using vmar_allocate. VM mappings are created using vmar_map.

VMARs have a hierarchical permission model for allowable mapping permissions. For example, the root VMAR allows read, write, and executable mapping. One could create a child VMAR that only allows read and write mappings, in which it would be illegal to create a child that allows executable mappings.

By default, all allocations of address space are randomized. At VMAR creation time, the caller can choose which randomization algorithm is used. The default allocator attempts to spread allocations widely across the full width of the VMAR. The alternate allocator, selected with MX_VM_FLAG_COMPACT, attempts to keep allocations close together within the VMAR, but at a random location within the range. It is recommended to use the default allocator.

VMARs optionally support a fixed-offset mapping mode (called specific mapping). This mode can be used to create guard pages or ensure the relative locations of mappings. Each VMAR may have the MX_VM_FLAG_CAN_MAP_SPECIFIC permission, regardless of whether or not its parent VMAR had that permission.

EXAMPLE

#include <magenta/syscalls.h>

/* Map this VMO into the given VMAR, with |before| bytes of unmapped guard space
   before it and |after| bytes after it.  */
mx_status_t map_with_guard(mx_handle_t vmar, size_t before, size_t after,
                           mx_handle_t vmo, uint64_t vmo_offset,
                           size_t mapping_len, uintptr_t* mapped_addr,
                           mx_handle_t* wrapping_vmar) {

    /* wrap around check elided */
    const size_t child_vmar_size = before + after + mapping_len;
    const uint32_t child_vmar_flags = MX_VM_FLAG_CAN_MAP_READ |
                                      MX_VM_FLAG_CAN_MAP_WRITE |
                                      MX_VM_FLAG_CAN_MAP_SPECIFIC;
    const uint32_t mapping_flags = MX_VM_FLAG_SPECIFIC |
                                   MX_VM_FLAG_PERM_READ |
                                   MX_VM_FLAG_PERM_WRITE;

    uintptr_t child_vmar_addr;
    mx_handle_t child_vmar;
    mx_status_t status = mx_vmar_allocate(vmar, 0, child_vmar_size,
                                          child_vmar_flags, &child_vmar,
                                          &child_vmar_addr);
    if (status != MX_OK) {
        return status;
    }

    status = mx_vmar_map(child_vmar, before, vmo, vmo_offset, mapping_len,
                         mapping_flags, mapped_addr);
    if (status != MX_OK) {
        mx_vmar_destroy(child_vmar);
        mx_handle_close(child_vmar);
        return status;
    }

    *wrapping_vmar = child_vmar;
    return MX_OK;
}

SEE ALSO

SYSCALLS