Message ID | 20230329065532.2122295-1-davidgow@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/2] drm: buddy_allocator: Fix buddy allocator init on 32-bit systems | expand |
Am 29.03.23 um 08:55 schrieb David Gow: > The drm buddy allocator tests were broken on 32-bit systems, as > rounddown_pow_of_two() takes a long, and the buddy allocator handles > 64-bit sizes even on 32-bit systems. > > This can be reproduced with the drm_buddy_allocator KUnit tests on i386: > ./tools/testing/kunit/kunit.py run --arch i386 \ > --kunitconfig ./drivers/gpu/drm/tests drm_buddy > > (It results in kernel BUG_ON() when too many blocks are created, due to > the block size being too small.) > > This was independently uncovered (and fixed) by Luís Mendes, whose patch > added a new u64 variant of rounddown_pow_of_two(). This version instead > recalculates the size based on the order. > > Reported-by: Luís Mendes <luis.p.mendes@gmail.com> > Link: https://lore.kernel.org/lkml/CAEzXK1oghXAB_KpKpm=-CviDQbNaH0qfgYTSSjZgvvyj4U78AA@mail.gmail.com/T/ > Signed-off-by: David Gow <davidgow@google.com> Acked-by: Christian König <christian.koenig@amd.com> for the series. > --- > drivers/gpu/drm/drm_buddy.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c > index 3d1f50f481cf..7098f125b54a 100644 > --- a/drivers/gpu/drm/drm_buddy.c > +++ b/drivers/gpu/drm/drm_buddy.c > @@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size) > unsigned int order; > u64 root_size; > > - root_size = rounddown_pow_of_two(size); > - order = ilog2(root_size) - ilog2(chunk_size); > + order = ilog2(size) - ilog2(chunk_size); > + root_size = chunk_size << order; > > root = drm_block_alloc(mm, NULL, order, offset); > if (!root)
On Wed, 29 Mar 2023, David Gow <davidgow@google.com> wrote: > The drm buddy allocator tests were broken on 32-bit systems, as > rounddown_pow_of_two() takes a long, and the buddy allocator handles > 64-bit sizes even on 32-bit systems. > > This can be reproduced with the drm_buddy_allocator KUnit tests on i386: > ./tools/testing/kunit/kunit.py run --arch i386 \ > --kunitconfig ./drivers/gpu/drm/tests drm_buddy > > (It results in kernel BUG_ON() when too many blocks are created, due to > the block size being too small.) > > This was independently uncovered (and fixed) by Luís Mendes, whose patch > added a new u64 variant of rounddown_pow_of_two(). This version instead > recalculates the size based on the order. > > Reported-by: Luís Mendes <luis.p.mendes@gmail.com> > Link: https://lore.kernel.org/lkml/CAEzXK1oghXAB_KpKpm=-CviDQbNaH0qfgYTSSjZgvvyj4U78AA@mail.gmail.com/T/ > Signed-off-by: David Gow <davidgow@google.com> > --- > drivers/gpu/drm/drm_buddy.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c > index 3d1f50f481cf..7098f125b54a 100644 > --- a/drivers/gpu/drm/drm_buddy.c > +++ b/drivers/gpu/drm/drm_buddy.c > @@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size) > unsigned int order; > u64 root_size; > > - root_size = rounddown_pow_of_two(size); > - order = ilog2(root_size) - ilog2(chunk_size); > + order = ilog2(size) - ilog2(chunk_size); > + root_size = chunk_size << order; Just noticed near the beginning of the function there's also: if (!is_power_of_2(chunk_size)) return -EINVAL; which is also wrong for 32-bit. BR, Jani. > > root = drm_block_alloc(mm, NULL, order, offset); > if (!root)
Am 30.03.23 um 12:53 schrieb Jani Nikula: > On Wed, 29 Mar 2023, David Gow <davidgow@google.com> wrote: >> The drm buddy allocator tests were broken on 32-bit systems, as >> rounddown_pow_of_two() takes a long, and the buddy allocator handles >> 64-bit sizes even on 32-bit systems. >> >> This can be reproduced with the drm_buddy_allocator KUnit tests on i386: >> ./tools/testing/kunit/kunit.py run --arch i386 \ >> --kunitconfig ./drivers/gpu/drm/tests drm_buddy >> >> (It results in kernel BUG_ON() when too many blocks are created, due to >> the block size being too small.) >> >> This was independently uncovered (and fixed) by Luís Mendes, whose patch >> added a new u64 variant of rounddown_pow_of_two(). This version instead >> recalculates the size based on the order. >> >> Reported-by: Luís Mendes <luis.p.mendes@gmail.com> >> Link: https://lore.kernel.org/lkml/CAEzXK1oghXAB_KpKpm=-CviDQbNaH0qfgYTSSjZgvvyj4U78AA@mail.gmail.com/T/ >> Signed-off-by: David Gow <davidgow@google.com> >> --- >> drivers/gpu/drm/drm_buddy.c | 4 ++-- >> 1 file changed, 2 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c >> index 3d1f50f481cf..7098f125b54a 100644 >> --- a/drivers/gpu/drm/drm_buddy.c >> +++ b/drivers/gpu/drm/drm_buddy.c >> @@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size) >> unsigned int order; >> u64 root_size; >> >> - root_size = rounddown_pow_of_two(size); >> - order = ilog2(root_size) - ilog2(chunk_size); >> + order = ilog2(size) - ilog2(chunk_size); >> + root_size = chunk_size << order; > Just noticed near the beginning of the function there's also: > > if (!is_power_of_2(chunk_size)) > return -EINVAL; > > which is also wrong for 32-bit. Yeah, but that isn't vital. We just use u64 for the chunk_size for consistency. In reality I wouldn't except more than 256K here. Regards, Christian. > > > BR, > Jani. > > >> >> root = drm_block_alloc(mm, NULL, order, offset); >> if (!root)
On Thu, 30 Mar 2023, Christian König <christian.koenig@amd.com> wrote: > Am 30.03.23 um 12:53 schrieb Jani Nikula: >> On Wed, 29 Mar 2023, David Gow <davidgow@google.com> wrote: >>> The drm buddy allocator tests were broken on 32-bit systems, as >>> rounddown_pow_of_two() takes a long, and the buddy allocator handles >>> 64-bit sizes even on 32-bit systems. >>> >>> This can be reproduced with the drm_buddy_allocator KUnit tests on i386: >>> ./tools/testing/kunit/kunit.py run --arch i386 \ >>> --kunitconfig ./drivers/gpu/drm/tests drm_buddy >>> >>> (It results in kernel BUG_ON() when too many blocks are created, due to >>> the block size being too small.) >>> >>> This was independently uncovered (and fixed) by Luís Mendes, whose patch >>> added a new u64 variant of rounddown_pow_of_two(). This version instead >>> recalculates the size based on the order. >>> >>> Reported-by: Luís Mendes <luis.p.mendes@gmail.com> >>> Link: https://lore.kernel.org/lkml/CAEzXK1oghXAB_KpKpm=-CviDQbNaH0qfgYTSSjZgvvyj4U78AA@mail.gmail.com/T/ >>> Signed-off-by: David Gow <davidgow@google.com> >>> --- >>> drivers/gpu/drm/drm_buddy.c | 4 ++-- >>> 1 file changed, 2 insertions(+), 2 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c >>> index 3d1f50f481cf..7098f125b54a 100644 >>> --- a/drivers/gpu/drm/drm_buddy.c >>> +++ b/drivers/gpu/drm/drm_buddy.c >>> @@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size) >>> unsigned int order; >>> u64 root_size; >>> >>> - root_size = rounddown_pow_of_two(size); >>> - order = ilog2(root_size) - ilog2(chunk_size); >>> + order = ilog2(size) - ilog2(chunk_size); >>> + root_size = chunk_size << order; >> Just noticed near the beginning of the function there's also: >> >> if (!is_power_of_2(chunk_size)) >> return -EINVAL; >> >> which is also wrong for 32-bit. > > Yeah, but that isn't vital. We just use u64 for the chunk_size for > consistency. > > In reality I wouldn't except more than 256K here. Right. It's just not pedantically correct either. ;) is_power_of_2() is pretty scary as it is, since it just truncates. BR, Jani. > > Regards, > Christian. > >> >> >> BR, >> Jani. >> >> >>> >>> root = drm_block_alloc(mm, NULL, order, offset); >>> if (!root) >
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 3d1f50f481cf..7098f125b54a 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size) unsigned int order; u64 root_size; - root_size = rounddown_pow_of_two(size); - order = ilog2(root_size) - ilog2(chunk_size); + order = ilog2(size) - ilog2(chunk_size); + root_size = chunk_size << order; root = drm_block_alloc(mm, NULL, order, offset); if (!root)
The drm buddy allocator tests were broken on 32-bit systems, as rounddown_pow_of_two() takes a long, and the buddy allocator handles 64-bit sizes even on 32-bit systems. This can be reproduced with the drm_buddy_allocator KUnit tests on i386: ./tools/testing/kunit/kunit.py run --arch i386 \ --kunitconfig ./drivers/gpu/drm/tests drm_buddy (It results in kernel BUG_ON() when too many blocks are created, due to the block size being too small.) This was independently uncovered (and fixed) by Luís Mendes, whose patch added a new u64 variant of rounddown_pow_of_two(). This version instead recalculates the size based on the order. Reported-by: Luís Mendes <luis.p.mendes@gmail.com> Link: https://lore.kernel.org/lkml/CAEzXK1oghXAB_KpKpm=-CviDQbNaH0qfgYTSSjZgvvyj4U78AA@mail.gmail.com/T/ Signed-off-by: David Gow <davidgow@google.com> --- drivers/gpu/drm/drm_buddy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)