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
