* [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
@ 2026-07-06 19:18 Yongqiang Sun
2026-07-08 14:17 ` Philip Yang
0 siblings, 1 reply; 5+ messages in thread
From: Yongqiang Sun @ 2026-07-06 19:18 UTC (permalink / raw)
To: amd-gfx; +Cc: Yongqiang Sun
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>
---
drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 25 +++++++++++++++++++------
1 file changed, 19 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..4b1c1e379244 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,15 @@ 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);
+ if (check_add_overflow(properties->ctx_save_restore_area_size,
+ topo_dev->node_props.debug_memory_size,
+ &total_cwsr_size) ||
+ check_mul_overflow(total_cwsr_size,
+ (u64)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 +352,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 +363,13 @@ 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);
+ if (check_add_overflow(properties->ctx_save_restore_area_size,
+ topo_dev->node_props.debug_memory_size,
+ &total_cwsr_size) ||
+ check_mul_overflow(total_cwsr_size,
+ (u64)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
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
2026-07-06 19:18 [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation Yongqiang Sun
@ 2026-07-08 14:17 ` Philip Yang
0 siblings, 0 replies; 5+ messages in thread
From: Philip Yang @ 2026-07-08 14:17 UTC (permalink / raw)
To: Yongqiang Sun, amd-gfx
[-- Attachment #1: Type: text/plain, Size: 3901 bytes --]
On 2026-07-06 15:18, Yongqiang Sun 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<Yongqiang.Sun@amd.com>
> ---
> drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 25 +++++++++++++++++++------
> 1 file changed, 19 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..4b1c1e379244 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,15 @@ 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);
> + if (check_add_overflow(properties->ctx_save_restore_area_size,
> + topo_dev->node_props.debug_memory_size,
> + &total_cwsr_size) ||
Because properties->ctx_save_restore_area_size and
topo_dev->node_props.debug_memory_size are u32, total_cwsr_size is u64
now, check_add_overflow will never overflow to return true, use typecast
u64 add instead
total_cwsr_size = (u64)properties->ctx_save_restore_area_size + topo_dev->node_props.debug_memory_size;
> + check_mul_overflow(total_cwsr_size,
> + (u64)NUM_XCC(pdd->dev->xcc_mask),
Since total_cwsr_size is u64, NUM_XCC(pdd->dev->xcc_mask) will promote
to u64 as well, this u64 typecast is not needed.
> + &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 +352,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 +363,13 @@ 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);
> + if (check_add_overflow(properties->ctx_save_restore_area_size,
> + topo_dev->node_props.debug_memory_size,
> + &total_cwsr_size) ||
> + check_mul_overflow(total_cwsr_size,
> + (u64)NUM_XCC(pdd->dev->xcc_mask),
> + &total_cwsr_size))
Do the same change as above kfd_queue_acquire_buffers. Regards, Philip
> + 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);
[-- Attachment #2: Type: text/html, Size: 5198 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
@ 2026-07-08 16:43 Yongqiang Sun
2026-07-08 17:26 ` Philip Yang
2026-07-08 17:26 ` Alex Deucher
0 siblings, 2 replies; 5+ messages in thread
From: Yongqiang Sun @ 2026-07-08 16:43 UTC (permalink / raw)
To: amd-gfx; +Cc: Yongqiang Sun
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>
---
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
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
2026-07-08 16:43 Yongqiang Sun
@ 2026-07-08 17:26 ` Philip Yang
2026-07-08 17:26 ` Alex Deucher
1 sibling, 0 replies; 5+ messages in thread
From: Philip Yang @ 2026-07-08 17:26 UTC (permalink / raw)
To: Yongqiang Sun, amd-gfx
[-- Attachment #1: Type: text/plain, Size: 3409 bytes --]
On 2026-07-08 12:43, Yongqiang Sun 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()/
Remove check_add_overflow(), with this fixed, this patch is
Reviewed-by: Philip Yang<philip.yang@amd.com>
> check_mul_overflow() in both kfd_queue_acquire_buffers() and
> kfd_queue_release_buffers().
>
> Signed-off-by: Yongqiang Sun<Yongqiang.Sun@amd.com>
> ---
> 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);
[-- Attachment #2: Type: text/html, Size: 4261 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
2026-07-08 16:43 Yongqiang Sun
2026-07-08 17:26 ` Philip Yang
@ 2026-07-08 17:26 ` Alex Deucher
1 sibling, 0 replies; 5+ messages in thread
From: Alex Deucher @ 2026-07-08 17:26 UTC (permalink / raw)
To: Yongqiang Sun; +Cc: amd-gfx
On Wed, Jul 8, 2026 at 12:54 PM Yongqiang Sun <Yongqiang.Sun@amd.com> 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 <Yongqiang.Sun@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
> ---
> 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
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-08 17:27 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 19:18 [PATCH] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation Yongqiang Sun
2026-07-08 14:17 ` Philip Yang
-- strict thread matches above, loose matches on Subject: below --
2026-07-08 16:43 Yongqiang Sun
2026-07-08 17:26 ` Philip Yang
2026-07-08 17:26 ` Alex Deucher
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.