Commit e6303f32 authored by Danilo Krummrich's avatar Danilo Krummrich

drm: manager to keep track of GPUs VA mappings

Add infrastructure to keep track of GPU virtual address (VA) mappings
with a decicated VA space manager implementation.

New UAPIs, motivated by Vulkan sparse memory bindings graphics drivers
start implementing, allow userspace applications to request multiple and
arbitrary GPU VA mappings of buffer objects. The DRM GPU VA manager is
intended to serve the following purposes in this context.

1) Provide infrastructure to track GPU VA allocations and mappings,
   using an interval tree (RB-tree).

2) Generically connect GPU VA mappings to their backing buffers, in
   particular DRM GEM objects.

3) Provide a common implementation to perform more complex mapping
   operations on the GPU VA space. In particular splitting and merging
   of GPU VA mappings, e.g. for intersecting mapping requests or partial
   unmap requests.
Acked-by: default avatarThomas Hellström <thomas.hellstrom@linux.intel.com>
Acked-by: default avatarMatthew Brost <matthew.brost@intel.com>
Reviewed-by: default avatarBoris Brezillon <boris.brezillon@collabora.com>
Tested-by: default avatarMatthew Brost <matthew.brost@intel.com>
Tested-by: default avatarDonald Robson <donald.robson@imgtec.com>
Suggested-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarDanilo Krummrich <dakr@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230720001443.2380-2-dakr@redhat.com
parent 41639b3a
...@@ -466,6 +466,42 @@ DRM MM Range Allocator Function References ...@@ -466,6 +466,42 @@ DRM MM Range Allocator Function References
.. kernel-doc:: drivers/gpu/drm/drm_mm.c .. kernel-doc:: drivers/gpu/drm/drm_mm.c
:export: :export:
DRM GPU VA Manager
==================
Overview
--------
.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
:doc: Overview
Split and Merge
---------------
.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
:doc: Split and Merge
Locking
-------
.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
:doc: Locking
Examples
--------
.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
:doc: Examples
DRM GPU VA Manager Function References
--------------------------------------
.. kernel-doc:: include/drm/drm_gpuva_mgr.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_gpuva_mgr.c
:export:
DRM Buddy Allocator DRM Buddy Allocator
=================== ===================
......
...@@ -45,6 +45,7 @@ drm-y := \ ...@@ -45,6 +45,7 @@ drm-y := \
drm_vblank.o \ drm_vblank.o \
drm_vblank_work.o \ drm_vblank_work.o \
drm_vma_manager.o \ drm_vma_manager.o \
drm_gpuva_mgr.o \
drm_writeback.o drm_writeback.o
drm-$(CONFIG_DRM_LEGACY) += \ drm-$(CONFIG_DRM_LEGACY) += \
drm_agpsupport.o \ drm_agpsupport.o \
......
...@@ -164,6 +164,9 @@ void drm_gem_private_object_init(struct drm_device *dev, ...@@ -164,6 +164,9 @@ void drm_gem_private_object_init(struct drm_device *dev,
if (!obj->resv) if (!obj->resv)
obj->resv = &obj->_resv; obj->resv = &obj->_resv;
if (drm_core_check_feature(dev, DRIVER_GEM_GPUVA))
drm_gem_gpuva_init(obj);
drm_vma_node_reset(&obj->vma_node); drm_vma_node_reset(&obj->vma_node);
INIT_LIST_HEAD(&obj->lru_node); INIT_LIST_HEAD(&obj->lru_node);
} }
......
This diff is collapsed.
...@@ -104,6 +104,12 @@ enum drm_driver_feature { ...@@ -104,6 +104,12 @@ enum drm_driver_feature {
* acceleration should be handled by two drivers that are connected using auxiliary bus. * acceleration should be handled by two drivers that are connected using auxiliary bus.
*/ */
DRIVER_COMPUTE_ACCEL = BIT(7), DRIVER_COMPUTE_ACCEL = BIT(7),
/**
* @DRIVER_GEM_GPUVA:
*
* Driver supports user defined GPU VA bindings for GEM objects.
*/
DRIVER_GEM_GPUVA = BIT(8),
/* IMPORTANT: Below are all the legacy flags, add new ones above. */ /* IMPORTANT: Below are all the legacy flags, add new ones above. */
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/dma-resv.h> #include <linux/dma-resv.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <drm/drm_vma_manager.h> #include <drm/drm_vma_manager.h>
...@@ -379,6 +381,22 @@ struct drm_gem_object { ...@@ -379,6 +381,22 @@ struct drm_gem_object {
*/ */
struct dma_resv _resv; struct dma_resv _resv;
/**
* @gpuva:
*
* Provides the list of GPU VAs attached to this GEM object.
*
* Drivers should lock list accesses with the GEMs &dma_resv lock
* (&drm_gem_object.resv) or a custom lock if one is provided.
*/
struct {
struct list_head list;
#ifdef CONFIG_LOCKDEP
struct lockdep_map *lock_dep_map;
#endif
} gpuva;
/** /**
* @funcs: * @funcs:
* *
...@@ -526,4 +544,65 @@ unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, ...@@ -526,4 +544,65 @@ unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru,
int drm_gem_evict(struct drm_gem_object *obj); int drm_gem_evict(struct drm_gem_object *obj);
#ifdef CONFIG_LOCKDEP
/**
* drm_gem_gpuva_set_lock() - Set the lock protecting accesses to the gpuva list.
* @obj: the &drm_gem_object
* @lock: the lock used to protect the gpuva list. The locking primitive
* must contain a dep_map field.
*
* Call this if you're not proctecting access to the gpuva list
* with the dma-resv lock, otherwise, drm_gem_gpuva_init() takes care
* of initializing lock_dep_map for you.
*/
#define drm_gem_gpuva_set_lock(obj, lock) \
if (!(obj)->gpuva.lock_dep_map) \
(obj)->gpuva.lock_dep_map = &(lock)->dep_map
#define drm_gem_gpuva_assert_lock_held(obj) \
lockdep_assert(lock_is_held((obj)->gpuva.lock_dep_map))
#else
#define drm_gem_gpuva_set_lock(obj, lock) do {} while (0)
#define drm_gem_gpuva_assert_lock_held(obj) do {} while (0)
#endif
/**
* drm_gem_gpuva_init() - initialize the gpuva list of a GEM object
* @obj: the &drm_gem_object
*
* This initializes the &drm_gem_object's &drm_gpuva list.
*
* Calling this function is only necessary for drivers intending to support the
* &drm_driver_feature DRIVER_GEM_GPUVA.
*/
static inline void drm_gem_gpuva_init(struct drm_gem_object *obj)
{
INIT_LIST_HEAD(&obj->gpuva.list);
drm_gem_gpuva_set_lock(obj, &obj->resv->lock.base);
}
/**
* drm_gem_for_each_gpuva() - iternator to walk over a list of gpuvas
* @entry__: &drm_gpuva structure to assign to in each iteration step
* @obj__: the &drm_gem_object the &drm_gpuvas to walk are associated with
*
* This iterator walks over all &drm_gpuva structures associated with the
* &drm_gpuva_manager.
*/
#define drm_gem_for_each_gpuva(entry__, obj__) \
list_for_each_entry(entry__, &(obj__)->gpuva.list, gem.entry)
/**
* drm_gem_for_each_gpuva_safe() - iternator to safely walk over a list of
* gpuvas
* @entry__: &drm_gpuva structure to assign to in each iteration step
* @next__: &next &drm_gpuva to store the next step
* @obj__: the &drm_gem_object the &drm_gpuvas to walk are associated with
*
* This iterator walks over all &drm_gpuva structures associated with the
* &drm_gem_object. It is implemented with list_for_each_entry_safe(), hence
* it is save against removal of elements.
*/
#define drm_gem_for_each_gpuva_safe(entry__, next__, obj__) \
list_for_each_entry_safe(entry__, next__, &(obj__)->gpuva.list, gem.entry)
#endif /* __DRM_GEM_H__ */ #endif /* __DRM_GEM_H__ */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment