On 5/26/26 18:06, Tvrtko Ursulin wrote:
> Add a new flag (AMDGPU_GEM_LIST_HANDLES_FLAG_IS_USERPTR) to the
> DRM_IOCTL_AMDGPU_GEM_LIST_CONTEXTS ioctl.
>
> This is required to allow for checkpoint and restore of userptr objects.
>
> The existing struct drm_amdgpu_gem_list_handles_entry is used with the
> userptr creation flags places in alloc_flags, while the alignment field
> contains the userspace address.
>
> Signed-off-by: Tvrtko Ursulin <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 18 +++++++----
> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 40 +++++++++++++++++--------
> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 19 +++++++++++-
> include/uapi/drm/amdgpu_drm.h | 7 +++--
> 4 files changed, 61 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index 0259d81e5157..5eb8433229b4 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -1186,14 +1186,20 @@ int amdgpu_gem_list_handles_ioctl(struct drm_device
> *dev, void *data,
>
> bo_entry = &bo_entries[bo_index];
>
> - bo_entry->size = amdgpu_bo_size(bo);
> - bo_entry->alloc_flags = bo->flags &
> AMDGPU_GEM_CREATE_SETTABLE_MASK;
> - bo_entry->preferred_domains = bo->preferred_domains;
> bo_entry->gem_handle = id;
> - bo_entry->alignment = bo->tbo.page_alignment;
> + bo_entry->size = amdgpu_bo_size(bo);
> + if (amdgpu_ttm_tt_is_userptr(bo->tbo.ttm)) {
> + bo_entry->flags =
> AMDGPU_GEM_LIST_HANDLES_FLAG_IS_USERPTR;
> + bo_entry->alloc_flags =
> amdgpu_ttm_tt_get_userptr_flags(bo->tbo.ttm);
> + bo_entry->alignment =
> amdgpu_ttm_tt_get_userptr_addr(bo->tbo.ttm);
> + } else {
> + bo_entry->alloc_flags = bo->flags &
> AMDGPU_GEM_CREATE_SETTABLE_MASK;
> + bo_entry->preferred_domains = bo->preferred_domains;
> + bo_entry->alignment = bo->tbo.page_alignment;
>
> - if (bo->tbo.base.import_attach)
> - bo_entry->flags |=
> AMDGPU_GEM_LIST_HANDLES_FLAG_IS_IMPORT;
> + if (bo->tbo.base.import_attach)
> + bo_entry->flags =
> AMDGPU_GEM_LIST_HANDLES_FLAG_IS_IMPORT;
> + }
>
> bo_index += 1;
> }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> index 3d2e00efc741..4023c84fe29d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> @@ -767,6 +767,33 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> return r;
> }
>
> +/*
> + * amdgpu_ttm_tt_is_userptr - Have the pages backing by userptr?
> + */
> +bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm)
> +{
> + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
> +
> + if (gtt == NULL || !gtt->userptr)
> + return false;
> +
> + return true;
> +}
> +
> +u32 amdgpu_ttm_tt_get_userptr_flags(struct ttm_tt *ttm)
> +{
> + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
> +
> + return gtt->userflags;
> +}
> +
> +u64 amdgpu_ttm_tt_get_userptr_addr(struct ttm_tt *ttm)
> +{
> + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
> +
> + return gtt->userptr;
> +}
> +
> #endif
>
> /*
> @@ -1374,19 +1401,6 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm,
> unsigned long start,
> return true;
> }
>
> -/*
> - * amdgpu_ttm_tt_is_userptr - Have the pages backing by userptr?
> - */
> -bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm)
> -{
> - struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm);
> -
> - if (gtt == NULL || !gtt->userptr)
> - return false;
> -
> - return true;
> -}
> -
> /*
> * amdgpu_ttm_tt_is_readonly - Is the ttm_tt object read only?
> */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> index f2f23a42b3cc..8c0424577dea 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> @@ -211,12 +211,30 @@ uint64_t amdgpu_ttm_domain_start(struct amdgpu_device
> *adev, uint32_t type);
> #if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
> int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> struct amdgpu_hmm_range *range);
> +bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm);
> +u32 amdgpu_ttm_tt_get_userptr_flags(struct ttm_tt *ttm);
> +u64 amdgpu_ttm_tt_get_userptr_addr(struct ttm_tt *ttm);
> #else
> static inline int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
> struct amdgpu_hmm_range *range)
> {
> return -EPERM;
> }
> +
> +static inline bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm)
> +{
> + return false;
> +}
> +
> +static inline u32 amdgpu_ttm_tt_get_userptr_flags(struct ttm_tt *ttm)
> +{
> + return -1;
> +}
> +
> +static inline u64 amdgpu_ttm_tt_get_userptr_addr(struct ttm_tt *ttm)
> +{
> + return 0;
> +}
> #endif
>
> /**
> @@ -251,7 +269,6 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm,
> unsigned long start,
> unsigned long end, unsigned long *userptr);
> bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm,
> int *last_invalidated);
> -bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm);
> bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm);
> uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource
> *mem);
> uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt
> *ttm,
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> index 9f3090db2f16..3069560ac26e 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -836,6 +836,7 @@ struct drm_amdgpu_gem_op {
> };
>
> #define AMDGPU_GEM_LIST_HANDLES_FLAG_IS_IMPORT (1 << 0)
> +#define AMDGPU_GEM_LIST_HANDLES_FLAG_IS_USERPTR (1 << 1)
>
> struct drm_amdgpu_gem_list_handles {
> /* User pointer to array of drm_amdgpu_gem_bo_info_entry */
> @@ -851,7 +852,7 @@ struct drm_amdgpu_gem_list_handles_entry {
> /* gem handle of buffer object */
> __u32 gem_handle;
>
> - /* Currently just one flag: IS_IMPORT */
> + /* AMDGPU_GEM_LIST_HANDLES_FLAG_* */
> __u32 flags;
>
> /* Size of bo */
> @@ -860,10 +861,10 @@ struct drm_amdgpu_gem_list_handles_entry {
> /* Preferred domains for GEM_CREATE */
> __u64 preferred_domains;
>
> - /* GEM_CREATE flags for re-creation of buffer */
> + /* GEM_CREATE flags for re-creation of buffer or
> drm_amdgpu_gem_userptr.flags */
> __u64 alloc_flags;
>
> - /* physical start_addr alignment in bytes for some HW requirements */
> + /* physical start_addr alignment in bytes for some HW requirements or
> drm_amdgpu_gem_userptr.addr */
> __u64 alignment;
Make that an union, e.g. union { __u64 alignment; __u64 userptr; }, apart looks
pretty good to me.
Regards,
Christian.
> };
>