drm/amdgpu: separate page table allocation from mapping
This makes it easier to implement a replace operation. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Junwei Zhang <Jerry.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
4388fc2ab0
commit
663e4577a5
@@ -631,8 +631,12 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
switch (args->operation) {
|
switch (args->operation) {
|
||||||
case AMDGPU_VA_OP_MAP:
|
case AMDGPU_VA_OP_MAP:
|
||||||
va_flags = amdgpu_vm_get_pte_flags(adev, args->flags);
|
r = amdgpu_vm_alloc_pts(adev, bo_va->vm, args->va_address,
|
||||||
|
args->map_size);
|
||||||
|
if (r)
|
||||||
|
goto error_backoff;
|
||||||
|
|
||||||
|
va_flags = amdgpu_vm_get_pte_flags(adev, args->flags);
|
||||||
r = amdgpu_vm_bo_map(adev, bo_va, args->va_address,
|
r = amdgpu_vm_bo_map(adev, bo_va, args->va_address,
|
||||||
args->offset_in_bo, args->map_size,
|
args->offset_in_bo, args->map_size,
|
||||||
va_flags);
|
va_flags);
|
||||||
|
|||||||
@@ -75,6 +75,15 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = amdgpu_vm_alloc_pts(adev, bo_va->vm, AMDGPU_CSA_VADDR,
|
||||||
|
AMDGPU_CSA_SIZE);
|
||||||
|
if (r) {
|
||||||
|
DRM_ERROR("failed to allocate pts for static CSA, err=%d\n", r);
|
||||||
|
amdgpu_vm_bo_rmv(adev, bo_va);
|
||||||
|
ttm_eu_backoff_reservation(&ticket, &list);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = amdgpu_vm_bo_map(adev, bo_va, AMDGPU_CSA_VADDR, 0,AMDGPU_CSA_SIZE,
|
r = amdgpu_vm_bo_map(adev, bo_va, AMDGPU_CSA_VADDR, 0,AMDGPU_CSA_SIZE,
|
||||||
AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE |
|
AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE |
|
||||||
AMDGPU_PTE_EXECUTABLE);
|
AMDGPU_PTE_EXECUTABLE);
|
||||||
|
|||||||
@@ -187,6 +187,78 @@ void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
|
|||||||
spin_unlock(&glob->lru_lock);
|
spin_unlock(&glob->lru_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* amdgpu_vm_alloc_pts - Allocate page tables.
|
||||||
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
|
* @vm: VM to allocate page tables for
|
||||||
|
* @saddr: Start address which needs to be allocated
|
||||||
|
* @size: Size from start address we need.
|
||||||
|
*
|
||||||
|
* Make sure the page tables are allocated.
|
||||||
|
*/
|
||||||
|
int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
|
||||||
|
struct amdgpu_vm *vm,
|
||||||
|
uint64_t saddr, uint64_t size)
|
||||||
|
{
|
||||||
|
unsigned last_pfn, pt_idx;
|
||||||
|
uint64_t eaddr;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* validate the parameters */
|
||||||
|
if (saddr & AMDGPU_GPU_PAGE_MASK || size & AMDGPU_GPU_PAGE_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
eaddr = saddr + size - 1;
|
||||||
|
last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
if (last_pfn >= adev->vm_manager.max_pfn) {
|
||||||
|
dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n",
|
||||||
|
last_pfn, adev->vm_manager.max_pfn);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
|
saddr >>= amdgpu_vm_block_size;
|
||||||
|
eaddr >>= amdgpu_vm_block_size;
|
||||||
|
|
||||||
|
BUG_ON(eaddr >= amdgpu_vm_num_pdes(adev));
|
||||||
|
|
||||||
|
if (eaddr > vm->max_pde_used)
|
||||||
|
vm->max_pde_used = eaddr;
|
||||||
|
|
||||||
|
/* walk over the address space and allocate the page tables */
|
||||||
|
for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
|
||||||
|
struct reservation_object *resv = vm->page_directory->tbo.resv;
|
||||||
|
struct amdgpu_bo *pt;
|
||||||
|
|
||||||
|
if (vm->page_tables[pt_idx].bo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
|
||||||
|
AMDGPU_GPU_PAGE_SIZE, true,
|
||||||
|
AMDGPU_GEM_DOMAIN_VRAM,
|
||||||
|
AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
|
||||||
|
AMDGPU_GEM_CREATE_SHADOW |
|
||||||
|
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
||||||
|
AMDGPU_GEM_CREATE_VRAM_CLEARED,
|
||||||
|
NULL, resv, &pt);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Keep a reference to the page table to avoid freeing
|
||||||
|
* them up in the wrong order.
|
||||||
|
*/
|
||||||
|
pt->parent = amdgpu_bo_ref(vm->page_directory);
|
||||||
|
|
||||||
|
vm->page_tables[pt_idx].bo = pt;
|
||||||
|
vm->page_tables[pt_idx].addr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool amdgpu_vm_is_gpu_reset(struct amdgpu_device *adev,
|
static bool amdgpu_vm_is_gpu_reset(struct amdgpu_device *adev,
|
||||||
struct amdgpu_vm_id *id)
|
struct amdgpu_vm_id *id)
|
||||||
{
|
{
|
||||||
@@ -1442,9 +1514,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_bo_va_mapping *mapping;
|
struct amdgpu_bo_va_mapping *mapping;
|
||||||
struct amdgpu_vm *vm = bo_va->vm;
|
struct amdgpu_vm *vm = bo_va->vm;
|
||||||
struct interval_tree_node *it;
|
struct interval_tree_node *it;
|
||||||
unsigned last_pfn, pt_idx;
|
|
||||||
uint64_t eaddr;
|
uint64_t eaddr;
|
||||||
int r;
|
|
||||||
|
|
||||||
/* validate the parameters */
|
/* validate the parameters */
|
||||||
if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
|
if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
|
||||||
@@ -1457,13 +1527,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||||||
(bo_va->bo && offset + size > amdgpu_bo_size(bo_va->bo)))
|
(bo_va->bo && offset + size > amdgpu_bo_size(bo_va->bo)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
|
|
||||||
if (last_pfn >= adev->vm_manager.max_pfn) {
|
|
||||||
dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n",
|
|
||||||
last_pfn, adev->vm_manager.max_pfn);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
@@ -1475,15 +1538,12 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||||||
dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with "
|
dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with "
|
||||||
"0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr,
|
"0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr,
|
||||||
tmp->it.start, tmp->it.last + 1);
|
tmp->it.start, tmp->it.last + 1);
|
||||||
r = -EINVAL;
|
return -EINVAL;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
||||||
if (!mapping) {
|
if (!mapping)
|
||||||
r = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&mapping->list);
|
INIT_LIST_HEAD(&mapping->list);
|
||||||
mapping->it.start = saddr;
|
mapping->it.start = saddr;
|
||||||
@@ -1494,56 +1554,10 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||||||
list_add(&mapping->list, &bo_va->invalids);
|
list_add(&mapping->list, &bo_va->invalids);
|
||||||
interval_tree_insert(&mapping->it, &vm->va);
|
interval_tree_insert(&mapping->it, &vm->va);
|
||||||
|
|
||||||
/* Make sure the page tables are allocated */
|
|
||||||
saddr >>= amdgpu_vm_block_size;
|
|
||||||
eaddr >>= amdgpu_vm_block_size;
|
|
||||||
|
|
||||||
BUG_ON(eaddr >= amdgpu_vm_num_pdes(adev));
|
|
||||||
|
|
||||||
if (eaddr > vm->max_pde_used)
|
|
||||||
vm->max_pde_used = eaddr;
|
|
||||||
|
|
||||||
/* walk over the address space and allocate the page tables */
|
|
||||||
for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
|
|
||||||
struct reservation_object *resv = vm->page_directory->tbo.resv;
|
|
||||||
struct amdgpu_bo *pt;
|
|
||||||
|
|
||||||
if (vm->page_tables[pt_idx].bo)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
|
|
||||||
AMDGPU_GPU_PAGE_SIZE, true,
|
|
||||||
AMDGPU_GEM_DOMAIN_VRAM,
|
|
||||||
AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
|
|
||||||
AMDGPU_GEM_CREATE_SHADOW |
|
|
||||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
|
||||||
AMDGPU_GEM_CREATE_VRAM_CLEARED,
|
|
||||||
NULL, resv, &pt);
|
|
||||||
if (r)
|
|
||||||
goto error_free;
|
|
||||||
|
|
||||||
/* Keep a reference to the page table to avoid freeing
|
|
||||||
* them up in the wrong order.
|
|
||||||
*/
|
|
||||||
pt->parent = amdgpu_bo_ref(vm->page_directory);
|
|
||||||
|
|
||||||
vm->page_tables[pt_idx].bo = pt;
|
|
||||||
vm->page_tables[pt_idx].addr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & AMDGPU_PTE_PRT)
|
if (flags & AMDGPU_PTE_PRT)
|
||||||
amdgpu_vm_prt_get(adev);
|
amdgpu_vm_prt_get(adev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_free:
|
|
||||||
list_del(&mapping->list);
|
|
||||||
interval_tree_remove(&mapping->it, &vm->va);
|
|
||||||
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
|
|
||||||
amdgpu_vm_free_mapping(adev, vm, mapping, NULL);
|
|
||||||
|
|
||||||
error:
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -179,6 +179,9 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
void *param);
|
void *param);
|
||||||
void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
|
void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
|
||||||
struct amdgpu_vm *vm);
|
struct amdgpu_vm *vm);
|
||||||
|
int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
|
||||||
|
struct amdgpu_vm *vm,
|
||||||
|
uint64_t saddr, uint64_t size);
|
||||||
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
||||||
struct amdgpu_sync *sync, struct dma_fence *fence,
|
struct amdgpu_sync *sync, struct dma_fence *fence,
|
||||||
struct amdgpu_job *job);
|
struct amdgpu_job *job);
|
||||||
|
|||||||
Reference in New Issue
Block a user