On 2025-07-24 22:43, Zhu Lingshan wrote:
This commit implemetns a new ioctl AMDKFD_IOC_CREATE_PROCESS
that creates a new secondary kfd_progress on the FD.

To add a new ioctl upstream, do you have a link to the corresponding user mode changes?

Other than that, this patch looks good to me.

Regards,
  Felix



To keep backward compatibility, userspace programs need to invoke
this ioctl explicitly on a FD to create a secondary
kfd_process which replacing its primary kfd_process.

This commit bumps ioctl minor version.

Signed-off-by: Zhu Lingshan <lingshan....@amd.com>
---
  drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 41 ++++++++++++++++++++++++
  drivers/gpu/drm/amd/amdkfd/kfd_priv.h    |  1 +
  drivers/gpu/drm/amd/amdkfd/kfd_process.c |  3 +-
  include/uapi/linux/kfd_ioctl.h           |  8 +++--
  4 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 5b22e1c47b2e..f9c43ff8a89f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -3136,6 +3136,44 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, 
struct kfd_process *p, v
        return r;
  }
+/* userspace programs need to invoke this ioctl explicitly on a FD to
+ * create a secondary kfd_process which replacing its primary kfd_process
+ */
+static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, 
void *data)
+{
+       struct kfd_process *process;
+       int ret;
+
+       if (!filep->private_data || !p)
+               return -EINVAL;
+
+       if (p != filep->private_data)
+               return -EINVAL;
+
+       /* Each FD owns only one kfd_process */
+       if (!p->primary)
+               return -EINVAL;
+
+       mutex_lock(&kfd_processes_mutex);
+       process = create_process(current, false);
+       mutex_unlock(&kfd_processes_mutex);
+
+       if (IS_ERR(process))
+               return PTR_ERR(process);
+
+       /* Each open() increases kref of the primary kfd_process,
+        * so we need to reduce it here before we create a new secondary 
process replacing it
+        */
+       kfd_unref_process(p);
+
+       filep->private_data = process;
+       ret = kfd_create_process_sysfs(process);
+       if (ret)
+               pr_warn("Failed to create sysfs entry for the kfd_process");
+
+       return 0;
+}
+
  #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \
        [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \
                            .cmd_drv = 0, .name = #ioctl}
@@ -3254,6 +3292,9 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_TRAP,
                        kfd_ioctl_set_debug_trap, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_PROCESS,
+                       kfd_ioctl_create_process, 0),
  };
#define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h 
b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index a6e12c705734..a2b5081fbfc0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -1051,6 +1051,7 @@ struct kfd_process *kfd_get_process(const struct 
task_struct *task);
  struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid,
                                                 struct kfd_process_device 
**pdd);
  struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm);
+struct kfd_process *create_process(const struct task_struct *thread, bool 
primary);
int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id);
  int kfd_process_gpuid_from_node(struct kfd_process *p, struct kfd_node *node,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index e1ba9015bb83..15a8de2275f4 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -71,7 +71,6 @@ static struct workqueue_struct *kfd_restore_wq;
  static struct kfd_process *find_process(const struct task_struct *thread,
                                        bool ref);
  static void kfd_process_ref_release(struct kref *ref);
-static struct kfd_process *create_process(const struct task_struct *thread, 
bool primary);
static void evict_process_worker(struct work_struct *work);
  static void restore_process_worker(struct work_struct *work);
@@ -1598,7 +1597,7 @@ void kfd_process_set_trap_debug_flag(struct 
qcm_process_device *qpd,
   * On return the kfd_process is fully operational and will be freed when the
   * mm is released
   */
-static struct kfd_process *create_process(const struct task_struct *thread, 
bool primary)
+struct kfd_process *create_process(const struct task_struct *thread, bool 
primary)
  {
        struct kfd_process *process;
        struct mmu_notifier *mn;
diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h
index 04c7d283dc7d..1d206ecc831e 100644
--- a/include/uapi/linux/kfd_ioctl.h
+++ b/include/uapi/linux/kfd_ioctl.h
@@ -44,9 +44,10 @@
   * - 1.16 - Add contiguous VRAM allocation flag
   * - 1.17 - Add SDMA queue creation with target SDMA engine ID
   * - 1.18 - Rename pad in set_memory_policy_args to misc_process_flag
+ * - 1.19 - Add a new ioctl to craete secondary kfd processes
   */
  #define KFD_IOCTL_MAJOR_VERSION 1
-#define KFD_IOCTL_MINOR_VERSION 18
+#define KFD_IOCTL_MINOR_VERSION 19
struct kfd_ioctl_get_version_args {
        __u32 major_version;    /* from KFD */
@@ -1671,7 +1672,10 @@ struct kfd_ioctl_dbg_trap_args {
  #define AMDKFD_IOC_DBG_TRAP                   \
                AMDKFD_IOWR(0x26, struct kfd_ioctl_dbg_trap_args)
+#define AMDKFD_IOC_CREATE_PROCESS \
+               AMDKFD_IO(0x27)
+
  #define AMDKFD_COMMAND_START          0x01
-#define AMDKFD_COMMAND_END             0x27
+#define AMDKFD_COMMAND_END             0x28
#endif

Reply via email to