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 >
