diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_chardev.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 97 |
1 files changed, 91 insertions, 6 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 22925df6a791..88621cb7d409 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -164,8 +164,13 @@ static int kfd_release(struct inode *inode, struct file *filep) { struct kfd_process *process = filep->private_data; - if (process) - kfd_unref_process(process); + if (!process) + return 0; + + if (process->context_id != KFD_CONTEXT_ID_PRIMARY) + kfd_process_notifier_release_internal(process); + + kfd_unref_process(process); return 0; } @@ -216,6 +221,11 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE"); } + if ((args->metadata_ring_size != 0) && !is_power_of_2(args->metadata_ring_size)) { + pr_err("Metadata ring size must be a power of 2 or 0\n"); + return -EINVAL; + } + if (!access_ok((const void __user *) args->read_pointer_address, sizeof(uint32_t))) { pr_err("Can't access read pointer\n"); @@ -250,6 +260,9 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, q_properties->priority = args->queue_priority; q_properties->queue_address = args->ring_base_address; q_properties->queue_size = args->ring_size; + if (args->queue_type == KFD_IOC_QUEUE_TYPE_COMPUTE_AQL) + q_properties->metadata_queue_size = args->metadata_ring_size; + q_properties->read_ptr = (void __user *)args->read_pointer_address; q_properties->write_ptr = (void __user *)args->write_pointer_address; q_properties->eop_ring_buffer_address = args->eop_buffer_address; @@ -1057,6 +1070,12 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, if (args->size == 0) return -EINVAL; + if (p->context_id != KFD_CONTEXT_ID_PRIMARY && (flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR)) { + pr_debug("USERPTR is not supported on non-primary kfd_process\n"); + + return -EOPNOTSUPP; + } + #if IS_ENABLED(CONFIG_HSA_AMD_SVM) /* Flush pending deferred work to avoid racing with deferred actions * from previous memory map changes (e.g. munmap). @@ -1713,6 +1732,12 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) struct kfd_ioctl_svm_args *args = data; int r = 0; + if (p->context_id != KFD_CONTEXT_ID_PRIMARY) { + pr_debug("SVM ioctl not supported on non-primary kfd process\n"); + + return -EOPNOTSUPP; + } + pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n", args->start_addr, args->size, args->op, args->nattr); @@ -2914,6 +2939,12 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, v struct kfd_process_device *pdd = NULL; int r = 0; + if (p->context_id != KFD_CONTEXT_ID_PRIMARY) { + pr_debug("Set debug trap ioctl can not be invoked on non-primary kfd process\n"); + + return -EOPNOTSUPP; + } + if (sched_policy == KFD_SCHED_POLICY_NO_HWS) { pr_err("Debugging does not support sched_policy %i", sched_policy); return -EINVAL; @@ -2958,6 +2989,12 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, v goto out; } + if (target->context_id != KFD_CONTEXT_ID_PRIMARY) { + pr_debug("Set debug trap ioctl not supported on non-primary kfd process\n"); + r = -EOPNOTSUPP; + goto out; + } + /* Check if target is still PTRACED. */ rcu_read_lock(); if (target != p && args->op != KFD_IOC_DBG_TRAP_DISABLE @@ -3121,6 +3158,48 @@ out: return r; } +/* userspace programs need to invoke this ioctl explicitly on a FD to + * create a secondary kfd_process which replacing its primary kfd_process + */ +static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, void *data) +{ + struct kfd_process *process; + int ret; + + /* Each FD owns only one kfd_process */ + if (p->context_id != KFD_CONTEXT_ID_PRIMARY) + return -EINVAL; + + if (!filep->private_data || !p) + return -EINVAL; + + mutex_lock(&kfd_processes_mutex); + if (p != filep->private_data) { + mutex_unlock(&kfd_processes_mutex); + return -EINVAL; + } + + process = create_process(current, false); + if (IS_ERR(process)) { + mutex_unlock(&kfd_processes_mutex); + return PTR_ERR(process); + } + + filep->private_data = process; + mutex_unlock(&kfd_processes_mutex); + + ret = kfd_create_process_sysfs(process); + if (ret) + pr_warn("Failed to create sysfs entry for the kfd_process"); + + /* Each open() increases kref of the primary kfd_process, + * so we need to reduce it here when we create a new secondary process replacing it + */ + kfd_unref_process(p); + + return 0; +} + #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ .cmd_drv = 0, .name = #ioctl} @@ -3239,6 +3318,9 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_TRAP, kfd_ioctl_set_debug_trap, 0), + + AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_PROCESS, + kfd_ioctl_create_process, 0), }; #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) @@ -3397,16 +3479,19 @@ static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process, } -static int kfd_mmap(struct file *filp, struct vm_area_struct *vma) +static int kfd_mmap(struct file *filep, struct vm_area_struct *vma) { struct kfd_process *process; struct kfd_node *dev = NULL; unsigned long mmap_offset; unsigned int gpu_id; - process = kfd_get_process(current); - if (IS_ERR(process)) - return PTR_ERR(process); + process = filep->private_data; + if (!process) + return -ESRCH; + + if (process->lead_thread != current->group_leader) + return -EBADF; mmap_offset = vma->vm_pgoff << PAGE_SHIFT; gpu_id = KFD_MMAP_GET_GPU_ID(mmap_offset); |
