On 2026-02-17 05:01, Christian König wrote:
It turned that using 4 level page tables on GMC generations which support
57bit VAs actually doesn't work at all.

Background is that the GMC actually can't switch between 4 and 5 levels,
but rather just uses a subset of address space when less than 5 levels are
selected.

Philip already removed the automatically switch to 4levels, now fix it as
well should it be enabled by module parameters.

v2: fix AMDGPU_GMC_HOLE_MASK as well, fix off by one issue pointed out
     by Philip

Signed-off-by: Christian König<[email protected]>
Reviewed-by: Philip Yang <[email protected]>
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 8 ++++----
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 1 +
  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h  | 1 +
  3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index e8e8bfa098c3..0e8a52d96573 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -33,9 +33,9 @@
  #include "amdgpu_ras.h"
/* VA hole for 48bit and 57bit addresses */
-#define AMDGPU_GMC_HOLE_START  (adev->vm_manager.root_level == AMDGPU_VM_PDB3 
?\
+#define AMDGPU_GMC_HOLE_START  (adev->vm_manager.max_level == 4 ?\
                                0x0100000000000000ULL : 0x0000800000000000ULL)
-#define AMDGPU_GMC_HOLE_END    (adev->vm_manager.root_level == AMDGPU_VM_PDB3 
?\
+#define AMDGPU_GMC_HOLE_END    (adev->vm_manager.max_level == 4 ?\
                                0xff00000000000000ULL : 0xffff800000000000ULL)
/*
@@ -45,8 +45,8 @@
   * This mask is used to remove the upper 16bits of the VA and so come up with
   * the linear addr value.
   */
-#define AMDGPU_GMC_HOLE_MASK   (adev->vm_manager.root_level == AMDGPU_VM_PDB3 
?\
-                               0x00ffffffffffffffULL : 0x0000ffffffffffffULL)
+#define AMDGPU_GMC_HOLE_MASK   (adev->vm_manager.max_level == 4 ?\
+                               0x01ffffffffffffffULL : 0x0000ffffffffffffULL)
/*
   * Ring size as power of two for the log of recent faults.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index dfad7d11826c..c6fd3a091613 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2409,6 +2409,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, 
uint32_t min_vm_size,
        }
adev->vm_manager.max_pfn = (uint64_t)vm_size << 18;
+       adev->vm_manager.max_level = max_level;
tmp = roundup_pow_of_two(adev->vm_manager.max_pfn);
        if (amdgpu_vm_block_size != -1)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 139642eacdd0..806d62ed61ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -456,6 +456,7 @@ struct amdgpu_vm_manager {
        bool                                    concurrent_flush;
uint64_t max_pfn;
+       uint32_t                                max_level;
        uint32_t                                num_level;
        uint32_t                                block_size;
        uint32_t                                fragment_size;

Reply via email to