[AMD Official Use Only - AMD Internal Distribution Only]
> -----Original Message-----
> From: Christian König <[email protected]>
> Sent: Tuesday, December 2, 2025 8:43 PM
> To: [email protected]; SHANMUGAM, SRINIVASAN
> <[email protected]>; Liu, Leo <[email protected]>; Dong,
> Ruijing <[email protected]>; [email protected]
> Subject: [RFC PATCH 2/3] drm/amdgpu: add
> AMDGPU_GEM_OP_OPEN_GLOBAL
>
> Instead of abusing the create IOCTL to open global BO add a new
> AMDGPU_GEM_OP_OPEN_GLOBAL functionality.
>
> The new AMDGPU_GEM_OP_OPEN_GLOBAL functionality expects an enum
> which tells it which global BO to open and copies the information about the
> BO to
> userspace similar to the AMDGPU_GEM_OP_GET_GEM_CREATE_INFO
> operation.
>
> The advantage is that we don't start overloading the create IOCTL with tons of
> special cases and opening the global BOs doesn't requires knowing the exact
> size
> and parameters of it in userspace any more.
>
> Heavily WIP and only compile tested.
>
> Signed-off-by: Christian König <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 26 ++++++++++++++++++++-----
> include/uapi/drm/amdgpu_drm.h | 5 ++++-
> 2 files changed, 25 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> index 9b81a6677f90..9e9b94dcb699 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
> @@ -968,22 +968,34 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void
> *data, int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
> struct drm_file *filp)
> {
> + struct amdgpu_fpriv *fpriv = filp->driver_priv;
> struct drm_amdgpu_gem_op *args = data;
> struct drm_gem_object *gobj;
> struct amdgpu_vm_bo_base *base;
> struct amdgpu_bo *robj;
> struct drm_exec exec;
> - struct amdgpu_fpriv *fpriv = filp->driver_priv;
> int r;
>
> if (args->padding)
> return -EINVAL;
>
> - gobj = drm_gem_object_lookup(filp, args->handle);
> - if (!gobj)
> - return -ENOENT;
> + if (args->op == AMDGPU_GEM_OP_OPEN_GLOBAL) {
> + switch (args->handle) {
> + case AMDGPU_GEM_GLOBAL_MMIO_REMAP:
> + robj = drm_to_adev(dev)->rmmio_remap.bo;
> + break;
> + default:
> + return -EINVAL;
> + }
> + gobj = &robj->tbo.base;
> + drm_gem_object_get(gobj);
> + } else {
> + gobj = drm_gem_object_lookup(filp, args->handle);
> + if (!gobj)
> + return -ENOENT;
>
> - robj = gem_to_amdgpu_bo(gobj);
> + robj = gem_to_amdgpu_bo(gobj);
> + }
>
For AMDGPU_GEM_OP_OPEN_GLOBAL, I think it would be nice to centralise the ID→BO
mapping into a small helper, e.g. amdgpu_get_global_bo(adev, id), and have it
return NULL if the global BO is not available on this device. Then the
OPEN_GLOBAL path can simply do:
robj = amdgpu_get_global_bo(drm_to_adev(dev), args->handle);
if (!robj)
return -EOPNOTSUPP;
That avoids the potential NULL deref on adev->rmmio_remap.bo when the remap
page isn’t present and also gives us a central place to extend with additional
AMDGPU_GEM_GLOBAL_* IDs in future.
Today, OPEN_GLOBAL switches on args->handle inside amdgpu_gem_op_ioctl():
switch (args->handle) {
case AMDGPU_GEM_GLOBAL_MMIO_REMAP:
robj = drm_to_adev(dev)->rmmio_remap.bo;
break;
default:
return -EINVAL;
}
Like adding a small helper
Add a small helper:
static struct amdgpu_bo *
amdgpu_get_global_bo(struct amdgpu_device *adev, u32 id)
{
switch (id) {
case AMDGPU_GEM_GLOBAL_MMIO_REMAP:
return adev->rmmio_remap.bo;
// future global BOs can be added here
default:
return NULL;
}
}
So, that only one function knows which global ID maps to which BO.
Easy to add new globals in future (DOORBELL, KFD, etc.).
UAPI and internal mapping stay in sync.
> drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT |
> DRM_EXEC_IGNORE_DUPLICATES, 0);
> @@ -1002,6 +1014,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void
> *data,
> }
>
> switch (args->op) {
> + case AMDGPU_GEM_OP_OPEN_GLOBAL:
for AMDGPU_GEM_OP_OPEN_GLOBAL we could treat args->value == 0 as “caller only
wants a handle, not the create_info”. In that case we can skip the
copy_to_user() entirely and just create the handle. Right now the code assumes
a non-NULL pointer for both GET_GEM_CREATE_INFO and OPEN_GLOBAL; relaxing that
for the latter would make the API a bit easier to use. (Optional not blocker)
case AMDGPU_GEM_OP_GET_GEM_CREATE_INFO: {
struct drm_amdgpu_gem_create_in info;
void __user *out = NULL;
r = amdgpu_gem_get_create_info(robj, &info);
if (r)
break;
/* For OPEN_GLOBAL, allow value == 0 when caller only wants the handle */
if (args->op == AMDGPU_GEM_OP_OPEN_GLOBAL && !args->value)
break;
out = u64_to_user_ptr(args->value);
if (copy_to_user(out, &info, sizeof(info)))
r = -EFAULT;
break;
}
> case AMDGPU_GEM_OP_GET_GEM_CREATE_INFO: {
> struct drm_amdgpu_gem_create_in info;
> void __user *out = u64_to_user_ptr(args->value); @@ -1096,6
> +1109,9 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
> r = -EINVAL;
> }
>
> + if (!r && args->op == AMDGPU_GEM_OP_OPEN_GLOBAL)
> + r = drm_gem_handle_create(filp, gobj, &args->handle);
> +
> drm_gem_object_put(gobj);
> return r;
> out_exec:
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> index
> c1336ed4ff75..6927c864a6d1 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -807,6 +807,9 @@ union drm_amdgpu_wait_fences {
> #define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0
> #define AMDGPU_GEM_OP_SET_PLACEMENT 1
> #define AMDGPU_GEM_OP_GET_MAPPING_INFO 2
> +#define AMDGPU_GEM_OP_OPEN_GLOBAL 3
> +
> +#define AMDGPU_GEM_GLOBAL_MMIO_REMAP 0
>
> struct drm_amdgpu_gem_vm_entry {
> /* Start of mapping (in bytes) */
> @@ -824,7 +827,7 @@ struct drm_amdgpu_gem_vm_entry {
>
> /* Sets or returns a value associated with a buffer. */ struct
> drm_amdgpu_gem_op
> {
> - /** GEM object handle */
> + /** GEM object handle or AMDGPU_GEM_GLOBAL_* */
For the UAPI docs, maybe can we add a short note that for
AMDGPU_GEM_OP_OPEN_GLOBAL the handle field is interpreted as an
AMDGPU_GEM_GLOBAL_* ID on input and overwritten with a per-file GEM handle on
success. That makes the dual use of handle a bit clearer for userspace.
> __u32 handle;
> /** AMDGPU_GEM_OP_* */
> __u32 op;
> --
> 2.43.0