drm/amd/display: Test MMHUB config read

[WHAT]
Add KUnit tests for the system aperture and GART configuration built by
mmhub_read_system_context(), covering the enabled and disabled AGP
aperture branches, the Raven2 and Renoir aperture workarounds, and the
GPUVM support flag.

[HOW]
Add struct amdgpu_dm_kunit_ops, a KUnit-only indirection table for
amdgpu_gmc_pd_addr(), which walks a live TTM buffer object back to its
device. Tests install a stub returning a fixed page directory address,
which makes the arithmetic reachable in the UML test environment. The
default table points at the existing AMDGPU function, so no test-only
wrapper is introduced.

Assisted-by: Copilot:Claude-Opus-5 GPT-5.6-Sol
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Hung 2026-08-13 21:00:44 -06:00 committed by Alex Deucher
parent d18cd30a82
commit 08fff7a45b
3 changed files with 161 additions and 2 deletions

View File

@ -309,8 +309,27 @@ EXPORT_IF_KUNIT(dm_set_powergating_state);
/* Prototypes of private functions */
static int dm_early_init(struct amdgpu_ip_block *ip_block);
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
static const struct amdgpu_dm_kunit_ops amdgpu_dm_default_ops = {
.gmc_pd_addr = amdgpu_gmc_pd_addr,
};
static const struct amdgpu_dm_kunit_ops *amdgpu_dm_ops = &amdgpu_dm_default_ops;
void amdgpu_dm_kunit_set_ops(const struct amdgpu_dm_kunit_ops *ops)
{
amdgpu_dm_ops = ops ? ops : &amdgpu_dm_default_ops;
}
EXPORT_IF_KUNIT(amdgpu_dm_kunit_set_ops);
#define dm_gmc_pd_addr amdgpu_dm_ops->gmc_pd_addr
#else
#define dm_gmc_pd_addr amdgpu_gmc_pd_addr
#endif
/* Allocate memory for FBC compressed data */
static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
STATIC_IFN_KUNIT void mmhub_read_system_context(struct amdgpu_device *adev,
struct dc_phy_addr_space_config *pa_config)
{
u64 pt_base;
u32 logical_addr_low;
@ -355,7 +374,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
logical_addr_high = max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18;
}
pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
pt_base = dm_gmc_pd_addr(adev->gart.bo);
page_table_start.high_part = upper_32_bits(adev->gmc.gart_start >>
AMDGPU_GPU_PAGE_SHIFT);
@ -386,6 +405,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
pa_config->is_hvm_enabled = adev->mode_info.gpu_vm_support;
}
EXPORT_IF_KUNIT(mmhub_read_system_context);
static int amdgpu_dm_init_power_module(struct amdgpu_display_manager *dm)
{

View File

@ -1241,6 +1241,17 @@ struct amdgpu_dm_services_kunit_ops {
};
void amdgpu_dm_services_kunit_set_ops(const struct amdgpu_dm_services_kunit_ops *ops);
struct amdgpu_dm_kunit_ops {
uint64_t (*gmc_pd_addr)(struct amdgpu_bo *bo);
};
void amdgpu_dm_kunit_set_ops(const struct amdgpu_dm_kunit_ops *ops);
struct dc_phy_addr_space_config;
void mmhub_read_system_context(struct amdgpu_device *adev,
struct dc_phy_addr_space_config *pa_config);
#endif
#endif /* __AMDGPU_DM_H__ */

View File

@ -3399,6 +3399,129 @@ static void dm_test_atomic_setup_commit_bad_lut(struct kunit *test)
KUNIT_EXPECT_EQ(test, amdgpu_dm_atomic_setup_commit(ctx->state), -EINVAL);
}
/* Tests for mmhub_read_system_context() */
#define DM_TEST_PD_ADDR 0x1234000ULL
/*
* Stub for the page directory address read: amdgpu_gmc_pd_addr() walks a live
* TTM buffer object back to its device, so return a fixed address instead.
*/
static uint64_t dm_test_gmc_pd_addr(struct amdgpu_bo *bo)
{
return DM_TEST_PD_ADDR;
}
static const struct amdgpu_dm_kunit_ops dm_test_dm_ops = {
.gmc_pd_addr = dm_test_gmc_pd_addr,
};
static void dm_test_restore_dm_ops(void *ctx)
{
amdgpu_dm_kunit_set_ops(NULL);
}
/*
* A device whose AGP aperture is disabled (bot above top), so the frame buffer
* alone decides the logical address range.
*/
static struct amdgpu_device *dm_test_mmhub_adev(struct kunit *test)
{
struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
amdgpu_dm_kunit_set_ops(&dm_test_dm_ops);
KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_restore_dm_ops, NULL), 0);
adev->gmc.agp_start = 0x2000000;
adev->gmc.agp_end = 0x1000000;
adev->gmc.fb_start = 0x40000000;
adev->gmc.fb_end = 0x7fffffff;
adev->gmc.gart_start = 0x100000000ULL;
adev->gmc.gart_end = 0x1ffffffffULL;
adev->vm_manager.vram_base_offset = 0x800000;
return adev;
}
/**
* dm_test_mmhub_agp_disabled - Test a disabled AGP aperture uses the frame buffer
* @test: The KUnit test context
*/
static void dm_test_mmhub_agp_disabled(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_mmhub_adev(test);
struct dc_phy_addr_space_config pa_config;
mmhub_read_system_context(adev, &pa_config);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.start_addr, 0x40000000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.end_addr, 0x7ffc0000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.agp_base, 0ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.agp_bot, 0x2000000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.agp_top, 0x1000000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.fb_base, 0x40000000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.fb_offset, 0x800000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.fb_top, 0x7fffffffULL);
KUNIT_EXPECT_EQ(test, pa_config.gart_config.page_table_start_addr, 0x100000000ULL);
KUNIT_EXPECT_EQ(test, pa_config.gart_config.page_table_end_addr, 0x1fffff000ULL);
KUNIT_EXPECT_EQ(test, pa_config.gart_config.page_table_base_addr, DM_TEST_PD_ADDR);
KUNIT_EXPECT_FALSE(test, pa_config.is_hvm_enabled);
}
/**
* dm_test_mmhub_agp_disabled_raven2 - Test the Raven2 aperture workaround
* @test: The KUnit test context
*/
static void dm_test_mmhub_agp_disabled_raven2(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_mmhub_adev(test);
struct dc_phy_addr_space_config pa_config;
adev->apu_flags = AMD_APU_IS_RAVEN2;
mmhub_read_system_context(adev, &pa_config);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.end_addr, 0x80000000ULL);
}
/**
* dm_test_mmhub_agp_enabled - Test an enabled AGP aperture widens the range
* @test: The KUnit test context
*/
static void dm_test_mmhub_agp_enabled(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_mmhub_adev(test);
struct dc_phy_addr_space_config pa_config;
adev->gmc.agp_start = 0x1000000;
adev->gmc.agp_end = 0x2000000;
adev->mode_info.gpu_vm_support = true;
mmhub_read_system_context(adev, &pa_config);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.start_addr, 0x1000000ULL);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.end_addr, 0x7ffc0000ULL);
KUNIT_EXPECT_TRUE(test, pa_config.is_hvm_enabled);
}
/**
* dm_test_mmhub_agp_enabled_renoir - Test the Renoir aperture workaround
* @test: The KUnit test context
*/
static void dm_test_mmhub_agp_enabled_renoir(struct kunit *test)
{
struct amdgpu_device *adev = dm_test_mmhub_adev(test);
struct dc_phy_addr_space_config pa_config;
adev->gmc.agp_start = 0x1000000;
adev->gmc.agp_end = 0x2000000;
adev->apu_flags = AMD_APU_IS_RENOIR;
mmhub_read_system_context(adev, &pa_config);
KUNIT_EXPECT_EQ(test, pa_config.system_aperture.end_addr, 0x80000000ULL);
}
static struct kunit_case amdgpu_dm_tests[] = {
/* Simple DM callbacks */
KUNIT_CASE(dm_test_wait_for_idle),
@ -3571,6 +3694,11 @@ static struct kunit_case amdgpu_dm_tests[] = {
KUNIT_CASE(dm_test_oem_i2c_hw_init_no_device),
KUNIT_CASE(dm_test_gpureset_commit_state_no_streams),
KUNIT_CASE(dm_test_emulated_link_detect_bad_signal),
/* mmhub_read_system_context */
KUNIT_CASE(dm_test_mmhub_agp_disabled),
KUNIT_CASE(dm_test_mmhub_agp_disabled_raven2),
KUNIT_CASE(dm_test_mmhub_agp_enabled),
KUNIT_CASE(dm_test_mmhub_agp_enabled_renoir),
{}
};