[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <a781f7781a9bf510c3707a5c9a235e1dab785617.camel@linux.intel.com>
Date: Tue, 19 Aug 2025 18:22:12 +0200
From: Thomas Hellström <thomas.hellstrom@...ux.intel.com>
To: Maarten Lankhorst <dev@...khorst.se>, Lucas De Marchi
<lucas.demarchi@...el.com>, Rodrigo Vivi <rodrigo.vivi@...el.com>, David
Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>, Maxime Ripard
<mripard@...nel.org>, Natalie Vock <natalie.vock@....de>, Tejun Heo
<tj@...nel.org>, Johannes Weiner <hannes@...xchg.org>, 'Michal
Koutný' <mkoutny@...e.com>, Michal Hocko
<mhocko@...nel.org>, Roman Gushchin <roman.gushchin@...ux.dev>, Shakeel
Butt <shakeel.butt@...ux.dev>, Muchun Song <muchun.song@...ux.dev>, Andrew
Morton <akpm@...ux-foundation.org>, David Hildenbrand <david@...hat.com>,
Lorenzo Stoakes <lorenzo.stoakes@...cle.com>, "'Liam R . Howlett'"
<Liam.Howlett@...cle.com>, Vlastimil Babka <vbabka@...e.cz>, Mike Rapoport
<rppt@...nel.org>, Suren Baghdasaryan <surenb@...gle.com>, Thomas
Zimmermann <tzimmermann@...e.de>
Cc: Michal Hocko <mhocko@...e.com>, intel-xe@...ts.freedesktop.org,
dri-devel@...ts.freedesktop.org, linux-kernel@...r.kernel.org,
cgroups@...r.kernel.org, linux-mm@...ck.org
Subject: Re: [RFC 3/3] drm/xe: Add DRM_XE_GEM_CREATE_FLAG_PINNED flag and
implementation
Hi, Maarten,
On Tue, 2025-08-19 at 13:49 +0200, Maarten Lankhorst wrote:
> Add an option to pin memory through the science of cgroup accounting.
> A bo will be pinned for its entire lifetime, and this allows buffers
> that are pinned for dma-buf export without requiring the pinning to
> be
> done at the dma-buf layer for all devices.
>
> For now only implement VRAM pinning. Dave Airlie has a series to
> implement
> memcg accounting for the GPU but that is not ready yet.
Previous discussions around this have favoured a UAPI where we pin a
gpu-vm range, with a pin at mapping time, or dma-buf pin time where
required, this allows for dynamic pinning and unpinning, and would
avoid having separate pinning interfaces for bos and userptr.
In particular if we don't know at bo creation time which buffer objects
will be exported with a method requiring pinning, how would UMD deduce
what buffer objects to pin?
Thanks,
Thomas
>
> Signed-off-by: Maarten Lankhorst <dev@...khorst.se>
> ---
> drivers/gpu/drm/xe/xe_bo.c | 66
> ++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/xe/xe_dma_buf.c | 10 ++++-
> include/uapi/drm/xe_drm.h | 10 ++++-
> 3 files changed, 82 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
> index 6fea39842e1e6..4095e6bd04ea9 100644
> --- a/drivers/gpu/drm/xe/xe_bo.c
> +++ b/drivers/gpu/drm/xe/xe_bo.c
> @@ -5,6 +5,7 @@
>
> #include "xe_bo.h"
>
> +#include <linux/cgroup_dmem.h>
> #include <linux/dma-buf.h>
> #include <linux/nospec.h>
>
> @@ -208,7 +209,8 @@ static bool force_contiguous(u32 bo_flags)
> * must be contiguous, also only contiguous BOs support
> xe_bo_vmap.
> */
> return bo_flags & XE_BO_FLAG_NEEDS_CPU_ACCESS &&
> - bo_flags & XE_BO_FLAG_PINNED;
> + bo_flags & XE_BO_FLAG_PINNED &&
> + !(bo_flags & XE_BO_FLAG_USER);
> }
>
> static void add_vram(struct xe_device *xe, struct xe_bo *bo,
> @@ -1697,6 +1699,16 @@ static void xe_gem_object_free(struct
> drm_gem_object *obj)
> ttm_bo_put(container_of(obj, struct ttm_buffer_object,
> base));
> }
>
> +static void xe_bo_unpin_user(struct xe_bo *bo)
> +{
> + xe_bo_unpin_external(bo);
> +
> + if (bo->flags & XE_BO_FLAG_SYSTEM)
> + WARN_ON(1);
> + else
> + dmem_cgroup_unpin(bo->ttm.resource->css,
> xe_bo_size(bo));
> +}
> +
> static void xe_gem_object_close(struct drm_gem_object *obj,
> struct drm_file *file_priv)
> {
> @@ -1708,6 +1720,10 @@ static void xe_gem_object_close(struct
> drm_gem_object *obj,
> xe_bo_lock(bo, false);
> ttm_bo_set_bulk_move(&bo->ttm, NULL);
> xe_bo_unlock(bo);
> + } else if (bo->flags & XE_BO_FLAG_PINNED) {
> + xe_bo_lock(bo, false);
> + xe_bo_unpin_user(bo);
> + xe_bo_unlock(bo);
> }
> }
>
> @@ -2128,8 +2144,27 @@ struct xe_bo *xe_bo_create_user(struct
> xe_device *xe, struct xe_tile *tile,
> struct xe_bo *bo = __xe_bo_create_locked(xe, tile, vm, size,
> 0, ~0ULL,
> cpu_caching,
> ttm_bo_type_device,
> flags |
> XE_BO_FLAG_USER, 0);
> - if (!IS_ERR(bo))
> + if (!IS_ERR(bo)) {
> + int ret = 0;
> +
> + if (bo->flags & XE_BO_FLAG_PINNED) {
> + if (bo->flags & XE_BO_FLAG_SYSTEM) {
> + ret = -ENOSYS; // TODO
> + } else {
> + ret = dmem_cgroup_try_pin(bo-
> >ttm.resource->css, size);
> + }
> + if (!ret)
> + ret = xe_bo_pin_external(bo);
> + else if (ret == -EAGAIN)
> + ret = -ENOSPC;
> + }
> +
> xe_bo_unlock_vm_held(bo);
> + if (ret) {
> + xe_bo_put(bo);
> + return ERR_PTR(ret);
> + }
> + }
>
> return bo;
> }
> @@ -2745,6 +2780,28 @@ int xe_gem_create_ioctl(struct drm_device
> *dev, void *data,
> args->cpu_caching ==
> DRM_XE_GEM_CPU_CACHING_WB))
> return -EINVAL;
>
> + if (XE_IOCTL_DBG(xe, args->flags &
> DRM_XE_GEM_CREATE_FLAG_PINNED)) {
> + bool pinned_flag = true;
> + /* Only allow a single placement for pinning */
> + if (XE_IOCTL_DBG(xe, pinned_flag && hweight32(args-
> >placement) != 1))
> + return -EINVAL;
> +
> + /* Meant for exporting, do not allow a VM-local BO
> */
> + if (XE_IOCTL_DBG(xe, pinned_flag && args->vm_id))
> + return -EINVAL;
> +
> + /* Similarly, force fail at creation time for now.
> We may relax this requirement later */
> + if (XE_IOCTL_DBG(xe, pinned_flag && args->flags &
> DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING))
> + return -EINVAL;
> +
> + /* Require the appropriate cgroups to be enabled. */
> + if (XE_IOCTL_DBG(xe, pinned_flag &&
> !IS_ENABLED(CONFIG_CGROUP_DMEM) && bo_flags & XE_BO_FLAG_VRAM_MASK)
> ||
> + XE_IOCTL_DBG(xe, pinned_flag &&
> !IS_ENABLED(CONFIG_MEMCG) && bo_flags & XE_BO_FLAG_SYSTEM))
> + return -EINVAL;
> +
> + bo_flags |= XE_BO_FLAG_PINNED;
> + }
> +
> if (args->vm_id) {
> vm = xe_vm_lookup(xef, args->vm_id);
> if (XE_IOCTL_DBG(xe, !vm))
> @@ -2790,6 +2847,11 @@ int xe_gem_create_ioctl(struct drm_device
> *dev, void *data,
> __xe_bo_unset_bulk_move(bo);
> xe_vm_unlock(vm);
> }
> + if (bo->flags & XE_BO_FLAG_PINNED) {
> + xe_bo_lock(bo, false);
> + xe_bo_unpin_user(bo);
> + xe_bo_unlock(bo);
> + }
> out_put:
> xe_bo_put(bo);
> out_vm:
> diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c
> b/drivers/gpu/drm/xe/xe_dma_buf.c
> index 346f857f38374..6719f4552ad37 100644
> --- a/drivers/gpu/drm/xe/xe_dma_buf.c
> +++ b/drivers/gpu/drm/xe/xe_dma_buf.c
> @@ -53,6 +53,11 @@ static int xe_dma_buf_pin(struct
> dma_buf_attachment *attach)
> struct xe_device *xe = xe_bo_device(bo);
> int ret;
>
> + if (bo->flags & XE_BO_FLAG_PINNED) {
> + ttm_bo_pin(&bo->ttm);
> + return 0;
> + }
> +
> /*
> * For now only support pinning in TT memory, for two
> reasons:
> * 1) Avoid pinning in a placement not accessible to some
> importers.
> @@ -83,7 +88,10 @@ static void xe_dma_buf_unpin(struct
> dma_buf_attachment *attach)
> struct drm_gem_object *obj = attach->dmabuf->priv;
> struct xe_bo *bo = gem_to_xe_bo(obj);
>
> - xe_bo_unpin_external(bo);
> + if (bo->flags & XE_BO_FLAG_PINNED)
> + ttm_bo_unpin(&bo->ttm);
> + else
> + xe_bo_unpin_external(bo);
> }
>
> static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment
> *attach,
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index c721e130c1d2d..3184fa38ce17e 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -765,12 +765,15 @@ struct drm_xe_device_query {
> * until the object is either bound to a virtual memory region
> via
> * VM_BIND or accessed by the CPU. As a result, no backing memory
> is
> * reserved at the time of GEM object creation.
> - * - %DRM_XE_GEM_CREATE_FLAG_SCANOUT
> + * - %DRM_XE_GEM_CREATE_FLAG_SCANOUT - GEM object will be used
> + * display framebuffer.
> * - %DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM - When using VRAM
> as a
> * possible placement, ensure that the corresponding VRAM
> allocation
> * will always use the CPU accessible part of VRAM. This is
> important
> * for small-bar systems (on full-bar systems this gets turned
> into a
> * noop).
> + * - %DRM_XE_GEM_CREATE_FLAG_PINNED - Pin the backing memory
> permanently
> + * on allocation, if withing cgroups limits.
> * Note1: System memory can be used as an extra placement if the
> kernel
> * should spill the allocation to system memory, if space can't
> be made
> * available in the CPU accessible part of VRAM (giving the same
> @@ -781,6 +784,10 @@ struct drm_xe_device_query {
> * need to use VRAM for display surfaces, therefore the kernel
> requires
> * setting this flag for such objects, otherwise an error is
> thrown on
> * small-bar systems.
> + * Note3: %DRM_XE_GEM_CREATE_FLAG_PINNED requires the BO to have
> only
> + * a single placement, no vm_id, requires (device) memory cgroups
> enabled,
> + * and is incompatible with the %DEFER_BACKING and
> %NEEDS_VISIBLE_VRAM
> + * flags.
> *
> * @cpu_caching supports the following values:
> * - %DRM_XE_GEM_CPU_CACHING_WB - Allocate the pages with write-
> back
> @@ -827,6 +834,7 @@ struct drm_xe_gem_create {
> #define DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING (1 << 0)
> #define DRM_XE_GEM_CREATE_FLAG_SCANOUT (1 << 1)
> #define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM (1 << 2)
> +#define DRM_XE_GEM_CREATE_FLAG_PINNED (1 << 3)
> /**
> * @flags: Flags, currently a mask of memory instances of
> where BO can
> * be placed
Powered by blists - more mailing lists