AMD General

Reviewed-by: Kent Russell <[email protected]>



> -----Original Message-----
> From: amd-gfx <[email protected]> On Behalf Of David
> Francis
> Sent: August 5, 2026 9:32 AM
> To: [email protected]
> Cc: Deucher, Alexander <[email protected]>; Francis, David
> <[email protected]>
> Subject: [PATCH] drm/amdkfd: Avoid integer underflow in EOP ring size
> calculation.
>
> The low 6 bits of cp_hqd_eop_control store the base-2 logarithm
> of the EOP ring size. This was calculated as
>
> order_base_2(q->eop_ring_buffer_size / 4) - 1
>
> But order_base_2 can in theory return 0, so this could underflow
> (although in practice the ring buffer size cannot be less than 4096).
>
> Change this to
>
> order_base_2(q->eop_ring_buffer_size / 8)
>
> using properties of logarithms.
>
> Also add to the above comment to make the mathematics more clear.
>
> Signed-off-by: David Francis <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 6 +++++-
>  drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 5 ++++-
>  2 files changed, 9 insertions(+), 2 deletions(-)
>
> 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 75e5a9f67d50..2c0d501bf527 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
> @@ -285,6 +285,10 @@ static void update_mqd(struct mqd_manager *mm, void
> *mqd,
>               1 << CP_HQD_IB_CONTROL__IB_EXE_DISABLE__SHIFT;
>
>       /*
> +      * The lowest 6 bits of eop_control store the EOP ring size. If
> +      * their value is X, the ring size is 2^(X + 1) dwords, or
> +      * 2^(X + 3) bytes.
> +      *
>        * HW does not clamp this field correctly. Maximum EOP queue size
>        * is constrained by per-SE EOP done signal count, which is 8-bit.
>        * Limit is 0xFF EOP entries (= 0x7F8 dwords). CP will not submit
> @@ -296,7 +300,7 @@ static void update_mqd(struct mqd_manager *mm, void
> *mqd,
>        *
>        */
>       m->cp_hqd_eop_control = q->eop_ring_buffer_size ?
> -             min(0xA, order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
> +             min(0xA, order_base_2(q->eop_ring_buffer_size / 8)) : 0;
>
>       m->cp_hqd_eop_base_addr_lo =
>                       lower_32_bits(q->eop_ring_buffer_address >> 8);
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
> b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
> index 60b87a500698..029572548c14 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
> @@ -208,6 +208,9 @@ static void __update_mqd(struct mqd_manager *mm,
> void *mqd,
>                       mtype << CP_HQD_IB_CONTROL__MTYPE__SHIFT;
>
>       /*
> +      * The lowest 6 bits of eop_control store the EOP ring size. If
> +      * their value is X, the ring size is 2^(X + 1) dwords, or
> +      * 2^(X + 3) bytes.
>        * HW does not clamp this field correctly. Maximum EOP queue size
>        * is constrained by per-SE EOP done signal count, which is 8-bit.
>        * Limit is 0xFF EOP entries (= 0x7F8 dwords). CP will not submit
> @@ -215,7 +218,7 @@ static void __update_mqd(struct mqd_manager *mm,
> void *mqd,
>        * is safe, giving a maximum field value of 0xA.
>        */
>       m->cp_hqd_eop_control |= q->eop_ring_buffer_size ? min(0xA,
> -             order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
> +             order_base_2(q->eop_ring_buffer_size / 8)) : 0;
>       m->cp_hqd_eop_base_addr_lo =
>                       lower_32_bits(q->eop_ring_buffer_address >> 8);
>       m->cp_hqd_eop_base_addr_hi =
> --
> 2.34.1

Reply via email to