Commit c21b328e authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon: fix VM page table setup on SI

Cayman and trinity allow for variable sized VM page
tables, but SI requires that all page tables be the
same size.  The current code assumes variablely sized
VM page tables so SI may end up with part of each page
table overlapping with other memory which could end
up being interpreted by the VM hw as garbage.

Change the code to better accomodate SI.  Allocate enough
space for at least 2 full page tables and always set
last_pfn to max_pfn on SI so each VM is backed by a full
page table.  This limits us to only 2 VMs active at any
given time on SI.  This will be rectified and the code can
be reunified once we move to two level page tables.
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarJerome Glisse <jglisse@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 9acc7bde
...@@ -289,8 +289,9 @@ int radeon_vm_manager_init(struct radeon_device *rdev) ...@@ -289,8 +289,9 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
rdev->vm_manager.enabled = false; rdev->vm_manager.enabled = false;
/* mark first vm as always in use, it's the system one */ /* mark first vm as always in use, it's the system one */
/* allocate enough for 2 full VM pts */
r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager,
rdev->vm_manager.max_pfn * 8, rdev->vm_manager.max_pfn * 8 * 2,
RADEON_GEM_DOMAIN_VRAM); RADEON_GEM_DOMAIN_VRAM);
if (r) { if (r) {
dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n",
...@@ -633,6 +634,14 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) ...@@ -633,6 +634,14 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
mutex_init(&vm->mutex); mutex_init(&vm->mutex);
INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->list);
INIT_LIST_HEAD(&vm->va); INIT_LIST_HEAD(&vm->va);
/* SI requires equal sized PTs for all VMs, so always set
* last_pfn to max_pfn. cayman allows variable sized
* pts so we can grow then as needed. Once we switch
* to two level pts we can unify this again.
*/
if (rdev->family >= CHIP_TAHITI)
vm->last_pfn = rdev->vm_manager.max_pfn;
else
vm->last_pfn = 0; vm->last_pfn = 0;
/* map the ib pool buffer at 0 in virtual address space, set /* map the ib pool buffer at 0 in virtual address space, set
* read only * read only
......
...@@ -2365,12 +2365,12 @@ int si_pcie_gart_enable(struct radeon_device *rdev) ...@@ -2365,12 +2365,12 @@ int si_pcie_gart_enable(struct radeon_device *rdev)
WREG32(0x15DC, 0); WREG32(0x15DC, 0);
/* empty context1-15 */ /* empty context1-15 */
/* FIXME start with 1G, once using 2 level pt switch to full /* FIXME start with 4G, once using 2 level pt switch to full
* vm size space * vm size space
*/ */
/* set vm size, must be a multiple of 4 */ /* set vm size, must be a multiple of 4 */
WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, (1 << 30) / RADEON_GPU_PAGE_SIZE); WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn);
for (i = 1; i < 16; i++) { for (i = 1; i < 16; i++) {
if (i < 8) if (i < 8)
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment