From: Philip Yang <[email protected]>

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.

Signed-off-by: Philip Yang <[email protected]>
Acked-by: Felix Kuehling <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c    | 20 ++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h    |  3 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c |  1 +
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 1fab953e9a030..df67a9752a390 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2352,9 +2352,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_5LEVEL
+       /*
+        * 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;
@@ -2397,6 +2414,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;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 78129cea7cee3..bea9485db3197 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -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,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index 30022123b0bf6..f6ffc207ec2a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -50,6 +50,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:
-- 
2.51.0

Reply via email to