| VMEM(9) | Kernel Concepts | VMEM(9) | 
vmem — virtual
    memory allocator
An address space is divided into a number of logically distinct
    pieces, or
    arenas:
    text, data, heap, stack, and so on. Within these arenas we often subdivide
    further; for example, we use heap addresses not only for the kernel heap
    (kmem_alloc()
    space), but also for DVMA,
    bp_mapin(),
    /dev/kmem, and even some device mappings.
The kernel address space, therefore, is most accurately described as a tree of arenas in which each node of the tree imports some subset of its parent. The virtual memory allocator manages these arenas and supports their natural hierarchical structure.
An arena is nothing more than a set of integers. These integers most commonly represent virtual addresses, but in fact they can represent anything at all. For example, we could use an arena containing the integers minpid through maxpid to allocate process IDs. For uses of this nature, prefer id_space(9F) instead.
vmem_create()
    and
    vmem_destroy()
    create and destroy vmem arenas. In order to differentiate between arenas
    used for addresses and arenas used for identifiers, the
    VMC_IDENTIFIER flag is passed to
    vmem_create(). This prevents identifier exhaustion
    from being diagnosed as general memory failure.
We represent the integers in an arena as a collection of
    spans,
    or contiguous ranges of integers. For example, the kernel heap consists of
    just one span: [kernelheap, ekernelheap). Spans can
    be added to an arena in two ways: explicitly, by
    vmem_add();
    or implicitly, by importing, as described in
    Imported Memory below.
Spans are subdivided into
    segments,
    each of which is either allocated or free. A segment, like a span, is a
    contiguous range of integers. Each allocated segment [addr,
    addr + size) represents exactly one
    vmem_alloc(size) that returned
    addr. Free
    segments represent the space between allocated segments. If two free
    segments are adjacent, we coalesce them into one larger segment; that is, if
    segments [a, b) and [b, c)
    are both free, we merge them into a single segment [a,
    c). The segments within a span are linked together in
    increasing-address order so we can easily determine whether coalescing is
    possible.
Segments never cross span boundaries. When all segments within an imported span become free, we return the span to its source.
As mentioned in the overview, some arenas are logical subsets of
    other arenas. For example, kmem_va_arena (a virtual
    address cache that satisfies most
    kmem_slab_create()
    requests) is just a subset of heap_arena (the kernel heap)
    that provides caching for the most common slab sizes. When
    kmem_va_arena runs out of virtual memory, it
    imports more from the heap; we say that
    heap_arena is the
    vmem
    source for
    kmem_va_arena.
    vmem_create() allows you to specify any existing
    vmem arena as the source for your new arena. Topologically, since every
    arena is a child of at most one source, the set of all arenas forms a
    collection of trees.
Some vmem clients are quite picky about the kind of address they
    want. For example, the DVMA code may need an address that is at a particular
    phase with respect to some alignment (to get good cache coloring), or that
    lies within certain limits (the addressable range of a device), or that
    doesn't cross some boundary (a DMA counter restriction) — or all of
    the above.
    vmem_xalloc()
    allows the client to specify any or all of these constraints.
Every arena has a notion of ‘quantum’, specified at
    vmem_create() time, that defines the arena's minimum
    unit of currency. Most commonly the quantum is either 1 or
    PAGESIZE, but any power of 2 is legal. All vmem
    allocations are guaranteed to be quantum-aligned.
Every kmem cache has a vmem arena as its slab supplier. The kernel
    memory allocator uses
    vmem_alloc()
    and
    vmem_free()
    to create and destroy slabs.
id_space(9F), vmem_add(9F), vmem_alloc(9F), vmem_contains(9F), vmem_create(9F), vmem_walk(9F)
Jeff Bonwick and Jonathan Adams, Magazines and vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources., Proceedings of the 2001 Usenix Conference, http://www.usenix.org/event/usenix01/bonwick.html.
| January 18, 2017 | OmniOS |