Memory management

The Translation Table Manager (TTM)
The Graphics Execution Manager (GEM)

The memory manager lies at the heart of many DRM operations; it is required to support advanced client features like OpenGL pbuffers. The DRM currently contains two memory managers: TTM and GEM.

The Translation Table Manager (TTM)

TTM was developed by Tungsten Graphics, primarily by Thomas Hellström, and is intended to be a flexible, high performance graphics memory manager.

Drivers wishing to support TTM must fill out a drm_bo_driver structure.

TTM design background and information belongs here.

The Graphics Execution Manager (GEM)

GEM is an Intel project, authored by Eric Anholt and Keith Packard. It provides simpler interfaces than TTM, and is well suited for UMA devices.

GEM-enabled drivers must provide gem_init_object() and gem_free_object() callbacks to support the core memory allocation routines. They should also provide several driver-specific ioctls to support command execution, pinning, buffer read & write, mapping, and domain ownership transfers.

On a fundamental level, GEM involves several operations:

  • Memory allocation and freeing
  • Command execution
  • Aperture management at command execution time

Buffer object allocation is relatively straightforward and largely provided by Linux's shmem layer, which provides memory to back each object. When mapped into the GTT or used in a command buffer, the backing pages for an object are flushed to memory and marked write combined so as to be coherent with the GPU. Likewise, if the CPU accesses an object after the GPU has finished rendering to the object, then the object must be made coherent with the CPU's view of memory, usually involving GPU cache flushing of various kinds. This core CPU<->GPU coherency management is provided by a device-specific ioctl, which evaluates an object's current domain and performs any necessary flushing or synchronization to put the object into the desired coherency domain (note that the object may be busy, i.e. an active render target; in that case, setting the domain blocks the client and waits for rendering to complete before performing any necessary flushing operations).

Perhaps the most important GEM function is providing a command execution interface to clients. Client programs construct command buffers containing references to previously allocated memory objects, and then submit them to GEM. At that point, GEM takes care to bind all the objects into the GTT, execute the buffer, and provide necessary synchronization between clients accessing the same buffers. This often involves evicting some objects from the GTT and re-binding others (a fairly expensive operation), and providing relocation support which hides fixed GTT offsets from clients. Clients must take care not to submit command buffers that reference more objects than can fit in the GTT; otherwise, GEM will reject them and no rendering will occur. Similarly, if several objects in the buffer require fence registers to be allocated for correct rendering (e.g. 2D blits on pre-965 chips), care must be taken not to require more fence registers than are available to the client. Such resource management should be abstracted from the client in libdrm.