[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 <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  24 +++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  11 ++
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 128 ++++++++++++++++++
 3 files changed, 161 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 71fe85498766..ffc5cea6b6df 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -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)
 {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 5ffaca8a6efe..a53246040948 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -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__ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index a8140747c25d..bb52da037e69 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -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),
        {}
 };
 
-- 
2.43.0

Reply via email to