Commit b38c074b authored by David Yat Sin's avatar David Yat Sin Committed by Alex Deucher

drm/amdkfd: CRIU Refactor restore BO function

Refactor CRIU restore BO to reduce identation.
Signed-off-by: default avatarDavid Yat Sin <david.yatsin@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 67a359d8
...@@ -2094,154 +2094,94 @@ static int criu_restore_devices(struct kfd_process *p, ...@@ -2094,154 +2094,94 @@ static int criu_restore_devices(struct kfd_process *p,
return ret; return ret;
} }
static int criu_restore_bos(struct kfd_process *p, static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd,
struct kfd_ioctl_criu_args *args, struct kfd_criu_bo_bucket *bo_bucket,
uint64_t *priv_offset, struct kfd_criu_bo_priv_data *bo_priv,
uint64_t max_priv_data_size) struct kgd_mem **kgd_mem)
{ {
struct kfd_criu_bo_bucket *bo_buckets = NULL; int idr_handle;
struct kfd_criu_bo_priv_data *bo_privs = NULL; int ret;
const bool criu_resume = true; const bool criu_resume = true;
int ret = 0, j = 0;
uint32_t i = 0;
if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size)
return -EINVAL;
/* Prevent MMU notifications until stage-4 IOCTL (CRIU_RESUME) is received */
amdgpu_amdkfd_block_mmu_notifications(p->kgd_process_info);
bo_buckets = kvmalloc_array(args->num_bos, sizeof(*bo_buckets), GFP_KERNEL);
if (!bo_buckets)
return -ENOMEM;
ret = copy_from_user(bo_buckets, (void __user *)args->bos,
args->num_bos * sizeof(*bo_buckets));
if (ret) {
pr_err("Failed to copy BOs information from user\n");
ret = -EFAULT;
goto exit;
}
bo_privs = kvmalloc_array(args->num_bos, sizeof(*bo_privs), GFP_KERNEL);
if (!bo_privs) {
ret = -ENOMEM;
goto exit;
}
ret = copy_from_user(bo_privs, (void __user *)args->priv_data + *priv_offset,
args->num_bos * sizeof(*bo_privs));
if (ret) {
pr_err("Failed to copy BOs information from user\n");
ret = -EFAULT;
goto exit;
}
*priv_offset += args->num_bos * sizeof(*bo_privs);
/* Create and map new BOs */
for (; i < args->num_bos; i++) {
struct kfd_criu_bo_bucket *bo_bucket;
struct kfd_criu_bo_priv_data *bo_priv;
struct kfd_dev *dev;
struct kfd_process_device *pdd;
struct kgd_mem *kgd_mem;
void *mem;
u64 offset; u64 offset;
int idr_handle;
bo_bucket = &bo_buckets[i];
bo_priv = &bo_privs[i];
pr_debug("kfd restore ioctl - bo_bucket[%d]:\n", i);
pr_debug("size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n"
"gpu_id = 0x%x alloc_flags = 0x%x\n"
"idr_handle = 0x%x\n",
bo_bucket->size,
bo_bucket->addr,
bo_bucket->offset,
bo_bucket->gpu_id,
bo_bucket->alloc_flags,
bo_priv->idr_handle);
pdd = kfd_process_device_data_by_id(p, bo_bucket->gpu_id);
if (!pdd) {
pr_err("Failed to get pdd\n");
ret = -ENODEV;
goto exit;
}
dev = pdd->dev;
if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) {
pr_debug("restore ioctl: KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL\n"); if (bo_bucket->size != kfd_doorbell_process_slice(pdd->dev))
if (bo_bucket->size != kfd_doorbell_process_slice(dev)) { return -EINVAL;
ret = -EINVAL;
goto exit;
}
offset = kfd_get_process_doorbells(pdd); offset = kfd_get_process_doorbells(pdd);
} else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) {
/* MMIO BOs need remapped bus address */ /* MMIO BOs need remapped bus address */
pr_debug("restore ioctl :KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP\n");
if (bo_bucket->size != PAGE_SIZE) { if (bo_bucket->size != PAGE_SIZE) {
pr_err("Invalid page size\n"); pr_err("Invalid page size\n");
ret = -EINVAL; return -EINVAL;
goto exit;
} }
offset = dev->adev->rmmio_remap.bus_addr; offset = pdd->dev->adev->rmmio_remap.bus_addr;
if (!offset) { if (!offset) {
pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n"); pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n");
ret = -ENOMEM; return -ENOMEM;
goto exit;
} }
} else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) {
offset = bo_priv->user_addr; offset = bo_priv->user_addr;
} }
/* Create the BO */ /* Create the BO */
ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(dev->adev, ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(pdd->dev->adev, bo_bucket->addr,
bo_bucket->addr, bo_bucket->size, pdd->drm_priv, kgd_mem,
bo_bucket->size, &offset, bo_bucket->alloc_flags, criu_resume);
pdd->drm_priv,
(struct kgd_mem **) &mem,
&offset,
bo_bucket->alloc_flags,
criu_resume);
if (ret) { if (ret) {
pr_err("Could not create the BO\n"); pr_err("Could not create the BO\n");
ret = -ENOMEM; return ret;
goto exit;
} }
pr_debug("New BO created: size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n", pr_debug("New BO created: size:0x%llx addr:0x%llx offset:0x%llx\n",
bo_bucket->size, bo_bucket->addr, offset); bo_bucket->size, bo_bucket->addr, offset);
/* Restore previuos IDR handle */ /* Restore previous IDR handle */
pr_debug("Restoring old IDR handle for the BO"); pr_debug("Restoring old IDR handle for the BO");
idr_handle = idr_alloc(&pdd->alloc_idr, mem, idr_handle = idr_alloc(&pdd->alloc_idr, *kgd_mem, bo_priv->idr_handle,
bo_priv->idr_handle,
bo_priv->idr_handle + 1, GFP_KERNEL); bo_priv->idr_handle + 1, GFP_KERNEL);
if (idr_handle < 0) { if (idr_handle < 0) {
pr_err("Could not allocate idr\n"); pr_err("Could not allocate idr\n");
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, *kgd_mem, pdd->drm_priv,
(struct kgd_mem *)mem, NULL);
pdd->drm_priv, NULL); return -ENOMEM;
ret = -ENOMEM;
goto exit;
} }
if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL)
bo_bucket->restored_offset = KFD_MMAP_TYPE_DOORBELL | bo_bucket->restored_offset = KFD_MMAP_TYPE_DOORBELL | KFD_MMAP_GPU_ID(pdd->dev->id);
KFD_MMAP_GPU_ID(pdd->dev->id);
if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) {
bo_bucket->restored_offset = KFD_MMAP_TYPE_MMIO | bo_bucket->restored_offset = KFD_MMAP_TYPE_MMIO | KFD_MMAP_GPU_ID(pdd->dev->id);
KFD_MMAP_GPU_ID(pdd->dev->id);
} else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) { } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
bo_bucket->restored_offset = offset; bo_bucket->restored_offset = offset;
pr_debug("updating offset for GTT\n");
} else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
bo_bucket->restored_offset = offset; bo_bucket->restored_offset = offset;
/* Update the VRAM usage count */ /* Update the VRAM usage count */
WRITE_ONCE(pdd->vram_usage, pdd->vram_usage + bo_bucket->size); WRITE_ONCE(pdd->vram_usage, pdd->vram_usage + bo_bucket->size);
pr_debug("updating offset for VRAM\n");
} }
return 0;
}
static int criu_restore_bo(struct kfd_process *p,
struct kfd_criu_bo_bucket *bo_bucket,
struct kfd_criu_bo_priv_data *bo_priv)
{
struct kfd_process_device *pdd;
struct kgd_mem *kgd_mem;
int ret;
int j;
pr_debug("Restoring BO size:0x%llx addr:0x%llx gpu_id:0x%x flags:0x%x idr_handle:0x%x\n",
bo_bucket->size, bo_bucket->addr, bo_bucket->gpu_id, bo_bucket->alloc_flags,
bo_priv->idr_handle);
pdd = kfd_process_device_data_by_id(p, bo_bucket->gpu_id);
if (!pdd) {
pr_err("Failed to get pdd\n");
return -ENODEV;
}
ret = criu_restore_memory_of_gpu(pdd, bo_bucket, bo_priv, &kgd_mem);
if (ret)
return ret;
/* now map these BOs to GPU/s */ /* now map these BOs to GPU/s */
for (j = 0; j < p->n_pdds; j++) { for (j = 0; j < p->n_pdds; j++) {
...@@ -2252,35 +2192,82 @@ static int criu_restore_bos(struct kfd_process *p, ...@@ -2252,35 +2192,82 @@ static int criu_restore_bos(struct kfd_process *p,
break; break;
peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]); peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]);
if (!peer_pdd) { if (!peer_pdd)
ret = -EINVAL; return -EINVAL;
goto exit;
}
peer = peer_pdd->dev; peer = peer_pdd->dev;
peer_pdd = kfd_bind_process_to_device(peer, p); peer_pdd = kfd_bind_process_to_device(peer, p);
if (IS_ERR(peer_pdd)) { if (IS_ERR(peer_pdd))
ret = PTR_ERR(peer_pdd); return PTR_ERR(peer_pdd);
goto exit;
} ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, kgd_mem, peer_pdd->drm_priv,
pr_debug("map mem in restore ioctl -> 0x%llx\n", NULL);
((struct kgd_mem *)mem)->va);
ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev,
(struct kgd_mem *)mem, peer_pdd->drm_priv, NULL);
if (ret) { if (ret) {
pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds);
goto exit; return ret;
} }
} }
pr_debug("map memory was successful for the BO\n"); pr_debug("map memory was successful for the BO\n");
/* create the dmabuf object and export the bo */ /* create the dmabuf object and export the bo */
kgd_mem = (struct kgd_mem *)mem;
if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
ret = criu_get_prime_handle(&kgd_mem->bo->tbo.base, ret = criu_get_prime_handle(&kgd_mem->bo->tbo.base, DRM_RDWR,
DRM_RDWR,
&bo_bucket->dmabuf_fd); &bo_bucket->dmabuf_fd);
if (ret) if (ret)
return ret;
}
return 0;
}
static int criu_restore_bos(struct kfd_process *p,
struct kfd_ioctl_criu_args *args,
uint64_t *priv_offset,
uint64_t max_priv_data_size)
{
struct kfd_criu_bo_bucket *bo_buckets = NULL;
struct kfd_criu_bo_priv_data *bo_privs = NULL;
int ret = 0;
uint32_t i = 0;
if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size)
return -EINVAL;
/* Prevent MMU notifications until stage-4 IOCTL (CRIU_RESUME) is received */
amdgpu_amdkfd_block_mmu_notifications(p->kgd_process_info);
bo_buckets = kvmalloc_array(args->num_bos, sizeof(*bo_buckets), GFP_KERNEL);
if (!bo_buckets)
return -ENOMEM;
ret = copy_from_user(bo_buckets, (void __user *)args->bos,
args->num_bos * sizeof(*bo_buckets));
if (ret) {
pr_err("Failed to copy BOs information from user\n");
ret = -EFAULT;
goto exit;
}
bo_privs = kvmalloc_array(args->num_bos, sizeof(*bo_privs), GFP_KERNEL);
if (!bo_privs) {
ret = -ENOMEM;
goto exit;
}
ret = copy_from_user(bo_privs, (void __user *)args->priv_data + *priv_offset,
args->num_bos * sizeof(*bo_privs));
if (ret) {
pr_err("Failed to copy BOs information from user\n");
ret = -EFAULT;
goto exit;
}
*priv_offset += args->num_bos * sizeof(*bo_privs);
/* Create and map new BOs */
for (; i < args->num_bos; i++) {
ret = criu_restore_bo(p, &bo_buckets[i], &bo_privs[i]);
if (ret) {
pr_debug("Failed to restore BO[%d] ret%d\n", i, ret);
goto exit; goto exit;
} }
} /* done */ } /* done */
......
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