mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
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 <Yongqiang.Sun@amd.com> Reviewed-by: Philip Yang <philip.yang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 319f7e13423ae3f486b9aea82f9ad2d6af0ee608) Cc: stable@vger.kernel.org
This commit is contained in:
parent
fbbbd98f20
commit
2b0386d429
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user