180 lines
7.5 KiB
C
180 lines
7.5 KiB
C
|
/* SPDX-License-Identifier: MIT */
|
||
|
/*
|
||
|
* Copyright © 2022 Intel Corporation
|
||
|
*/
|
||
|
|
||
|
#ifndef _XE_BO_DOC_H_
|
||
|
#define _XE_BO_DOC_H_
|
||
|
|
||
|
/**
|
||
|
* DOC: Buffer Objects (BO)
|
||
|
*
|
||
|
* BO management
|
||
|
* =============
|
||
|
*
|
||
|
* TTM manages (placement, eviction, etc...) all BOs in XE.
|
||
|
*
|
||
|
* BO creation
|
||
|
* ===========
|
||
|
*
|
||
|
* Create a chunk of memory which can be used by the GPU. Placement rules
|
||
|
* (sysmem or vram region) passed in upon creation. TTM handles placement of BO
|
||
|
* and can trigger eviction of other BOs to make space for the new BO.
|
||
|
*
|
||
|
* Kernel BOs
|
||
|
* ----------
|
||
|
*
|
||
|
* A kernel BO is created as part of driver load (e.g. uC firmware images, GuC
|
||
|
* ADS, etc...) or a BO created as part of a user operation which requires
|
||
|
* a kernel BO (e.g. engine state, memory for page tables, etc...). These BOs
|
||
|
* are typically mapped in the GGTT (any kernel BOs aside memory for page tables
|
||
|
* are in the GGTT), are pinned (can't move or be evicted at runtime), have a
|
||
|
* vmap (XE can access the memory via xe_map layer) and have contiguous physical
|
||
|
* memory.
|
||
|
*
|
||
|
* More details of why kernel BOs are pinned and contiguous below.
|
||
|
*
|
||
|
* User BOs
|
||
|
* --------
|
||
|
*
|
||
|
* A user BO is created via the DRM_IOCTL_XE_GEM_CREATE IOCTL. Once it is
|
||
|
* created the BO can be mmap'd (via DRM_IOCTL_XE_GEM_MMAP_OFFSET) for user
|
||
|
* access and it can be bound for GPU access (via DRM_IOCTL_XE_VM_BIND). All
|
||
|
* user BOs are evictable and user BOs are never pinned by XE. The allocation of
|
||
|
* the backing store can be defered from creation time until first use which is
|
||
|
* either mmap, bind, or pagefault.
|
||
|
*
|
||
|
* Private BOs
|
||
|
* ~~~~~~~~~~~
|
||
|
*
|
||
|
* A private BO is a user BO created with a valid VM argument passed into the
|
||
|
* create IOCTL. If a BO is private it cannot be exported via prime FD and
|
||
|
* mappings can only be created for the BO within the VM it is tied to. Lastly,
|
||
|
* the BO dma-resv slots / lock point to the VM's dma-resv slots / lock (all
|
||
|
* private BOs to a VM share common dma-resv slots / lock).
|
||
|
*
|
||
|
* External BOs
|
||
|
* ~~~~~~~~~~~~
|
||
|
*
|
||
|
* An external BO is a user BO created with a NULL VM argument passed into the
|
||
|
* create IOCTL. An external BO can be shared with different UMDs / devices via
|
||
|
* prime FD and the BO can be mapped into multiple VMs. An external BO has its
|
||
|
* own unique dma-resv slots / lock. An external BO will be in an array of all
|
||
|
* VMs which has a mapping of the BO. This allows VMs to lookup and lock all
|
||
|
* external BOs mapped in the VM as needed.
|
||
|
*
|
||
|
* BO placement
|
||
|
* ~~~~~~~~~~~~
|
||
|
*
|
||
|
* When a user BO is created, a mask of valid placements is passed indicating
|
||
|
* which memory regions are considered valid.
|
||
|
*
|
||
|
* The memory region information is available via query uAPI (TODO: add link).
|
||
|
*
|
||
|
* BO validation
|
||
|
* =============
|
||
|
*
|
||
|
* BO validation (ttm_bo_validate) refers to ensuring a BO has a valid
|
||
|
* placement. If a BO was swapped to temporary storage, a validation call will
|
||
|
* trigger a move back to a valid (location where GPU can access BO) placement.
|
||
|
* Validation of a BO may evict other BOs to make room for the BO being
|
||
|
* validated.
|
||
|
*
|
||
|
* BO eviction / moving
|
||
|
* ====================
|
||
|
*
|
||
|
* All eviction (or in other words, moving a BO from one memory location to
|
||
|
* another) is routed through TTM with a callback into XE.
|
||
|
*
|
||
|
* Runtime eviction
|
||
|
* ----------------
|
||
|
*
|
||
|
* Runtime evictions refers to during normal operations where TTM decides it
|
||
|
* needs to move a BO. Typically this is because TTM needs to make room for
|
||
|
* another BO and the evicted BO is first BO on LRU list that is not locked.
|
||
|
*
|
||
|
* An example of this is a new BO which can only be placed in VRAM but there is
|
||
|
* not space in VRAM. There could be multiple BOs which have sysmem and VRAM
|
||
|
* placement rules which currently reside in VRAM, TTM trigger a will move of
|
||
|
* one (or multiple) of these BO(s) until there is room in VRAM to place the new
|
||
|
* BO. The evicted BO(s) are valid but still need new bindings before the BO
|
||
|
* used again (exec or compute mode rebind worker).
|
||
|
*
|
||
|
* Another example would be, TTM can't find a BO to evict which has another
|
||
|
* valid placement. In this case TTM will evict one (or multiple) unlocked BO(s)
|
||
|
* to a temporary unreachable (invalid) placement. The evicted BO(s) are invalid
|
||
|
* and before next use need to be moved to a valid placement and rebound.
|
||
|
*
|
||
|
* In both cases, moves of these BOs are scheduled behind the fences in the BO's
|
||
|
* dma-resv slots.
|
||
|
*
|
||
|
* WW locking tries to ensures if 2 VMs use 51% of the memory forward progress
|
||
|
* is made on both VMs.
|
||
|
*
|
||
|
* Runtime eviction uses per a GT migration engine (TODO: link to migration
|
||
|
* engine doc) to do a GPU memcpy from one location to another.
|
||
|
*
|
||
|
* Rebinds after runtime eviction
|
||
|
* ------------------------------
|
||
|
*
|
||
|
* When BOs are moved, every mapping (VMA) of the BO needs to rebound before
|
||
|
* the BO is used again. Every VMA is added to an evicted list of its VM when
|
||
|
* the BO is moved. This is safe because of the VM locking structure (TODO: link
|
||
|
* to VM locking doc). On the next use of a VM (exec or compute mode rebind
|
||
|
* worker) the evicted VMA list is checked and rebinds are triggered. In the
|
||
|
* case of faulting VM, the rebind is done in the page fault handler.
|
||
|
*
|
||
|
* Suspend / resume eviction of VRAM
|
||
|
* ---------------------------------
|
||
|
*
|
||
|
* During device suspend / resume VRAM may lose power which means the contents
|
||
|
* of VRAM's memory is blown away. Thus BOs present in VRAM at the time of
|
||
|
* suspend must be moved to sysmem in order for their contents to be saved.
|
||
|
*
|
||
|
* A simple TTM call (ttm_resource_manager_evict_all) can move all non-pinned
|
||
|
* (user) BOs to sysmem. External BOs that are pinned need to be manually
|
||
|
* evicted with a simple loop + xe_bo_evict call. It gets a little trickier
|
||
|
* with kernel BOs.
|
||
|
*
|
||
|
* Some kernel BOs are used by the GT migration engine to do moves, thus we
|
||
|
* can't move all of the BOs via the GT migration engine. For simplity, use a
|
||
|
* TTM memcpy (CPU) to move any kernel (pinned) BO on either suspend or resume.
|
||
|
*
|
||
|
* Some kernel BOs need to be restored to the exact same physical location. TTM
|
||
|
* makes this rather easy but the caveat is the memory must be contiguous. Again
|
||
|
* for simplity, we enforce that all kernel (pinned) BOs are contiguous and
|
||
|
* restored to the same physical location.
|
||
|
*
|
||
|
* Pinned external BOs in VRAM are restored on resume via the GPU.
|
||
|
*
|
||
|
* Rebinds after suspend / resume
|
||
|
* ------------------------------
|
||
|
*
|
||
|
* Most kernel BOs have GGTT mappings which must be restored during the resume
|
||
|
* process. All user BOs are rebound after validation on their next use.
|
||
|
*
|
||
|
* Future work
|
||
|
* ===========
|
||
|
*
|
||
|
* Trim the list of BOs which is saved / restored via TTM memcpy on suspend /
|
||
|
* resume. All we really need to save / restore via TTM memcpy is the memory
|
||
|
* required for the GuC to load and the memory for the GT migrate engine to
|
||
|
* operate.
|
||
|
*
|
||
|
* Do not require kernel BOs to be contiguous in physical memory / restored to
|
||
|
* the same physical address on resume. In all likelihood the only memory that
|
||
|
* needs to be restored to the same physical address is memory used for page
|
||
|
* tables. All of that memory is allocated 1 page at time so the contiguous
|
||
|
* requirement isn't needed. Some work on the vmap code would need to be done if
|
||
|
* kernel BOs are not contiguous too.
|
||
|
*
|
||
|
* Make some kernel BO evictable rather than pinned. An example of this would be
|
||
|
* engine state, in all likelihood if the dma-slots of these BOs where properly
|
||
|
* used rather than pinning we could safely evict + rebind these BOs as needed.
|
||
|
*
|
||
|
* Some kernel BOs do not need to be restored on resume (e.g. GuC ADS as that is
|
||
|
* repopulated on resume), add flag to mark such objects as no save / restore.
|
||
|
*/
|
||
|
|
||
|
#endif
|