get_queue_checkpoint_info() reports mqd_size as the per-XCC MQD
size times NUM_XCC, and checkpoint_mqd_v9_4_3() stores one MQD per XCC.
The mqd_size check added to the CRIU restore path compares against the
single per-XCC size, so every checkpoint image of a queue on a multi-XCC
node is rejected with -EINVAL.

Worse, a single-MQD size is the only value that check accepts there, and
restore_mqd_v9_4_3() then reads one MQD per XCC from a buffer holding
only one, copying up to (NUM_XCC - 1) * sizeof(struct v9_mqd) bytes of
adjacent kernel heap into the queue's MQD.

Make mqd_size_from_queue_type() return the size checkpoint writes, so a
restore image must carry exactly one MQD per XCC. With that,
restore_mqd_v9_4_3() must also not keep the image's cp_mqd_stride_size:
checkpoint and get_wave_state() step through the per-XCC MQDs with it,
so set it to the stride of the new allocation as init_mqd_v9_4_3() does.

Restore only MQD types that have checkpoint_mqd(), since no other image
layout exists. GFX12 and GFX12.1 have restore_mqd() but no checkpoint
yet, and restore_mqd_v12_1() handles XCC0 only, so a multi-XCC GFX12.1
image would now pass the size check and leave XCC1..N with zeroed MQDs.

Fixes: c76bcb1cfce6 ("drm/amdkfd: Check bounds on CRIU restore queue type and 
mqd size")
Signed-off-by: William Palacek <[email protected]>
---
 .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 15 ++++++++++-----
 .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c    |  9 +--------
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c   |  1 +
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 5e57576fba21..88bbef08c39c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -816,8 +816,9 @@ static int create_queue_nocpsch(struct device_queue_manager 
*dqm,
 
        mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
                        q->properties.type)];
-       if (qd && !mqd_mgr->restore_mqd) {
-               pr_debug("restore_mqd not implemented for queue type %d\n",
+       /* Restore takes the image layout that checkpoint_mqd() writes */
+       if (qd && (!mqd_mgr->restore_mqd || !mqd_mgr->checkpoint_mqd)) {
+               pr_debug("CRIU not implemented for queue type %d\n",
                         q->properties.type);
                retval = -EOPNOTSUPP;
                goto deallocate_vmid;
@@ -2399,8 +2400,9 @@ static int create_queue_cpsch(struct device_queue_manager 
*dqm, struct queue *q,
 
        mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
                        q->properties.type)];
-       if (qd && !mqd_mgr->restore_mqd) {
-               pr_debug("restore_mqd not implemented for queue type %d\n",
+       /* Restore takes the image layout that checkpoint_mqd() writes */
+       if (qd && (!mqd_mgr->restore_mqd || !mqd_mgr->checkpoint_mqd)) {
+               pr_debug("CRIU not implemented for queue type %d\n",
                         q->properties.type);
                retval = -EOPNOTSUPP;
                goto out_deallocate_doorbell;
@@ -4123,7 +4125,10 @@ bool kfd_dqm_is_queue_in_process(struct 
device_queue_manager *dqm,
 
 size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, enum 
kfd_queue_type type)
 {
-       return dqm->mqd_mgrs[get_mqd_type_from_queue_type(type)]->mqd_size;
+       struct mqd_manager *mqd_mgr = 
dqm->mqd_mgrs[get_mqd_type_from_queue_type(type)];
+
+       /* Checkpoint stores one MQD per XCC, see get_queue_checkpoint_info() */
+       return mqd_mgr->mqd_size * NUM_XCC(mqd_mgr->dev->xcc_mask);
 }
 
 #if defined(CONFIG_DEBUG_FS)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c
index 79e0d6250720..4eac85a654cb 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c
@@ -670,14 +670,7 @@ static void restore_mqd_v12_1(struct mqd_manager *mm, void 
**mqd,
        u64 addr;
        struct v12_1_compute_mqd *m;
 
-       /*
-        * GFX12.1 is multi-XCC capable but this restore handles XCC0 only.
-        * Multi-XCC CRIU restore is currently unreachable because
-        * kfd_criu_restore_queue() validates against unscaled mqd_size.
-        */
-       if (NUM_XCC(mm->dev->xcc_mask) > 1)
-               pr_warn_once("GFX12.1 multi-XCC CRIU restore not fully 
supported\n");
-
+       /* Handles XCC0 only, unreachable until there is a checkpoint_mqd() */
        m = (struct v12_1_compute_mqd *)mqd_mem_obj->cpu_ptr;
        addr = mqd_mem_obj->gpu_addr;
 
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
index 948415908551..d95a28a80917 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -864,6 +864,7 @@ static void restore_mqd_v9_4_3(struct mqd_manager *mm, void 
**mqd,
                                        (uint8_t *)mqd_src + xcc * sizeof(*m),
                                        (uint8_t *)ctl_stack_src + xcc *  
mqd_ctl_stack_size,
                                        mqd_ctl_stack_size);
+               m->cp_mqd_stride_size = offset;
        }
 
        if (mqd_on_vram(mm->dev->adev))
-- 
2.43.0

Reply via email to