>> +
>> +     if (q_data->type == KFD_QUEUE_TYPE_COMPUTE) {
>> +             if (q_data->ctl_stack_size)
>> +                     qp->ctl_stack_size = q_data->ctl_stack_size / num_xcc;
>> +             else if (topo_dev)
>> +                     qp->ctl_stack_size = 
>> topo_dev->node_props.ctl_stack_size;
>
>I'm curious what this case is needed for. In what circumstances would a
>CRIU checkpoint contain 0 ctl_stack_size? And is that's the case,
>wouldn't that break restore anyway?
>

A lot of mqd managers don't set mqd->get_checkpoint_info,
so the ctl_stack_size ends up as 0.

kfd_queue_acquire_buffers requires the ctl_stack_size to be equal to
topo_dev->node_props.ctl_stack_size anyways, so I think it
makes sense to default to that value if the input is 0.

David Francis

________________________________________
From: Kuehling, Felix <[email protected]>
Sent: Friday, October 30, 2026 5:15 PM
To: Francis, David; [email protected]
Cc: Koenig, Christian
Subject: Re: [PATCH v2 1/3] drm/amdkfd: Acquire buffers in CRIU queue restore 
(again)

On 2026-10-30 10:05, David Francis wrote:
> CRIU queue restore doesn't acquire the bo buffers in the same way
> normal queue creation does. In normal queue creation, the driver
> gets an additional reference on the queue's underlying buffers
> that lasts until the queue is destroyed; this prevents the
> queue's buffers from being removed from underneath it.
>
> Acquire them, but don't get the svm bo. SVM isn't yet fully
> restored by this point in CRIU and so there's no svm range to get.
> This will be addressed in the next patch.
>
> Signed-off-by: David Francis <[email protected]>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_chardev.c      |  2 +-
>   drivers/gpu/drm/amd/amdkfd/kfd_priv.h         |  2 +-
>   .../amd/amdkfd/kfd_process_queue_manager.c    | 34 +++++++++++++++++--
>   drivers/gpu/drm/amd/amdkfd/kfd_queue.c        |  8 ++++-
>   4 files changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> index 6c710e4a5220c..d8233337b8d5e 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> @@ -433,7 +433,7 @@ static int kfd_ioctl_create_queue(struct file *filep, 
> struct kfd_process *p,
>               goto err_bind_process;
>       }
>
> -     err = kfd_queue_acquire_buffers(pdd, &q_properties);
> +     err = kfd_queue_acquire_buffers(pdd, &q_properties, false);
>       if (err) {
>               pr_debug("failed to acquire user queue buffers\n");
>               goto err_acquire_queue_buf;
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h 
> b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> index f0ce5fc4a138f..eb4d35a42e917 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> @@ -1381,7 +1381,7 @@ void print_queue(struct queue *q);
>   int kfd_queue_buffer_get(struct amdgpu_vm *vm, void __user *addr, struct 
> amdgpu_bo **pbo,
>                        u64 expected_size);
>   void kfd_queue_buffer_put(struct amdgpu_bo **bo);
> -int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct 
> queue_properties *properties);
> +int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct 
> queue_properties *properties, bool is_criu);
>   int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct 
> queue_properties *properties);
>   void kfd_queue_unref_bo_va(struct amdgpu_vm *vm, struct amdgpu_bo **bo);
>   int kfd_queue_unref_bo_vas(struct kfd_process_device *pdd,
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> index 4c4a3a8587f46..509529af2dc3c 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> @@ -985,8 +985,14 @@ int kfd_criu_checkpoint_queues(struct kfd_process *p,
>   }
>
>   static void set_queue_properties_from_criu(struct queue_properties *qp,
> -                                       struct kfd_criu_queue_priv_data 
> *q_data)
> +                                        struct kfd_criu_queue_priv_data 
> *q_data,
> +                                        struct kfd_process_device *pdd)
>   {
> +     struct kfd_topology_device *topo_dev;
> +     uint32_t num_xcc = NUM_XCC(pdd->dev->xcc_mask);
> +
> +     topo_dev = kfd_topology_device_by_id(pdd->dev->id);
> +
>       qp->is_interop = false;
>       qp->queue_percent = q_data->q_percent;
>       qp->priority = q_data->priority;
> @@ -998,6 +1004,16 @@ static void set_queue_properties_from_criu(struct 
> queue_properties *qp,
>       qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size;
>       qp->ctx_save_restore_area_address = 
> q_data->ctx_save_restore_area_address;
>       qp->ctx_save_restore_area_size = q_data->ctx_save_restore_area_size;
> +
> +     if (q_data->type == KFD_QUEUE_TYPE_COMPUTE) {
> +             if (q_data->ctl_stack_size)
> +                     qp->ctl_stack_size = q_data->ctl_stack_size / num_xcc;
> +             else if (topo_dev)
> +                     qp->ctl_stack_size = 
> topo_dev->node_props.ctl_stack_size;

I'm curious what this case is needed for. In what circumstances would a
CRIU checkpoint contain 0 ctl_stack_size? And is that's the case,
wouldn't that break restore anyway?

Other than that, this patch looks good to me.

Regards,
   Felix


> +     } else {
> +             qp->ctl_stack_size = q_data->ctl_stack_size;
> +     }
> +
>       qp->type = q_data->type;
>       qp->format = q_data->format;
>   }
> @@ -1047,7 +1063,13 @@ int kfd_criu_restore_queue(struct kfd_process *p,
>       }
>
>       memset(&qp, 0, sizeof(qp));
> -     set_queue_properties_from_criu(&qp, q_data);
> +     set_queue_properties_from_criu(&qp, q_data, pdd);
> +
> +     if (q_data->type == KFD_QUEUE_TYPE_COMPUTE && !qp.ctl_stack_size) {
> +             pr_err("Failed to determine ctl_stack_size for compute 
> queue\n");
> +             ret = -EINVAL;
> +             goto exit;
> +     }
>
>       /* Per-XCC control stack size from topology, as create-queue requires */
>       if (qp.type == KFD_QUEUE_TYPE_COMPUTE && pdd->dev->kfd->cwsr_enabled) {
> @@ -1095,9 +1117,17 @@ int kfd_criu_restore_queue(struct kfd_process *p,
>
>       print_queue_properties(&qp);
>
> +     ret = kfd_queue_acquire_buffers(pdd, &qp, true);
> +     if (ret) {
> +             pr_err("Failed to acquire user queue buffers err:%d\n", ret);
> +             goto exit;
> +     }
> +
>       ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, 
> ctl_stack, NULL);
>       if (ret) {
>               pr_err("Failed to create new queue err:%d\n", ret);
> +             kfd_queue_unref_bo_vas(pdd, &qp);
> +             kfd_queue_release_buffers(pdd, &qp);
>               goto exit;
>       }
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> index 6010a5d7a7eb9..18d24ddb455eb 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> @@ -239,7 +239,7 @@ static void kfd_queue_put_bos(struct queue_properties 
> *properties)
>       kfd_queue_buffer_put(&properties->cwsr_bo);
>   }
>
> -int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct 
> queue_properties *properties)
> +int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct 
> queue_properties *properties, bool is_criu)
>   {
>       struct kfd_topology_device *topo_dev;
>       u64 expected_queue_size;
> @@ -334,6 +334,12 @@ int kfd_queue_acquire_buffers(struct kfd_process_device 
> *pdd, struct queue_prope
>
>       amdgpu_bo_unreserve(vm->root.bo);
>
> +     /* CRIU svm buffers are restored at a later stage than queues. They'll 
> be in
> +      * before the queue is actually used, so no risk here
> +      */
> +     if (is_criu)
> +             return 0;
> +
>       err = kfd_queue_buffer_svm_get(pdd, 
> properties->ctx_save_restore_area_address,
>                                      total_cwsr_size);
>       if (err)

Reply via email to