summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c249
1 files changed, 160 insertions, 89 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index a12a1654e124..1d6e1479da38 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -333,9 +333,9 @@ static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo)
* again. Page directories are only updated after updating page
* tables.
*/
-static int vm_validate_pt_pd_bos(struct amdkfd_vm *vm)
+static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm)
{
- struct amdgpu_bo *pd = vm->base.root.base.bo;
+ struct amdgpu_bo *pd = vm->root.base.bo;
struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev);
struct amdgpu_vm_parser param;
uint64_t addr, flags = AMDGPU_PTE_VALID;
@@ -344,7 +344,7 @@ static int vm_validate_pt_pd_bos(struct amdkfd_vm *vm)
param.domain = AMDGPU_GEM_DOMAIN_VRAM;
param.wait = false;
- ret = amdgpu_vm_validate_pt_bos(adev, &vm->base, amdgpu_amdkfd_validate,
+ ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate,
&param);
if (ret) {
pr_err("amdgpu: failed to validate PT BOs\n");
@@ -357,11 +357,11 @@ static int vm_validate_pt_pd_bos(struct amdkfd_vm *vm)
return ret;
}
- addr = amdgpu_bo_gpu_offset(vm->base.root.base.bo);
+ addr = amdgpu_bo_gpu_offset(vm->root.base.bo);
amdgpu_gmc_get_vm_pde(adev, -1, &addr, &flags);
vm->pd_phys_addr = addr;
- if (vm->base.use_cpu_for_update) {
+ if (vm->use_cpu_for_update) {
ret = amdgpu_bo_kmap(pd, NULL);
if (ret) {
pr_err("amdgpu: failed to kmap PD, ret=%d\n", ret);
@@ -415,14 +415,12 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync)
* 4a. Validate new page tables and directories
*/
static int add_bo_to_vm(struct amdgpu_device *adev, struct kgd_mem *mem,
- struct amdgpu_vm *avm, bool is_aql,
+ struct amdgpu_vm *vm, bool is_aql,
struct kfd_bo_va_list **p_bo_va_entry)
{
int ret;
struct kfd_bo_va_list *bo_va_entry;
- struct amdkfd_vm *kvm = container_of(avm,
- struct amdkfd_vm, base);
- struct amdgpu_bo *pd = avm->root.base.bo;
+ struct amdgpu_bo *pd = vm->root.base.bo;
struct amdgpu_bo *bo = mem->bo;
uint64_t va = mem->va;
struct list_head *list_bo_va = &mem->bo_va_list;
@@ -441,10 +439,10 @@ static int add_bo_to_vm(struct amdgpu_device *adev, struct kgd_mem *mem,
return -ENOMEM;
pr_debug("\t add VA 0x%llx - 0x%llx to vm %p\n", va,
- va + bo_size, avm);
+ va + bo_size, vm);
/* Add BO to VM internal data structures*/
- bo_va_entry->bo_va = amdgpu_vm_bo_add(adev, avm, bo);
+ bo_va_entry->bo_va = amdgpu_vm_bo_add(adev, vm, bo);
if (!bo_va_entry->bo_va) {
ret = -EINVAL;
pr_err("Failed to add BO object to VM. ret == %d\n",
@@ -467,28 +465,28 @@ static int add_bo_to_vm(struct amdgpu_device *adev, struct kgd_mem *mem,
* fence, so remove it temporarily.
*/
amdgpu_amdkfd_remove_eviction_fence(pd,
- kvm->process_info->eviction_fence,
+ vm->process_info->eviction_fence,
NULL, NULL);
- ret = amdgpu_vm_alloc_pts(adev, avm, va, amdgpu_bo_size(bo));
+ ret = amdgpu_vm_alloc_pts(adev, vm, va, amdgpu_bo_size(bo));
if (ret) {
pr_err("Failed to allocate pts, err=%d\n", ret);
goto err_alloc_pts;
}
- ret = vm_validate_pt_pd_bos(kvm);
+ ret = vm_validate_pt_pd_bos(vm);
if (ret) {
pr_err("validate_pt_pd_bos() failed\n");
goto err_alloc_pts;
}
/* Add the eviction fence back */
- amdgpu_bo_fence(pd, &kvm->process_info->eviction_fence->base, true);
+ amdgpu_bo_fence(pd, &vm->process_info->eviction_fence->base, true);
return 0;
err_alloc_pts:
- amdgpu_bo_fence(pd, &kvm->process_info->eviction_fence->base, true);
+ amdgpu_bo_fence(pd, &vm->process_info->eviction_fence->base, true);
amdgpu_vm_bo_rmv(adev, bo_va_entry->bo_va);
list_del(&bo_va_entry->bo_list);
err_vmadd:
@@ -703,7 +701,6 @@ static int unmap_bo_from_gpuvm(struct amdgpu_device *adev,
{
struct amdgpu_bo_va *bo_va = entry->bo_va;
struct amdgpu_vm *vm = bo_va->base.vm;
- struct amdkfd_vm *kvm = container_of(vm, struct amdkfd_vm, base);
struct amdgpu_bo *pd = vm->root.base.bo;
/* Remove eviction fence from PD (and thereby from PTs too as
@@ -713,14 +710,14 @@ static int unmap_bo_from_gpuvm(struct amdgpu_device *adev,
* trigger the eviction fence.
*/
amdgpu_amdkfd_remove_eviction_fence(pd,
- kvm->process_info->eviction_fence,
+ vm->process_info->eviction_fence,
NULL, NULL);
amdgpu_vm_bo_unmap(adev, bo_va, entry->va);
amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
/* Add the eviction fence back */
- amdgpu_bo_fence(pd, &kvm->process_info->eviction_fence->base, true);
+ amdgpu_bo_fence(pd, &vm->process_info->eviction_fence->base, true);
sync_vm_fence(adev, sync, bo_va->last_pt_update);
@@ -780,7 +777,7 @@ update_gpuvm_pte_failed:
static int process_validate_vms(struct amdkfd_process_info *process_info)
{
- struct amdkfd_vm *peer_vm;
+ struct amdgpu_vm *peer_vm;
int ret;
list_for_each_entry(peer_vm, &process_info->vm_list_head,
@@ -796,12 +793,12 @@ static int process_validate_vms(struct amdkfd_process_info *process_info)
static int process_update_pds(struct amdkfd_process_info *process_info,
struct amdgpu_sync *sync)
{
- struct amdkfd_vm *peer_vm;
+ struct amdgpu_vm *peer_vm;
int ret;
list_for_each_entry(peer_vm, &process_info->vm_list_head,
vm_list_node) {
- ret = vm_update_pds(&peer_vm->base, sync);
+ ret = vm_update_pds(peer_vm, sync);
if (ret)
return ret;
}
@@ -809,33 +806,16 @@ static int process_update_pds(struct amdkfd_process_info *process_info,
return 0;
}
-int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
- void **process_info,
- struct dma_fence **ef)
+static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
+ struct dma_fence **ef)
{
+ struct amdkfd_process_info *info = NULL;
int ret;
- struct amdkfd_vm *new_vm;
- struct amdkfd_process_info *info;
- struct amdgpu_device *adev = get_amdgpu_device(kgd);
-
- new_vm = kzalloc(sizeof(*new_vm), GFP_KERNEL);
- if (!new_vm)
- return -ENOMEM;
-
- /* Initialize the VM context, allocate the page directory and zero it */
- ret = amdgpu_vm_init(adev, &new_vm->base, AMDGPU_VM_CONTEXT_COMPUTE, 0);
- if (ret) {
- pr_err("Failed init vm ret %d\n", ret);
- goto vm_init_fail;
- }
- new_vm->adev = adev;
if (!*process_info) {
info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- ret = -ENOMEM;
- goto alloc_process_info_fail;
- }
+ if (!info)
+ return -ENOMEM;
mutex_init(&info->lock);
INIT_LIST_HEAD(&info->vm_list_head);
@@ -846,6 +826,7 @@ int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
current->mm);
if (!info->eviction_fence) {
pr_err("Failed to create eviction fence\n");
+ ret = -ENOMEM;
goto create_evict_fence_fail;
}
@@ -853,57 +834,137 @@ int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
*ef = dma_fence_get(&info->eviction_fence->base);
}
- new_vm->process_info = *process_info;
-
- mutex_lock(&new_vm->process_info->lock);
- list_add_tail(&new_vm->vm_list_node,
- &(new_vm->process_info->vm_list_head));
- new_vm->process_info->n_vms++;
- mutex_unlock(&new_vm->process_info->lock);
+ vm->process_info = *process_info;
- *vm = (void *) new_vm;
+ /* Validate page directory and attach eviction fence */
+ ret = amdgpu_bo_reserve(vm->root.base.bo, true);
+ if (ret)
+ goto reserve_pd_fail;
+ ret = vm_validate_pt_pd_bos(vm);
+ if (ret) {
+ pr_err("validate_pt_pd_bos() failed\n");
+ goto validate_pd_fail;
+ }
+ ret = ttm_bo_wait(&vm->root.base.bo->tbo, false, false);
+ if (ret)
+ goto wait_pd_fail;
+ amdgpu_bo_fence(vm->root.base.bo,
+ &vm->process_info->eviction_fence->base, true);
+ amdgpu_bo_unreserve(vm->root.base.bo);
+
+ /* Update process info */
+ mutex_lock(&vm->process_info->lock);
+ list_add_tail(&vm->vm_list_node,
+ &(vm->process_info->vm_list_head));
+ vm->process_info->n_vms++;
+ mutex_unlock(&vm->process_info->lock);
- pr_debug("Created process vm %p\n", *vm);
+ return 0;
+wait_pd_fail:
+validate_pd_fail:
+ amdgpu_bo_unreserve(vm->root.base.bo);
+reserve_pd_fail:
+ vm->process_info = NULL;
+ if (info) {
+ /* Two fence references: one in info and one in *ef */
+ dma_fence_put(&info->eviction_fence->base);
+ dma_fence_put(*ef);
+ *ef = NULL;
+ *process_info = NULL;
+create_evict_fence_fail:
+ mutex_destroy(&info->lock);
+ kfree(info);
+ }
return ret;
+}
-create_evict_fence_fail:
- mutex_destroy(&info->lock);
- kfree(info);
-alloc_process_info_fail:
- amdgpu_vm_fini(adev, &new_vm->base);
-vm_init_fail:
+int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
+ void **process_info,
+ struct dma_fence **ef)
+{
+ struct amdgpu_device *adev = get_amdgpu_device(kgd);
+ struct amdgpu_vm *new_vm;
+ int ret;
+
+ new_vm = kzalloc(sizeof(*new_vm), GFP_KERNEL);
+ if (!new_vm)
+ return -ENOMEM;
+
+ /* Initialize AMDGPU part of the VM */
+ ret = amdgpu_vm_init(adev, new_vm, AMDGPU_VM_CONTEXT_COMPUTE, 0);
+ if (ret) {
+ pr_err("Failed init vm ret %d\n", ret);
+ goto amdgpu_vm_init_fail;
+ }
+
+ /* Initialize KFD part of the VM and process info */
+ ret = init_kfd_vm(new_vm, process_info, ef);
+ if (ret)
+ goto init_kfd_vm_fail;
+
+ *vm = (void *) new_vm;
+
+ return 0;
+
+init_kfd_vm_fail:
+ amdgpu_vm_fini(adev, new_vm);
+amdgpu_vm_init_fail:
kfree(new_vm);
return ret;
-
}
-void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm)
+int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
+ struct file *filp,
+ void **vm, void **process_info,
+ struct dma_fence **ef)
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
- struct amdkfd_vm *kfd_vm = (struct amdkfd_vm *) vm;
- struct amdgpu_vm *avm = &kfd_vm->base;
- struct amdgpu_bo *pd;
- struct amdkfd_process_info *process_info;
+ struct drm_file *drm_priv = filp->private_data;
+ struct amdgpu_fpriv *drv_priv = drm_priv->driver_priv;
+ struct amdgpu_vm *avm = &drv_priv->vm;
+ int ret;
- if (WARN_ON(!kgd || !vm))
+ /* Already a compute VM? */
+ if (avm->process_info)
+ return -EINVAL;
+
+ /* Convert VM into a compute VM */
+ ret = amdgpu_vm_make_compute(adev, avm);
+ if (ret)
+ return ret;
+
+ /* Initialize KFD part of the VM and process info */
+ ret = init_kfd_vm(avm, process_info, ef);
+ if (ret)
+ return ret;
+
+ *vm = (void *)avm;
+
+ return 0;
+}
+
+void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm)
+{
+ struct amdkfd_process_info *process_info = vm->process_info;
+ struct amdgpu_bo *pd = vm->root.base.bo;
+
+ if (!process_info)
return;
- pr_debug("Destroying process vm %p\n", vm);
/* Release eviction fence from PD */
- pd = avm->root.base.bo;
amdgpu_bo_reserve(pd, false);
amdgpu_bo_fence(pd, NULL, false);
amdgpu_bo_unreserve(pd);
- process_info = kfd_vm->process_info;
-
+ /* Update process info */
mutex_lock(&process_info->lock);
process_info->n_vms--;
- list_del(&kfd_vm->vm_list_node);
+ list_del(&vm->vm_list_node);
mutex_unlock(&process_info->lock);
- /* Release per-process resources */
+ /* Release per-process resources when last compute VM is destroyed */
if (!process_info->n_vms) {
WARN_ON(!list_empty(&process_info->kfd_bo_list));
@@ -911,6 +972,17 @@ void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm)
mutex_destroy(&process_info->lock);
kfree(process_info);
}
+}
+
+void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm)
+{
+ struct amdgpu_device *adev = get_amdgpu_device(kgd);
+ struct amdgpu_vm *avm = (struct amdgpu_vm *)vm;
+
+ if (WARN_ON(!kgd || !vm))
+ return;
+
+ pr_debug("Destroying process vm %p\n", vm);
/* Release the VM context */
amdgpu_vm_fini(adev, avm);
@@ -919,7 +991,7 @@ void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm)
uint32_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *vm)
{
- struct amdkfd_vm *avm = (struct amdkfd_vm *)vm;
+ struct amdgpu_vm *avm = (struct amdgpu_vm *)vm;
return avm->pd_phys_addr >> AMDGPU_GPU_PAGE_SHIFT;
}
@@ -930,7 +1002,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
uint64_t *offset, uint32_t flags)
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
- struct amdkfd_vm *kfd_vm = (struct amdkfd_vm *)vm;
+ struct amdgpu_vm *avm = (struct amdgpu_vm *)vm;
struct amdgpu_bo *bo;
int byte_align;
u32 alloc_domain;
@@ -1010,8 +1082,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
(*mem)->va = va;
(*mem)->domain = alloc_domain;
(*mem)->mapped_to_gpu_memory = 0;
- (*mem)->process_info = kfd_vm->process_info;
- add_kgd_mem_to_kfd_bo_list(*mem, kfd_vm->process_info);
+ (*mem)->process_info = avm->process_info;
+ add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info);
if (offset)
*offset = amdgpu_bo_mmap_offset(bo);
@@ -1092,7 +1164,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *vm)
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
- struct amdkfd_vm *kfd_vm = (struct amdkfd_vm *)vm;
+ struct amdgpu_vm *avm = (struct amdgpu_vm *)vm;
int ret;
struct amdgpu_bo *bo;
uint32_t domain;
@@ -1128,19 +1200,19 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
if (unlikely(ret))
goto out;
- if (check_if_add_bo_to_vm((struct amdgpu_vm *)vm, mem)) {
- ret = add_bo_to_vm(adev, mem, (struct amdgpu_vm *)vm, false,
+ if (check_if_add_bo_to_vm(avm, mem)) {
+ ret = add_bo_to_vm(adev, mem, avm, false,
&bo_va_entry);
if (ret)
goto add_bo_to_vm_failed;
if (mem->aql_queue) {
- ret = add_bo_to_vm(adev, mem, (struct amdgpu_vm *)vm,
+ ret = add_bo_to_vm(adev, mem, avm,
true, &bo_va_entry_aql);
if (ret)
goto add_bo_to_vm_failed_aql;
}
} else {
- ret = vm_validate_pt_pd_bos((struct amdkfd_vm *)vm);
+ ret = vm_validate_pt_pd_bos(avm);
if (unlikely(ret))
goto add_bo_to_vm_failed;
}
@@ -1184,7 +1256,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->pin_count)
amdgpu_bo_fence(bo,
- &kfd_vm->process_info->eviction_fence->base,
+ &avm->process_info->eviction_fence->base,
true);
ret = unreserve_bo_and_vms(&ctx, false, false);
@@ -1209,7 +1281,7 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
struct amdkfd_process_info *process_info =
- ((struct amdkfd_vm *)vm)->process_info;
+ ((struct amdgpu_vm *)vm)->process_info;
unsigned long bo_size = mem->bo->tbo.mem.size;
struct kfd_bo_va_list *entry;
struct bo_vm_reservation_context ctx;
@@ -1226,7 +1298,7 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
goto unreserve_out;
}
- ret = vm_validate_pt_pd_bos((struct amdkfd_vm *)vm);
+ ret = vm_validate_pt_pd_bos((struct amdgpu_vm *)vm);
if (unlikely(ret))
goto unreserve_out;
@@ -1368,7 +1440,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
{
struct amdgpu_bo_list_entry *pd_bo_list;
struct amdkfd_process_info *process_info = info;
- struct amdkfd_vm *peer_vm;
+ struct amdgpu_vm *peer_vm;
struct kgd_mem *mem;
struct bo_vm_reservation_context ctx;
struct amdgpu_amdkfd_fence *new_fence;
@@ -1390,8 +1462,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
mutex_lock(&process_info->lock);
list_for_each_entry(peer_vm, &process_info->vm_list_head,
vm_list_node)
- amdgpu_vm_get_pd_bo(&peer_vm->base, &ctx.list,
- &pd_bo_list[i++]);
+ amdgpu_vm_get_pd_bo(peer_vm, &ctx.list, &pd_bo_list[i++]);
/* Reserve all BOs and page tables/directory. Add all BOs from
* kfd_bo_list to ctx.list
@@ -1422,7 +1493,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
/* FIXME: I think this isn't needed */
list_for_each_entry(peer_vm, &process_info->vm_list_head,
vm_list_node) {
- struct amdgpu_bo *bo = peer_vm->base.root.base.bo;
+ struct amdgpu_bo *bo = peer_vm->root.base.bo;
ttm_bo_wait(&bo->tbo, false, false);
}
@@ -1491,7 +1562,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
/* Attach eviction fence to PD / PT BOs */
list_for_each_entry(peer_vm, &process_info->vm_list_head,
vm_list_node) {
- struct amdgpu_bo *bo = peer_vm->base.root.base.bo;
+ struct amdgpu_bo *bo = peer_vm->root.base.bo;
amdgpu_bo_fence(bo, &process_info->eviction_fence->base, true);
}