On Wed, Jul 8, 2026 at 12:54 PM Yongqiang Sun <[email protected]> wrote:
>
> total_cwsr_size was computed in 32-bit before being used as a BO/SVM
> allocation size.
> With large ctx_save_restore_area_size and debug_memory_size
> multiplied by the XCC count, the product can wrap,
> yielding an undersized CWSR save area that firmware later overruns.
>
> Promote total_cwsr_size to u64 and use check_add_overflow()/
> check_mul_overflow() in both kfd_queue_acquire_buffers() and
> kfd_queue_release_buffers().
>
> Signed-off-by: Yongqiang Sun <[email protected]>

Acked-by: Alex Deucher <[email protected]>

> ---
>  drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c 
> b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> index 9d4838461168..01e228fc1860 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> @@ -23,6 +23,7 @@
>   */
>
>  #include <linux/slab.h>
> +#include <linux/overflow.h>
>  #include "kfd_priv.h"
>  #include "kfd_topology.h"
>  #include "kfd_svm.h"
> @@ -235,7 +236,7 @@ int kfd_queue_acquire_buffers(struct kfd_process_device 
> *pdd, struct queue_prope
>         struct kfd_topology_device *topo_dev;
>         u64 expected_queue_size;
>         struct amdgpu_vm *vm;
> -       u32 total_cwsr_size;
> +       u64 total_cwsr_size;
>         int err;
>
>         topo_dev = kfd_topology_device_by_id(pdd->dev->id);
> @@ -308,8 +309,14 @@ int kfd_queue_acquire_buffers(struct kfd_process_device 
> *pdd, struct queue_prope
>                 goto out_err_unreserve;
>         }
>
> -       total_cwsr_size = (properties->ctx_save_restore_area_size +
> -                          topo_dev->node_props.debug_memory_size) * 
> NUM_XCC(pdd->dev->xcc_mask);
> +       total_cwsr_size = (u64)properties->ctx_save_restore_area_size +
> +                         topo_dev->node_props.debug_memory_size;
> +       if (check_mul_overflow(total_cwsr_size,
> +                              NUM_XCC(pdd->dev->xcc_mask),
> +                              &total_cwsr_size)) {
> +               err = -EINVAL;
> +               goto out_err_unreserve;
> +       }
>         total_cwsr_size = ALIGN(total_cwsr_size, PAGE_SIZE);
>
>         err = kfd_queue_buffer_get(vm, (void 
> *)properties->ctx_save_restore_area_address,
> @@ -344,7 +351,7 @@ int kfd_queue_acquire_buffers(struct kfd_process_device 
> *pdd, struct queue_prope
>  int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct 
> queue_properties *properties)
>  {
>         struct kfd_topology_device *topo_dev;
> -       u32 total_cwsr_size;
> +       u64 total_cwsr_size;
>
>         kfd_queue_buffer_put(&properties->wptr_bo);
>         kfd_queue_buffer_put(&properties->rptr_bo);
> @@ -355,8 +362,12 @@ int kfd_queue_release_buffers(struct kfd_process_device 
> *pdd, struct queue_prope
>         topo_dev = kfd_topology_device_by_id(pdd->dev->id);
>         if (!topo_dev)
>                 return -EINVAL;
> -       total_cwsr_size = (properties->ctx_save_restore_area_size +
> -                          topo_dev->node_props.debug_memory_size) * 
> NUM_XCC(pdd->dev->xcc_mask);
> +       total_cwsr_size = (u64)properties->ctx_save_restore_area_size +
> +                         topo_dev->node_props.debug_memory_size;
> +       if (check_mul_overflow(total_cwsr_size,
> +                              NUM_XCC(pdd->dev->xcc_mask),
> +                              &total_cwsr_size))
> +               return -EINVAL;
>         total_cwsr_size = ALIGN(total_cwsr_size, PAGE_SIZE);
>
>         kfd_queue_buffer_svm_put(pdd, 
> properties->ctx_save_restore_area_address, total_cwsr_size);
> --
> 2.43.0
>

Reply via email to