You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Documentation/gpu: split up mm, kms and kms-helpers from internals
Make the documents more manageable. Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/be992e56eb8442d6e03b52444df5a42525085718.1466506505.git.jani.nikula@intel.com
This commit is contained in:
committed by
Daniel Vetter
parent
9b20fa08d3
commit
2fa91d1558
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,260 @@
|
||||
=============================
|
||||
Mode Setting Helper Functions
|
||||
=============================
|
||||
|
||||
The plane, CRTC, encoder and connector functions provided by the drivers
|
||||
implement the DRM API. They're called by the DRM core and ioctl handlers
|
||||
to handle device state changes and configuration request. As
|
||||
implementing those functions often requires logic not specific to
|
||||
drivers, mid-layer helper functions are available to avoid duplicating
|
||||
boilerplate code.
|
||||
|
||||
The DRM core contains one mid-layer implementation. The mid-layer
|
||||
provides implementations of several plane, CRTC, encoder and connector
|
||||
functions (called from the top of the mid-layer) that pre-process
|
||||
requests and call lower-level functions provided by the driver (at the
|
||||
bottom of the mid-layer). For instance, the
|
||||
:c:func:`drm_crtc_helper_set_config()` function can be used to
|
||||
fill the :c:type:`struct drm_crtc_funcs <drm_crtc_funcs>`
|
||||
set_config field. When called, it will split the set_config operation
|
||||
in smaller, simpler operations and call the driver to handle them.
|
||||
|
||||
To use the mid-layer, drivers call
|
||||
:c:func:`drm_crtc_helper_add()`,
|
||||
:c:func:`drm_encoder_helper_add()` and
|
||||
:c:func:`drm_connector_helper_add()` functions to install their
|
||||
mid-layer bottom operations handlers, and fill the :c:type:`struct
|
||||
drm_crtc_funcs <drm_crtc_funcs>`, :c:type:`struct
|
||||
drm_encoder_funcs <drm_encoder_funcs>` and :c:type:`struct
|
||||
drm_connector_funcs <drm_connector_funcs>` structures with
|
||||
pointers to the mid-layer top API functions. Installing the mid-layer
|
||||
bottom operation handlers is best done right after registering the
|
||||
corresponding KMS object.
|
||||
|
||||
The mid-layer is not split between CRTC, encoder and connector
|
||||
operations. To use it, a driver must provide bottom functions for all of
|
||||
the three KMS entities.
|
||||
|
||||
Atomic Modeset Helper Functions Reference
|
||||
=========================================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
||||
:doc: overview
|
||||
|
||||
Implementing Asynchronous Atomic Commit
|
||||
---------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
||||
:doc: implementing nonblocking commit
|
||||
|
||||
Atomic State Reset and Initialization
|
||||
-------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
||||
:doc: atomic state reset and initialization
|
||||
|
||||
.. kernel-doc:: include/drm/drm_atomic_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
||||
:export:
|
||||
|
||||
Modeset Helper Reference for Common Vtables
|
||||
===========================================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
||||
:doc: overview
|
||||
|
||||
Legacy CRTC/Modeset Helper Functions Reference
|
||||
==============================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:doc: overview
|
||||
|
||||
Output Probing Helper Functions Reference
|
||||
=========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
||||
:doc: output probing helper overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
||||
:export:
|
||||
|
||||
fbdev Helper Functions Reference
|
||||
================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
|
||||
:doc: fbdev helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_fb_helper.h
|
||||
:internal:
|
||||
|
||||
Framebuffer CMA Helper Functions Reference
|
||||
==========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
||||
:doc: framebuffer cma helper functions
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
||||
:export:
|
||||
|
||||
Display Port Helper Functions Reference
|
||||
=======================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
||||
:doc: dp helpers
|
||||
|
||||
.. kernel-doc:: include/drm/drm_dp_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
||||
:export:
|
||||
|
||||
Display Port Dual Mode Adaptor Helper Functions Reference
|
||||
=========================================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
|
||||
:doc: dp dual mode helpers
|
||||
|
||||
.. kernel-doc:: include/drm/drm_dp_dual_mode_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
|
||||
:export:
|
||||
|
||||
Display Port MST Helper Functions Reference
|
||||
===========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
||||
:doc: dp mst helper
|
||||
|
||||
.. kernel-doc:: include/drm/drm_dp_mst_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
||||
:export:
|
||||
|
||||
MIPI DSI Helper Functions Reference
|
||||
===================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
|
||||
:doc: dsi helpers
|
||||
|
||||
.. kernel-doc:: include/drm/drm_mipi_dsi.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
|
||||
:export:
|
||||
|
||||
EDID Helper Functions Reference
|
||||
===============================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_edid.c
|
||||
:export:
|
||||
|
||||
Rectangle Utilities Reference
|
||||
=============================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_rect.h
|
||||
:doc: rect utils
|
||||
|
||||
.. kernel-doc:: include/drm/drm_rect.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_rect.c
|
||||
:export:
|
||||
|
||||
Flip-work Helper Reference
|
||||
==========================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_flip_work.h
|
||||
:doc: flip utils
|
||||
|
||||
.. kernel-doc:: include/drm/drm_flip_work.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
|
||||
:export:
|
||||
|
||||
HDMI Infoframes Helper Reference
|
||||
================================
|
||||
|
||||
Strictly speaking this is not a DRM helper library but generally useable
|
||||
by any driver interfacing with HDMI outputs like v4l or alsa drivers.
|
||||
But it nicely fits into the overall topic of mode setting helper
|
||||
libraries and hence is also included here.
|
||||
|
||||
.. kernel-doc:: include/linux/hdmi.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/video/hdmi.c
|
||||
:export:
|
||||
|
||||
Plane Helper Reference
|
||||
======================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
||||
:doc: overview
|
||||
|
||||
Tile group
|
||||
----------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
|
||||
:doc: Tile group
|
||||
|
||||
Bridges
|
||||
=======
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: overview
|
||||
|
||||
Default bridge callback sequence
|
||||
--------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: bridge callbacks
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:export:
|
||||
|
||||
Panel Helper Reference
|
||||
======================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_panel.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
||||
:doc: drm panel
|
||||
|
||||
Simple KMS Helper Reference
|
||||
===========================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_simple_kms_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
:doc: overview
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,454 @@
|
||||
=====================
|
||||
DRM Memory Management
|
||||
=====================
|
||||
|
||||
Modern Linux systems require large amount of graphics memory to store
|
||||
frame buffers, textures, vertices and other graphics-related data. Given
|
||||
the very dynamic nature of many of that data, managing graphics memory
|
||||
efficiently is thus crucial for the graphics stack and plays a central
|
||||
role in the DRM infrastructure.
|
||||
|
||||
The DRM core includes two memory managers, namely Translation Table Maps
|
||||
(TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory
|
||||
manager to be developed and tried to be a one-size-fits-them all
|
||||
solution. It provides a single userspace API to accommodate the need of
|
||||
all hardware, supporting both Unified Memory Architecture (UMA) devices
|
||||
and devices with dedicated video RAM (i.e. most discrete video cards).
|
||||
This resulted in a large, complex piece of code that turned out to be
|
||||
hard to use for driver development.
|
||||
|
||||
GEM started as an Intel-sponsored project in reaction to TTM's
|
||||
complexity. Its design philosophy is completely different: instead of
|
||||
providing a solution to every graphics memory-related problems, GEM
|
||||
identified common code between drivers and created a support library to
|
||||
share it. GEM has simpler initialization and execution requirements than
|
||||
TTM, but has no video RAM management capabilities and is thus limited to
|
||||
UMA devices.
|
||||
|
||||
The Translation Table Manager (TTM)
|
||||
-----------------------------------
|
||||
|
||||
TTM design background and information belongs here.
|
||||
|
||||
TTM initialization
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Warning**
|
||||
|
||||
This section is outdated.
|
||||
|
||||
Drivers wishing to support TTM must fill out a drm_bo_driver
|
||||
structure. The structure contains several fields with function pointers
|
||||
for initializing the TTM, allocating and freeing memory, waiting for
|
||||
command completion and fence synchronization, and memory migration. See
|
||||
the radeon_ttm.c file for an example of usage.
|
||||
|
||||
The ttm_global_reference structure is made up of several fields:
|
||||
|
||||
::
|
||||
|
||||
struct ttm_global_reference {
|
||||
enum ttm_global_types global_type;
|
||||
size_t size;
|
||||
void *object;
|
||||
int (*init) (struct ttm_global_reference *);
|
||||
void (*release) (struct ttm_global_reference *);
|
||||
};
|
||||
|
||||
|
||||
There should be one global reference structure for your memory manager
|
||||
as a whole, and there will be others for each object created by the
|
||||
memory manager at runtime. Your global TTM should have a type of
|
||||
TTM_GLOBAL_TTM_MEM. The size field for the global object should be
|
||||
sizeof(struct ttm_mem_global), and the init and release hooks should
|
||||
point at your driver-specific init and release routines, which probably
|
||||
eventually call ttm_mem_global_init and ttm_mem_global_release,
|
||||
respectively.
|
||||
|
||||
Once your global TTM accounting structure is set up and initialized by
|
||||
calling ttm_global_item_ref() on it, you need to create a buffer
|
||||
object TTM to provide a pool for buffer object allocation by clients and
|
||||
the kernel itself. The type of this object should be
|
||||
TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct
|
||||
ttm_bo_global). Again, driver-specific init and release functions may
|
||||
be provided, likely eventually calling ttm_bo_global_init() and
|
||||
ttm_bo_global_release(), respectively. Also, like the previous
|
||||
object, ttm_global_item_ref() is used to create an initial reference
|
||||
count for the TTM, which will call your initialization function.
|
||||
|
||||
The Graphics Execution Manager (GEM)
|
||||
------------------------------------
|
||||
|
||||
The GEM design approach has resulted in a memory manager that doesn't
|
||||
provide full coverage of all (or even all common) use cases in its
|
||||
userspace or kernel API. GEM exposes a set of standard memory-related
|
||||
operations to userspace and a set of helper functions to drivers, and
|
||||
let drivers implement hardware-specific operations with their own
|
||||
private API.
|
||||
|
||||
The GEM userspace API is described in the `GEM - the Graphics Execution
|
||||
Manager <http://lwn.net/Articles/283798/>`__ article on LWN. While
|
||||
slightly outdated, the document provides a good overview of the GEM API
|
||||
principles. Buffer allocation and read and write operations, described
|
||||
as part of the common GEM API, are currently implemented using
|
||||
driver-specific ioctls.
|
||||
|
||||
GEM is data-agnostic. It manages abstract buffer objects without knowing
|
||||
what individual buffers contain. APIs that require knowledge of buffer
|
||||
contents or purpose, such as buffer allocation or synchronization
|
||||
primitives, are thus outside of the scope of GEM and must be implemented
|
||||
using driver-specific ioctls.
|
||||
|
||||
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.
|
||||
|
||||
Device-specific operations, such as command execution, pinning, buffer
|
||||
read & write, mapping, and domain ownership transfers are left to
|
||||
driver-specific ioctls.
|
||||
|
||||
GEM Initialization
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Drivers that use GEM must set the DRIVER_GEM bit in the struct
|
||||
:c:type:`struct drm_driver <drm_driver>` driver_features
|
||||
field. The DRM core will then automatically initialize the GEM core
|
||||
before calling the load operation. Behind the scene, this will create a
|
||||
DRM Memory Manager object which provides an address space pool for
|
||||
object allocation.
|
||||
|
||||
In a KMS configuration, drivers need to allocate and initialize a
|
||||
command ring buffer following core GEM initialization if required by the
|
||||
hardware. UMA devices usually have what is called a "stolen" memory
|
||||
region, which provides space for the initial framebuffer and large,
|
||||
contiguous memory regions required by the device. This space is
|
||||
typically not managed by GEM, and must be initialized separately into
|
||||
its own DRM MM object.
|
||||
|
||||
GEM Objects Creation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GEM splits creation of GEM objects and allocation of the memory that
|
||||
backs them in two distinct operations.
|
||||
|
||||
GEM objects are represented by an instance of struct :c:type:`struct
|
||||
drm_gem_object <drm_gem_object>`. Drivers usually need to
|
||||
extend GEM objects with private information and thus create a
|
||||
driver-specific GEM object structure type that embeds an instance of
|
||||
struct :c:type:`struct drm_gem_object <drm_gem_object>`.
|
||||
|
||||
To create a GEM object, a driver allocates memory for an instance of its
|
||||
specific GEM object type and initializes the embedded struct
|
||||
:c:type:`struct drm_gem_object <drm_gem_object>` with a call
|
||||
to :c:func:`drm_gem_object_init()`. The function takes a pointer
|
||||
to the DRM device, a pointer to the GEM object and the buffer object
|
||||
size in bytes.
|
||||
|
||||
GEM uses shmem to allocate anonymous pageable memory.
|
||||
:c:func:`drm_gem_object_init()` will create an shmfs file of the
|
||||
requested size and store it into the struct :c:type:`struct
|
||||
drm_gem_object <drm_gem_object>` filp field. The memory is
|
||||
used as either main storage for the object when the graphics hardware
|
||||
uses system memory directly or as a backing store otherwise.
|
||||
|
||||
Drivers are responsible for the actual physical pages allocation by
|
||||
calling :c:func:`shmem_read_mapping_page_gfp()` for each page.
|
||||
Note that they can decide to allocate pages when initializing the GEM
|
||||
object, or to delay allocation until the memory is needed (for instance
|
||||
when a page fault occurs as a result of a userspace memory access or
|
||||
when the driver needs to start a DMA transfer involving the memory).
|
||||
|
||||
Anonymous pageable memory allocation is not always desired, for instance
|
||||
when the hardware requires physically contiguous system memory as is
|
||||
often the case in embedded devices. Drivers can create GEM objects with
|
||||
no shmfs backing (called private GEM objects) by initializing them with
|
||||
a call to :c:func:`drm_gem_private_object_init()` instead of
|
||||
:c:func:`drm_gem_object_init()`. Storage for private GEM objects
|
||||
must be managed by drivers.
|
||||
|
||||
GEM Objects Lifetime
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All GEM objects are reference-counted by the GEM core. References can be
|
||||
acquired and release by :c:func:`calling
|
||||
drm_gem_object_reference()` and
|
||||
:c:func:`drm_gem_object_unreference()` respectively. The caller
|
||||
must hold the :c:type:`struct drm_device <drm_device>`
|
||||
struct_mutex lock when calling
|
||||
:c:func:`drm_gem_object_reference()`. As a convenience, GEM
|
||||
provides :c:func:`drm_gem_object_unreference_unlocked()`
|
||||
functions that can be called without holding the lock.
|
||||
|
||||
When the last reference to a GEM object is released the GEM core calls
|
||||
the :c:type:`struct drm_driver <drm_driver>` gem_free_object
|
||||
operation. That operation is mandatory for GEM-enabled drivers and must
|
||||
free the GEM object and all associated resources.
|
||||
|
||||
void (\*gem_free_object) (struct drm_gem_object \*obj); Drivers are
|
||||
responsible for freeing all GEM object resources. This includes the
|
||||
resources created by the GEM core, which need to be released with
|
||||
:c:func:`drm_gem_object_release()`.
|
||||
|
||||
GEM Objects Naming
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Communication between userspace and the kernel refers to GEM objects
|
||||
using local handles, global names or, more recently, file descriptors.
|
||||
All of those are 32-bit integer values; the usual Linux kernel limits
|
||||
apply to the file descriptors.
|
||||
|
||||
GEM handles are local to a DRM file. Applications get a handle to a GEM
|
||||
object through a driver-specific ioctl, and can use that handle to refer
|
||||
to the GEM object in other standard or driver-specific ioctls. Closing a
|
||||
DRM file handle frees all its GEM handles and dereferences the
|
||||
associated GEM objects.
|
||||
|
||||
To create a handle for a GEM object drivers call
|
||||
:c:func:`drm_gem_handle_create()`. The function takes a pointer
|
||||
to the DRM file and the GEM object and returns a locally unique handle.
|
||||
When the handle is no longer needed drivers delete it with a call to
|
||||
:c:func:`drm_gem_handle_delete()`. Finally the GEM object
|
||||
associated with a handle can be retrieved by a call to
|
||||
:c:func:`drm_gem_object_lookup()`.
|
||||
|
||||
Handles don't take ownership of GEM objects, they only take a reference
|
||||
to the object that will be dropped when the handle is destroyed. To
|
||||
avoid leaking GEM objects, drivers must make sure they drop the
|
||||
reference(s) they own (such as the initial reference taken at object
|
||||
creation time) as appropriate, without any special consideration for the
|
||||
handle. For example, in the particular case of combined GEM object and
|
||||
handle creation in the implementation of the dumb_create operation,
|
||||
drivers must drop the initial reference to the GEM object before
|
||||
returning the handle.
|
||||
|
||||
GEM names are similar in purpose to handles but are not local to DRM
|
||||
files. They can be passed between processes to reference a GEM object
|
||||
globally. Names can't be used directly to refer to objects in the DRM
|
||||
API, applications must convert handles to names and names to handles
|
||||
using the DRM_IOCTL_GEM_FLINK and DRM_IOCTL_GEM_OPEN ioctls
|
||||
respectively. The conversion is handled by the DRM core without any
|
||||
driver-specific support.
|
||||
|
||||
GEM also supports buffer sharing with dma-buf file descriptors through
|
||||
PRIME. GEM-based drivers must use the provided helpers functions to
|
||||
implement the exporting and importing correctly. See ?. Since sharing
|
||||
file descriptors is inherently more secure than the easily guessable and
|
||||
global GEM names it is the preferred buffer sharing mechanism. Sharing
|
||||
buffers through GEM names is only supported for legacy userspace.
|
||||
Furthermore PRIME also allows cross-device buffer sharing since it is
|
||||
based on dma-bufs.
|
||||
|
||||
GEM Objects Mapping
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Because mapping operations are fairly heavyweight GEM favours
|
||||
read/write-like access to buffers, implemented through driver-specific
|
||||
ioctls, over mapping buffers to userspace. However, when random access
|
||||
to the buffer is needed (to perform software rendering for instance),
|
||||
direct access to the object can be more efficient.
|
||||
|
||||
The mmap system call can't be used directly to map GEM objects, as they
|
||||
don't have their own file handle. Two alternative methods currently
|
||||
co-exist to map GEM objects to userspace. The first method uses a
|
||||
driver-specific ioctl to perform the mapping operation, calling
|
||||
:c:func:`do_mmap()` under the hood. This is often considered
|
||||
dubious, seems to be discouraged for new GEM-enabled drivers, and will
|
||||
thus not be described here.
|
||||
|
||||
The second method uses the mmap system call on the DRM file handle. void
|
||||
\*mmap(void \*addr, size_t length, int prot, int flags, int fd, off_t
|
||||
offset); DRM identifies the GEM object to be mapped by a fake offset
|
||||
passed through the mmap offset argument. Prior to being mapped, a GEM
|
||||
object must thus be associated with a fake offset. To do so, drivers
|
||||
must call :c:func:`drm_gem_create_mmap_offset()` on the object.
|
||||
|
||||
Once allocated, the fake offset value must be passed to the application
|
||||
in a driver-specific way and can then be used as the mmap offset
|
||||
argument.
|
||||
|
||||
The GEM core provides a helper method :c:func:`drm_gem_mmap()` to
|
||||
handle object mapping. The method can be set directly as the mmap file
|
||||
operation handler. It will look up the GEM object based on the offset
|
||||
value and set the VMA operations to the :c:type:`struct drm_driver
|
||||
<drm_driver>` gem_vm_ops field. Note that
|
||||
:c:func:`drm_gem_mmap()` doesn't map memory to userspace, but
|
||||
relies on the driver-provided fault handler to map pages individually.
|
||||
|
||||
To use :c:func:`drm_gem_mmap()`, drivers must fill the struct
|
||||
:c:type:`struct drm_driver <drm_driver>` gem_vm_ops field
|
||||
with a pointer to VM operations.
|
||||
|
||||
struct vm_operations_struct \*gem_vm_ops struct
|
||||
vm_operations_struct { void (\*open)(struct vm_area_struct \* area);
|
||||
void (\*close)(struct vm_area_struct \* area); int (\*fault)(struct
|
||||
vm_area_struct \*vma, struct vm_fault \*vmf); };
|
||||
|
||||
The open and close operations must update the GEM object reference
|
||||
count. Drivers can use the :c:func:`drm_gem_vm_open()` and
|
||||
:c:func:`drm_gem_vm_close()` helper functions directly as open
|
||||
and close handlers.
|
||||
|
||||
The fault operation handler is responsible for mapping individual pages
|
||||
to userspace when a page fault occurs. Depending on the memory
|
||||
allocation scheme, drivers can allocate pages at fault time, or can
|
||||
decide to allocate memory for the GEM object at the time the object is
|
||||
created.
|
||||
|
||||
Drivers that want to map the GEM object upfront instead of handling page
|
||||
faults can implement their own mmap file operation handler.
|
||||
|
||||
Memory Coherency
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
When mapped to the device or used in a command buffer, 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).
|
||||
|
||||
Command Execution
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Perhaps the most important GEM function for GPU devices 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.
|
||||
|
||||
GEM Function Reference
|
||||
----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem.h
|
||||
:internal:
|
||||
|
||||
VMA Offset Manager
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vma_manager.c
|
||||
:doc: vma offset manager
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vma_manager.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_vma_manager.h
|
||||
:internal:
|
||||
|
||||
PRIME Buffer Sharing
|
||||
--------------------
|
||||
|
||||
PRIME is the cross device buffer sharing framework in drm, originally
|
||||
created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME
|
||||
buffers are dma-buf based file descriptors.
|
||||
|
||||
Overview and Driver Interface
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similar to GEM global names, PRIME file descriptors are also used to
|
||||
share buffer objects across processes. They offer additional security:
|
||||
as file descriptors must be explicitly sent over UNIX domain sockets to
|
||||
be shared between applications, they can't be guessed like the globally
|
||||
unique GEM names.
|
||||
|
||||
Drivers that support the PRIME API must set the DRIVER_PRIME bit in the
|
||||
struct :c:type:`struct drm_driver <drm_driver>`
|
||||
driver_features field, and implement the prime_handle_to_fd and
|
||||
prime_fd_to_handle operations.
|
||||
|
||||
int (\*prime_handle_to_fd)(struct drm_device \*dev, struct drm_file
|
||||
\*file_priv, uint32_t handle, uint32_t flags, int \*prime_fd); int
|
||||
(\*prime_fd_to_handle)(struct drm_device \*dev, struct drm_file
|
||||
\*file_priv, int prime_fd, uint32_t \*handle); Those two operations
|
||||
convert a handle to a PRIME file descriptor and vice versa. Drivers must
|
||||
use the kernel dma-buf buffer sharing framework to manage the PRIME file
|
||||
descriptors. Similar to the mode setting API PRIME is agnostic to the
|
||||
underlying buffer object manager, as long as handles are 32bit unsigned
|
||||
integers.
|
||||
|
||||
While non-GEM drivers must implement the operations themselves, GEM
|
||||
drivers must use the :c:func:`drm_gem_prime_handle_to_fd()` and
|
||||
:c:func:`drm_gem_prime_fd_to_handle()` helper functions. Those
|
||||
helpers rely on the driver gem_prime_export and gem_prime_import
|
||||
operations to create a dma-buf instance from a GEM object (dma-buf
|
||||
exporter role) and to create a GEM object from a dma-buf instance
|
||||
(dma-buf importer role).
|
||||
|
||||
struct dma_buf \* (\*gem_prime_export)(struct drm_device \*dev,
|
||||
struct drm_gem_object \*obj, int flags); struct drm_gem_object \*
|
||||
(\*gem_prime_import)(struct drm_device \*dev, struct dma_buf
|
||||
\*dma_buf); These two operations are mandatory for GEM drivers that
|
||||
support PRIME.
|
||||
|
||||
PRIME Helper Functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_prime.c
|
||||
:doc: PRIME Helpers
|
||||
|
||||
PRIME Function References
|
||||
-------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_prime.c
|
||||
:export:
|
||||
|
||||
DRM MM Range Allocator
|
||||
----------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
|
||||
:doc: Overview
|
||||
|
||||
LRU Scan/Eviction Support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
|
||||
:doc: lru scan roaster
|
||||
|
||||
DRM MM Range Allocator Function References
|
||||
------------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_mm.h
|
||||
:internal:
|
||||
|
||||
CMA Helper Functions Reference
|
||||
------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:doc: cma helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_cma_helper.h
|
||||
:internal:
|
||||
@@ -6,6 +6,9 @@ Linux GPU Driver Developer's Guide
|
||||
|
||||
introduction
|
||||
drm-internals
|
||||
drm-mm
|
||||
drm-kms
|
||||
drm-kms-helpers
|
||||
drm-uapi
|
||||
i915
|
||||
vga-switcheroo
|
||||
|
||||
Reference in New Issue
Block a user