On Mon, Mar 09, 2026 at 10:46:03AM +0000, Tvrtko Ursulin wrote:
> 
> On 06/03/2026 18:00, Thadeu Lima de Souza Cascardo wrote:
> > Currently, ttm_bo_swapout is not exercised by the TTM KUnit tests.
> > 
> > It used to be exercised until commit 76689eb52667 ("drm/ttm: remove
> > ttm_bo_validate_swapout test"), but that test was removed as it was
> > unreliable due to requiring to allocate half of the system memory.
> > 
> > Calling ttm_bo_swapout directly with a single allocated BO, however, does
> > not suffer from that problem, and was able to detect a UAF introduced by
> > commit c06da4b3573a ("drm/ttm: Tidy usage of local variables a little
> > bit"), when built with KASAN.
> > 
> > When applying a fix to that UAF, the test passed without any issues.
> 
> Thank you for closing this gap and again for fixing up after me. I have some
> minor comments below, but the test looks good to me and either way:
> 
> Reviewed-by: Tvrtko Ursulin <[email protected]>
> 
> > 
> > Cc: Karolina Stolarek <[email protected]>
> > Cc: Tvrtko Ursulin <[email protected]>
> > Cc: Christian König <[email protected]>
> > Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
> > ---
> >   drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c | 42 
> > ++++++++++++++++++++++++
> >   1 file changed, 42 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c 
> > b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
> > index 
> > 6d95447a989d20d60227025be874265b2b491f59..9848c008a443d70ad16c6e018381878f0898e487
> >  100644
> > --- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
> > +++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
> > @@ -759,6 +759,47 @@ static void 
> > ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
> >     ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
> >   }
> > +static void ttm_bo_validate_swapout(struct kunit *test)
> > +{
> > +   u32 mem_type = TTM_PL_TT;
> > +   struct ttm_test_devices *priv = test->priv;
> > +   struct ttm_operation_ctx ctx_init = { };
> > +   enum ttm_bo_type bo_type = ttm_bo_type_device;
> > +   struct ttm_resource_manager *man;
> > +   struct ttm_placement *placement;
> > +   struct ttm_buffer_object *bo;
> > +   struct ttm_place *place;
> > +   int err;
> > +   s64 swapped;
> > +
> > +   ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
> > +   man = ttm_manager_type(priv->ttm_dev, mem_type);
> > +   KUNIT_ASSERT_NOT_NULL(test, man);
> > +
> > +   place = ttm_place_kunit_init(test, mem_type, 0);
> > +   KUNIT_ASSERT_NOT_NULL(test, place);
> > +   placement = ttm_placement_kunit_init(test, place, 1);
> > +   KUNIT_ASSERT_NOT_NULL(test, placement);
> 
> Above two seem to have internal asserts so you could drop them from the
> test.
> 

Thanks for pointing that out. I have fixed that and also the need to export
ttm_bo_swapout for tests in case the tests are built as modules.

> > +
> > +   bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
> > +   KUNIT_ASSERT_NOT_NULL(test, bo);
> > +
> > +   drm_gem_private_object_init(priv->drm, &bo->base, MANAGER_SIZE);
> > +   err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
> > +                              PAGE_SIZE, &ctx_init, NULL, NULL,
> > +                              &dummy_ttm_bo_destroy);
> > +   KUNIT_EXPECT_EQ(test, err, 0);
> > +   dma_resv_unlock(bo->base.resv);
> > +
> > +   swapped = ttm_bo_swapout(priv->ttm_dev, &ctx_init, man, GFP_KERNEL, 1);
> 
> Is there a particular reason to ask for 1 page to swap out instead of
> matching the bo size? Might be more obvious (I dare not to say future proof)
> to match it with the expectation from the below assert.
> 

Just that I found that all callers for ttm_lru_walk_for_evict use 1 as the
target except for ttm_bo_swapout, which uses its parameter as the argument
but its only callers uses 1 as the target too.  :-D

> > +   KUNIT_EXPECT_EQ(test, swapped, MANAGER_SIZE / PAGE_SIZE);

Another future proof way to do it would be to test for swapped >= 1. Let me
try using MANAGER_SIZE / PAGE_SIZE and keep the expectation here.

> 
> Side note, it looks like ttm_bo_swapout() kerneldoc should be fixed to
> correctly say return is number of pages, not bytes.

Nice catch. target too should be number of pages. Let me send the fix for
that too.

Thanks.
Cascardo.

> 
> Regards,
> 
> Tvrtko
> 
> > +   KUNIT_EXPECT_EQ(test, bo->resource->mem_type, TTM_PL_SYSTEM);
> > +   KUNIT_EXPECT_TRUE(test, bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED);
> > +
> > +   ttm_bo_fini(bo);
> > +   ttm_mock_manager_fini(priv->ttm_dev, mem_type);
> > +}
> > +
> >   static void ttm_bo_validate_happy_evict(struct kunit *test)
> >   {
> >     u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT,
> > @@ -1153,6 +1194,7 @@ static struct kunit_case ttm_bo_validate_test_cases[] 
> > = {
> >     KUNIT_CASE(ttm_bo_validate_move_fence_signaled),
> >     KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled,
> >                      ttm_bo_validate_wait_gen_params),
> > +   KUNIT_CASE(ttm_bo_validate_swapout),
> >     KUNIT_CASE(ttm_bo_validate_happy_evict),
> >     KUNIT_CASE(ttm_bo_validate_all_pinned_evict),
> >     KUNIT_CASE(ttm_bo_validate_allowed_only_evict),
> > 
> > ---
> > base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
> > change-id: 20260306-ttm_bo_swapout_test-ad130eac0bcf
> > 
> > Best regards,
> 

Reply via email to