]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amdgpu: GPU vm support 5-level page table
authorPhilip Yang <Philip.Yang@amd.com>
Fri, 25 Apr 2025 14:55:07 +0000 (10:55 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 8 Dec 2025 18:56:30 +0000 (13:56 -0500)
If GPU supports 5-level page table, but CPU disable 5-level page table
by using boot option no5lvl or CPU feature not available, the virtual
address will be 48bit, not needed to enable 5-level page table on GPU
vm.

If adev->vm_manager.num_level, number of pde levels, set to 4, then
gfxhub and mmhub register VM_CONTEXTx_CNTL/PAGE_TABLE_DEPTH will set
to 4 to enable 5-level page table in page table walker.

Set vm_manager.root_level to AMDGPU_VM_PDE3, then update GPU mapping
will allocate and update PDE3/PDE2/PDE1/PDE0/PTB 5-level page tables.

If max_level is not 4, no change for the logic to support features
needed by old ASICs.

v2: squash in CONFIG fix

Signed-off-by: Philip Yang <Philip.Yang@amd.com>
Acked-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c

index 3b002e37b55beffc1bd9f268edf912655e27554b..6a2ea200d90c86e55142ba52bea70e5c22685fa8 100644 (file)
@@ -2360,9 +2360,26 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
                           unsigned max_bits)
 {
        unsigned int max_size = 1 << (max_bits - 30);
+       bool sys_5level_pgtable = false;
        unsigned int vm_size;
        uint64_t tmp;
 
+#ifdef CONFIG_X86_64
+       /*
+        * Refer to function configure_5level_paging() for details.
+        */
+       sys_5level_pgtable = (native_read_cr4() & X86_CR4_LA57);
+#endif
+
+       /*
+        * If GPU supports 5-level page table, but system uses 4-level page table,
+        * then use 4-level page table on GPU
+        */
+       if (max_level == 4 && !sys_5level_pgtable) {
+               min_vm_size = 256 * 1024;
+               max_level = 3;
+       }
+
        /* adjust vm size first */
        if (amdgpu_vm_size != -1) {
                vm_size = amdgpu_vm_size;
@@ -2405,6 +2422,9 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
        tmp = DIV_ROUND_UP(fls64(tmp) - 1, 9) - 1;
        adev->vm_manager.num_level = min_t(unsigned int, max_level, tmp);
        switch (adev->vm_manager.num_level) {
+       case 4:
+               adev->vm_manager.root_level = AMDGPU_VM_PDB3;
+               break;
        case 3:
                adev->vm_manager.root_level = AMDGPU_VM_PDB2;
                break;
index d83c2a95ebea38ee10bd34e7e90952cc2bb80330..139642eacdd0c898cfe4c7fbbc1a68d99464392a 100644 (file)
@@ -186,9 +186,10 @@ struct amdgpu_bo_vm;
 #define AMDGPU_VM_USE_CPU_FOR_COMPUTE (1 << 1)
 
 /* VMPT level enumerate, and the hiberachy is:
- * PDB2->PDB1->PDB0->PTB
+ * PDB3->PDB2->PDB1->PDB0->PTB
  */
 enum amdgpu_vm_level {
+       AMDGPU_VM_PDB3,
        AMDGPU_VM_PDB2,
        AMDGPU_VM_PDB1,
        AMDGPU_VM_PDB0,
index f794fb1cc06e66d245a6342f83d2d9df5dc03be5..c7a7d51080a876709daa924505972674df142aa5 100644 (file)
@@ -51,6 +51,7 @@ static unsigned int amdgpu_vm_pt_level_shift(struct amdgpu_device *adev,
                                             unsigned int level)
 {
        switch (level) {
+       case AMDGPU_VM_PDB3:
        case AMDGPU_VM_PDB2:
        case AMDGPU_VM_PDB1:
        case AMDGPU_VM_PDB0: