11bb76ff1Sjsg // SPDX-License-Identifier: GPL-2.0 OR MIT 2fb4d8502Sjsg /* 31bb76ff1Sjsg * Copyright 2014-2022 Advanced Micro Devices, Inc. 4fb4d8502Sjsg * 5fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 6fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"), 7fb4d8502Sjsg * to deal in the Software without restriction, including without limitation 8fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the 10fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions: 11fb4d8502Sjsg * 12fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in 13fb4d8502Sjsg * all copies or substantial portions of the Software. 14fb4d8502Sjsg * 15fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE. 22fb4d8502Sjsg */ 23fb4d8502Sjsg 24fb4d8502Sjsg #include <linux/device.h> 25fb4d8502Sjsg #include <linux/export.h> 26fb4d8502Sjsg #include <linux/err.h> 27fb4d8502Sjsg #include <linux/fs.h> 28fb4d8502Sjsg #include <linux/file.h> 29fb4d8502Sjsg #include <linux/sched.h> 30fb4d8502Sjsg #include <linux/slab.h> 31fb4d8502Sjsg #include <linux/uaccess.h> 32fb4d8502Sjsg #include <linux/compat.h> 33fb4d8502Sjsg #include <uapi/linux/kfd_ioctl.h> 34fb4d8502Sjsg #include <linux/time.h> 35fb4d8502Sjsg #include <linux/mm.h> 36fb4d8502Sjsg #include <linux/mman.h> 371bb76ff1Sjsg #include <linux/ptrace.h> 38c349dbc7Sjsg #include <linux/dma-buf.h> 391bb76ff1Sjsg #include <linux/fdtable.h> 401bb76ff1Sjsg #include <linux/processor.h> 41fb4d8502Sjsg #include "kfd_priv.h" 42fb4d8502Sjsg #include "kfd_device_queue_manager.h" 435ca02815Sjsg #include "kfd_svm.h" 44c349dbc7Sjsg #include "amdgpu_amdkfd.h" 45ad8b1aafSjsg #include "kfd_smi_events.h" 461bb76ff1Sjsg #include "amdgpu_dma_buf.h" 47f005ef32Sjsg #include "kfd_debug.h" 48fb4d8502Sjsg 49fb4d8502Sjsg static long kfd_ioctl(struct file *, unsigned int, unsigned long); 50fb4d8502Sjsg static int kfd_open(struct inode *, struct file *); 51c349dbc7Sjsg static int kfd_release(struct inode *, struct file *); 52fb4d8502Sjsg static int kfd_mmap(struct file *, struct vm_area_struct *); 53fb4d8502Sjsg 54fb4d8502Sjsg static const char kfd_dev_name[] = "kfd"; 55fb4d8502Sjsg 56fb4d8502Sjsg static const struct file_operations kfd_fops = { 57fb4d8502Sjsg .owner = THIS_MODULE, 58fb4d8502Sjsg .unlocked_ioctl = kfd_ioctl, 59c349dbc7Sjsg .compat_ioctl = compat_ptr_ioctl, 60fb4d8502Sjsg .open = kfd_open, 61c349dbc7Sjsg .release = kfd_release, 62fb4d8502Sjsg .mmap = kfd_mmap, 63fb4d8502Sjsg }; 64fb4d8502Sjsg 65fb4d8502Sjsg static int kfd_char_dev_major = -1; 66fb4d8502Sjsg static struct class *kfd_class; 67fb4d8502Sjsg struct device *kfd_device; 68fb4d8502Sjsg 691bb76ff1Sjsg static inline struct kfd_process_device *kfd_lock_pdd_by_id(struct kfd_process *p, __u32 gpu_id) 701bb76ff1Sjsg { 711bb76ff1Sjsg struct kfd_process_device *pdd; 721bb76ff1Sjsg 731bb76ff1Sjsg mutex_lock(&p->mutex); 741bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, gpu_id); 751bb76ff1Sjsg 761bb76ff1Sjsg if (pdd) 771bb76ff1Sjsg return pdd; 781bb76ff1Sjsg 791bb76ff1Sjsg mutex_unlock(&p->mutex); 801bb76ff1Sjsg return NULL; 811bb76ff1Sjsg } 821bb76ff1Sjsg 831bb76ff1Sjsg static inline void kfd_unlock_pdd(struct kfd_process_device *pdd) 841bb76ff1Sjsg { 851bb76ff1Sjsg mutex_unlock(&pdd->process->mutex); 861bb76ff1Sjsg } 871bb76ff1Sjsg 88fb4d8502Sjsg int kfd_chardev_init(void) 89fb4d8502Sjsg { 90fb4d8502Sjsg int err = 0; 91fb4d8502Sjsg 92fb4d8502Sjsg kfd_char_dev_major = register_chrdev(0, kfd_dev_name, &kfd_fops); 93fb4d8502Sjsg err = kfd_char_dev_major; 94fb4d8502Sjsg if (err < 0) 95fb4d8502Sjsg goto err_register_chrdev; 96fb4d8502Sjsg 97f005ef32Sjsg kfd_class = class_create(kfd_dev_name); 98fb4d8502Sjsg err = PTR_ERR(kfd_class); 99fb4d8502Sjsg if (IS_ERR(kfd_class)) 100fb4d8502Sjsg goto err_class_create; 101fb4d8502Sjsg 102fb4d8502Sjsg kfd_device = device_create(kfd_class, NULL, 103fb4d8502Sjsg MKDEV(kfd_char_dev_major, 0), 104fb4d8502Sjsg NULL, kfd_dev_name); 105fb4d8502Sjsg err = PTR_ERR(kfd_device); 106fb4d8502Sjsg if (IS_ERR(kfd_device)) 107fb4d8502Sjsg goto err_device_create; 108fb4d8502Sjsg 109fb4d8502Sjsg return 0; 110fb4d8502Sjsg 111fb4d8502Sjsg err_device_create: 112fb4d8502Sjsg class_destroy(kfd_class); 113fb4d8502Sjsg err_class_create: 114fb4d8502Sjsg unregister_chrdev(kfd_char_dev_major, kfd_dev_name); 115fb4d8502Sjsg err_register_chrdev: 116fb4d8502Sjsg return err; 117fb4d8502Sjsg } 118fb4d8502Sjsg 119fb4d8502Sjsg void kfd_chardev_exit(void) 120fb4d8502Sjsg { 121fb4d8502Sjsg device_destroy(kfd_class, MKDEV(kfd_char_dev_major, 0)); 122fb4d8502Sjsg class_destroy(kfd_class); 123fb4d8502Sjsg unregister_chrdev(kfd_char_dev_major, kfd_dev_name); 124ad8b1aafSjsg kfd_device = NULL; 125fb4d8502Sjsg } 126fb4d8502Sjsg 127fb4d8502Sjsg 128fb4d8502Sjsg static int kfd_open(struct inode *inode, struct file *filep) 129fb4d8502Sjsg { 130fb4d8502Sjsg struct kfd_process *process; 131fb4d8502Sjsg bool is_32bit_user_mode; 132fb4d8502Sjsg 133fb4d8502Sjsg if (iminor(inode) != 0) 134fb4d8502Sjsg return -ENODEV; 135fb4d8502Sjsg 136fb4d8502Sjsg is_32bit_user_mode = in_compat_syscall(); 137fb4d8502Sjsg 138fb4d8502Sjsg if (is_32bit_user_mode) { 139fb4d8502Sjsg dev_warn(kfd_device, 140fb4d8502Sjsg "Process %d (32-bit) failed to open /dev/kfd\n" 141fb4d8502Sjsg "32-bit processes are not supported by amdkfd\n", 142fb4d8502Sjsg current->pid); 143fb4d8502Sjsg return -EPERM; 144fb4d8502Sjsg } 145fb4d8502Sjsg 146f005ef32Sjsg process = kfd_create_process(current); 147fb4d8502Sjsg if (IS_ERR(process)) 148fb4d8502Sjsg return PTR_ERR(process); 149fb4d8502Sjsg 150f005ef32Sjsg if (kfd_process_init_cwsr_apu(process, filep)) { 151c349dbc7Sjsg kfd_unref_process(process); 152f005ef32Sjsg return -EFAULT; 153c349dbc7Sjsg } 154c349dbc7Sjsg 155c349dbc7Sjsg /* filep now owns the reference returned by kfd_create_process */ 156c349dbc7Sjsg filep->private_data = process; 157fb4d8502Sjsg 158fb4d8502Sjsg dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", 159fb4d8502Sjsg process->pasid, process->is_32bit_user_mode); 160fb4d8502Sjsg 161fb4d8502Sjsg return 0; 162fb4d8502Sjsg } 163fb4d8502Sjsg 164c349dbc7Sjsg static int kfd_release(struct inode *inode, struct file *filep) 165c349dbc7Sjsg { 166c349dbc7Sjsg struct kfd_process *process = filep->private_data; 167c349dbc7Sjsg 168c349dbc7Sjsg if (process) 169c349dbc7Sjsg kfd_unref_process(process); 170c349dbc7Sjsg 171c349dbc7Sjsg return 0; 172c349dbc7Sjsg } 173c349dbc7Sjsg 174fb4d8502Sjsg static int kfd_ioctl_get_version(struct file *filep, struct kfd_process *p, 175fb4d8502Sjsg void *data) 176fb4d8502Sjsg { 177fb4d8502Sjsg struct kfd_ioctl_get_version_args *args = data; 178fb4d8502Sjsg 179fb4d8502Sjsg args->major_version = KFD_IOCTL_MAJOR_VERSION; 180fb4d8502Sjsg args->minor_version = KFD_IOCTL_MINOR_VERSION; 181fb4d8502Sjsg 182fb4d8502Sjsg return 0; 183fb4d8502Sjsg } 184fb4d8502Sjsg 185fb4d8502Sjsg static int set_queue_properties_from_user(struct queue_properties *q_properties, 186fb4d8502Sjsg struct kfd_ioctl_create_queue_args *args) 187fb4d8502Sjsg { 188f005ef32Sjsg /* 189f005ef32Sjsg * Repurpose queue percentage to accommodate new features: 190f005ef32Sjsg * bit 0-7: queue percentage 191f005ef32Sjsg * bit 8-15: pm4_target_xcc 192f005ef32Sjsg */ 193f005ef32Sjsg if ((args->queue_percentage & 0xFF) > KFD_MAX_QUEUE_PERCENTAGE) { 194fb4d8502Sjsg pr_err("Queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); 195fb4d8502Sjsg return -EINVAL; 196fb4d8502Sjsg } 197fb4d8502Sjsg 198fb4d8502Sjsg if (args->queue_priority > KFD_MAX_QUEUE_PRIORITY) { 199fb4d8502Sjsg pr_err("Queue priority must be between 0 to KFD_MAX_QUEUE_PRIORITY\n"); 200fb4d8502Sjsg return -EINVAL; 201fb4d8502Sjsg } 202fb4d8502Sjsg 203fb4d8502Sjsg if ((args->ring_base_address) && 204c349dbc7Sjsg (!access_ok((const void __user *) args->ring_base_address, 205fb4d8502Sjsg sizeof(uint64_t)))) { 206fb4d8502Sjsg pr_err("Can't access ring base address\n"); 207fb4d8502Sjsg return -EFAULT; 208fb4d8502Sjsg } 209fb4d8502Sjsg 210fb4d8502Sjsg if (!is_power_of_2(args->ring_size) && (args->ring_size != 0)) { 211fb4d8502Sjsg pr_err("Ring size must be a power of 2 or 0\n"); 212fb4d8502Sjsg return -EINVAL; 213fb4d8502Sjsg } 214fb4d8502Sjsg 215c349dbc7Sjsg if (!access_ok((const void __user *) args->read_pointer_address, 216fb4d8502Sjsg sizeof(uint32_t))) { 217fb4d8502Sjsg pr_err("Can't access read pointer\n"); 218fb4d8502Sjsg return -EFAULT; 219fb4d8502Sjsg } 220fb4d8502Sjsg 221c349dbc7Sjsg if (!access_ok((const void __user *) args->write_pointer_address, 222fb4d8502Sjsg sizeof(uint32_t))) { 223fb4d8502Sjsg pr_err("Can't access write pointer\n"); 224fb4d8502Sjsg return -EFAULT; 225fb4d8502Sjsg } 226fb4d8502Sjsg 227fb4d8502Sjsg if (args->eop_buffer_address && 228c349dbc7Sjsg !access_ok((const void __user *) args->eop_buffer_address, 229fb4d8502Sjsg sizeof(uint32_t))) { 230fb4d8502Sjsg pr_debug("Can't access eop buffer"); 231fb4d8502Sjsg return -EFAULT; 232fb4d8502Sjsg } 233fb4d8502Sjsg 234fb4d8502Sjsg if (args->ctx_save_restore_address && 235c349dbc7Sjsg !access_ok((const void __user *) args->ctx_save_restore_address, 236fb4d8502Sjsg sizeof(uint32_t))) { 237fb4d8502Sjsg pr_debug("Can't access ctx save restore buffer"); 238fb4d8502Sjsg return -EFAULT; 239fb4d8502Sjsg } 240fb4d8502Sjsg 241fb4d8502Sjsg q_properties->is_interop = false; 242ad8b1aafSjsg q_properties->is_gws = false; 243f005ef32Sjsg q_properties->queue_percent = args->queue_percentage & 0xFF; 244f005ef32Sjsg /* bit 8-15 are repurposed to be PM4 target XCC */ 245f005ef32Sjsg q_properties->pm4_target_xcc = (args->queue_percentage >> 8) & 0xFF; 246fb4d8502Sjsg q_properties->priority = args->queue_priority; 247fb4d8502Sjsg q_properties->queue_address = args->ring_base_address; 248fb4d8502Sjsg q_properties->queue_size = args->ring_size; 249fb4d8502Sjsg q_properties->read_ptr = (uint32_t *) args->read_pointer_address; 250fb4d8502Sjsg q_properties->write_ptr = (uint32_t *) args->write_pointer_address; 251fb4d8502Sjsg q_properties->eop_ring_buffer_address = args->eop_buffer_address; 252fb4d8502Sjsg q_properties->eop_ring_buffer_size = args->eop_buffer_size; 253fb4d8502Sjsg q_properties->ctx_save_restore_area_address = 254fb4d8502Sjsg args->ctx_save_restore_address; 255fb4d8502Sjsg q_properties->ctx_save_restore_area_size = args->ctx_save_restore_size; 256fb4d8502Sjsg q_properties->ctl_stack_size = args->ctl_stack_size; 257fb4d8502Sjsg if (args->queue_type == KFD_IOC_QUEUE_TYPE_COMPUTE || 258fb4d8502Sjsg args->queue_type == KFD_IOC_QUEUE_TYPE_COMPUTE_AQL) 259fb4d8502Sjsg q_properties->type = KFD_QUEUE_TYPE_COMPUTE; 260fb4d8502Sjsg else if (args->queue_type == KFD_IOC_QUEUE_TYPE_SDMA) 261fb4d8502Sjsg q_properties->type = KFD_QUEUE_TYPE_SDMA; 262c349dbc7Sjsg else if (args->queue_type == KFD_IOC_QUEUE_TYPE_SDMA_XGMI) 263c349dbc7Sjsg q_properties->type = KFD_QUEUE_TYPE_SDMA_XGMI; 264fb4d8502Sjsg else 265fb4d8502Sjsg return -ENOTSUPP; 266fb4d8502Sjsg 267fb4d8502Sjsg if (args->queue_type == KFD_IOC_QUEUE_TYPE_COMPUTE_AQL) 268fb4d8502Sjsg q_properties->format = KFD_QUEUE_FORMAT_AQL; 269fb4d8502Sjsg else 270fb4d8502Sjsg q_properties->format = KFD_QUEUE_FORMAT_PM4; 271fb4d8502Sjsg 272fb4d8502Sjsg pr_debug("Queue Percentage: %d, %d\n", 273fb4d8502Sjsg q_properties->queue_percent, args->queue_percentage); 274fb4d8502Sjsg 275fb4d8502Sjsg pr_debug("Queue Priority: %d, %d\n", 276fb4d8502Sjsg q_properties->priority, args->queue_priority); 277fb4d8502Sjsg 278fb4d8502Sjsg pr_debug("Queue Address: 0x%llX, 0x%llX\n", 279fb4d8502Sjsg q_properties->queue_address, args->ring_base_address); 280fb4d8502Sjsg 281fb4d8502Sjsg pr_debug("Queue Size: 0x%llX, %u\n", 282fb4d8502Sjsg q_properties->queue_size, args->ring_size); 283fb4d8502Sjsg 284fb4d8502Sjsg pr_debug("Queue r/w Pointers: %px, %px\n", 285fb4d8502Sjsg q_properties->read_ptr, 286fb4d8502Sjsg q_properties->write_ptr); 287fb4d8502Sjsg 288fb4d8502Sjsg pr_debug("Queue Format: %d\n", q_properties->format); 289fb4d8502Sjsg 290fb4d8502Sjsg pr_debug("Queue EOP: 0x%llX\n", q_properties->eop_ring_buffer_address); 291fb4d8502Sjsg 292fb4d8502Sjsg pr_debug("Queue CTX save area: 0x%llX\n", 293fb4d8502Sjsg q_properties->ctx_save_restore_area_address); 294fb4d8502Sjsg 295fb4d8502Sjsg return 0; 296fb4d8502Sjsg } 297fb4d8502Sjsg 298fb4d8502Sjsg static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, 299fb4d8502Sjsg void *data) 300fb4d8502Sjsg { 301fb4d8502Sjsg struct kfd_ioctl_create_queue_args *args = data; 302f005ef32Sjsg struct kfd_node *dev; 303fb4d8502Sjsg int err = 0; 304fb4d8502Sjsg unsigned int queue_id; 305fb4d8502Sjsg struct kfd_process_device *pdd; 306fb4d8502Sjsg struct queue_properties q_properties; 307c349dbc7Sjsg uint32_t doorbell_offset_in_process = 0; 3081bb76ff1Sjsg struct amdgpu_bo *wptr_bo = NULL; 309fb4d8502Sjsg 310fb4d8502Sjsg memset(&q_properties, 0, sizeof(struct queue_properties)); 311fb4d8502Sjsg 312fb4d8502Sjsg pr_debug("Creating queue ioctl\n"); 313fb4d8502Sjsg 314fb4d8502Sjsg err = set_queue_properties_from_user(&q_properties, args); 315fb4d8502Sjsg if (err) 316fb4d8502Sjsg return err; 317fb4d8502Sjsg 318fb4d8502Sjsg pr_debug("Looking for gpu id 0x%x\n", args->gpu_id); 319fb4d8502Sjsg 320fb4d8502Sjsg mutex_lock(&p->mutex); 321fb4d8502Sjsg 3221bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 3231bb76ff1Sjsg if (!pdd) { 3241bb76ff1Sjsg pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); 3251bb76ff1Sjsg err = -EINVAL; 3261bb76ff1Sjsg goto err_pdd; 3271bb76ff1Sjsg } 3281bb76ff1Sjsg dev = pdd->dev; 3291bb76ff1Sjsg 330fb4d8502Sjsg pdd = kfd_bind_process_to_device(dev, p); 331fb4d8502Sjsg if (IS_ERR(pdd)) { 332fb4d8502Sjsg err = -ESRCH; 333fb4d8502Sjsg goto err_bind_process; 334fb4d8502Sjsg } 335fb4d8502Sjsg 336f005ef32Sjsg if (!pdd->qpd.proc_doorbells) { 337f005ef32Sjsg err = kfd_alloc_process_doorbells(dev->kfd, pdd); 338f005ef32Sjsg if (err) { 339f005ef32Sjsg pr_debug("failed to allocate process doorbells\n"); 340f005ef32Sjsg goto err_bind_process; 341f005ef32Sjsg } 3421bb76ff1Sjsg } 3431bb76ff1Sjsg 3441bb76ff1Sjsg /* Starting with GFX11, wptr BOs must be mapped to GART for MES to determine work 3451bb76ff1Sjsg * on unmapped queues for usermode queue oversubscription (no aggregated doorbell) 3461bb76ff1Sjsg */ 347f005ef32Sjsg if (dev->kfd->shared_resources.enable_mes && 3481bb76ff1Sjsg ((dev->adev->mes.sched_version & AMDGPU_MES_API_VERSION_MASK) 3491bb76ff1Sjsg >> AMDGPU_MES_API_VERSION_SHIFT) >= 2) { 3501bb76ff1Sjsg struct amdgpu_bo_va_mapping *wptr_mapping; 3511bb76ff1Sjsg struct amdgpu_vm *wptr_vm; 3521bb76ff1Sjsg 3531bb76ff1Sjsg wptr_vm = drm_priv_to_vm(pdd->drm_priv); 3541bb76ff1Sjsg err = amdgpu_bo_reserve(wptr_vm->root.bo, false); 3551bb76ff1Sjsg if (err) 3561bb76ff1Sjsg goto err_wptr_map_gart; 3571bb76ff1Sjsg 3581bb76ff1Sjsg wptr_mapping = amdgpu_vm_bo_lookup_mapping( 3591bb76ff1Sjsg wptr_vm, args->write_pointer_address >> PAGE_SHIFT); 3601bb76ff1Sjsg amdgpu_bo_unreserve(wptr_vm->root.bo); 3611bb76ff1Sjsg if (!wptr_mapping) { 3621bb76ff1Sjsg pr_err("Failed to lookup wptr bo\n"); 3631bb76ff1Sjsg err = -EINVAL; 3641bb76ff1Sjsg goto err_wptr_map_gart; 3651bb76ff1Sjsg } 3661bb76ff1Sjsg 3671bb76ff1Sjsg wptr_bo = wptr_mapping->bo_va->base.bo; 3681bb76ff1Sjsg if (wptr_bo->tbo.base.size > PAGE_SIZE) { 3691bb76ff1Sjsg pr_err("Requested GART mapping for wptr bo larger than one page\n"); 3701bb76ff1Sjsg err = -EINVAL; 3711bb76ff1Sjsg goto err_wptr_map_gart; 3721bb76ff1Sjsg } 3731bb76ff1Sjsg 3741bb76ff1Sjsg err = amdgpu_amdkfd_map_gtt_bo_to_gart(dev->adev, wptr_bo); 3751bb76ff1Sjsg if (err) { 3761bb76ff1Sjsg pr_err("Failed to map wptr bo to GART\n"); 3771bb76ff1Sjsg goto err_wptr_map_gart; 3781bb76ff1Sjsg } 3791bb76ff1Sjsg } 3801bb76ff1Sjsg 381c349dbc7Sjsg pr_debug("Creating queue for PASID 0x%x on gpu 0x%x\n", 382fb4d8502Sjsg p->pasid, 383fb4d8502Sjsg dev->id); 384fb4d8502Sjsg 3851bb76ff1Sjsg err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, wptr_bo, 3861bb76ff1Sjsg NULL, NULL, NULL, &doorbell_offset_in_process); 387fb4d8502Sjsg if (err != 0) 388fb4d8502Sjsg goto err_create_queue; 389fb4d8502Sjsg 390fb4d8502Sjsg args->queue_id = queue_id; 391fb4d8502Sjsg 392fb4d8502Sjsg 393fb4d8502Sjsg /* Return gpu_id as doorbell offset for mmap usage */ 394fb4d8502Sjsg args->doorbell_offset = KFD_MMAP_TYPE_DOORBELL; 395fb4d8502Sjsg args->doorbell_offset |= KFD_MMAP_GPU_ID(args->gpu_id); 3961bb76ff1Sjsg if (KFD_IS_SOC15(dev)) 397c349dbc7Sjsg /* On SOC15 ASICs, include the doorbell offset within the 398c349dbc7Sjsg * process doorbell frame, which is 2 pages. 399fb4d8502Sjsg */ 400c349dbc7Sjsg args->doorbell_offset |= doorbell_offset_in_process; 401fb4d8502Sjsg 402fb4d8502Sjsg mutex_unlock(&p->mutex); 403fb4d8502Sjsg 404fb4d8502Sjsg pr_debug("Queue id %d was created successfully\n", args->queue_id); 405fb4d8502Sjsg 406fb4d8502Sjsg pr_debug("Ring buffer address == 0x%016llX\n", 407fb4d8502Sjsg args->ring_base_address); 408fb4d8502Sjsg 409fb4d8502Sjsg pr_debug("Read ptr address == 0x%016llX\n", 410fb4d8502Sjsg args->read_pointer_address); 411fb4d8502Sjsg 412fb4d8502Sjsg pr_debug("Write ptr address == 0x%016llX\n", 413fb4d8502Sjsg args->write_pointer_address); 414fb4d8502Sjsg 415f005ef32Sjsg kfd_dbg_ev_raise(KFD_EC_MASK(EC_QUEUE_NEW), p, dev, queue_id, false, NULL, 0); 416fb4d8502Sjsg return 0; 417fb4d8502Sjsg 418fb4d8502Sjsg err_create_queue: 4191bb76ff1Sjsg if (wptr_bo) 420ff6d5195Sjsg amdgpu_amdkfd_free_gtt_mem(dev->adev, (void **)&wptr_bo); 4211bb76ff1Sjsg err_wptr_map_gart: 422fb4d8502Sjsg err_bind_process: 4231bb76ff1Sjsg err_pdd: 424fb4d8502Sjsg mutex_unlock(&p->mutex); 425fb4d8502Sjsg return err; 426fb4d8502Sjsg } 427fb4d8502Sjsg 428fb4d8502Sjsg static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, 429fb4d8502Sjsg void *data) 430fb4d8502Sjsg { 431fb4d8502Sjsg int retval; 432fb4d8502Sjsg struct kfd_ioctl_destroy_queue_args *args = data; 433fb4d8502Sjsg 434c349dbc7Sjsg pr_debug("Destroying queue id %d for pasid 0x%x\n", 435fb4d8502Sjsg args->queue_id, 436fb4d8502Sjsg p->pasid); 437fb4d8502Sjsg 438fb4d8502Sjsg mutex_lock(&p->mutex); 439fb4d8502Sjsg 440fb4d8502Sjsg retval = pqm_destroy_queue(&p->pqm, args->queue_id); 441fb4d8502Sjsg 442fb4d8502Sjsg mutex_unlock(&p->mutex); 443fb4d8502Sjsg return retval; 444fb4d8502Sjsg } 445fb4d8502Sjsg 446fb4d8502Sjsg static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, 447fb4d8502Sjsg void *data) 448fb4d8502Sjsg { 449fb4d8502Sjsg int retval; 450fb4d8502Sjsg struct kfd_ioctl_update_queue_args *args = data; 451fb4d8502Sjsg struct queue_properties properties; 452fb4d8502Sjsg 453f005ef32Sjsg /* 454f005ef32Sjsg * Repurpose queue percentage to accommodate new features: 455f005ef32Sjsg * bit 0-7: queue percentage 456f005ef32Sjsg * bit 8-15: pm4_target_xcc 457f005ef32Sjsg */ 458f005ef32Sjsg if ((args->queue_percentage & 0xFF) > KFD_MAX_QUEUE_PERCENTAGE) { 459fb4d8502Sjsg pr_err("Queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); 460fb4d8502Sjsg return -EINVAL; 461fb4d8502Sjsg } 462fb4d8502Sjsg 463fb4d8502Sjsg if (args->queue_priority > KFD_MAX_QUEUE_PRIORITY) { 464fb4d8502Sjsg pr_err("Queue priority must be between 0 to KFD_MAX_QUEUE_PRIORITY\n"); 465fb4d8502Sjsg return -EINVAL; 466fb4d8502Sjsg } 467fb4d8502Sjsg 468fb4d8502Sjsg if ((args->ring_base_address) && 469c349dbc7Sjsg (!access_ok((const void __user *) args->ring_base_address, 470fb4d8502Sjsg sizeof(uint64_t)))) { 471fb4d8502Sjsg pr_err("Can't access ring base address\n"); 472fb4d8502Sjsg return -EFAULT; 473fb4d8502Sjsg } 474fb4d8502Sjsg 475fb4d8502Sjsg if (!is_power_of_2(args->ring_size) && (args->ring_size != 0)) { 476fb4d8502Sjsg pr_err("Ring size must be a power of 2 or 0\n"); 477fb4d8502Sjsg return -EINVAL; 478fb4d8502Sjsg } 479fb4d8502Sjsg 480fb4d8502Sjsg properties.queue_address = args->ring_base_address; 481fb4d8502Sjsg properties.queue_size = args->ring_size; 482f005ef32Sjsg properties.queue_percent = args->queue_percentage & 0xFF; 483f005ef32Sjsg /* bit 8-15 are repurposed to be PM4 target XCC */ 484f005ef32Sjsg properties.pm4_target_xcc = (args->queue_percentage >> 8) & 0xFF; 485fb4d8502Sjsg properties.priority = args->queue_priority; 486fb4d8502Sjsg 487c349dbc7Sjsg pr_debug("Updating queue id %d for pasid 0x%x\n", 488fb4d8502Sjsg args->queue_id, p->pasid); 489fb4d8502Sjsg 490fb4d8502Sjsg mutex_lock(&p->mutex); 491fb4d8502Sjsg 4921bb76ff1Sjsg retval = pqm_update_queue_properties(&p->pqm, args->queue_id, &properties); 493fb4d8502Sjsg 494fb4d8502Sjsg mutex_unlock(&p->mutex); 495fb4d8502Sjsg 496fb4d8502Sjsg return retval; 497fb4d8502Sjsg } 498fb4d8502Sjsg 499fb4d8502Sjsg static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p, 500fb4d8502Sjsg void *data) 501fb4d8502Sjsg { 502fb4d8502Sjsg int retval; 503fb4d8502Sjsg const int max_num_cus = 1024; 504fb4d8502Sjsg struct kfd_ioctl_set_cu_mask_args *args = data; 5051bb76ff1Sjsg struct mqd_update_info minfo = {0}; 506fb4d8502Sjsg uint32_t __user *cu_mask_ptr = (uint32_t __user *)args->cu_mask_ptr; 507fb4d8502Sjsg size_t cu_mask_size = sizeof(uint32_t) * (args->num_cu_mask / 32); 508fb4d8502Sjsg 509fb4d8502Sjsg if ((args->num_cu_mask % 32) != 0) { 510fb4d8502Sjsg pr_debug("num_cu_mask 0x%x must be a multiple of 32", 511fb4d8502Sjsg args->num_cu_mask); 512fb4d8502Sjsg return -EINVAL; 513fb4d8502Sjsg } 514fb4d8502Sjsg 5151bb76ff1Sjsg minfo.cu_mask.count = args->num_cu_mask; 5161bb76ff1Sjsg if (minfo.cu_mask.count == 0) { 517fb4d8502Sjsg pr_debug("CU mask cannot be 0"); 518fb4d8502Sjsg return -EINVAL; 519fb4d8502Sjsg } 520fb4d8502Sjsg 521fb4d8502Sjsg /* To prevent an unreasonably large CU mask size, set an arbitrary 522fb4d8502Sjsg * limit of max_num_cus bits. We can then just drop any CU mask bits 523fb4d8502Sjsg * past max_num_cus bits and just use the first max_num_cus bits. 524fb4d8502Sjsg */ 5251bb76ff1Sjsg if (minfo.cu_mask.count > max_num_cus) { 526fb4d8502Sjsg pr_debug("CU mask cannot be greater than 1024 bits"); 5271bb76ff1Sjsg minfo.cu_mask.count = max_num_cus; 528fb4d8502Sjsg cu_mask_size = sizeof(uint32_t) * (max_num_cus/32); 529fb4d8502Sjsg } 530fb4d8502Sjsg 5311bb76ff1Sjsg minfo.cu_mask.ptr = kzalloc(cu_mask_size, GFP_KERNEL); 5321bb76ff1Sjsg if (!minfo.cu_mask.ptr) 533fb4d8502Sjsg return -ENOMEM; 534fb4d8502Sjsg 5351bb76ff1Sjsg retval = copy_from_user(minfo.cu_mask.ptr, cu_mask_ptr, cu_mask_size); 536fb4d8502Sjsg if (retval) { 537fb4d8502Sjsg pr_debug("Could not copy CU mask from userspace"); 5381bb76ff1Sjsg retval = -EFAULT; 5391bb76ff1Sjsg goto out; 540fb4d8502Sjsg } 541fb4d8502Sjsg 542fb4d8502Sjsg mutex_lock(&p->mutex); 543fb4d8502Sjsg 5441bb76ff1Sjsg retval = pqm_update_mqd(&p->pqm, args->queue_id, &minfo); 545fb4d8502Sjsg 546fb4d8502Sjsg mutex_unlock(&p->mutex); 547fb4d8502Sjsg 5481bb76ff1Sjsg out: 5491bb76ff1Sjsg kfree(minfo.cu_mask.ptr); 550fb4d8502Sjsg return retval; 551fb4d8502Sjsg } 552fb4d8502Sjsg 553c349dbc7Sjsg static int kfd_ioctl_get_queue_wave_state(struct file *filep, 554c349dbc7Sjsg struct kfd_process *p, void *data) 555c349dbc7Sjsg { 556c349dbc7Sjsg struct kfd_ioctl_get_queue_wave_state_args *args = data; 557c349dbc7Sjsg int r; 558c349dbc7Sjsg 559c349dbc7Sjsg mutex_lock(&p->mutex); 560c349dbc7Sjsg 561c349dbc7Sjsg r = pqm_get_wave_state(&p->pqm, args->queue_id, 562c349dbc7Sjsg (void __user *)args->ctl_stack_address, 563c349dbc7Sjsg &args->ctl_stack_used_size, 564c349dbc7Sjsg &args->save_area_used_size); 565c349dbc7Sjsg 566c349dbc7Sjsg mutex_unlock(&p->mutex); 567c349dbc7Sjsg 568c349dbc7Sjsg return r; 569c349dbc7Sjsg } 570c349dbc7Sjsg 571fb4d8502Sjsg static int kfd_ioctl_set_memory_policy(struct file *filep, 572fb4d8502Sjsg struct kfd_process *p, void *data) 573fb4d8502Sjsg { 574fb4d8502Sjsg struct kfd_ioctl_set_memory_policy_args *args = data; 575fb4d8502Sjsg int err = 0; 576fb4d8502Sjsg struct kfd_process_device *pdd; 577fb4d8502Sjsg enum cache_policy default_policy, alternate_policy; 578fb4d8502Sjsg 579fb4d8502Sjsg if (args->default_policy != KFD_IOC_CACHE_POLICY_COHERENT 580fb4d8502Sjsg && args->default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { 581fb4d8502Sjsg return -EINVAL; 582fb4d8502Sjsg } 583fb4d8502Sjsg 584fb4d8502Sjsg if (args->alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT 585fb4d8502Sjsg && args->alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { 586fb4d8502Sjsg return -EINVAL; 587fb4d8502Sjsg } 588fb4d8502Sjsg 589fb4d8502Sjsg mutex_lock(&p->mutex); 5901bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 5911bb76ff1Sjsg if (!pdd) { 5921bb76ff1Sjsg pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); 5931bb76ff1Sjsg err = -EINVAL; 5941bb76ff1Sjsg goto err_pdd; 5951bb76ff1Sjsg } 596fb4d8502Sjsg 5971bb76ff1Sjsg pdd = kfd_bind_process_to_device(pdd->dev, p); 598fb4d8502Sjsg if (IS_ERR(pdd)) { 599fb4d8502Sjsg err = -ESRCH; 600fb4d8502Sjsg goto out; 601fb4d8502Sjsg } 602fb4d8502Sjsg 603fb4d8502Sjsg default_policy = (args->default_policy == KFD_IOC_CACHE_POLICY_COHERENT) 604fb4d8502Sjsg ? cache_policy_coherent : cache_policy_noncoherent; 605fb4d8502Sjsg 606fb4d8502Sjsg alternate_policy = 607fb4d8502Sjsg (args->alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) 608fb4d8502Sjsg ? cache_policy_coherent : cache_policy_noncoherent; 609fb4d8502Sjsg 6101bb76ff1Sjsg if (!pdd->dev->dqm->ops.set_cache_memory_policy(pdd->dev->dqm, 611fb4d8502Sjsg &pdd->qpd, 612fb4d8502Sjsg default_policy, 613fb4d8502Sjsg alternate_policy, 614fb4d8502Sjsg (void __user *)args->alternate_aperture_base, 615fb4d8502Sjsg args->alternate_aperture_size)) 616fb4d8502Sjsg err = -EINVAL; 617fb4d8502Sjsg 618fb4d8502Sjsg out: 6191bb76ff1Sjsg err_pdd: 620fb4d8502Sjsg mutex_unlock(&p->mutex); 621fb4d8502Sjsg 622fb4d8502Sjsg return err; 623fb4d8502Sjsg } 624fb4d8502Sjsg 625fb4d8502Sjsg static int kfd_ioctl_set_trap_handler(struct file *filep, 626fb4d8502Sjsg struct kfd_process *p, void *data) 627fb4d8502Sjsg { 628fb4d8502Sjsg struct kfd_ioctl_set_trap_handler_args *args = data; 629fb4d8502Sjsg int err = 0; 630fb4d8502Sjsg struct kfd_process_device *pdd; 631fb4d8502Sjsg 632fb4d8502Sjsg mutex_lock(&p->mutex); 633fb4d8502Sjsg 6341bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 6351bb76ff1Sjsg if (!pdd) { 6361bb76ff1Sjsg err = -EINVAL; 6371bb76ff1Sjsg goto err_pdd; 6381bb76ff1Sjsg } 6391bb76ff1Sjsg 6401bb76ff1Sjsg pdd = kfd_bind_process_to_device(pdd->dev, p); 641fb4d8502Sjsg if (IS_ERR(pdd)) { 642fb4d8502Sjsg err = -ESRCH; 643fb4d8502Sjsg goto out; 644fb4d8502Sjsg } 645fb4d8502Sjsg 6465ca02815Sjsg kfd_process_set_trap_handler(&pdd->qpd, args->tba_addr, args->tma_addr); 647fb4d8502Sjsg 648fb4d8502Sjsg out: 6491bb76ff1Sjsg err_pdd: 650fb4d8502Sjsg mutex_unlock(&p->mutex); 651fb4d8502Sjsg 652fb4d8502Sjsg return err; 653fb4d8502Sjsg } 654fb4d8502Sjsg 655fb4d8502Sjsg static int kfd_ioctl_dbg_register(struct file *filep, 656fb4d8502Sjsg struct kfd_process *p, void *data) 657fb4d8502Sjsg { 6581bb76ff1Sjsg return -EPERM; 659fb4d8502Sjsg } 660fb4d8502Sjsg 661fb4d8502Sjsg static int kfd_ioctl_dbg_unregister(struct file *filep, 662fb4d8502Sjsg struct kfd_process *p, void *data) 663fb4d8502Sjsg { 6641bb76ff1Sjsg return -EPERM; 665fb4d8502Sjsg } 666fb4d8502Sjsg 667fb4d8502Sjsg static int kfd_ioctl_dbg_address_watch(struct file *filep, 668fb4d8502Sjsg struct kfd_process *p, void *data) 669fb4d8502Sjsg { 6701bb76ff1Sjsg return -EPERM; 671fb4d8502Sjsg } 672fb4d8502Sjsg 673fb4d8502Sjsg /* Parse and generate fixed size data structure for wave control */ 674fb4d8502Sjsg static int kfd_ioctl_dbg_wave_control(struct file *filep, 675fb4d8502Sjsg struct kfd_process *p, void *data) 676fb4d8502Sjsg { 6771bb76ff1Sjsg return -EPERM; 678fb4d8502Sjsg } 679fb4d8502Sjsg 680fb4d8502Sjsg static int kfd_ioctl_get_clock_counters(struct file *filep, 681fb4d8502Sjsg struct kfd_process *p, void *data) 682fb4d8502Sjsg { 683fb4d8502Sjsg struct kfd_ioctl_get_clock_counters_args *args = data; 6841bb76ff1Sjsg struct kfd_process_device *pdd; 685fb4d8502Sjsg 6861bb76ff1Sjsg mutex_lock(&p->mutex); 6871bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 6881bb76ff1Sjsg mutex_unlock(&p->mutex); 6891bb76ff1Sjsg if (pdd) 690fb4d8502Sjsg /* Reading GPU clock counter from KGD */ 6911bb76ff1Sjsg args->gpu_clock_counter = amdgpu_amdkfd_get_gpu_clock_counter(pdd->dev->adev); 692fb4d8502Sjsg else 693fb4d8502Sjsg /* Node without GPU resource */ 694fb4d8502Sjsg args->gpu_clock_counter = 0; 695fb4d8502Sjsg 696fb4d8502Sjsg /* No access to rdtsc. Using raw monotonic time */ 697fb4d8502Sjsg args->cpu_clock_counter = ktime_get_raw_ns(); 698c349dbc7Sjsg args->system_clock_counter = ktime_get_boottime_ns(); 699fb4d8502Sjsg 700fb4d8502Sjsg /* Since the counter is in nano-seconds we use 1GHz frequency */ 701fb4d8502Sjsg args->system_clock_freq = 1000000000; 702fb4d8502Sjsg 703fb4d8502Sjsg return 0; 704fb4d8502Sjsg } 705fb4d8502Sjsg 706fb4d8502Sjsg 707fb4d8502Sjsg static int kfd_ioctl_get_process_apertures(struct file *filp, 708fb4d8502Sjsg struct kfd_process *p, void *data) 709fb4d8502Sjsg { 710fb4d8502Sjsg struct kfd_ioctl_get_process_apertures_args *args = data; 711fb4d8502Sjsg struct kfd_process_device_apertures *pAperture; 7125ca02815Sjsg int i; 713fb4d8502Sjsg 714c349dbc7Sjsg dev_dbg(kfd_device, "get apertures for PASID 0x%x", p->pasid); 715fb4d8502Sjsg 716fb4d8502Sjsg args->num_of_nodes = 0; 717fb4d8502Sjsg 718fb4d8502Sjsg mutex_lock(&p->mutex); 719fb4d8502Sjsg /* Run over all pdd of the process */ 7205ca02815Sjsg for (i = 0; i < p->n_pdds; i++) { 7215ca02815Sjsg struct kfd_process_device *pdd = p->pdds[i]; 7225ca02815Sjsg 723fb4d8502Sjsg pAperture = 724fb4d8502Sjsg &args->process_apertures[args->num_of_nodes]; 725fb4d8502Sjsg pAperture->gpu_id = pdd->dev->id; 726fb4d8502Sjsg pAperture->lds_base = pdd->lds_base; 727fb4d8502Sjsg pAperture->lds_limit = pdd->lds_limit; 728fb4d8502Sjsg pAperture->gpuvm_base = pdd->gpuvm_base; 729fb4d8502Sjsg pAperture->gpuvm_limit = pdd->gpuvm_limit; 730fb4d8502Sjsg pAperture->scratch_base = pdd->scratch_base; 731fb4d8502Sjsg pAperture->scratch_limit = pdd->scratch_limit; 732fb4d8502Sjsg 733fb4d8502Sjsg dev_dbg(kfd_device, 734fb4d8502Sjsg "node id %u\n", args->num_of_nodes); 735fb4d8502Sjsg dev_dbg(kfd_device, 736fb4d8502Sjsg "gpu id %u\n", pdd->dev->id); 737fb4d8502Sjsg dev_dbg(kfd_device, 738fb4d8502Sjsg "lds_base %llX\n", pdd->lds_base); 739fb4d8502Sjsg dev_dbg(kfd_device, 740fb4d8502Sjsg "lds_limit %llX\n", pdd->lds_limit); 741fb4d8502Sjsg dev_dbg(kfd_device, 742fb4d8502Sjsg "gpuvm_base %llX\n", pdd->gpuvm_base); 743fb4d8502Sjsg dev_dbg(kfd_device, 744fb4d8502Sjsg "gpuvm_limit %llX\n", pdd->gpuvm_limit); 745fb4d8502Sjsg dev_dbg(kfd_device, 746fb4d8502Sjsg "scratch_base %llX\n", pdd->scratch_base); 747fb4d8502Sjsg dev_dbg(kfd_device, 748fb4d8502Sjsg "scratch_limit %llX\n", pdd->scratch_limit); 749fb4d8502Sjsg 7505ca02815Sjsg if (++args->num_of_nodes >= NUM_OF_SUPPORTED_GPUS) 7515ca02815Sjsg break; 752fb4d8502Sjsg } 753fb4d8502Sjsg mutex_unlock(&p->mutex); 754fb4d8502Sjsg 755fb4d8502Sjsg return 0; 756fb4d8502Sjsg } 757fb4d8502Sjsg 758fb4d8502Sjsg static int kfd_ioctl_get_process_apertures_new(struct file *filp, 759fb4d8502Sjsg struct kfd_process *p, void *data) 760fb4d8502Sjsg { 761fb4d8502Sjsg struct kfd_ioctl_get_process_apertures_new_args *args = data; 762fb4d8502Sjsg struct kfd_process_device_apertures *pa; 763fb4d8502Sjsg int ret; 7645ca02815Sjsg int i; 765fb4d8502Sjsg 766c349dbc7Sjsg dev_dbg(kfd_device, "get apertures for PASID 0x%x", p->pasid); 767fb4d8502Sjsg 768fb4d8502Sjsg if (args->num_of_nodes == 0) { 769fb4d8502Sjsg /* Return number of nodes, so that user space can alloacate 770fb4d8502Sjsg * sufficient memory 771fb4d8502Sjsg */ 772fb4d8502Sjsg mutex_lock(&p->mutex); 7735ca02815Sjsg args->num_of_nodes = p->n_pdds; 774fb4d8502Sjsg goto out_unlock; 775fb4d8502Sjsg } 776fb4d8502Sjsg 777fb4d8502Sjsg /* Fill in process-aperture information for all available 778fb4d8502Sjsg * nodes, but not more than args->num_of_nodes as that is 779fb4d8502Sjsg * the amount of memory allocated by user 780fb4d8502Sjsg */ 781b492a601Sjsg pa = kcalloc(args->num_of_nodes, sizeof(struct kfd_process_device_apertures), 782b492a601Sjsg GFP_KERNEL); 783fb4d8502Sjsg if (!pa) 784fb4d8502Sjsg return -ENOMEM; 785fb4d8502Sjsg 786fb4d8502Sjsg mutex_lock(&p->mutex); 787fb4d8502Sjsg 7885ca02815Sjsg if (!p->n_pdds) { 789fb4d8502Sjsg args->num_of_nodes = 0; 790fb4d8502Sjsg kfree(pa); 791fb4d8502Sjsg goto out_unlock; 792fb4d8502Sjsg } 793fb4d8502Sjsg 794fb4d8502Sjsg /* Run over all pdd of the process */ 7955ca02815Sjsg for (i = 0; i < min(p->n_pdds, args->num_of_nodes); i++) { 7965ca02815Sjsg struct kfd_process_device *pdd = p->pdds[i]; 7975ca02815Sjsg 7985ca02815Sjsg pa[i].gpu_id = pdd->dev->id; 7995ca02815Sjsg pa[i].lds_base = pdd->lds_base; 8005ca02815Sjsg pa[i].lds_limit = pdd->lds_limit; 8015ca02815Sjsg pa[i].gpuvm_base = pdd->gpuvm_base; 8025ca02815Sjsg pa[i].gpuvm_limit = pdd->gpuvm_limit; 8035ca02815Sjsg pa[i].scratch_base = pdd->scratch_base; 8045ca02815Sjsg pa[i].scratch_limit = pdd->scratch_limit; 805fb4d8502Sjsg 806fb4d8502Sjsg dev_dbg(kfd_device, 807fb4d8502Sjsg "gpu id %u\n", pdd->dev->id); 808fb4d8502Sjsg dev_dbg(kfd_device, 809fb4d8502Sjsg "lds_base %llX\n", pdd->lds_base); 810fb4d8502Sjsg dev_dbg(kfd_device, 811fb4d8502Sjsg "lds_limit %llX\n", pdd->lds_limit); 812fb4d8502Sjsg dev_dbg(kfd_device, 813fb4d8502Sjsg "gpuvm_base %llX\n", pdd->gpuvm_base); 814fb4d8502Sjsg dev_dbg(kfd_device, 815fb4d8502Sjsg "gpuvm_limit %llX\n", pdd->gpuvm_limit); 816fb4d8502Sjsg dev_dbg(kfd_device, 817fb4d8502Sjsg "scratch_base %llX\n", pdd->scratch_base); 818fb4d8502Sjsg dev_dbg(kfd_device, 819fb4d8502Sjsg "scratch_limit %llX\n", pdd->scratch_limit); 8205ca02815Sjsg } 821fb4d8502Sjsg mutex_unlock(&p->mutex); 822fb4d8502Sjsg 8235ca02815Sjsg args->num_of_nodes = i; 824fb4d8502Sjsg ret = copy_to_user( 825fb4d8502Sjsg (void __user *)args->kfd_process_device_apertures_ptr, 826fb4d8502Sjsg pa, 8275ca02815Sjsg (i * sizeof(struct kfd_process_device_apertures))); 828fb4d8502Sjsg kfree(pa); 829fb4d8502Sjsg return ret ? -EFAULT : 0; 830fb4d8502Sjsg 831fb4d8502Sjsg out_unlock: 832fb4d8502Sjsg mutex_unlock(&p->mutex); 833fb4d8502Sjsg return 0; 834fb4d8502Sjsg } 835fb4d8502Sjsg 836fb4d8502Sjsg static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p, 837fb4d8502Sjsg void *data) 838fb4d8502Sjsg { 839fb4d8502Sjsg struct kfd_ioctl_create_event_args *args = data; 840fb4d8502Sjsg int err; 841fb4d8502Sjsg 842fb4d8502Sjsg /* For dGPUs the event page is allocated in user mode. The 843fb4d8502Sjsg * handle is passed to KFD with the first call to this IOCTL 844fb4d8502Sjsg * through the event_page_offset field. 845fb4d8502Sjsg */ 846fb4d8502Sjsg if (args->event_page_offset) { 847fb4d8502Sjsg mutex_lock(&p->mutex); 8481bb76ff1Sjsg err = kfd_kmap_event_page(p, args->event_page_offset); 849fb4d8502Sjsg mutex_unlock(&p->mutex); 8501bb76ff1Sjsg if (err) 851fb4d8502Sjsg return err; 852fb4d8502Sjsg } 853fb4d8502Sjsg 854fb4d8502Sjsg err = kfd_event_create(filp, p, args->event_type, 855fb4d8502Sjsg args->auto_reset != 0, args->node_id, 856fb4d8502Sjsg &args->event_id, &args->event_trigger_data, 857fb4d8502Sjsg &args->event_page_offset, 858fb4d8502Sjsg &args->event_slot_index); 859fb4d8502Sjsg 8601bb76ff1Sjsg pr_debug("Created event (id:0x%08x) (%s)\n", args->event_id, __func__); 861fb4d8502Sjsg return err; 862fb4d8502Sjsg } 863fb4d8502Sjsg 864fb4d8502Sjsg static int kfd_ioctl_destroy_event(struct file *filp, struct kfd_process *p, 865fb4d8502Sjsg void *data) 866fb4d8502Sjsg { 867fb4d8502Sjsg struct kfd_ioctl_destroy_event_args *args = data; 868fb4d8502Sjsg 869fb4d8502Sjsg return kfd_event_destroy(p, args->event_id); 870fb4d8502Sjsg } 871fb4d8502Sjsg 872fb4d8502Sjsg static int kfd_ioctl_set_event(struct file *filp, struct kfd_process *p, 873fb4d8502Sjsg void *data) 874fb4d8502Sjsg { 875fb4d8502Sjsg struct kfd_ioctl_set_event_args *args = data; 876fb4d8502Sjsg 877fb4d8502Sjsg return kfd_set_event(p, args->event_id); 878fb4d8502Sjsg } 879fb4d8502Sjsg 880fb4d8502Sjsg static int kfd_ioctl_reset_event(struct file *filp, struct kfd_process *p, 881fb4d8502Sjsg void *data) 882fb4d8502Sjsg { 883fb4d8502Sjsg struct kfd_ioctl_reset_event_args *args = data; 884fb4d8502Sjsg 885fb4d8502Sjsg return kfd_reset_event(p, args->event_id); 886fb4d8502Sjsg } 887fb4d8502Sjsg 888fb4d8502Sjsg static int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p, 889fb4d8502Sjsg void *data) 890fb4d8502Sjsg { 891fb4d8502Sjsg struct kfd_ioctl_wait_events_args *args = data; 892fb4d8502Sjsg 8931bb76ff1Sjsg return kfd_wait_on_events(p, args->num_events, 894fb4d8502Sjsg (void __user *)args->events_ptr, 895fb4d8502Sjsg (args->wait_for_all != 0), 8961bb76ff1Sjsg &args->timeout, &args->wait_result); 897fb4d8502Sjsg } 898fb4d8502Sjsg static int kfd_ioctl_set_scratch_backing_va(struct file *filep, 899fb4d8502Sjsg struct kfd_process *p, void *data) 900fb4d8502Sjsg { 901fb4d8502Sjsg struct kfd_ioctl_set_scratch_backing_va_args *args = data; 902fb4d8502Sjsg struct kfd_process_device *pdd; 903f005ef32Sjsg struct kfd_node *dev; 904fb4d8502Sjsg long err; 905fb4d8502Sjsg 906fb4d8502Sjsg mutex_lock(&p->mutex); 9071bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 9081bb76ff1Sjsg if (!pdd) { 9091bb76ff1Sjsg err = -EINVAL; 9101bb76ff1Sjsg goto err_pdd; 9111bb76ff1Sjsg } 9121bb76ff1Sjsg dev = pdd->dev; 913fb4d8502Sjsg 914fb4d8502Sjsg pdd = kfd_bind_process_to_device(dev, p); 915fb4d8502Sjsg if (IS_ERR(pdd)) { 916fb4d8502Sjsg err = PTR_ERR(pdd); 917fb4d8502Sjsg goto bind_process_to_device_fail; 918fb4d8502Sjsg } 919fb4d8502Sjsg 920fb4d8502Sjsg pdd->qpd.sh_hidden_private_base = args->va_addr; 921fb4d8502Sjsg 922fb4d8502Sjsg mutex_unlock(&p->mutex); 923fb4d8502Sjsg 924fb4d8502Sjsg if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS && 925c349dbc7Sjsg pdd->qpd.vmid != 0 && dev->kfd2kgd->set_scratch_backing_va) 926fb4d8502Sjsg dev->kfd2kgd->set_scratch_backing_va( 9271bb76ff1Sjsg dev->adev, args->va_addr, pdd->qpd.vmid); 928fb4d8502Sjsg 929fb4d8502Sjsg return 0; 930fb4d8502Sjsg 931fb4d8502Sjsg bind_process_to_device_fail: 9321bb76ff1Sjsg err_pdd: 933fb4d8502Sjsg mutex_unlock(&p->mutex); 934fb4d8502Sjsg return err; 935fb4d8502Sjsg } 936fb4d8502Sjsg 937fb4d8502Sjsg static int kfd_ioctl_get_tile_config(struct file *filep, 938fb4d8502Sjsg struct kfd_process *p, void *data) 939fb4d8502Sjsg { 940fb4d8502Sjsg struct kfd_ioctl_get_tile_config_args *args = data; 9411bb76ff1Sjsg struct kfd_process_device *pdd; 942fb4d8502Sjsg struct tile_config config; 943fb4d8502Sjsg int err = 0; 944fb4d8502Sjsg 9451bb76ff1Sjsg mutex_lock(&p->mutex); 9461bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 9471bb76ff1Sjsg mutex_unlock(&p->mutex); 9481bb76ff1Sjsg if (!pdd) 949fb4d8502Sjsg return -EINVAL; 950fb4d8502Sjsg 9511bb76ff1Sjsg amdgpu_amdkfd_get_tile_config(pdd->dev->adev, &config); 952fb4d8502Sjsg 953fb4d8502Sjsg args->gb_addr_config = config.gb_addr_config; 954fb4d8502Sjsg args->num_banks = config.num_banks; 955fb4d8502Sjsg args->num_ranks = config.num_ranks; 956fb4d8502Sjsg 957fb4d8502Sjsg if (args->num_tile_configs > config.num_tile_configs) 958fb4d8502Sjsg args->num_tile_configs = config.num_tile_configs; 959fb4d8502Sjsg err = copy_to_user((void __user *)args->tile_config_ptr, 960fb4d8502Sjsg config.tile_config_ptr, 961fb4d8502Sjsg args->num_tile_configs * sizeof(uint32_t)); 962fb4d8502Sjsg if (err) { 963fb4d8502Sjsg args->num_tile_configs = 0; 964fb4d8502Sjsg return -EFAULT; 965fb4d8502Sjsg } 966fb4d8502Sjsg 967fb4d8502Sjsg if (args->num_macro_tile_configs > config.num_macro_tile_configs) 968fb4d8502Sjsg args->num_macro_tile_configs = 969fb4d8502Sjsg config.num_macro_tile_configs; 970fb4d8502Sjsg err = copy_to_user((void __user *)args->macro_tile_config_ptr, 971fb4d8502Sjsg config.macro_tile_config_ptr, 972fb4d8502Sjsg args->num_macro_tile_configs * sizeof(uint32_t)); 973fb4d8502Sjsg if (err) { 974fb4d8502Sjsg args->num_macro_tile_configs = 0; 975fb4d8502Sjsg return -EFAULT; 976fb4d8502Sjsg } 977fb4d8502Sjsg 978fb4d8502Sjsg return 0; 979fb4d8502Sjsg } 980fb4d8502Sjsg 981fb4d8502Sjsg static int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p, 982fb4d8502Sjsg void *data) 983fb4d8502Sjsg { 984fb4d8502Sjsg struct kfd_ioctl_acquire_vm_args *args = data; 985fb4d8502Sjsg struct kfd_process_device *pdd; 986fb4d8502Sjsg struct file *drm_file; 987fb4d8502Sjsg int ret; 988fb4d8502Sjsg 989fb4d8502Sjsg drm_file = fget(args->drm_fd); 990fb4d8502Sjsg if (!drm_file) 991fb4d8502Sjsg return -EINVAL; 992fb4d8502Sjsg 993fb4d8502Sjsg mutex_lock(&p->mutex); 9941bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 995fb4d8502Sjsg if (!pdd) { 996fb4d8502Sjsg ret = -EINVAL; 9971bb76ff1Sjsg goto err_pdd; 998fb4d8502Sjsg } 999fb4d8502Sjsg 1000fb4d8502Sjsg if (pdd->drm_file) { 1001fb4d8502Sjsg ret = pdd->drm_file == drm_file ? 0 : -EBUSY; 10021bb76ff1Sjsg goto err_drm_file; 1003fb4d8502Sjsg } 1004fb4d8502Sjsg 1005fb4d8502Sjsg ret = kfd_process_device_init_vm(pdd, drm_file); 1006fb4d8502Sjsg if (ret) 1007fb4d8502Sjsg goto err_unlock; 10081bb76ff1Sjsg 1009fb4d8502Sjsg /* On success, the PDD keeps the drm_file reference */ 1010fb4d8502Sjsg mutex_unlock(&p->mutex); 1011fb4d8502Sjsg 1012fb4d8502Sjsg return 0; 1013fb4d8502Sjsg 1014fb4d8502Sjsg err_unlock: 10151bb76ff1Sjsg err_pdd: 10161bb76ff1Sjsg err_drm_file: 1017fb4d8502Sjsg mutex_unlock(&p->mutex); 1018fb4d8502Sjsg fput(drm_file); 1019fb4d8502Sjsg return ret; 1020fb4d8502Sjsg } 1021fb4d8502Sjsg 1022f005ef32Sjsg bool kfd_dev_is_large_bar(struct kfd_node *dev) 1023fb4d8502Sjsg { 1024fb4d8502Sjsg if (debug_largebar) { 1025fb4d8502Sjsg pr_debug("Simulate large-bar allocation on non large-bar machine\n"); 1026fb4d8502Sjsg return true; 1027fb4d8502Sjsg } 1028fb4d8502Sjsg 10291bb76ff1Sjsg if (dev->local_mem_info.local_mem_size_private == 0 && 10301bb76ff1Sjsg dev->local_mem_info.local_mem_size_public > 0) 1031fb4d8502Sjsg return true; 1032f005ef32Sjsg 1033f005ef32Sjsg if (dev->local_mem_info.local_mem_size_public == 0 && 1034f005ef32Sjsg dev->kfd->adev->gmc.is_app_apu) { 1035f005ef32Sjsg pr_debug("APP APU, Consider like a large bar system\n"); 1036f005ef32Sjsg return true; 1037f005ef32Sjsg } 1038f005ef32Sjsg 1039fb4d8502Sjsg return false; 1040fb4d8502Sjsg } 1041fb4d8502Sjsg 10421bb76ff1Sjsg static int kfd_ioctl_get_available_memory(struct file *filep, 10431bb76ff1Sjsg struct kfd_process *p, void *data) 10441bb76ff1Sjsg { 10451bb76ff1Sjsg struct kfd_ioctl_get_available_memory_args *args = data; 10461bb76ff1Sjsg struct kfd_process_device *pdd = kfd_lock_pdd_by_id(p, args->gpu_id); 10471bb76ff1Sjsg 10481bb76ff1Sjsg if (!pdd) 10491bb76ff1Sjsg return -EINVAL; 1050f005ef32Sjsg args->available = amdgpu_amdkfd_get_available_memory(pdd->dev->adev, 1051f005ef32Sjsg pdd->dev->node_id); 10521bb76ff1Sjsg kfd_unlock_pdd(pdd); 10531bb76ff1Sjsg return 0; 10541bb76ff1Sjsg } 10551bb76ff1Sjsg 1056fb4d8502Sjsg static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, 1057fb4d8502Sjsg struct kfd_process *p, void *data) 1058fb4d8502Sjsg { 1059fb4d8502Sjsg struct kfd_ioctl_alloc_memory_of_gpu_args *args = data; 1060fb4d8502Sjsg struct kfd_process_device *pdd; 1061fb4d8502Sjsg void *mem; 1062f005ef32Sjsg struct kfd_node *dev; 1063fb4d8502Sjsg int idr_handle; 1064fb4d8502Sjsg long err; 1065fb4d8502Sjsg uint64_t offset = args->mmap_offset; 1066fb4d8502Sjsg uint32_t flags = args->flags; 1067fb4d8502Sjsg 1068fb4d8502Sjsg if (args->size == 0) 1069fb4d8502Sjsg return -EINVAL; 1070fb4d8502Sjsg 10711bb76ff1Sjsg #if IS_ENABLED(CONFIG_HSA_AMD_SVM) 10721bb76ff1Sjsg /* Flush pending deferred work to avoid racing with deferred actions 10731bb76ff1Sjsg * from previous memory map changes (e.g. munmap). 10741bb76ff1Sjsg */ 10751bb76ff1Sjsg svm_range_list_lock_and_flush_work(&p->svms, current->mm); 10761bb76ff1Sjsg mutex_lock(&p->svms.lock); 10771bb76ff1Sjsg mmap_write_unlock(current->mm); 10781bb76ff1Sjsg if (interval_tree_iter_first(&p->svms.objects, 10791bb76ff1Sjsg args->va_addr >> PAGE_SHIFT, 10801bb76ff1Sjsg (args->va_addr + args->size - 1) >> PAGE_SHIFT)) { 10811bb76ff1Sjsg pr_err("Address: 0x%llx already allocated by SVM\n", 10821bb76ff1Sjsg args->va_addr); 10831bb76ff1Sjsg mutex_unlock(&p->svms.lock); 10841bb76ff1Sjsg return -EADDRINUSE; 10851bb76ff1Sjsg } 1086f005ef32Sjsg 1087f005ef32Sjsg /* When register user buffer check if it has been registered by svm by 1088f005ef32Sjsg * buffer cpu virtual address. 1089f005ef32Sjsg */ 1090f005ef32Sjsg if ((flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) && 1091f005ef32Sjsg interval_tree_iter_first(&p->svms.objects, 1092f005ef32Sjsg args->mmap_offset >> PAGE_SHIFT, 1093f005ef32Sjsg (args->mmap_offset + args->size - 1) >> PAGE_SHIFT)) { 1094f005ef32Sjsg pr_err("User Buffer Address: 0x%llx already allocated by SVM\n", 1095f005ef32Sjsg args->mmap_offset); 1096f005ef32Sjsg mutex_unlock(&p->svms.lock); 1097f005ef32Sjsg return -EADDRINUSE; 1098f005ef32Sjsg } 1099f005ef32Sjsg 11001bb76ff1Sjsg mutex_unlock(&p->svms.lock); 11011bb76ff1Sjsg #endif 11021bb76ff1Sjsg mutex_lock(&p->mutex); 11031bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 11041bb76ff1Sjsg if (!pdd) { 11051bb76ff1Sjsg err = -EINVAL; 11061bb76ff1Sjsg goto err_pdd; 11071bb76ff1Sjsg } 11081bb76ff1Sjsg 11091bb76ff1Sjsg dev = pdd->dev; 1110fb4d8502Sjsg 1111fb4d8502Sjsg if ((flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) && 1112fb4d8502Sjsg (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) && 1113fb4d8502Sjsg !kfd_dev_is_large_bar(dev)) { 1114fb4d8502Sjsg pr_err("Alloc host visible vram on small bar is not allowed\n"); 11151bb76ff1Sjsg err = -EINVAL; 11161bb76ff1Sjsg goto err_large_bar; 1117fb4d8502Sjsg } 1118fb4d8502Sjsg 1119fb4d8502Sjsg pdd = kfd_bind_process_to_device(dev, p); 1120fb4d8502Sjsg if (IS_ERR(pdd)) { 1121fb4d8502Sjsg err = PTR_ERR(pdd); 1122fb4d8502Sjsg goto err_unlock; 1123fb4d8502Sjsg } 1124fb4d8502Sjsg 1125ad8b1aafSjsg if (flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { 1126f005ef32Sjsg if (args->size != kfd_doorbell_process_slice(dev->kfd)) { 1127ad8b1aafSjsg err = -EINVAL; 1128ad8b1aafSjsg goto err_unlock; 1129ad8b1aafSjsg } 1130ad8b1aafSjsg offset = kfd_get_process_doorbells(pdd); 11311bb76ff1Sjsg if (!offset) { 11321bb76ff1Sjsg err = -ENOMEM; 11331bb76ff1Sjsg goto err_unlock; 11341bb76ff1Sjsg } 1135ad8b1aafSjsg } else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { 1136ad8b1aafSjsg if (args->size != PAGE_SIZE) { 1137ad8b1aafSjsg err = -EINVAL; 1138ad8b1aafSjsg goto err_unlock; 1139ad8b1aafSjsg } 11401bb76ff1Sjsg offset = dev->adev->rmmio_remap.bus_addr; 1141ab5fd4cbSjsg if (!offset || (PAGE_SIZE > 4096)) { 1142ad8b1aafSjsg err = -ENOMEM; 1143ad8b1aafSjsg goto err_unlock; 1144ad8b1aafSjsg } 1145ad8b1aafSjsg } 1146ad8b1aafSjsg 1147c349dbc7Sjsg err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( 11481bb76ff1Sjsg dev->adev, args->va_addr, args->size, 11495ca02815Sjsg pdd->drm_priv, (struct kgd_mem **) &mem, &offset, 11501bb76ff1Sjsg flags, false); 1151fb4d8502Sjsg 1152fb4d8502Sjsg if (err) 1153fb4d8502Sjsg goto err_unlock; 1154fb4d8502Sjsg 1155fb4d8502Sjsg idr_handle = kfd_process_device_create_obj_handle(pdd, mem); 1156fb4d8502Sjsg if (idr_handle < 0) { 1157fb4d8502Sjsg err = -EFAULT; 1158fb4d8502Sjsg goto err_free; 1159fb4d8502Sjsg } 1160fb4d8502Sjsg 1161ad8b1aafSjsg /* Update the VRAM usage count */ 1162baad244fSjsg if (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { 1163baad244fSjsg uint64_t size = args->size; 1164baad244fSjsg 1165baad244fSjsg if (flags & KFD_IOC_ALLOC_MEM_FLAGS_AQL_QUEUE_MEM) 1166baad244fSjsg size >>= 1; 1167*f7304f60Sjsg atomic64_add(PAGE_ALIGN(size), &pdd->vram_usage); 1168baad244fSjsg } 1169ad8b1aafSjsg 1170fb4d8502Sjsg mutex_unlock(&p->mutex); 1171fb4d8502Sjsg 1172fb4d8502Sjsg args->handle = MAKE_HANDLE(args->gpu_id, idr_handle); 1173fb4d8502Sjsg args->mmap_offset = offset; 1174fb4d8502Sjsg 1175c349dbc7Sjsg /* MMIO is mapped through kfd device 1176c349dbc7Sjsg * Generate a kfd mmap offset 1177c349dbc7Sjsg */ 1178c349dbc7Sjsg if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) 1179c349dbc7Sjsg args->mmap_offset = KFD_MMAP_TYPE_MMIO 1180c349dbc7Sjsg | KFD_MMAP_GPU_ID(args->gpu_id); 1181c349dbc7Sjsg 1182fb4d8502Sjsg return 0; 1183fb4d8502Sjsg 1184fb4d8502Sjsg err_free: 11851bb76ff1Sjsg amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, (struct kgd_mem *)mem, 11865ca02815Sjsg pdd->drm_priv, NULL); 1187fb4d8502Sjsg err_unlock: 11881bb76ff1Sjsg err_pdd: 11891bb76ff1Sjsg err_large_bar: 1190fb4d8502Sjsg mutex_unlock(&p->mutex); 1191fb4d8502Sjsg return err; 1192fb4d8502Sjsg } 1193fb4d8502Sjsg 1194fb4d8502Sjsg static int kfd_ioctl_free_memory_of_gpu(struct file *filep, 1195fb4d8502Sjsg struct kfd_process *p, void *data) 1196fb4d8502Sjsg { 1197fb4d8502Sjsg struct kfd_ioctl_free_memory_of_gpu_args *args = data; 1198fb4d8502Sjsg struct kfd_process_device *pdd; 1199fb4d8502Sjsg void *mem; 1200fb4d8502Sjsg int ret; 1201ad8b1aafSjsg uint64_t size = 0; 1202fb4d8502Sjsg 1203fb4d8502Sjsg mutex_lock(&p->mutex); 12041bb76ff1Sjsg /* 12051bb76ff1Sjsg * Safeguard to prevent user space from freeing signal BO. 12061bb76ff1Sjsg * It will be freed at process termination. 12071bb76ff1Sjsg */ 12081bb76ff1Sjsg if (p->signal_handle && (p->signal_handle == args->handle)) { 12091bb76ff1Sjsg pr_err("Free signal BO is not allowed\n"); 12101bb76ff1Sjsg ret = -EPERM; 12111bb76ff1Sjsg goto err_unlock; 12121bb76ff1Sjsg } 1213fb4d8502Sjsg 12141bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle)); 1215fb4d8502Sjsg if (!pdd) { 1216fb4d8502Sjsg pr_err("Process device data doesn't exist\n"); 1217fb4d8502Sjsg ret = -EINVAL; 12181bb76ff1Sjsg goto err_pdd; 1219fb4d8502Sjsg } 1220fb4d8502Sjsg 1221fb4d8502Sjsg mem = kfd_process_device_translate_handle( 1222fb4d8502Sjsg pdd, GET_IDR_HANDLE(args->handle)); 1223fb4d8502Sjsg if (!mem) { 1224fb4d8502Sjsg ret = -EINVAL; 1225fb4d8502Sjsg goto err_unlock; 1226fb4d8502Sjsg } 1227fb4d8502Sjsg 12281bb76ff1Sjsg ret = amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, 12295ca02815Sjsg (struct kgd_mem *)mem, pdd->drm_priv, &size); 1230fb4d8502Sjsg 1231fb4d8502Sjsg /* If freeing the buffer failed, leave the handle in place for 1232fb4d8502Sjsg * clean-up during process tear-down. 1233fb4d8502Sjsg */ 1234fb4d8502Sjsg if (!ret) 1235fb4d8502Sjsg kfd_process_device_remove_obj_handle( 1236fb4d8502Sjsg pdd, GET_IDR_HANDLE(args->handle)); 1237fb4d8502Sjsg 1238*f7304f60Sjsg atomic64_sub(size, &pdd->vram_usage); 1239ad8b1aafSjsg 1240fb4d8502Sjsg err_unlock: 12411bb76ff1Sjsg err_pdd: 1242fb4d8502Sjsg mutex_unlock(&p->mutex); 1243fb4d8502Sjsg return ret; 1244fb4d8502Sjsg } 1245fb4d8502Sjsg 1246fb4d8502Sjsg static int kfd_ioctl_map_memory_to_gpu(struct file *filep, 1247fb4d8502Sjsg struct kfd_process *p, void *data) 1248fb4d8502Sjsg { 1249fb4d8502Sjsg struct kfd_ioctl_map_memory_to_gpu_args *args = data; 1250fb4d8502Sjsg struct kfd_process_device *pdd, *peer_pdd; 1251fb4d8502Sjsg void *mem; 1252f005ef32Sjsg struct kfd_node *dev; 1253fb4d8502Sjsg long err = 0; 1254fb4d8502Sjsg int i; 1255fb4d8502Sjsg uint32_t *devices_arr = NULL; 1256fb4d8502Sjsg 1257fb4d8502Sjsg if (!args->n_devices) { 1258fb4d8502Sjsg pr_debug("Device IDs array empty\n"); 1259fb4d8502Sjsg return -EINVAL; 1260fb4d8502Sjsg } 1261fb4d8502Sjsg if (args->n_success > args->n_devices) { 1262fb4d8502Sjsg pr_debug("n_success exceeds n_devices\n"); 1263fb4d8502Sjsg return -EINVAL; 1264fb4d8502Sjsg } 1265fb4d8502Sjsg 1266fb4d8502Sjsg devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr), 1267fb4d8502Sjsg GFP_KERNEL); 1268fb4d8502Sjsg if (!devices_arr) 1269fb4d8502Sjsg return -ENOMEM; 1270fb4d8502Sjsg 1271fb4d8502Sjsg err = copy_from_user(devices_arr, 1272fb4d8502Sjsg (void __user *)args->device_ids_array_ptr, 1273fb4d8502Sjsg args->n_devices * sizeof(*devices_arr)); 1274fb4d8502Sjsg if (err != 0) { 1275fb4d8502Sjsg err = -EFAULT; 1276fb4d8502Sjsg goto copy_from_user_failed; 1277fb4d8502Sjsg } 1278fb4d8502Sjsg 1279fb4d8502Sjsg mutex_lock(&p->mutex); 12801bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle)); 12811bb76ff1Sjsg if (!pdd) { 12821bb76ff1Sjsg err = -EINVAL; 12831bb76ff1Sjsg goto get_process_device_data_failed; 12841bb76ff1Sjsg } 12851bb76ff1Sjsg dev = pdd->dev; 1286fb4d8502Sjsg 1287fb4d8502Sjsg pdd = kfd_bind_process_to_device(dev, p); 1288fb4d8502Sjsg if (IS_ERR(pdd)) { 1289fb4d8502Sjsg err = PTR_ERR(pdd); 1290fb4d8502Sjsg goto bind_process_to_device_failed; 1291fb4d8502Sjsg } 1292fb4d8502Sjsg 1293fb4d8502Sjsg mem = kfd_process_device_translate_handle(pdd, 1294fb4d8502Sjsg GET_IDR_HANDLE(args->handle)); 1295fb4d8502Sjsg if (!mem) { 1296fb4d8502Sjsg err = -ENOMEM; 1297fb4d8502Sjsg goto get_mem_obj_from_handle_failed; 1298fb4d8502Sjsg } 1299fb4d8502Sjsg 1300fb4d8502Sjsg for (i = args->n_success; i < args->n_devices; i++) { 13011bb76ff1Sjsg peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); 13021bb76ff1Sjsg if (!peer_pdd) { 1303fb4d8502Sjsg pr_debug("Getting device by id failed for 0x%x\n", 1304fb4d8502Sjsg devices_arr[i]); 1305fb4d8502Sjsg err = -EINVAL; 1306fb4d8502Sjsg goto get_mem_obj_from_handle_failed; 1307fb4d8502Sjsg } 1308fb4d8502Sjsg 13091bb76ff1Sjsg peer_pdd = kfd_bind_process_to_device(peer_pdd->dev, p); 1310fb4d8502Sjsg if (IS_ERR(peer_pdd)) { 1311fb4d8502Sjsg err = PTR_ERR(peer_pdd); 1312fb4d8502Sjsg goto get_mem_obj_from_handle_failed; 1313fb4d8502Sjsg } 13141bb76ff1Sjsg 1315c349dbc7Sjsg err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu( 13161bb76ff1Sjsg peer_pdd->dev->adev, (struct kgd_mem *)mem, 13171bb76ff1Sjsg peer_pdd->drm_priv); 1318fb4d8502Sjsg if (err) { 13191bb76ff1Sjsg struct pci_dev *pdev = peer_pdd->dev->adev->pdev; 13201bb76ff1Sjsg 13211bb76ff1Sjsg dev_err(dev->adev->dev, 13221bb76ff1Sjsg "Failed to map peer:%04x:%02x:%02x.%d mem_domain:%d\n", 13231bb76ff1Sjsg pci_domain_nr(pdev->bus), 13241bb76ff1Sjsg pdev->bus->number, 13251bb76ff1Sjsg PCI_SLOT(pdev->devfn), 13261bb76ff1Sjsg PCI_FUNC(pdev->devfn), 13271bb76ff1Sjsg ((struct kgd_mem *)mem)->domain); 1328fb4d8502Sjsg goto map_memory_to_gpu_failed; 1329fb4d8502Sjsg } 1330fb4d8502Sjsg args->n_success = i+1; 1331fb4d8502Sjsg } 1332fb4d8502Sjsg 13331bb76ff1Sjsg err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true); 1334fb4d8502Sjsg if (err) { 1335fb4d8502Sjsg pr_debug("Sync memory failed, wait interrupted by user signal\n"); 1336fb4d8502Sjsg goto sync_memory_failed; 1337fb4d8502Sjsg } 1338fb4d8502Sjsg 133909e2c6b1Sjsg mutex_unlock(&p->mutex); 134009e2c6b1Sjsg 1341fb4d8502Sjsg /* Flush TLBs after waiting for the page table updates to complete */ 1342fb4d8502Sjsg for (i = 0; i < args->n_devices; i++) { 13431bb76ff1Sjsg peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); 1344fb4d8502Sjsg if (WARN_ON_ONCE(!peer_pdd)) 1345fb4d8502Sjsg continue; 13465ca02815Sjsg kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); 1347fb4d8502Sjsg } 1348fb4d8502Sjsg kfree(devices_arr); 1349fb4d8502Sjsg 1350fb4d8502Sjsg return err; 1351fb4d8502Sjsg 13521bb76ff1Sjsg get_process_device_data_failed: 1353fb4d8502Sjsg bind_process_to_device_failed: 1354fb4d8502Sjsg get_mem_obj_from_handle_failed: 1355fb4d8502Sjsg map_memory_to_gpu_failed: 135609e2c6b1Sjsg sync_memory_failed: 1357fb4d8502Sjsg mutex_unlock(&p->mutex); 1358fb4d8502Sjsg copy_from_user_failed: 1359fb4d8502Sjsg kfree(devices_arr); 1360fb4d8502Sjsg 1361fb4d8502Sjsg return err; 1362fb4d8502Sjsg } 1363fb4d8502Sjsg 1364fb4d8502Sjsg static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, 1365fb4d8502Sjsg struct kfd_process *p, void *data) 1366fb4d8502Sjsg { 1367fb4d8502Sjsg struct kfd_ioctl_unmap_memory_from_gpu_args *args = data; 1368fb4d8502Sjsg struct kfd_process_device *pdd, *peer_pdd; 1369fb4d8502Sjsg void *mem; 1370fb4d8502Sjsg long err = 0; 1371fb4d8502Sjsg uint32_t *devices_arr = NULL, i; 137209e2c6b1Sjsg bool flush_tlb; 1373fb4d8502Sjsg 1374fb4d8502Sjsg if (!args->n_devices) { 1375fb4d8502Sjsg pr_debug("Device IDs array empty\n"); 1376fb4d8502Sjsg return -EINVAL; 1377fb4d8502Sjsg } 1378fb4d8502Sjsg if (args->n_success > args->n_devices) { 1379fb4d8502Sjsg pr_debug("n_success exceeds n_devices\n"); 1380fb4d8502Sjsg return -EINVAL; 1381fb4d8502Sjsg } 1382fb4d8502Sjsg 1383fb4d8502Sjsg devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr), 1384fb4d8502Sjsg GFP_KERNEL); 1385fb4d8502Sjsg if (!devices_arr) 1386fb4d8502Sjsg return -ENOMEM; 1387fb4d8502Sjsg 1388fb4d8502Sjsg err = copy_from_user(devices_arr, 1389fb4d8502Sjsg (void __user *)args->device_ids_array_ptr, 1390fb4d8502Sjsg args->n_devices * sizeof(*devices_arr)); 1391fb4d8502Sjsg if (err != 0) { 1392fb4d8502Sjsg err = -EFAULT; 1393fb4d8502Sjsg goto copy_from_user_failed; 1394fb4d8502Sjsg } 1395fb4d8502Sjsg 1396fb4d8502Sjsg mutex_lock(&p->mutex); 13971bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle)); 1398fb4d8502Sjsg if (!pdd) { 1399fb4d8502Sjsg err = -EINVAL; 1400fb4d8502Sjsg goto bind_process_to_device_failed; 1401fb4d8502Sjsg } 1402fb4d8502Sjsg 1403fb4d8502Sjsg mem = kfd_process_device_translate_handle(pdd, 1404fb4d8502Sjsg GET_IDR_HANDLE(args->handle)); 1405fb4d8502Sjsg if (!mem) { 1406fb4d8502Sjsg err = -ENOMEM; 1407fb4d8502Sjsg goto get_mem_obj_from_handle_failed; 1408fb4d8502Sjsg } 1409fb4d8502Sjsg 1410fb4d8502Sjsg for (i = args->n_success; i < args->n_devices; i++) { 14111bb76ff1Sjsg peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); 14121bb76ff1Sjsg if (!peer_pdd) { 1413fb4d8502Sjsg err = -EINVAL; 1414fb4d8502Sjsg goto get_mem_obj_from_handle_failed; 1415fb4d8502Sjsg } 1416c349dbc7Sjsg err = amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( 14171bb76ff1Sjsg peer_pdd->dev->adev, (struct kgd_mem *)mem, peer_pdd->drm_priv); 1418fb4d8502Sjsg if (err) { 1419fb4d8502Sjsg pr_err("Failed to unmap from gpu %d/%d\n", 1420fb4d8502Sjsg i, args->n_devices); 1421fb4d8502Sjsg goto unmap_memory_from_gpu_failed; 1422fb4d8502Sjsg } 1423fb4d8502Sjsg args->n_success = i+1; 1424fb4d8502Sjsg } 1425fb4d8502Sjsg 1426f005ef32Sjsg flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev->kfd); 142709e2c6b1Sjsg if (flush_tlb) { 14281bb76ff1Sjsg err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev, 14295ca02815Sjsg (struct kgd_mem *) mem, true); 14305ca02815Sjsg if (err) { 14315ca02815Sjsg pr_debug("Sync memory failed, wait interrupted by user signal\n"); 14325ca02815Sjsg goto sync_memory_failed; 14335ca02815Sjsg } 143409e2c6b1Sjsg } 14355ca02815Sjsg 14365ca02815Sjsg /* Flush TLBs after waiting for the page table updates to complete */ 14375ca02815Sjsg for (i = 0; i < args->n_devices; i++) { 14381bb76ff1Sjsg peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); 14395ca02815Sjsg if (WARN_ON_ONCE(!peer_pdd)) 14405ca02815Sjsg continue; 1441fe6a82ebSjsg if (flush_tlb) 14425ca02815Sjsg kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); 1443fe6a82ebSjsg 1444fe6a82ebSjsg /* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */ 1445c37b0968Sjsg err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv); 1446c37b0968Sjsg if (err) 1447c37b0968Sjsg goto sync_memory_failed; 14485ca02815Sjsg } 1449fe6a82ebSjsg 1450fe6a82ebSjsg mutex_unlock(&p->mutex); 1451fe6a82ebSjsg 14525ca02815Sjsg kfree(devices_arr); 14535ca02815Sjsg 1454fb4d8502Sjsg return 0; 1455fb4d8502Sjsg 1456fb4d8502Sjsg bind_process_to_device_failed: 1457fb4d8502Sjsg get_mem_obj_from_handle_failed: 1458fb4d8502Sjsg unmap_memory_from_gpu_failed: 145909e2c6b1Sjsg sync_memory_failed: 1460fb4d8502Sjsg mutex_unlock(&p->mutex); 1461fb4d8502Sjsg copy_from_user_failed: 1462fb4d8502Sjsg kfree(devices_arr); 1463fb4d8502Sjsg return err; 1464fb4d8502Sjsg } 1465fb4d8502Sjsg 1466ad8b1aafSjsg static int kfd_ioctl_alloc_queue_gws(struct file *filep, 1467ad8b1aafSjsg struct kfd_process *p, void *data) 1468ad8b1aafSjsg { 1469ad8b1aafSjsg int retval; 1470ad8b1aafSjsg struct kfd_ioctl_alloc_queue_gws_args *args = data; 1471ad8b1aafSjsg struct queue *q; 1472f005ef32Sjsg struct kfd_node *dev; 1473ad8b1aafSjsg 1474ad8b1aafSjsg mutex_lock(&p->mutex); 1475ad8b1aafSjsg q = pqm_get_user_queue(&p->pqm, args->queue_id); 1476ad8b1aafSjsg 1477ad8b1aafSjsg if (q) { 1478ad8b1aafSjsg dev = q->device; 1479ad8b1aafSjsg } else { 1480ad8b1aafSjsg retval = -EINVAL; 1481ad8b1aafSjsg goto out_unlock; 1482ad8b1aafSjsg } 1483ad8b1aafSjsg 1484ad8b1aafSjsg if (!dev->gws) { 1485ad8b1aafSjsg retval = -ENODEV; 1486ad8b1aafSjsg goto out_unlock; 1487ad8b1aafSjsg } 1488ad8b1aafSjsg 1489ad8b1aafSjsg if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { 1490ad8b1aafSjsg retval = -ENODEV; 1491ad8b1aafSjsg goto out_unlock; 1492ad8b1aafSjsg } 1493ad8b1aafSjsg 1494f005ef32Sjsg if (p->debug_trap_enabled && (!kfd_dbg_has_gws_support(dev) || 1495f005ef32Sjsg kfd_dbg_has_cwsr_workaround(dev))) { 1496f005ef32Sjsg retval = -EBUSY; 1497f005ef32Sjsg goto out_unlock; 1498f005ef32Sjsg } 1499f005ef32Sjsg 1500ad8b1aafSjsg retval = pqm_set_gws(&p->pqm, args->queue_id, args->num_gws ? dev->gws : NULL); 1501ad8b1aafSjsg mutex_unlock(&p->mutex); 1502ad8b1aafSjsg 1503ad8b1aafSjsg args->first_gws = 0; 1504ad8b1aafSjsg return retval; 1505ad8b1aafSjsg 1506ad8b1aafSjsg out_unlock: 1507ad8b1aafSjsg mutex_unlock(&p->mutex); 1508ad8b1aafSjsg return retval; 1509ad8b1aafSjsg } 1510ad8b1aafSjsg 1511c349dbc7Sjsg static int kfd_ioctl_get_dmabuf_info(struct file *filep, 1512c349dbc7Sjsg struct kfd_process *p, void *data) 1513c349dbc7Sjsg { 1514c349dbc7Sjsg struct kfd_ioctl_get_dmabuf_info_args *args = data; 1515f005ef32Sjsg struct kfd_node *dev = NULL; 15161bb76ff1Sjsg struct amdgpu_device *dmabuf_adev; 1517c349dbc7Sjsg void *metadata_buffer = NULL; 1518c349dbc7Sjsg uint32_t flags; 1519f005ef32Sjsg int8_t xcp_id; 1520c349dbc7Sjsg unsigned int i; 1521c349dbc7Sjsg int r; 1522c349dbc7Sjsg 1523c349dbc7Sjsg /* Find a KFD GPU device that supports the get_dmabuf_info query */ 1524c349dbc7Sjsg for (i = 0; kfd_topology_enum_kfd_devices(i, &dev) == 0; i++) 152579673ecaSjsg if (dev && !kfd_devcgroup_check_permission(dev)) 1526c349dbc7Sjsg break; 1527c349dbc7Sjsg if (!dev) 1528c349dbc7Sjsg return -EINVAL; 1529c349dbc7Sjsg 1530c349dbc7Sjsg if (args->metadata_ptr) { 1531c349dbc7Sjsg metadata_buffer = kzalloc(args->metadata_size, GFP_KERNEL); 1532c349dbc7Sjsg if (!metadata_buffer) 1533c349dbc7Sjsg return -ENOMEM; 1534c349dbc7Sjsg } 1535c349dbc7Sjsg 1536c349dbc7Sjsg /* Get dmabuf info from KGD */ 15371bb76ff1Sjsg r = amdgpu_amdkfd_get_dmabuf_info(dev->adev, args->dmabuf_fd, 15381bb76ff1Sjsg &dmabuf_adev, &args->size, 1539c349dbc7Sjsg metadata_buffer, args->metadata_size, 1540f005ef32Sjsg &args->metadata_size, &flags, &xcp_id); 1541c349dbc7Sjsg if (r) 1542c349dbc7Sjsg goto exit; 1543c349dbc7Sjsg 1544f005ef32Sjsg if (xcp_id >= 0) 1545f005ef32Sjsg args->gpu_id = dmabuf_adev->kfd.dev->nodes[xcp_id]->id; 1546f005ef32Sjsg else 154779673ecaSjsg args->gpu_id = dev->id; 1548c349dbc7Sjsg args->flags = flags; 1549c349dbc7Sjsg 1550c349dbc7Sjsg /* Copy metadata buffer to user mode */ 1551c349dbc7Sjsg if (metadata_buffer) { 1552c349dbc7Sjsg r = copy_to_user((void __user *)args->metadata_ptr, 1553c349dbc7Sjsg metadata_buffer, args->metadata_size); 1554c349dbc7Sjsg if (r != 0) 1555c349dbc7Sjsg r = -EFAULT; 1556c349dbc7Sjsg } 1557c349dbc7Sjsg 1558c349dbc7Sjsg exit: 1559c349dbc7Sjsg kfree(metadata_buffer); 1560c349dbc7Sjsg 1561c349dbc7Sjsg return r; 1562c349dbc7Sjsg } 1563c349dbc7Sjsg 1564c349dbc7Sjsg static int kfd_ioctl_import_dmabuf(struct file *filep, 1565c349dbc7Sjsg struct kfd_process *p, void *data) 1566c349dbc7Sjsg { 1567c349dbc7Sjsg struct kfd_ioctl_import_dmabuf_args *args = data; 1568c349dbc7Sjsg struct kfd_process_device *pdd; 1569c349dbc7Sjsg struct dma_buf *dmabuf; 1570c349dbc7Sjsg int idr_handle; 1571c349dbc7Sjsg uint64_t size; 1572c349dbc7Sjsg void *mem; 1573c349dbc7Sjsg int r; 1574c349dbc7Sjsg 1575c349dbc7Sjsg dmabuf = dma_buf_get(args->dmabuf_fd); 1576c349dbc7Sjsg if (IS_ERR(dmabuf)) 1577c349dbc7Sjsg return PTR_ERR(dmabuf); 1578c349dbc7Sjsg 1579c349dbc7Sjsg mutex_lock(&p->mutex); 15801bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpu_id); 15811bb76ff1Sjsg if (!pdd) { 15821bb76ff1Sjsg r = -EINVAL; 15831bb76ff1Sjsg goto err_unlock; 15841bb76ff1Sjsg } 1585c349dbc7Sjsg 15861bb76ff1Sjsg pdd = kfd_bind_process_to_device(pdd->dev, p); 1587c349dbc7Sjsg if (IS_ERR(pdd)) { 1588c349dbc7Sjsg r = PTR_ERR(pdd); 1589c349dbc7Sjsg goto err_unlock; 1590c349dbc7Sjsg } 1591c349dbc7Sjsg 15921bb76ff1Sjsg r = amdgpu_amdkfd_gpuvm_import_dmabuf(pdd->dev->adev, dmabuf, 15935ca02815Sjsg args->va_addr, pdd->drm_priv, 1594c349dbc7Sjsg (struct kgd_mem **)&mem, &size, 1595c349dbc7Sjsg NULL); 1596c349dbc7Sjsg if (r) 1597c349dbc7Sjsg goto err_unlock; 1598c349dbc7Sjsg 1599c349dbc7Sjsg idr_handle = kfd_process_device_create_obj_handle(pdd, mem); 1600c349dbc7Sjsg if (idr_handle < 0) { 1601c349dbc7Sjsg r = -EFAULT; 1602c349dbc7Sjsg goto err_free; 1603c349dbc7Sjsg } 1604c349dbc7Sjsg 1605c349dbc7Sjsg mutex_unlock(&p->mutex); 1606ad8b1aafSjsg dma_buf_put(dmabuf); 1607c349dbc7Sjsg 1608c349dbc7Sjsg args->handle = MAKE_HANDLE(args->gpu_id, idr_handle); 1609c349dbc7Sjsg 1610c349dbc7Sjsg return 0; 1611c349dbc7Sjsg 1612c349dbc7Sjsg err_free: 16131bb76ff1Sjsg amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, (struct kgd_mem *)mem, 16145ca02815Sjsg pdd->drm_priv, NULL); 1615c349dbc7Sjsg err_unlock: 1616c349dbc7Sjsg mutex_unlock(&p->mutex); 1617ad8b1aafSjsg dma_buf_put(dmabuf); 1618c349dbc7Sjsg return r; 1619c349dbc7Sjsg } 1620c349dbc7Sjsg 1621f005ef32Sjsg static int kfd_ioctl_export_dmabuf(struct file *filep, 1622f005ef32Sjsg struct kfd_process *p, void *data) 1623f005ef32Sjsg { 1624f005ef32Sjsg struct kfd_ioctl_export_dmabuf_args *args = data; 1625f005ef32Sjsg struct kfd_process_device *pdd; 1626f005ef32Sjsg struct dma_buf *dmabuf; 1627f005ef32Sjsg struct kfd_node *dev; 1628f005ef32Sjsg void *mem; 1629f005ef32Sjsg int ret = 0; 1630f005ef32Sjsg 1631f005ef32Sjsg dev = kfd_device_by_id(GET_GPU_ID(args->handle)); 1632f005ef32Sjsg if (!dev) 1633f005ef32Sjsg return -EINVAL; 1634f005ef32Sjsg 1635f005ef32Sjsg mutex_lock(&p->mutex); 1636f005ef32Sjsg 1637f005ef32Sjsg pdd = kfd_get_process_device_data(dev, p); 1638f005ef32Sjsg if (!pdd) { 1639f005ef32Sjsg ret = -EINVAL; 1640f005ef32Sjsg goto err_unlock; 1641f005ef32Sjsg } 1642f005ef32Sjsg 1643f005ef32Sjsg mem = kfd_process_device_translate_handle(pdd, 1644f005ef32Sjsg GET_IDR_HANDLE(args->handle)); 1645f005ef32Sjsg if (!mem) { 1646f005ef32Sjsg ret = -EINVAL; 1647f005ef32Sjsg goto err_unlock; 1648f005ef32Sjsg } 1649f005ef32Sjsg 1650f005ef32Sjsg ret = amdgpu_amdkfd_gpuvm_export_dmabuf(mem, &dmabuf); 1651f005ef32Sjsg mutex_unlock(&p->mutex); 1652f005ef32Sjsg if (ret) 1653f005ef32Sjsg goto err_out; 1654f005ef32Sjsg 1655f005ef32Sjsg ret = dma_buf_fd(dmabuf, args->flags); 1656f005ef32Sjsg if (ret < 0) { 1657f005ef32Sjsg dma_buf_put(dmabuf); 1658f005ef32Sjsg goto err_out; 1659f005ef32Sjsg } 1660f005ef32Sjsg /* dma_buf_fd assigns the reference count to the fd, no need to 1661f005ef32Sjsg * put the reference here. 1662f005ef32Sjsg */ 1663f005ef32Sjsg args->dmabuf_fd = ret; 1664f005ef32Sjsg 1665f005ef32Sjsg return 0; 1666f005ef32Sjsg 1667f005ef32Sjsg err_unlock: 1668f005ef32Sjsg mutex_unlock(&p->mutex); 1669f005ef32Sjsg err_out: 1670f005ef32Sjsg return ret; 1671f005ef32Sjsg } 1672f005ef32Sjsg 1673ad8b1aafSjsg /* Handle requests for watching SMI events */ 1674ad8b1aafSjsg static int kfd_ioctl_smi_events(struct file *filep, 1675ad8b1aafSjsg struct kfd_process *p, void *data) 1676ad8b1aafSjsg { 1677ad8b1aafSjsg struct kfd_ioctl_smi_events_args *args = data; 16781bb76ff1Sjsg struct kfd_process_device *pdd; 1679ad8b1aafSjsg 16801bb76ff1Sjsg mutex_lock(&p->mutex); 16811bb76ff1Sjsg 16821bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, args->gpuid); 16831bb76ff1Sjsg mutex_unlock(&p->mutex); 16841bb76ff1Sjsg if (!pdd) 1685ad8b1aafSjsg return -EINVAL; 1686ad8b1aafSjsg 16871bb76ff1Sjsg return kfd_smi_event_open(pdd->dev, &args->anon_fd); 1688ad8b1aafSjsg } 1689ad8b1aafSjsg 16901bb76ff1Sjsg #if IS_ENABLED(CONFIG_HSA_AMD_SVM) 16911bb76ff1Sjsg 16925ca02815Sjsg static int kfd_ioctl_set_xnack_mode(struct file *filep, 16935ca02815Sjsg struct kfd_process *p, void *data) 16945ca02815Sjsg { 16955ca02815Sjsg struct kfd_ioctl_set_xnack_mode_args *args = data; 16965ca02815Sjsg int r = 0; 16975ca02815Sjsg 16985ca02815Sjsg mutex_lock(&p->mutex); 16995ca02815Sjsg if (args->xnack_enabled >= 0) { 17005ca02815Sjsg if (!list_empty(&p->pqm.queues)) { 17015ca02815Sjsg pr_debug("Process has user queues running\n"); 17021bb76ff1Sjsg r = -EBUSY; 17031bb76ff1Sjsg goto out_unlock; 17045ca02815Sjsg } 17051bb76ff1Sjsg 17061bb76ff1Sjsg if (p->xnack_enabled == args->xnack_enabled) 17071bb76ff1Sjsg goto out_unlock; 17081bb76ff1Sjsg 17091bb76ff1Sjsg if (args->xnack_enabled && !kfd_process_xnack_mode(p, true)) { 17105ca02815Sjsg r = -EPERM; 17111bb76ff1Sjsg goto out_unlock; 17121bb76ff1Sjsg } 17131bb76ff1Sjsg 17141bb76ff1Sjsg r = svm_range_switch_xnack_reserve_mem(p, args->xnack_enabled); 17155ca02815Sjsg } else { 17165ca02815Sjsg args->xnack_enabled = p->xnack_enabled; 17175ca02815Sjsg } 17181bb76ff1Sjsg 17191bb76ff1Sjsg out_unlock: 17205ca02815Sjsg mutex_unlock(&p->mutex); 17215ca02815Sjsg 17225ca02815Sjsg return r; 17235ca02815Sjsg } 17245ca02815Sjsg 17255ca02815Sjsg static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) 17265ca02815Sjsg { 17275ca02815Sjsg struct kfd_ioctl_svm_args *args = data; 17285ca02815Sjsg int r = 0; 17295ca02815Sjsg 17305ca02815Sjsg pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n", 17315ca02815Sjsg args->start_addr, args->size, args->op, args->nattr); 17325ca02815Sjsg 17335ca02815Sjsg if ((args->start_addr & ~LINUX_PAGE_MASK) || (args->size & ~LINUX_PAGE_MASK)) 17345ca02815Sjsg return -EINVAL; 17355ca02815Sjsg if (!args->start_addr || !args->size) 17365ca02815Sjsg return -EINVAL; 17375ca02815Sjsg 17385ca02815Sjsg r = svm_ioctl(p, args->op, args->start_addr, args->size, args->nattr, 17395ca02815Sjsg args->attrs); 17405ca02815Sjsg 17415ca02815Sjsg return r; 17425ca02815Sjsg } 17435ca02815Sjsg #else 17441bb76ff1Sjsg static int kfd_ioctl_set_xnack_mode(struct file *filep, 17451bb76ff1Sjsg struct kfd_process *p, void *data) 17461bb76ff1Sjsg { 17471bb76ff1Sjsg return -EPERM; 17481bb76ff1Sjsg } 17495ca02815Sjsg static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) 17505ca02815Sjsg { 17515ca02815Sjsg return -EPERM; 17525ca02815Sjsg } 17535ca02815Sjsg #endif 17545ca02815Sjsg 17551bb76ff1Sjsg static int criu_checkpoint_process(struct kfd_process *p, 17561bb76ff1Sjsg uint8_t __user *user_priv_data, 17571bb76ff1Sjsg uint64_t *priv_offset) 17581bb76ff1Sjsg { 17591bb76ff1Sjsg struct kfd_criu_process_priv_data process_priv; 17601bb76ff1Sjsg int ret; 17611bb76ff1Sjsg 17621bb76ff1Sjsg memset(&process_priv, 0, sizeof(process_priv)); 17631bb76ff1Sjsg 17641bb76ff1Sjsg process_priv.version = KFD_CRIU_PRIV_VERSION; 17651bb76ff1Sjsg /* For CR, we don't consider negative xnack mode which is used for 17661bb76ff1Sjsg * querying without changing it, here 0 simply means disabled and 1 17671bb76ff1Sjsg * means enabled so retry for finding a valid PTE. 17681bb76ff1Sjsg */ 17691bb76ff1Sjsg process_priv.xnack_mode = p->xnack_enabled ? 1 : 0; 17701bb76ff1Sjsg 17711bb76ff1Sjsg ret = copy_to_user(user_priv_data + *priv_offset, 17721bb76ff1Sjsg &process_priv, sizeof(process_priv)); 17731bb76ff1Sjsg 17741bb76ff1Sjsg if (ret) { 17751bb76ff1Sjsg pr_err("Failed to copy process information to user\n"); 17761bb76ff1Sjsg ret = -EFAULT; 17771bb76ff1Sjsg } 17781bb76ff1Sjsg 17791bb76ff1Sjsg *priv_offset += sizeof(process_priv); 17801bb76ff1Sjsg return ret; 17811bb76ff1Sjsg } 17821bb76ff1Sjsg 17831bb76ff1Sjsg static int criu_checkpoint_devices(struct kfd_process *p, 17841bb76ff1Sjsg uint32_t num_devices, 17851bb76ff1Sjsg uint8_t __user *user_addr, 17861bb76ff1Sjsg uint8_t __user *user_priv_data, 17871bb76ff1Sjsg uint64_t *priv_offset) 17881bb76ff1Sjsg { 17891bb76ff1Sjsg struct kfd_criu_device_priv_data *device_priv = NULL; 17901bb76ff1Sjsg struct kfd_criu_device_bucket *device_buckets = NULL; 17911bb76ff1Sjsg int ret = 0, i; 17921bb76ff1Sjsg 17931bb76ff1Sjsg device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), GFP_KERNEL); 17941bb76ff1Sjsg if (!device_buckets) { 17951bb76ff1Sjsg ret = -ENOMEM; 17961bb76ff1Sjsg goto exit; 17971bb76ff1Sjsg } 17981bb76ff1Sjsg 17991bb76ff1Sjsg device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL); 18001bb76ff1Sjsg if (!device_priv) { 18011bb76ff1Sjsg ret = -ENOMEM; 18021bb76ff1Sjsg goto exit; 18031bb76ff1Sjsg } 18041bb76ff1Sjsg 18051bb76ff1Sjsg for (i = 0; i < num_devices; i++) { 18061bb76ff1Sjsg struct kfd_process_device *pdd = p->pdds[i]; 18071bb76ff1Sjsg 18081bb76ff1Sjsg device_buckets[i].user_gpu_id = pdd->user_gpu_id; 18091bb76ff1Sjsg device_buckets[i].actual_gpu_id = pdd->dev->id; 18101bb76ff1Sjsg 18111bb76ff1Sjsg /* 18121bb76ff1Sjsg * priv_data does not contain useful information for now and is reserved for 18131bb76ff1Sjsg * future use, so we do not set its contents. 18141bb76ff1Sjsg */ 18151bb76ff1Sjsg } 18161bb76ff1Sjsg 18171bb76ff1Sjsg ret = copy_to_user(user_addr, device_buckets, num_devices * sizeof(*device_buckets)); 18181bb76ff1Sjsg if (ret) { 18191bb76ff1Sjsg pr_err("Failed to copy device information to user\n"); 18201bb76ff1Sjsg ret = -EFAULT; 18211bb76ff1Sjsg goto exit; 18221bb76ff1Sjsg } 18231bb76ff1Sjsg 18241bb76ff1Sjsg ret = copy_to_user(user_priv_data + *priv_offset, 18251bb76ff1Sjsg device_priv, 18261bb76ff1Sjsg num_devices * sizeof(*device_priv)); 18271bb76ff1Sjsg if (ret) { 18281bb76ff1Sjsg pr_err("Failed to copy device information to user\n"); 18291bb76ff1Sjsg ret = -EFAULT; 18301bb76ff1Sjsg } 18311bb76ff1Sjsg *priv_offset += num_devices * sizeof(*device_priv); 18321bb76ff1Sjsg 18331bb76ff1Sjsg exit: 18341bb76ff1Sjsg kvfree(device_buckets); 18351bb76ff1Sjsg kvfree(device_priv); 18361bb76ff1Sjsg return ret; 18371bb76ff1Sjsg } 18381bb76ff1Sjsg 18391bb76ff1Sjsg static uint32_t get_process_num_bos(struct kfd_process *p) 18401bb76ff1Sjsg { 18411bb76ff1Sjsg uint32_t num_of_bos = 0; 18421bb76ff1Sjsg int i; 18431bb76ff1Sjsg 18441bb76ff1Sjsg /* Run over all PDDs of the process */ 18451bb76ff1Sjsg for (i = 0; i < p->n_pdds; i++) { 18461bb76ff1Sjsg struct kfd_process_device *pdd = p->pdds[i]; 18471bb76ff1Sjsg void *mem; 18481bb76ff1Sjsg int id; 18491bb76ff1Sjsg 18501bb76ff1Sjsg idr_for_each_entry(&pdd->alloc_idr, mem, id) { 18511bb76ff1Sjsg struct kgd_mem *kgd_mem = (struct kgd_mem *)mem; 18521bb76ff1Sjsg 1853f005ef32Sjsg if (!kgd_mem->va || kgd_mem->va > pdd->gpuvm_base) 18541bb76ff1Sjsg num_of_bos++; 18551bb76ff1Sjsg } 18561bb76ff1Sjsg } 18571bb76ff1Sjsg return num_of_bos; 18581bb76ff1Sjsg } 18591bb76ff1Sjsg 1860f005ef32Sjsg static int criu_get_prime_handle(struct kgd_mem *mem, int flags, 18611bb76ff1Sjsg u32 *shared_fd) 18621bb76ff1Sjsg { 18631bb76ff1Sjsg struct dma_buf *dmabuf; 18641bb76ff1Sjsg int ret; 18651bb76ff1Sjsg 1866f005ef32Sjsg ret = amdgpu_amdkfd_gpuvm_export_dmabuf(mem, &dmabuf); 1867f005ef32Sjsg if (ret) { 18681bb76ff1Sjsg pr_err("dmabuf export failed for the BO\n"); 18691bb76ff1Sjsg return ret; 18701bb76ff1Sjsg } 18711bb76ff1Sjsg 18721bb76ff1Sjsg ret = dma_buf_fd(dmabuf, flags); 18731bb76ff1Sjsg if (ret < 0) { 18741bb76ff1Sjsg pr_err("dmabuf create fd failed, ret:%d\n", ret); 18751bb76ff1Sjsg goto out_free_dmabuf; 18761bb76ff1Sjsg } 18771bb76ff1Sjsg 18781bb76ff1Sjsg *shared_fd = ret; 18791bb76ff1Sjsg return 0; 18801bb76ff1Sjsg 18811bb76ff1Sjsg out_free_dmabuf: 18821bb76ff1Sjsg dma_buf_put(dmabuf); 18831bb76ff1Sjsg return ret; 18841bb76ff1Sjsg } 18851bb76ff1Sjsg 18861bb76ff1Sjsg static int criu_checkpoint_bos(struct kfd_process *p, 18871bb76ff1Sjsg uint32_t num_bos, 18881bb76ff1Sjsg uint8_t __user *user_bos, 18891bb76ff1Sjsg uint8_t __user *user_priv_data, 18901bb76ff1Sjsg uint64_t *priv_offset) 18911bb76ff1Sjsg { 18921bb76ff1Sjsg struct kfd_criu_bo_bucket *bo_buckets; 18931bb76ff1Sjsg struct kfd_criu_bo_priv_data *bo_privs; 18941bb76ff1Sjsg int ret = 0, pdd_index, bo_index = 0, id; 18951bb76ff1Sjsg void *mem; 18961bb76ff1Sjsg 18971bb76ff1Sjsg bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), GFP_KERNEL); 18981bb76ff1Sjsg if (!bo_buckets) 18991bb76ff1Sjsg return -ENOMEM; 19001bb76ff1Sjsg 19011bb76ff1Sjsg bo_privs = kvzalloc(num_bos * sizeof(*bo_privs), GFP_KERNEL); 19021bb76ff1Sjsg if (!bo_privs) { 19031bb76ff1Sjsg ret = -ENOMEM; 19041bb76ff1Sjsg goto exit; 19051bb76ff1Sjsg } 19061bb76ff1Sjsg 19071bb76ff1Sjsg for (pdd_index = 0; pdd_index < p->n_pdds; pdd_index++) { 19081bb76ff1Sjsg struct kfd_process_device *pdd = p->pdds[pdd_index]; 19091bb76ff1Sjsg struct amdgpu_bo *dumper_bo; 19101bb76ff1Sjsg struct kgd_mem *kgd_mem; 19111bb76ff1Sjsg 19121bb76ff1Sjsg idr_for_each_entry(&pdd->alloc_idr, mem, id) { 19131bb76ff1Sjsg struct kfd_criu_bo_bucket *bo_bucket; 19141bb76ff1Sjsg struct kfd_criu_bo_priv_data *bo_priv; 19151bb76ff1Sjsg int i, dev_idx = 0; 19161bb76ff1Sjsg 19171bb76ff1Sjsg if (!mem) { 19181bb76ff1Sjsg ret = -ENOMEM; 19191bb76ff1Sjsg goto exit; 19201bb76ff1Sjsg } 19211bb76ff1Sjsg 19221bb76ff1Sjsg kgd_mem = (struct kgd_mem *)mem; 19231bb76ff1Sjsg dumper_bo = kgd_mem->bo; 19241bb76ff1Sjsg 1925f005ef32Sjsg /* Skip checkpointing BOs that are used for Trap handler 1926f005ef32Sjsg * code and state. Currently, these BOs have a VA that 1927f005ef32Sjsg * is less GPUVM Base 1928f005ef32Sjsg */ 1929f005ef32Sjsg if (kgd_mem->va && kgd_mem->va <= pdd->gpuvm_base) 19301bb76ff1Sjsg continue; 19311bb76ff1Sjsg 19321bb76ff1Sjsg bo_bucket = &bo_buckets[bo_index]; 19331bb76ff1Sjsg bo_priv = &bo_privs[bo_index]; 19341bb76ff1Sjsg 19351bb76ff1Sjsg bo_bucket->gpu_id = pdd->user_gpu_id; 19361bb76ff1Sjsg bo_bucket->addr = (uint64_t)kgd_mem->va; 19371bb76ff1Sjsg bo_bucket->size = amdgpu_bo_size(dumper_bo); 19381bb76ff1Sjsg bo_bucket->alloc_flags = (uint32_t)kgd_mem->alloc_flags; 19391bb76ff1Sjsg bo_priv->idr_handle = id; 19401bb76ff1Sjsg 19411bb76ff1Sjsg if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { 19421bb76ff1Sjsg ret = amdgpu_ttm_tt_get_userptr(&dumper_bo->tbo, 19431bb76ff1Sjsg &bo_priv->user_addr); 19441bb76ff1Sjsg if (ret) { 19451bb76ff1Sjsg pr_err("Failed to obtain user address for user-pointer bo\n"); 19461bb76ff1Sjsg goto exit; 19471bb76ff1Sjsg } 19481bb76ff1Sjsg } 19491bb76ff1Sjsg if (bo_bucket->alloc_flags 19501bb76ff1Sjsg & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) { 1951f005ef32Sjsg ret = criu_get_prime_handle(kgd_mem, 19521bb76ff1Sjsg bo_bucket->alloc_flags & 19531bb76ff1Sjsg KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0, 19541bb76ff1Sjsg &bo_bucket->dmabuf_fd); 19551bb76ff1Sjsg if (ret) 19561bb76ff1Sjsg goto exit; 19571bb76ff1Sjsg } else { 19581bb76ff1Sjsg bo_bucket->dmabuf_fd = KFD_INVALID_FD; 19591bb76ff1Sjsg } 19601bb76ff1Sjsg 19611bb76ff1Sjsg if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) 19621bb76ff1Sjsg bo_bucket->offset = KFD_MMAP_TYPE_DOORBELL | 19631bb76ff1Sjsg KFD_MMAP_GPU_ID(pdd->dev->id); 19641bb76ff1Sjsg else if (bo_bucket->alloc_flags & 19651bb76ff1Sjsg KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) 19661bb76ff1Sjsg bo_bucket->offset = KFD_MMAP_TYPE_MMIO | 19671bb76ff1Sjsg KFD_MMAP_GPU_ID(pdd->dev->id); 19681bb76ff1Sjsg else 19691bb76ff1Sjsg bo_bucket->offset = amdgpu_bo_mmap_offset(dumper_bo); 19701bb76ff1Sjsg 19711bb76ff1Sjsg for (i = 0; i < p->n_pdds; i++) { 19721bb76ff1Sjsg if (amdgpu_amdkfd_bo_mapped_to_dev(p->pdds[i]->dev->adev, kgd_mem)) 19731bb76ff1Sjsg bo_priv->mapped_gpuids[dev_idx++] = p->pdds[i]->user_gpu_id; 19741bb76ff1Sjsg } 19751bb76ff1Sjsg 19761bb76ff1Sjsg pr_debug("bo_size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n" 19771bb76ff1Sjsg "gpu_id = 0x%x alloc_flags = 0x%x idr_handle = 0x%x", 19781bb76ff1Sjsg bo_bucket->size, 19791bb76ff1Sjsg bo_bucket->addr, 19801bb76ff1Sjsg bo_bucket->offset, 19811bb76ff1Sjsg bo_bucket->gpu_id, 19821bb76ff1Sjsg bo_bucket->alloc_flags, 19831bb76ff1Sjsg bo_priv->idr_handle); 19841bb76ff1Sjsg bo_index++; 19851bb76ff1Sjsg } 19861bb76ff1Sjsg } 19871bb76ff1Sjsg 19881bb76ff1Sjsg ret = copy_to_user(user_bos, bo_buckets, num_bos * sizeof(*bo_buckets)); 19891bb76ff1Sjsg if (ret) { 19901bb76ff1Sjsg pr_err("Failed to copy BO information to user\n"); 19911bb76ff1Sjsg ret = -EFAULT; 19921bb76ff1Sjsg goto exit; 19931bb76ff1Sjsg } 19941bb76ff1Sjsg 19951bb76ff1Sjsg ret = copy_to_user(user_priv_data + *priv_offset, bo_privs, num_bos * sizeof(*bo_privs)); 19961bb76ff1Sjsg if (ret) { 19971bb76ff1Sjsg pr_err("Failed to copy BO priv information to user\n"); 19981bb76ff1Sjsg ret = -EFAULT; 19991bb76ff1Sjsg goto exit; 20001bb76ff1Sjsg } 20011bb76ff1Sjsg 20021bb76ff1Sjsg *priv_offset += num_bos * sizeof(*bo_privs); 20031bb76ff1Sjsg 20041bb76ff1Sjsg exit: 20051bb76ff1Sjsg while (ret && bo_index--) { 20061bb76ff1Sjsg if (bo_buckets[bo_index].alloc_flags 20071bb76ff1Sjsg & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) 20081bb76ff1Sjsg close_fd(bo_buckets[bo_index].dmabuf_fd); 20091bb76ff1Sjsg } 20101bb76ff1Sjsg 20111bb76ff1Sjsg kvfree(bo_buckets); 20121bb76ff1Sjsg kvfree(bo_privs); 20131bb76ff1Sjsg return ret; 20141bb76ff1Sjsg } 20151bb76ff1Sjsg 20161bb76ff1Sjsg static int criu_get_process_object_info(struct kfd_process *p, 20171bb76ff1Sjsg uint32_t *num_devices, 20181bb76ff1Sjsg uint32_t *num_bos, 20191bb76ff1Sjsg uint32_t *num_objects, 20201bb76ff1Sjsg uint64_t *objs_priv_size) 20211bb76ff1Sjsg { 20221bb76ff1Sjsg uint64_t queues_priv_data_size, svm_priv_data_size, priv_size; 20231bb76ff1Sjsg uint32_t num_queues, num_events, num_svm_ranges; 20241bb76ff1Sjsg int ret; 20251bb76ff1Sjsg 20261bb76ff1Sjsg *num_devices = p->n_pdds; 20271bb76ff1Sjsg *num_bos = get_process_num_bos(p); 20281bb76ff1Sjsg 20291bb76ff1Sjsg ret = kfd_process_get_queue_info(p, &num_queues, &queues_priv_data_size); 20301bb76ff1Sjsg if (ret) 20311bb76ff1Sjsg return ret; 20321bb76ff1Sjsg 20331bb76ff1Sjsg num_events = kfd_get_num_events(p); 20341bb76ff1Sjsg 20351bb76ff1Sjsg ret = svm_range_get_info(p, &num_svm_ranges, &svm_priv_data_size); 20361bb76ff1Sjsg if (ret) 20371bb76ff1Sjsg return ret; 20381bb76ff1Sjsg 20391bb76ff1Sjsg *num_objects = num_queues + num_events + num_svm_ranges; 20401bb76ff1Sjsg 20411bb76ff1Sjsg if (objs_priv_size) { 20421bb76ff1Sjsg priv_size = sizeof(struct kfd_criu_process_priv_data); 20431bb76ff1Sjsg priv_size += *num_devices * sizeof(struct kfd_criu_device_priv_data); 20441bb76ff1Sjsg priv_size += *num_bos * sizeof(struct kfd_criu_bo_priv_data); 20451bb76ff1Sjsg priv_size += queues_priv_data_size; 20461bb76ff1Sjsg priv_size += num_events * sizeof(struct kfd_criu_event_priv_data); 20471bb76ff1Sjsg priv_size += svm_priv_data_size; 20481bb76ff1Sjsg *objs_priv_size = priv_size; 20491bb76ff1Sjsg } 20501bb76ff1Sjsg return 0; 20511bb76ff1Sjsg } 20521bb76ff1Sjsg 20531bb76ff1Sjsg static int criu_checkpoint(struct file *filep, 20541bb76ff1Sjsg struct kfd_process *p, 20551bb76ff1Sjsg struct kfd_ioctl_criu_args *args) 20561bb76ff1Sjsg { 20571bb76ff1Sjsg int ret; 20581bb76ff1Sjsg uint32_t num_devices, num_bos, num_objects; 20591bb76ff1Sjsg uint64_t priv_size, priv_offset = 0, bo_priv_offset; 20601bb76ff1Sjsg 20611bb76ff1Sjsg if (!args->devices || !args->bos || !args->priv_data) 20621bb76ff1Sjsg return -EINVAL; 20631bb76ff1Sjsg 20641bb76ff1Sjsg mutex_lock(&p->mutex); 20651bb76ff1Sjsg 20661bb76ff1Sjsg if (!p->n_pdds) { 20671bb76ff1Sjsg pr_err("No pdd for given process\n"); 20681bb76ff1Sjsg ret = -ENODEV; 20691bb76ff1Sjsg goto exit_unlock; 20701bb76ff1Sjsg } 20711bb76ff1Sjsg 20721bb76ff1Sjsg /* Confirm all process queues are evicted */ 20731bb76ff1Sjsg if (!p->queues_paused) { 20741bb76ff1Sjsg pr_err("Cannot dump process when queues are not in evicted state\n"); 20751bb76ff1Sjsg /* CRIU plugin did not call op PROCESS_INFO before checkpointing */ 20761bb76ff1Sjsg ret = -EINVAL; 20771bb76ff1Sjsg goto exit_unlock; 20781bb76ff1Sjsg } 20791bb76ff1Sjsg 20801bb76ff1Sjsg ret = criu_get_process_object_info(p, &num_devices, &num_bos, &num_objects, &priv_size); 20811bb76ff1Sjsg if (ret) 20821bb76ff1Sjsg goto exit_unlock; 20831bb76ff1Sjsg 20841bb76ff1Sjsg if (num_devices != args->num_devices || 20851bb76ff1Sjsg num_bos != args->num_bos || 20861bb76ff1Sjsg num_objects != args->num_objects || 20871bb76ff1Sjsg priv_size != args->priv_data_size) { 20881bb76ff1Sjsg 20891bb76ff1Sjsg ret = -EINVAL; 20901bb76ff1Sjsg goto exit_unlock; 20911bb76ff1Sjsg } 20921bb76ff1Sjsg 20931bb76ff1Sjsg /* each function will store private data inside priv_data and adjust priv_offset */ 20941bb76ff1Sjsg ret = criu_checkpoint_process(p, (uint8_t __user *)args->priv_data, &priv_offset); 20951bb76ff1Sjsg if (ret) 20961bb76ff1Sjsg goto exit_unlock; 20971bb76ff1Sjsg 20981bb76ff1Sjsg ret = criu_checkpoint_devices(p, num_devices, (uint8_t __user *)args->devices, 20991bb76ff1Sjsg (uint8_t __user *)args->priv_data, &priv_offset); 21001bb76ff1Sjsg if (ret) 21011bb76ff1Sjsg goto exit_unlock; 21021bb76ff1Sjsg 21031bb76ff1Sjsg /* Leave room for BOs in the private data. They need to be restored 21041bb76ff1Sjsg * before events, but we checkpoint them last to simplify the error 21051bb76ff1Sjsg * handling. 21061bb76ff1Sjsg */ 21071bb76ff1Sjsg bo_priv_offset = priv_offset; 21081bb76ff1Sjsg priv_offset += num_bos * sizeof(struct kfd_criu_bo_priv_data); 21091bb76ff1Sjsg 21101bb76ff1Sjsg if (num_objects) { 21111bb76ff1Sjsg ret = kfd_criu_checkpoint_queues(p, (uint8_t __user *)args->priv_data, 21121bb76ff1Sjsg &priv_offset); 21131bb76ff1Sjsg if (ret) 21141bb76ff1Sjsg goto exit_unlock; 21151bb76ff1Sjsg 21161bb76ff1Sjsg ret = kfd_criu_checkpoint_events(p, (uint8_t __user *)args->priv_data, 21171bb76ff1Sjsg &priv_offset); 21181bb76ff1Sjsg if (ret) 21191bb76ff1Sjsg goto exit_unlock; 21201bb76ff1Sjsg 21211bb76ff1Sjsg ret = kfd_criu_checkpoint_svm(p, (uint8_t __user *)args->priv_data, &priv_offset); 21221bb76ff1Sjsg if (ret) 21231bb76ff1Sjsg goto exit_unlock; 21241bb76ff1Sjsg } 21251bb76ff1Sjsg 21261bb76ff1Sjsg /* This must be the last thing in this function that can fail. 21271bb76ff1Sjsg * Otherwise we leak dmabuf file descriptors. 21281bb76ff1Sjsg */ 21291bb76ff1Sjsg ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, 21301bb76ff1Sjsg (uint8_t __user *)args->priv_data, &bo_priv_offset); 21311bb76ff1Sjsg 21321bb76ff1Sjsg exit_unlock: 21331bb76ff1Sjsg mutex_unlock(&p->mutex); 21341bb76ff1Sjsg if (ret) 21351bb76ff1Sjsg pr_err("Failed to dump CRIU ret:%d\n", ret); 21361bb76ff1Sjsg else 21371bb76ff1Sjsg pr_debug("CRIU dump ret:%d\n", ret); 21381bb76ff1Sjsg 21391bb76ff1Sjsg return ret; 21401bb76ff1Sjsg } 21411bb76ff1Sjsg 21421bb76ff1Sjsg static int criu_restore_process(struct kfd_process *p, 21431bb76ff1Sjsg struct kfd_ioctl_criu_args *args, 21441bb76ff1Sjsg uint64_t *priv_offset, 21451bb76ff1Sjsg uint64_t max_priv_data_size) 21461bb76ff1Sjsg { 21471bb76ff1Sjsg int ret = 0; 21481bb76ff1Sjsg struct kfd_criu_process_priv_data process_priv; 21491bb76ff1Sjsg 21501bb76ff1Sjsg if (*priv_offset + sizeof(process_priv) > max_priv_data_size) 21511bb76ff1Sjsg return -EINVAL; 21521bb76ff1Sjsg 21531bb76ff1Sjsg ret = copy_from_user(&process_priv, 21541bb76ff1Sjsg (void __user *)(args->priv_data + *priv_offset), 21551bb76ff1Sjsg sizeof(process_priv)); 21561bb76ff1Sjsg if (ret) { 21571bb76ff1Sjsg pr_err("Failed to copy process private information from user\n"); 21581bb76ff1Sjsg ret = -EFAULT; 21591bb76ff1Sjsg goto exit; 21601bb76ff1Sjsg } 21611bb76ff1Sjsg *priv_offset += sizeof(process_priv); 21621bb76ff1Sjsg 21631bb76ff1Sjsg if (process_priv.version != KFD_CRIU_PRIV_VERSION) { 21641bb76ff1Sjsg pr_err("Invalid CRIU API version (checkpointed:%d current:%d)\n", 21651bb76ff1Sjsg process_priv.version, KFD_CRIU_PRIV_VERSION); 21661bb76ff1Sjsg return -EINVAL; 21671bb76ff1Sjsg } 21681bb76ff1Sjsg 21691bb76ff1Sjsg pr_debug("Setting XNACK mode\n"); 21701bb76ff1Sjsg if (process_priv.xnack_mode && !kfd_process_xnack_mode(p, true)) { 21711bb76ff1Sjsg pr_err("xnack mode cannot be set\n"); 21721bb76ff1Sjsg ret = -EPERM; 21731bb76ff1Sjsg goto exit; 21741bb76ff1Sjsg } else { 21751bb76ff1Sjsg pr_debug("set xnack mode: %d\n", process_priv.xnack_mode); 21761bb76ff1Sjsg p->xnack_enabled = process_priv.xnack_mode; 21771bb76ff1Sjsg } 21781bb76ff1Sjsg 21791bb76ff1Sjsg exit: 21801bb76ff1Sjsg return ret; 21811bb76ff1Sjsg } 21821bb76ff1Sjsg 21831bb76ff1Sjsg static int criu_restore_devices(struct kfd_process *p, 21841bb76ff1Sjsg struct kfd_ioctl_criu_args *args, 21851bb76ff1Sjsg uint64_t *priv_offset, 21861bb76ff1Sjsg uint64_t max_priv_data_size) 21871bb76ff1Sjsg { 21881bb76ff1Sjsg struct kfd_criu_device_bucket *device_buckets; 21891bb76ff1Sjsg struct kfd_criu_device_priv_data *device_privs; 21901bb76ff1Sjsg int ret = 0; 21911bb76ff1Sjsg uint32_t i; 21921bb76ff1Sjsg 21931bb76ff1Sjsg if (args->num_devices != p->n_pdds) 21941bb76ff1Sjsg return -EINVAL; 21951bb76ff1Sjsg 21961bb76ff1Sjsg if (*priv_offset + (args->num_devices * sizeof(*device_privs)) > max_priv_data_size) 21971bb76ff1Sjsg return -EINVAL; 21981bb76ff1Sjsg 21991bb76ff1Sjsg device_buckets = kmalloc_array(args->num_devices, sizeof(*device_buckets), GFP_KERNEL); 22001bb76ff1Sjsg if (!device_buckets) 22011bb76ff1Sjsg return -ENOMEM; 22021bb76ff1Sjsg 22031bb76ff1Sjsg ret = copy_from_user(device_buckets, (void __user *)args->devices, 22041bb76ff1Sjsg args->num_devices * sizeof(*device_buckets)); 22051bb76ff1Sjsg if (ret) { 22061bb76ff1Sjsg pr_err("Failed to copy devices buckets from user\n"); 22071bb76ff1Sjsg ret = -EFAULT; 22081bb76ff1Sjsg goto exit; 22091bb76ff1Sjsg } 22101bb76ff1Sjsg 22111bb76ff1Sjsg for (i = 0; i < args->num_devices; i++) { 2212f005ef32Sjsg struct kfd_node *dev; 22131bb76ff1Sjsg struct kfd_process_device *pdd; 22141bb76ff1Sjsg struct file *drm_file; 22151bb76ff1Sjsg 22161bb76ff1Sjsg /* device private data is not currently used */ 22171bb76ff1Sjsg 22181bb76ff1Sjsg if (!device_buckets[i].user_gpu_id) { 22191bb76ff1Sjsg pr_err("Invalid user gpu_id\n"); 22201bb76ff1Sjsg ret = -EINVAL; 22211bb76ff1Sjsg goto exit; 22221bb76ff1Sjsg } 22231bb76ff1Sjsg 22241bb76ff1Sjsg dev = kfd_device_by_id(device_buckets[i].actual_gpu_id); 22251bb76ff1Sjsg if (!dev) { 22261bb76ff1Sjsg pr_err("Failed to find device with gpu_id = %x\n", 22271bb76ff1Sjsg device_buckets[i].actual_gpu_id); 22281bb76ff1Sjsg ret = -EINVAL; 22291bb76ff1Sjsg goto exit; 22301bb76ff1Sjsg } 22311bb76ff1Sjsg 22321bb76ff1Sjsg pdd = kfd_get_process_device_data(dev, p); 22331bb76ff1Sjsg if (!pdd) { 22341bb76ff1Sjsg pr_err("Failed to get pdd for gpu_id = %x\n", 22351bb76ff1Sjsg device_buckets[i].actual_gpu_id); 22361bb76ff1Sjsg ret = -EINVAL; 22371bb76ff1Sjsg goto exit; 22381bb76ff1Sjsg } 22391bb76ff1Sjsg pdd->user_gpu_id = device_buckets[i].user_gpu_id; 22401bb76ff1Sjsg 22411bb76ff1Sjsg drm_file = fget(device_buckets[i].drm_fd); 22421bb76ff1Sjsg if (!drm_file) { 22431bb76ff1Sjsg pr_err("Invalid render node file descriptor sent from plugin (%d)\n", 22441bb76ff1Sjsg device_buckets[i].drm_fd); 22451bb76ff1Sjsg ret = -EINVAL; 22461bb76ff1Sjsg goto exit; 22471bb76ff1Sjsg } 22481bb76ff1Sjsg 22491bb76ff1Sjsg if (pdd->drm_file) { 22501bb76ff1Sjsg ret = -EINVAL; 22511bb76ff1Sjsg goto exit; 22521bb76ff1Sjsg } 22531bb76ff1Sjsg 22541bb76ff1Sjsg /* create the vm using render nodes for kfd pdd */ 22551bb76ff1Sjsg if (kfd_process_device_init_vm(pdd, drm_file)) { 22561bb76ff1Sjsg pr_err("could not init vm for given pdd\n"); 22571bb76ff1Sjsg /* On success, the PDD keeps the drm_file reference */ 22581bb76ff1Sjsg fput(drm_file); 22591bb76ff1Sjsg ret = -EINVAL; 22601bb76ff1Sjsg goto exit; 22611bb76ff1Sjsg } 22621bb76ff1Sjsg /* 22631bb76ff1Sjsg * pdd now already has the vm bound to render node so below api won't create a new 22641bb76ff1Sjsg * exclusive kfd mapping but use existing one with renderDXXX but is still needed 22651bb76ff1Sjsg * for iommu v2 binding and runtime pm. 22661bb76ff1Sjsg */ 22671bb76ff1Sjsg pdd = kfd_bind_process_to_device(dev, p); 22681bb76ff1Sjsg if (IS_ERR(pdd)) { 22691bb76ff1Sjsg ret = PTR_ERR(pdd); 22701bb76ff1Sjsg goto exit; 22711bb76ff1Sjsg } 22721bb76ff1Sjsg 2273f005ef32Sjsg if (!pdd->qpd.proc_doorbells) { 2274f005ef32Sjsg ret = kfd_alloc_process_doorbells(dev->kfd, pdd); 2275f005ef32Sjsg if (ret) 22761bb76ff1Sjsg goto exit; 22771bb76ff1Sjsg } 22781bb76ff1Sjsg } 22791bb76ff1Sjsg 22801bb76ff1Sjsg /* 22811bb76ff1Sjsg * We are not copying device private data from user as we are not using the data for now, 22821bb76ff1Sjsg * but we still adjust for its private data. 22831bb76ff1Sjsg */ 22841bb76ff1Sjsg *priv_offset += args->num_devices * sizeof(*device_privs); 22851bb76ff1Sjsg 22861bb76ff1Sjsg exit: 22871bb76ff1Sjsg kfree(device_buckets); 22881bb76ff1Sjsg return ret; 22891bb76ff1Sjsg } 22901bb76ff1Sjsg 22911bb76ff1Sjsg static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd, 22921bb76ff1Sjsg struct kfd_criu_bo_bucket *bo_bucket, 22931bb76ff1Sjsg struct kfd_criu_bo_priv_data *bo_priv, 22941bb76ff1Sjsg struct kgd_mem **kgd_mem) 22951bb76ff1Sjsg { 22961bb76ff1Sjsg int idr_handle; 22971bb76ff1Sjsg int ret; 22981bb76ff1Sjsg const bool criu_resume = true; 22991bb76ff1Sjsg u64 offset; 23001bb76ff1Sjsg 23011bb76ff1Sjsg if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { 2302f005ef32Sjsg if (bo_bucket->size != 2303f005ef32Sjsg kfd_doorbell_process_slice(pdd->dev->kfd)) 23041bb76ff1Sjsg return -EINVAL; 23051bb76ff1Sjsg 23061bb76ff1Sjsg offset = kfd_get_process_doorbells(pdd); 23071bb76ff1Sjsg if (!offset) 23081bb76ff1Sjsg return -ENOMEM; 23091bb76ff1Sjsg } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { 23101bb76ff1Sjsg /* MMIO BOs need remapped bus address */ 23111bb76ff1Sjsg if (bo_bucket->size != PAGE_SIZE) { 23121bb76ff1Sjsg pr_err("Invalid page size\n"); 23131bb76ff1Sjsg return -EINVAL; 23141bb76ff1Sjsg } 23151bb76ff1Sjsg offset = pdd->dev->adev->rmmio_remap.bus_addr; 2316ab5fd4cbSjsg if (!offset || (PAGE_SIZE > 4096)) { 23171bb76ff1Sjsg pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n"); 23181bb76ff1Sjsg return -ENOMEM; 23191bb76ff1Sjsg } 23201bb76ff1Sjsg } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { 23211bb76ff1Sjsg offset = bo_priv->user_addr; 23221bb76ff1Sjsg } 23231bb76ff1Sjsg /* Create the BO */ 23241bb76ff1Sjsg ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(pdd->dev->adev, bo_bucket->addr, 23251bb76ff1Sjsg bo_bucket->size, pdd->drm_priv, kgd_mem, 23261bb76ff1Sjsg &offset, bo_bucket->alloc_flags, criu_resume); 23271bb76ff1Sjsg if (ret) { 23281bb76ff1Sjsg pr_err("Could not create the BO\n"); 23291bb76ff1Sjsg return ret; 23301bb76ff1Sjsg } 23311bb76ff1Sjsg pr_debug("New BO created: size:0x%llx addr:0x%llx offset:0x%llx\n", 23321bb76ff1Sjsg bo_bucket->size, bo_bucket->addr, offset); 23331bb76ff1Sjsg 23341bb76ff1Sjsg /* Restore previous IDR handle */ 23351bb76ff1Sjsg pr_debug("Restoring old IDR handle for the BO"); 23361bb76ff1Sjsg idr_handle = idr_alloc(&pdd->alloc_idr, *kgd_mem, bo_priv->idr_handle, 23371bb76ff1Sjsg bo_priv->idr_handle + 1, GFP_KERNEL); 23381bb76ff1Sjsg 23391bb76ff1Sjsg if (idr_handle < 0) { 23401bb76ff1Sjsg pr_err("Could not allocate idr\n"); 23411bb76ff1Sjsg amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, *kgd_mem, pdd->drm_priv, 23421bb76ff1Sjsg NULL); 23431bb76ff1Sjsg return -ENOMEM; 23441bb76ff1Sjsg } 23451bb76ff1Sjsg 23461bb76ff1Sjsg if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) 23471bb76ff1Sjsg bo_bucket->restored_offset = KFD_MMAP_TYPE_DOORBELL | KFD_MMAP_GPU_ID(pdd->dev->id); 23481bb76ff1Sjsg if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { 23491bb76ff1Sjsg bo_bucket->restored_offset = KFD_MMAP_TYPE_MMIO | KFD_MMAP_GPU_ID(pdd->dev->id); 23501bb76ff1Sjsg } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) { 23511bb76ff1Sjsg bo_bucket->restored_offset = offset; 23521bb76ff1Sjsg } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { 23531bb76ff1Sjsg bo_bucket->restored_offset = offset; 23541bb76ff1Sjsg /* Update the VRAM usage count */ 2355*f7304f60Sjsg atomic64_add(bo_bucket->size, &pdd->vram_usage); 23561bb76ff1Sjsg } 23571bb76ff1Sjsg return 0; 23581bb76ff1Sjsg } 23591bb76ff1Sjsg 23601bb76ff1Sjsg static int criu_restore_bo(struct kfd_process *p, 23611bb76ff1Sjsg struct kfd_criu_bo_bucket *bo_bucket, 23621bb76ff1Sjsg struct kfd_criu_bo_priv_data *bo_priv) 23631bb76ff1Sjsg { 23641bb76ff1Sjsg struct kfd_process_device *pdd; 23651bb76ff1Sjsg struct kgd_mem *kgd_mem; 23661bb76ff1Sjsg int ret; 23671bb76ff1Sjsg int j; 23681bb76ff1Sjsg 23691bb76ff1Sjsg pr_debug("Restoring BO size:0x%llx addr:0x%llx gpu_id:0x%x flags:0x%x idr_handle:0x%x\n", 23701bb76ff1Sjsg bo_bucket->size, bo_bucket->addr, bo_bucket->gpu_id, bo_bucket->alloc_flags, 23711bb76ff1Sjsg bo_priv->idr_handle); 23721bb76ff1Sjsg 23731bb76ff1Sjsg pdd = kfd_process_device_data_by_id(p, bo_bucket->gpu_id); 23741bb76ff1Sjsg if (!pdd) { 23751bb76ff1Sjsg pr_err("Failed to get pdd\n"); 23761bb76ff1Sjsg return -ENODEV; 23771bb76ff1Sjsg } 23781bb76ff1Sjsg 23791bb76ff1Sjsg ret = criu_restore_memory_of_gpu(pdd, bo_bucket, bo_priv, &kgd_mem); 23801bb76ff1Sjsg if (ret) 23811bb76ff1Sjsg return ret; 23821bb76ff1Sjsg 23831bb76ff1Sjsg /* now map these BOs to GPU/s */ 23841bb76ff1Sjsg for (j = 0; j < p->n_pdds; j++) { 2385f005ef32Sjsg struct kfd_node *peer; 23861bb76ff1Sjsg struct kfd_process_device *peer_pdd; 23871bb76ff1Sjsg 23881bb76ff1Sjsg if (!bo_priv->mapped_gpuids[j]) 23891bb76ff1Sjsg break; 23901bb76ff1Sjsg 23911bb76ff1Sjsg peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]); 23921bb76ff1Sjsg if (!peer_pdd) 23931bb76ff1Sjsg return -EINVAL; 23941bb76ff1Sjsg 23951bb76ff1Sjsg peer = peer_pdd->dev; 23961bb76ff1Sjsg 23971bb76ff1Sjsg peer_pdd = kfd_bind_process_to_device(peer, p); 23981bb76ff1Sjsg if (IS_ERR(peer_pdd)) 23991bb76ff1Sjsg return PTR_ERR(peer_pdd); 24001bb76ff1Sjsg 24011bb76ff1Sjsg ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, kgd_mem, 24021bb76ff1Sjsg peer_pdd->drm_priv); 24031bb76ff1Sjsg if (ret) { 24041bb76ff1Sjsg pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); 24051bb76ff1Sjsg return ret; 24061bb76ff1Sjsg } 24071bb76ff1Sjsg } 24081bb76ff1Sjsg 24091bb76ff1Sjsg pr_debug("map memory was successful for the BO\n"); 24101bb76ff1Sjsg /* create the dmabuf object and export the bo */ 24111bb76ff1Sjsg if (bo_bucket->alloc_flags 24121bb76ff1Sjsg & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) { 2413f005ef32Sjsg ret = criu_get_prime_handle(kgd_mem, DRM_RDWR, 24141bb76ff1Sjsg &bo_bucket->dmabuf_fd); 24151bb76ff1Sjsg if (ret) 24161bb76ff1Sjsg return ret; 24171bb76ff1Sjsg } else { 24181bb76ff1Sjsg bo_bucket->dmabuf_fd = KFD_INVALID_FD; 24191bb76ff1Sjsg } 24201bb76ff1Sjsg 24211bb76ff1Sjsg return 0; 24221bb76ff1Sjsg } 24231bb76ff1Sjsg 24241bb76ff1Sjsg static int criu_restore_bos(struct kfd_process *p, 24251bb76ff1Sjsg struct kfd_ioctl_criu_args *args, 24261bb76ff1Sjsg uint64_t *priv_offset, 24271bb76ff1Sjsg uint64_t max_priv_data_size) 24281bb76ff1Sjsg { 24291bb76ff1Sjsg struct kfd_criu_bo_bucket *bo_buckets = NULL; 24301bb76ff1Sjsg struct kfd_criu_bo_priv_data *bo_privs = NULL; 24311bb76ff1Sjsg int ret = 0; 24321bb76ff1Sjsg uint32_t i = 0; 24331bb76ff1Sjsg 24341bb76ff1Sjsg if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size) 24351bb76ff1Sjsg return -EINVAL; 24361bb76ff1Sjsg 24371bb76ff1Sjsg /* Prevent MMU notifications until stage-4 IOCTL (CRIU_RESUME) is received */ 24381bb76ff1Sjsg amdgpu_amdkfd_block_mmu_notifications(p->kgd_process_info); 24391bb76ff1Sjsg 24401bb76ff1Sjsg bo_buckets = kvmalloc_array(args->num_bos, sizeof(*bo_buckets), GFP_KERNEL); 24411bb76ff1Sjsg if (!bo_buckets) 24421bb76ff1Sjsg return -ENOMEM; 24431bb76ff1Sjsg 24441bb76ff1Sjsg ret = copy_from_user(bo_buckets, (void __user *)args->bos, 24451bb76ff1Sjsg args->num_bos * sizeof(*bo_buckets)); 24461bb76ff1Sjsg if (ret) { 24471bb76ff1Sjsg pr_err("Failed to copy BOs information from user\n"); 24481bb76ff1Sjsg ret = -EFAULT; 24491bb76ff1Sjsg goto exit; 24501bb76ff1Sjsg } 24511bb76ff1Sjsg 24521bb76ff1Sjsg bo_privs = kvmalloc_array(args->num_bos, sizeof(*bo_privs), GFP_KERNEL); 24531bb76ff1Sjsg if (!bo_privs) { 24541bb76ff1Sjsg ret = -ENOMEM; 24551bb76ff1Sjsg goto exit; 24561bb76ff1Sjsg } 24571bb76ff1Sjsg 24581bb76ff1Sjsg ret = copy_from_user(bo_privs, (void __user *)args->priv_data + *priv_offset, 24591bb76ff1Sjsg args->num_bos * sizeof(*bo_privs)); 24601bb76ff1Sjsg if (ret) { 24611bb76ff1Sjsg pr_err("Failed to copy BOs information from user\n"); 24621bb76ff1Sjsg ret = -EFAULT; 24631bb76ff1Sjsg goto exit; 24641bb76ff1Sjsg } 24651bb76ff1Sjsg *priv_offset += args->num_bos * sizeof(*bo_privs); 24661bb76ff1Sjsg 24671bb76ff1Sjsg /* Create and map new BOs */ 24681bb76ff1Sjsg for (; i < args->num_bos; i++) { 24691bb76ff1Sjsg ret = criu_restore_bo(p, &bo_buckets[i], &bo_privs[i]); 24701bb76ff1Sjsg if (ret) { 24711bb76ff1Sjsg pr_debug("Failed to restore BO[%d] ret%d\n", i, ret); 24721bb76ff1Sjsg goto exit; 24731bb76ff1Sjsg } 24741bb76ff1Sjsg } /* done */ 24751bb76ff1Sjsg 24761bb76ff1Sjsg /* Copy only the buckets back so user can read bo_buckets[N].restored_offset */ 24771bb76ff1Sjsg ret = copy_to_user((void __user *)args->bos, 24781bb76ff1Sjsg bo_buckets, 24791bb76ff1Sjsg (args->num_bos * sizeof(*bo_buckets))); 24801bb76ff1Sjsg if (ret) 24811bb76ff1Sjsg ret = -EFAULT; 24821bb76ff1Sjsg 24831bb76ff1Sjsg exit: 24841bb76ff1Sjsg while (ret && i--) { 24851bb76ff1Sjsg if (bo_buckets[i].alloc_flags 24861bb76ff1Sjsg & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) 24871bb76ff1Sjsg close_fd(bo_buckets[i].dmabuf_fd); 24881bb76ff1Sjsg } 24891bb76ff1Sjsg kvfree(bo_buckets); 24901bb76ff1Sjsg kvfree(bo_privs); 24911bb76ff1Sjsg return ret; 24921bb76ff1Sjsg } 24931bb76ff1Sjsg 24941bb76ff1Sjsg static int criu_restore_objects(struct file *filep, 24951bb76ff1Sjsg struct kfd_process *p, 24961bb76ff1Sjsg struct kfd_ioctl_criu_args *args, 24971bb76ff1Sjsg uint64_t *priv_offset, 24981bb76ff1Sjsg uint64_t max_priv_data_size) 24991bb76ff1Sjsg { 25001bb76ff1Sjsg int ret = 0; 25011bb76ff1Sjsg uint32_t i; 25021bb76ff1Sjsg 25031bb76ff1Sjsg BUILD_BUG_ON(offsetof(struct kfd_criu_queue_priv_data, object_type)); 25041bb76ff1Sjsg BUILD_BUG_ON(offsetof(struct kfd_criu_event_priv_data, object_type)); 25051bb76ff1Sjsg BUILD_BUG_ON(offsetof(struct kfd_criu_svm_range_priv_data, object_type)); 25061bb76ff1Sjsg 25071bb76ff1Sjsg for (i = 0; i < args->num_objects; i++) { 25081bb76ff1Sjsg uint32_t object_type; 25091bb76ff1Sjsg 25101bb76ff1Sjsg if (*priv_offset + sizeof(object_type) > max_priv_data_size) { 25111bb76ff1Sjsg pr_err("Invalid private data size\n"); 25121bb76ff1Sjsg return -EINVAL; 25131bb76ff1Sjsg } 25141bb76ff1Sjsg 25151bb76ff1Sjsg ret = get_user(object_type, (uint32_t __user *)(args->priv_data + *priv_offset)); 25161bb76ff1Sjsg if (ret) { 25171bb76ff1Sjsg pr_err("Failed to copy private information from user\n"); 25181bb76ff1Sjsg goto exit; 25191bb76ff1Sjsg } 25201bb76ff1Sjsg 25211bb76ff1Sjsg switch (object_type) { 25221bb76ff1Sjsg case KFD_CRIU_OBJECT_TYPE_QUEUE: 25231bb76ff1Sjsg ret = kfd_criu_restore_queue(p, (uint8_t __user *)args->priv_data, 25241bb76ff1Sjsg priv_offset, max_priv_data_size); 25251bb76ff1Sjsg if (ret) 25261bb76ff1Sjsg goto exit; 25271bb76ff1Sjsg break; 25281bb76ff1Sjsg case KFD_CRIU_OBJECT_TYPE_EVENT: 25291bb76ff1Sjsg ret = kfd_criu_restore_event(filep, p, (uint8_t __user *)args->priv_data, 25301bb76ff1Sjsg priv_offset, max_priv_data_size); 25311bb76ff1Sjsg if (ret) 25321bb76ff1Sjsg goto exit; 25331bb76ff1Sjsg break; 25341bb76ff1Sjsg case KFD_CRIU_OBJECT_TYPE_SVM_RANGE: 25351bb76ff1Sjsg ret = kfd_criu_restore_svm(p, (uint8_t __user *)args->priv_data, 25361bb76ff1Sjsg priv_offset, max_priv_data_size); 25371bb76ff1Sjsg if (ret) 25381bb76ff1Sjsg goto exit; 25391bb76ff1Sjsg break; 25401bb76ff1Sjsg default: 25411bb76ff1Sjsg pr_err("Invalid object type:%u at index:%d\n", object_type, i); 25421bb76ff1Sjsg ret = -EINVAL; 25431bb76ff1Sjsg goto exit; 25441bb76ff1Sjsg } 25451bb76ff1Sjsg } 25461bb76ff1Sjsg exit: 25471bb76ff1Sjsg return ret; 25481bb76ff1Sjsg } 25491bb76ff1Sjsg 25501bb76ff1Sjsg static int criu_restore(struct file *filep, 25511bb76ff1Sjsg struct kfd_process *p, 25521bb76ff1Sjsg struct kfd_ioctl_criu_args *args) 25531bb76ff1Sjsg { 25541bb76ff1Sjsg uint64_t priv_offset = 0; 25551bb76ff1Sjsg int ret = 0; 25561bb76ff1Sjsg 25571bb76ff1Sjsg pr_debug("CRIU restore (num_devices:%u num_bos:%u num_objects:%u priv_data_size:%llu)\n", 25581bb76ff1Sjsg args->num_devices, args->num_bos, args->num_objects, args->priv_data_size); 25591bb76ff1Sjsg 25601bb76ff1Sjsg if (!args->bos || !args->devices || !args->priv_data || !args->priv_data_size || 25611bb76ff1Sjsg !args->num_devices || !args->num_bos) 25621bb76ff1Sjsg return -EINVAL; 25631bb76ff1Sjsg 25641bb76ff1Sjsg mutex_lock(&p->mutex); 25651bb76ff1Sjsg 25661bb76ff1Sjsg /* 25671bb76ff1Sjsg * Set the process to evicted state to avoid running any new queues before all the memory 25681bb76ff1Sjsg * mappings are ready. 25691bb76ff1Sjsg */ 25701bb76ff1Sjsg ret = kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_CRIU_RESTORE); 25711bb76ff1Sjsg if (ret) 25721bb76ff1Sjsg goto exit_unlock; 25731bb76ff1Sjsg 25741bb76ff1Sjsg /* Each function will adjust priv_offset based on how many bytes they consumed */ 25751bb76ff1Sjsg ret = criu_restore_process(p, args, &priv_offset, args->priv_data_size); 25761bb76ff1Sjsg if (ret) 25771bb76ff1Sjsg goto exit_unlock; 25781bb76ff1Sjsg 25791bb76ff1Sjsg ret = criu_restore_devices(p, args, &priv_offset, args->priv_data_size); 25801bb76ff1Sjsg if (ret) 25811bb76ff1Sjsg goto exit_unlock; 25821bb76ff1Sjsg 25831bb76ff1Sjsg ret = criu_restore_bos(p, args, &priv_offset, args->priv_data_size); 25841bb76ff1Sjsg if (ret) 25851bb76ff1Sjsg goto exit_unlock; 25861bb76ff1Sjsg 25871bb76ff1Sjsg ret = criu_restore_objects(filep, p, args, &priv_offset, args->priv_data_size); 25881bb76ff1Sjsg if (ret) 25891bb76ff1Sjsg goto exit_unlock; 25901bb76ff1Sjsg 25911bb76ff1Sjsg if (priv_offset != args->priv_data_size) { 25921bb76ff1Sjsg pr_err("Invalid private data size\n"); 25931bb76ff1Sjsg ret = -EINVAL; 25941bb76ff1Sjsg } 25951bb76ff1Sjsg 25961bb76ff1Sjsg exit_unlock: 25971bb76ff1Sjsg mutex_unlock(&p->mutex); 25981bb76ff1Sjsg if (ret) 25991bb76ff1Sjsg pr_err("Failed to restore CRIU ret:%d\n", ret); 26001bb76ff1Sjsg else 26011bb76ff1Sjsg pr_debug("CRIU restore successful\n"); 26021bb76ff1Sjsg 26031bb76ff1Sjsg return ret; 26041bb76ff1Sjsg } 26051bb76ff1Sjsg 26061bb76ff1Sjsg static int criu_unpause(struct file *filep, 26071bb76ff1Sjsg struct kfd_process *p, 26081bb76ff1Sjsg struct kfd_ioctl_criu_args *args) 26091bb76ff1Sjsg { 26101bb76ff1Sjsg int ret; 26111bb76ff1Sjsg 26121bb76ff1Sjsg mutex_lock(&p->mutex); 26131bb76ff1Sjsg 26141bb76ff1Sjsg if (!p->queues_paused) { 26151bb76ff1Sjsg mutex_unlock(&p->mutex); 26161bb76ff1Sjsg return -EINVAL; 26171bb76ff1Sjsg } 26181bb76ff1Sjsg 26191bb76ff1Sjsg ret = kfd_process_restore_queues(p); 26201bb76ff1Sjsg if (ret) 26211bb76ff1Sjsg pr_err("Failed to unpause queues ret:%d\n", ret); 26221bb76ff1Sjsg else 26231bb76ff1Sjsg p->queues_paused = false; 26241bb76ff1Sjsg 26251bb76ff1Sjsg mutex_unlock(&p->mutex); 26261bb76ff1Sjsg 26271bb76ff1Sjsg return ret; 26281bb76ff1Sjsg } 26291bb76ff1Sjsg 26301bb76ff1Sjsg static int criu_resume(struct file *filep, 26311bb76ff1Sjsg struct kfd_process *p, 26321bb76ff1Sjsg struct kfd_ioctl_criu_args *args) 26331bb76ff1Sjsg { 26341bb76ff1Sjsg struct kfd_process *target = NULL; 26351bb76ff1Sjsg struct pid *pid = NULL; 26361bb76ff1Sjsg int ret = 0; 26371bb76ff1Sjsg 26381bb76ff1Sjsg pr_debug("Inside %s, target pid for criu restore: %d\n", __func__, 26391bb76ff1Sjsg args->pid); 26401bb76ff1Sjsg 26411bb76ff1Sjsg pid = find_get_pid(args->pid); 26421bb76ff1Sjsg if (!pid) { 26431bb76ff1Sjsg pr_err("Cannot find pid info for %i\n", args->pid); 26441bb76ff1Sjsg return -ESRCH; 26451bb76ff1Sjsg } 26461bb76ff1Sjsg 26471bb76ff1Sjsg pr_debug("calling kfd_lookup_process_by_pid\n"); 26481bb76ff1Sjsg target = kfd_lookup_process_by_pid(pid); 26491bb76ff1Sjsg 26501bb76ff1Sjsg put_pid(pid); 26511bb76ff1Sjsg 26521bb76ff1Sjsg if (!target) { 26531bb76ff1Sjsg pr_debug("Cannot find process info for %i\n", args->pid); 26541bb76ff1Sjsg return -ESRCH; 26551bb76ff1Sjsg } 26561bb76ff1Sjsg 26571bb76ff1Sjsg mutex_lock(&target->mutex); 26581bb76ff1Sjsg ret = kfd_criu_resume_svm(target); 26591bb76ff1Sjsg if (ret) { 26601bb76ff1Sjsg pr_err("kfd_criu_resume_svm failed for %i\n", args->pid); 26611bb76ff1Sjsg goto exit; 26621bb76ff1Sjsg } 26631bb76ff1Sjsg 26641bb76ff1Sjsg ret = amdgpu_amdkfd_criu_resume(target->kgd_process_info); 26651bb76ff1Sjsg if (ret) 26661bb76ff1Sjsg pr_err("amdgpu_amdkfd_criu_resume failed for %i\n", args->pid); 26671bb76ff1Sjsg 26681bb76ff1Sjsg exit: 26691bb76ff1Sjsg mutex_unlock(&target->mutex); 26701bb76ff1Sjsg 26711bb76ff1Sjsg kfd_unref_process(target); 26721bb76ff1Sjsg return ret; 26731bb76ff1Sjsg } 26741bb76ff1Sjsg 26751bb76ff1Sjsg static int criu_process_info(struct file *filep, 26761bb76ff1Sjsg struct kfd_process *p, 26771bb76ff1Sjsg struct kfd_ioctl_criu_args *args) 26781bb76ff1Sjsg { 26791bb76ff1Sjsg int ret = 0; 26801bb76ff1Sjsg 26811bb76ff1Sjsg mutex_lock(&p->mutex); 26821bb76ff1Sjsg 26831bb76ff1Sjsg if (!p->n_pdds) { 26841bb76ff1Sjsg pr_err("No pdd for given process\n"); 26851bb76ff1Sjsg ret = -ENODEV; 26861bb76ff1Sjsg goto err_unlock; 26871bb76ff1Sjsg } 26881bb76ff1Sjsg 26891bb76ff1Sjsg ret = kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_CRIU_CHECKPOINT); 26901bb76ff1Sjsg if (ret) 26911bb76ff1Sjsg goto err_unlock; 26921bb76ff1Sjsg 26931bb76ff1Sjsg p->queues_paused = true; 26941bb76ff1Sjsg 26951bb76ff1Sjsg args->pid = task_pid_nr_ns(p->lead_thread, 26961bb76ff1Sjsg task_active_pid_ns(p->lead_thread)); 26971bb76ff1Sjsg 26981bb76ff1Sjsg ret = criu_get_process_object_info(p, &args->num_devices, &args->num_bos, 26991bb76ff1Sjsg &args->num_objects, &args->priv_data_size); 27001bb76ff1Sjsg if (ret) 27011bb76ff1Sjsg goto err_unlock; 27021bb76ff1Sjsg 27031bb76ff1Sjsg dev_dbg(kfd_device, "Num of devices:%u bos:%u objects:%u priv_data_size:%lld\n", 27041bb76ff1Sjsg args->num_devices, args->num_bos, args->num_objects, 27051bb76ff1Sjsg args->priv_data_size); 27061bb76ff1Sjsg 27071bb76ff1Sjsg err_unlock: 27081bb76ff1Sjsg if (ret) { 27091bb76ff1Sjsg kfd_process_restore_queues(p); 27101bb76ff1Sjsg p->queues_paused = false; 27111bb76ff1Sjsg } 27121bb76ff1Sjsg mutex_unlock(&p->mutex); 27131bb76ff1Sjsg return ret; 27141bb76ff1Sjsg } 27151bb76ff1Sjsg 27161bb76ff1Sjsg static int kfd_ioctl_criu(struct file *filep, struct kfd_process *p, void *data) 27171bb76ff1Sjsg { 27181bb76ff1Sjsg struct kfd_ioctl_criu_args *args = data; 27191bb76ff1Sjsg int ret; 27201bb76ff1Sjsg 27211bb76ff1Sjsg dev_dbg(kfd_device, "CRIU operation: %d\n", args->op); 27221bb76ff1Sjsg switch (args->op) { 27231bb76ff1Sjsg case KFD_CRIU_OP_PROCESS_INFO: 27241bb76ff1Sjsg ret = criu_process_info(filep, p, args); 27251bb76ff1Sjsg break; 27261bb76ff1Sjsg case KFD_CRIU_OP_CHECKPOINT: 27271bb76ff1Sjsg ret = criu_checkpoint(filep, p, args); 27281bb76ff1Sjsg break; 27291bb76ff1Sjsg case KFD_CRIU_OP_UNPAUSE: 27301bb76ff1Sjsg ret = criu_unpause(filep, p, args); 27311bb76ff1Sjsg break; 27321bb76ff1Sjsg case KFD_CRIU_OP_RESTORE: 27331bb76ff1Sjsg ret = criu_restore(filep, p, args); 27341bb76ff1Sjsg break; 27351bb76ff1Sjsg case KFD_CRIU_OP_RESUME: 27361bb76ff1Sjsg ret = criu_resume(filep, p, args); 27371bb76ff1Sjsg break; 27381bb76ff1Sjsg default: 27391bb76ff1Sjsg dev_dbg(kfd_device, "Unsupported CRIU operation:%d\n", args->op); 27401bb76ff1Sjsg ret = -EINVAL; 27411bb76ff1Sjsg break; 27421bb76ff1Sjsg } 27431bb76ff1Sjsg 27441bb76ff1Sjsg if (ret) 27451bb76ff1Sjsg dev_dbg(kfd_device, "CRIU operation:%d err:%d\n", args->op, ret); 27461bb76ff1Sjsg 27471bb76ff1Sjsg return ret; 27481bb76ff1Sjsg } 27491bb76ff1Sjsg 2750f005ef32Sjsg static int runtime_enable(struct kfd_process *p, uint64_t r_debug, 2751f005ef32Sjsg bool enable_ttmp_setup) 2752f005ef32Sjsg { 2753f005ef32Sjsg int i = 0, ret = 0; 2754f005ef32Sjsg 2755f005ef32Sjsg if (p->is_runtime_retry) 2756f005ef32Sjsg goto retry; 2757f005ef32Sjsg 2758f005ef32Sjsg if (p->runtime_info.runtime_state != DEBUG_RUNTIME_STATE_DISABLED) 2759f005ef32Sjsg return -EBUSY; 2760f005ef32Sjsg 2761f005ef32Sjsg for (i = 0; i < p->n_pdds; i++) { 2762f005ef32Sjsg struct kfd_process_device *pdd = p->pdds[i]; 2763f005ef32Sjsg 2764f005ef32Sjsg if (pdd->qpd.queue_count) 2765f005ef32Sjsg return -EEXIST; 2766f005ef32Sjsg 2767f005ef32Sjsg /* 2768f005ef32Sjsg * Setup TTMPs by default. 2769f005ef32Sjsg * Note that this call must remain here for MES ADD QUEUE to 2770f005ef32Sjsg * skip_process_ctx_clear unconditionally as the first call to 2771f005ef32Sjsg * SET_SHADER_DEBUGGER clears any stale process context data 2772f005ef32Sjsg * saved in MES. 2773f005ef32Sjsg */ 2774f005ef32Sjsg if (pdd->dev->kfd->shared_resources.enable_mes) 2775f005ef32Sjsg kfd_dbg_set_mes_debug_mode(pdd, !kfd_dbg_has_cwsr_workaround(pdd->dev)); 2776f005ef32Sjsg } 2777f005ef32Sjsg 2778f005ef32Sjsg p->runtime_info.runtime_state = DEBUG_RUNTIME_STATE_ENABLED; 2779f005ef32Sjsg p->runtime_info.r_debug = r_debug; 2780f005ef32Sjsg p->runtime_info.ttmp_setup = enable_ttmp_setup; 2781f005ef32Sjsg 2782f005ef32Sjsg if (p->runtime_info.ttmp_setup) { 2783f005ef32Sjsg for (i = 0; i < p->n_pdds; i++) { 2784f005ef32Sjsg struct kfd_process_device *pdd = p->pdds[i]; 2785f005ef32Sjsg 2786f005ef32Sjsg if (!kfd_dbg_is_rlc_restore_supported(pdd->dev)) { 2787f005ef32Sjsg amdgpu_gfx_off_ctrl(pdd->dev->adev, false); 2788f005ef32Sjsg pdd->dev->kfd2kgd->enable_debug_trap( 2789f005ef32Sjsg pdd->dev->adev, 2790f005ef32Sjsg true, 2791f005ef32Sjsg pdd->dev->vm_info.last_vmid_kfd); 2792f005ef32Sjsg } else if (kfd_dbg_is_per_vmid_supported(pdd->dev)) { 2793f005ef32Sjsg pdd->spi_dbg_override = pdd->dev->kfd2kgd->enable_debug_trap( 2794f005ef32Sjsg pdd->dev->adev, 2795f005ef32Sjsg false, 2796f005ef32Sjsg 0); 2797f005ef32Sjsg } 2798f005ef32Sjsg } 2799f005ef32Sjsg } 2800f005ef32Sjsg 2801f005ef32Sjsg retry: 2802f005ef32Sjsg if (p->debug_trap_enabled) { 2803f005ef32Sjsg if (!p->is_runtime_retry) { 2804f005ef32Sjsg kfd_dbg_trap_activate(p); 2805f005ef32Sjsg kfd_dbg_ev_raise(KFD_EC_MASK(EC_PROCESS_RUNTIME), 2806f005ef32Sjsg p, NULL, 0, false, NULL, 0); 2807f005ef32Sjsg } 2808f005ef32Sjsg 2809f005ef32Sjsg mutex_unlock(&p->mutex); 2810f005ef32Sjsg ret = down_interruptible(&p->runtime_enable_sema); 2811f005ef32Sjsg mutex_lock(&p->mutex); 2812f005ef32Sjsg 2813f005ef32Sjsg p->is_runtime_retry = !!ret; 2814f005ef32Sjsg } 2815f005ef32Sjsg 2816f005ef32Sjsg return ret; 2817f005ef32Sjsg } 2818f005ef32Sjsg 2819f005ef32Sjsg static int runtime_disable(struct kfd_process *p) 2820f005ef32Sjsg { 2821f005ef32Sjsg int i = 0, ret; 2822f005ef32Sjsg bool was_enabled = p->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED; 2823f005ef32Sjsg 2824f005ef32Sjsg p->runtime_info.runtime_state = DEBUG_RUNTIME_STATE_DISABLED; 2825f005ef32Sjsg p->runtime_info.r_debug = 0; 2826f005ef32Sjsg 2827f005ef32Sjsg if (p->debug_trap_enabled) { 2828f005ef32Sjsg if (was_enabled) 2829f005ef32Sjsg kfd_dbg_trap_deactivate(p, false, 0); 2830f005ef32Sjsg 2831f005ef32Sjsg if (!p->is_runtime_retry) 2832f005ef32Sjsg kfd_dbg_ev_raise(KFD_EC_MASK(EC_PROCESS_RUNTIME), 2833f005ef32Sjsg p, NULL, 0, false, NULL, 0); 2834f005ef32Sjsg 2835f005ef32Sjsg mutex_unlock(&p->mutex); 2836f005ef32Sjsg ret = down_interruptible(&p->runtime_enable_sema); 2837f005ef32Sjsg mutex_lock(&p->mutex); 2838f005ef32Sjsg 2839f005ef32Sjsg p->is_runtime_retry = !!ret; 2840f005ef32Sjsg if (ret) 2841f005ef32Sjsg return ret; 2842f005ef32Sjsg } 2843f005ef32Sjsg 2844f005ef32Sjsg if (was_enabled && p->runtime_info.ttmp_setup) { 2845f005ef32Sjsg for (i = 0; i < p->n_pdds; i++) { 2846f005ef32Sjsg struct kfd_process_device *pdd = p->pdds[i]; 2847f005ef32Sjsg 2848f005ef32Sjsg if (!kfd_dbg_is_rlc_restore_supported(pdd->dev)) 2849f005ef32Sjsg amdgpu_gfx_off_ctrl(pdd->dev->adev, true); 2850f005ef32Sjsg } 2851f005ef32Sjsg } 2852f005ef32Sjsg 2853f005ef32Sjsg p->runtime_info.ttmp_setup = false; 2854f005ef32Sjsg 2855f005ef32Sjsg /* disable ttmp setup */ 2856f005ef32Sjsg for (i = 0; i < p->n_pdds; i++) { 2857f005ef32Sjsg struct kfd_process_device *pdd = p->pdds[i]; 2858f005ef32Sjsg 2859f005ef32Sjsg if (kfd_dbg_is_per_vmid_supported(pdd->dev)) { 2860f005ef32Sjsg pdd->spi_dbg_override = 2861f005ef32Sjsg pdd->dev->kfd2kgd->disable_debug_trap( 2862f005ef32Sjsg pdd->dev->adev, 2863f005ef32Sjsg false, 2864f005ef32Sjsg pdd->dev->vm_info.last_vmid_kfd); 2865f005ef32Sjsg 2866f005ef32Sjsg if (!pdd->dev->kfd->shared_resources.enable_mes) 2867f005ef32Sjsg debug_refresh_runlist(pdd->dev->dqm); 2868f005ef32Sjsg else 2869f005ef32Sjsg kfd_dbg_set_mes_debug_mode(pdd, 2870f005ef32Sjsg !kfd_dbg_has_cwsr_workaround(pdd->dev)); 2871f005ef32Sjsg } 2872f005ef32Sjsg } 2873f005ef32Sjsg 2874f005ef32Sjsg return 0; 2875f005ef32Sjsg } 2876f005ef32Sjsg 2877f005ef32Sjsg static int kfd_ioctl_runtime_enable(struct file *filep, struct kfd_process *p, void *data) 2878f005ef32Sjsg { 2879f005ef32Sjsg struct kfd_ioctl_runtime_enable_args *args = data; 2880f005ef32Sjsg int r; 2881f005ef32Sjsg 2882f005ef32Sjsg mutex_lock(&p->mutex); 2883f005ef32Sjsg 2884f005ef32Sjsg if (args->mode_mask & KFD_RUNTIME_ENABLE_MODE_ENABLE_MASK) 2885f005ef32Sjsg r = runtime_enable(p, args->r_debug, 2886f005ef32Sjsg !!(args->mode_mask & KFD_RUNTIME_ENABLE_MODE_TTMP_SAVE_MASK)); 2887f005ef32Sjsg else 2888f005ef32Sjsg r = runtime_disable(p); 2889f005ef32Sjsg 2890f005ef32Sjsg mutex_unlock(&p->mutex); 2891f005ef32Sjsg 2892f005ef32Sjsg return r; 2893f005ef32Sjsg } 2894f005ef32Sjsg 2895f005ef32Sjsg static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, void *data) 2896f005ef32Sjsg { 2897f005ef32Sjsg struct kfd_ioctl_dbg_trap_args *args = data; 2898f005ef32Sjsg struct task_struct *thread = NULL; 2899f005ef32Sjsg struct mm_struct *mm = NULL; 2900f005ef32Sjsg struct pid *pid = NULL; 2901f005ef32Sjsg struct kfd_process *target = NULL; 2902f005ef32Sjsg struct kfd_process_device *pdd = NULL; 2903f005ef32Sjsg int r = 0; 2904f005ef32Sjsg 2905f005ef32Sjsg if (sched_policy == KFD_SCHED_POLICY_NO_HWS) { 2906f005ef32Sjsg pr_err("Debugging does not support sched_policy %i", sched_policy); 2907f005ef32Sjsg return -EINVAL; 2908f005ef32Sjsg } 2909f005ef32Sjsg 2910f005ef32Sjsg pid = find_get_pid(args->pid); 2911f005ef32Sjsg if (!pid) { 2912f005ef32Sjsg pr_debug("Cannot find pid info for %i\n", args->pid); 2913f005ef32Sjsg r = -ESRCH; 2914f005ef32Sjsg goto out; 2915f005ef32Sjsg } 2916f005ef32Sjsg 2917f005ef32Sjsg thread = get_pid_task(pid, PIDTYPE_PID); 2918f005ef32Sjsg if (!thread) { 2919f005ef32Sjsg r = -ESRCH; 2920f005ef32Sjsg goto out; 2921f005ef32Sjsg } 2922f005ef32Sjsg 2923f005ef32Sjsg mm = get_task_mm(thread); 2924f005ef32Sjsg if (!mm) { 2925f005ef32Sjsg r = -ESRCH; 2926f005ef32Sjsg goto out; 2927f005ef32Sjsg } 2928f005ef32Sjsg 2929f005ef32Sjsg if (args->op == KFD_IOC_DBG_TRAP_ENABLE) { 2930f005ef32Sjsg bool create_process; 2931f005ef32Sjsg 2932f005ef32Sjsg rcu_read_lock(); 2933f005ef32Sjsg create_process = thread && thread != current && ptrace_parent(thread) == current; 2934f005ef32Sjsg rcu_read_unlock(); 2935f005ef32Sjsg 2936f005ef32Sjsg target = create_process ? kfd_create_process(thread) : 2937f005ef32Sjsg kfd_lookup_process_by_pid(pid); 2938f005ef32Sjsg } else { 2939f005ef32Sjsg target = kfd_lookup_process_by_pid(pid); 2940f005ef32Sjsg } 2941f005ef32Sjsg 2942f005ef32Sjsg if (IS_ERR_OR_NULL(target)) { 2943f005ef32Sjsg pr_debug("Cannot find process PID %i to debug\n", args->pid); 2944f005ef32Sjsg r = target ? PTR_ERR(target) : -ESRCH; 2945f005ef32Sjsg goto out; 2946f005ef32Sjsg } 2947f005ef32Sjsg 2948f005ef32Sjsg /* Check if target is still PTRACED. */ 2949f005ef32Sjsg rcu_read_lock(); 2950f005ef32Sjsg if (target != p && args->op != KFD_IOC_DBG_TRAP_DISABLE 2951f005ef32Sjsg && ptrace_parent(target->lead_thread) != current) { 2952f005ef32Sjsg pr_err("PID %i is not PTRACED and cannot be debugged\n", args->pid); 2953f005ef32Sjsg r = -EPERM; 2954f005ef32Sjsg } 2955f005ef32Sjsg rcu_read_unlock(); 2956f005ef32Sjsg 2957f005ef32Sjsg if (r) 2958f005ef32Sjsg goto out; 2959f005ef32Sjsg 2960f005ef32Sjsg mutex_lock(&target->mutex); 2961f005ef32Sjsg 2962f005ef32Sjsg if (args->op != KFD_IOC_DBG_TRAP_ENABLE && !target->debug_trap_enabled) { 2963f005ef32Sjsg pr_err("PID %i not debug enabled for op %i\n", args->pid, args->op); 2964f005ef32Sjsg r = -EINVAL; 2965f005ef32Sjsg goto unlock_out; 2966f005ef32Sjsg } 2967f005ef32Sjsg 2968f005ef32Sjsg if (target->runtime_info.runtime_state != DEBUG_RUNTIME_STATE_ENABLED && 2969f005ef32Sjsg (args->op == KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE || 2970f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE || 2971f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_SUSPEND_QUEUES || 2972f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_RESUME_QUEUES || 2973f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH || 2974f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH || 2975f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_SET_FLAGS)) { 2976f005ef32Sjsg r = -EPERM; 2977f005ef32Sjsg goto unlock_out; 2978f005ef32Sjsg } 2979f005ef32Sjsg 2980f005ef32Sjsg if (args->op == KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH || 2981f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH) { 2982f005ef32Sjsg int user_gpu_id = kfd_process_get_user_gpu_id(target, 2983f005ef32Sjsg args->op == KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH ? 2984f005ef32Sjsg args->set_node_address_watch.gpu_id : 2985f005ef32Sjsg args->clear_node_address_watch.gpu_id); 2986f005ef32Sjsg 2987f005ef32Sjsg pdd = kfd_process_device_data_by_id(target, user_gpu_id); 2988f005ef32Sjsg if (user_gpu_id == -EINVAL || !pdd) { 2989f005ef32Sjsg r = -ENODEV; 2990f005ef32Sjsg goto unlock_out; 2991f005ef32Sjsg } 2992f005ef32Sjsg } 2993f005ef32Sjsg 2994f005ef32Sjsg switch (args->op) { 2995f005ef32Sjsg case KFD_IOC_DBG_TRAP_ENABLE: 2996f005ef32Sjsg if (target != p) 2997f005ef32Sjsg target->debugger_process = p; 2998f005ef32Sjsg 2999f005ef32Sjsg r = kfd_dbg_trap_enable(target, 3000f005ef32Sjsg args->enable.dbg_fd, 3001f005ef32Sjsg (void __user *)args->enable.rinfo_ptr, 3002f005ef32Sjsg &args->enable.rinfo_size); 3003f005ef32Sjsg if (!r) 3004f005ef32Sjsg target->exception_enable_mask = args->enable.exception_mask; 3005f005ef32Sjsg 3006f005ef32Sjsg break; 3007f005ef32Sjsg case KFD_IOC_DBG_TRAP_DISABLE: 3008f005ef32Sjsg r = kfd_dbg_trap_disable(target); 3009f005ef32Sjsg break; 3010f005ef32Sjsg case KFD_IOC_DBG_TRAP_SEND_RUNTIME_EVENT: 3011f005ef32Sjsg r = kfd_dbg_send_exception_to_runtime(target, 3012f005ef32Sjsg args->send_runtime_event.gpu_id, 3013f005ef32Sjsg args->send_runtime_event.queue_id, 3014f005ef32Sjsg args->send_runtime_event.exception_mask); 3015f005ef32Sjsg break; 3016f005ef32Sjsg case KFD_IOC_DBG_TRAP_SET_EXCEPTIONS_ENABLED: 3017f005ef32Sjsg kfd_dbg_set_enabled_debug_exception_mask(target, 3018f005ef32Sjsg args->set_exceptions_enabled.exception_mask); 3019f005ef32Sjsg break; 3020f005ef32Sjsg case KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_OVERRIDE: 3021f005ef32Sjsg r = kfd_dbg_trap_set_wave_launch_override(target, 3022f005ef32Sjsg args->launch_override.override_mode, 3023f005ef32Sjsg args->launch_override.enable_mask, 3024f005ef32Sjsg args->launch_override.support_request_mask, 3025f005ef32Sjsg &args->launch_override.enable_mask, 3026f005ef32Sjsg &args->launch_override.support_request_mask); 3027f005ef32Sjsg break; 3028f005ef32Sjsg case KFD_IOC_DBG_TRAP_SET_WAVE_LAUNCH_MODE: 3029f005ef32Sjsg r = kfd_dbg_trap_set_wave_launch_mode(target, 3030f005ef32Sjsg args->launch_mode.launch_mode); 3031f005ef32Sjsg break; 3032f005ef32Sjsg case KFD_IOC_DBG_TRAP_SUSPEND_QUEUES: 3033f005ef32Sjsg r = suspend_queues(target, 3034f005ef32Sjsg args->suspend_queues.num_queues, 3035f005ef32Sjsg args->suspend_queues.grace_period, 3036f005ef32Sjsg args->suspend_queues.exception_mask, 3037f005ef32Sjsg (uint32_t *)args->suspend_queues.queue_array_ptr); 3038f005ef32Sjsg 3039f005ef32Sjsg break; 3040f005ef32Sjsg case KFD_IOC_DBG_TRAP_RESUME_QUEUES: 3041f005ef32Sjsg r = resume_queues(target, args->resume_queues.num_queues, 3042f005ef32Sjsg (uint32_t *)args->resume_queues.queue_array_ptr); 3043f005ef32Sjsg break; 3044f005ef32Sjsg case KFD_IOC_DBG_TRAP_SET_NODE_ADDRESS_WATCH: 3045f005ef32Sjsg r = kfd_dbg_trap_set_dev_address_watch(pdd, 3046f005ef32Sjsg args->set_node_address_watch.address, 3047f005ef32Sjsg args->set_node_address_watch.mask, 3048f005ef32Sjsg &args->set_node_address_watch.id, 3049f005ef32Sjsg args->set_node_address_watch.mode); 3050f005ef32Sjsg break; 3051f005ef32Sjsg case KFD_IOC_DBG_TRAP_CLEAR_NODE_ADDRESS_WATCH: 3052f005ef32Sjsg r = kfd_dbg_trap_clear_dev_address_watch(pdd, 3053f005ef32Sjsg args->clear_node_address_watch.id); 3054f005ef32Sjsg break; 3055f005ef32Sjsg case KFD_IOC_DBG_TRAP_SET_FLAGS: 3056f005ef32Sjsg r = kfd_dbg_trap_set_flags(target, &args->set_flags.flags); 3057f005ef32Sjsg break; 3058f005ef32Sjsg case KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT: 3059f005ef32Sjsg r = kfd_dbg_ev_query_debug_event(target, 3060f005ef32Sjsg &args->query_debug_event.queue_id, 3061f005ef32Sjsg &args->query_debug_event.gpu_id, 3062f005ef32Sjsg args->query_debug_event.exception_mask, 3063f005ef32Sjsg &args->query_debug_event.exception_mask); 3064f005ef32Sjsg break; 3065f005ef32Sjsg case KFD_IOC_DBG_TRAP_QUERY_EXCEPTION_INFO: 3066f005ef32Sjsg r = kfd_dbg_trap_query_exception_info(target, 3067f005ef32Sjsg args->query_exception_info.source_id, 3068f005ef32Sjsg args->query_exception_info.exception_code, 3069f005ef32Sjsg args->query_exception_info.clear_exception, 3070f005ef32Sjsg (void __user *)args->query_exception_info.info_ptr, 3071f005ef32Sjsg &args->query_exception_info.info_size); 3072f005ef32Sjsg break; 3073f005ef32Sjsg case KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT: 3074f005ef32Sjsg r = pqm_get_queue_snapshot(&target->pqm, 3075f005ef32Sjsg args->queue_snapshot.exception_mask, 3076f005ef32Sjsg (void __user *)args->queue_snapshot.snapshot_buf_ptr, 3077f005ef32Sjsg &args->queue_snapshot.num_queues, 3078f005ef32Sjsg &args->queue_snapshot.entry_size); 3079f005ef32Sjsg break; 3080f005ef32Sjsg case KFD_IOC_DBG_TRAP_GET_DEVICE_SNAPSHOT: 3081f005ef32Sjsg r = kfd_dbg_trap_device_snapshot(target, 3082f005ef32Sjsg args->device_snapshot.exception_mask, 3083f005ef32Sjsg (void __user *)args->device_snapshot.snapshot_buf_ptr, 3084f005ef32Sjsg &args->device_snapshot.num_devices, 3085f005ef32Sjsg &args->device_snapshot.entry_size); 3086f005ef32Sjsg break; 3087f005ef32Sjsg default: 3088f005ef32Sjsg pr_err("Invalid option: %i\n", args->op); 3089f005ef32Sjsg r = -EINVAL; 3090f005ef32Sjsg } 3091f005ef32Sjsg 3092f005ef32Sjsg unlock_out: 3093f005ef32Sjsg mutex_unlock(&target->mutex); 3094f005ef32Sjsg 3095f005ef32Sjsg out: 3096f005ef32Sjsg if (thread) 3097f005ef32Sjsg put_task_struct(thread); 3098f005ef32Sjsg 3099f005ef32Sjsg if (mm) 3100f005ef32Sjsg mmput(mm); 3101f005ef32Sjsg 3102f005ef32Sjsg if (pid) 3103f005ef32Sjsg put_pid(pid); 3104f005ef32Sjsg 3105f005ef32Sjsg if (target) 3106f005ef32Sjsg kfd_unref_process(target); 3107f005ef32Sjsg 3108f005ef32Sjsg return r; 3109f005ef32Sjsg } 3110f005ef32Sjsg 3111fb4d8502Sjsg #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ 3112fb4d8502Sjsg [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ 3113fb4d8502Sjsg .cmd_drv = 0, .name = #ioctl} 3114fb4d8502Sjsg 3115fb4d8502Sjsg /** Ioctl table */ 3116fb4d8502Sjsg static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { 3117fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_VERSION, 3118fb4d8502Sjsg kfd_ioctl_get_version, 0), 3119fb4d8502Sjsg 3120fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_QUEUE, 3121fb4d8502Sjsg kfd_ioctl_create_queue, 0), 3122fb4d8502Sjsg 3123fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DESTROY_QUEUE, 3124fb4d8502Sjsg kfd_ioctl_destroy_queue, 0), 3125fb4d8502Sjsg 3126fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_MEMORY_POLICY, 3127fb4d8502Sjsg kfd_ioctl_set_memory_policy, 0), 3128fb4d8502Sjsg 3129fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_CLOCK_COUNTERS, 3130fb4d8502Sjsg kfd_ioctl_get_clock_counters, 0), 3131fb4d8502Sjsg 3132fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_PROCESS_APERTURES, 3133fb4d8502Sjsg kfd_ioctl_get_process_apertures, 0), 3134fb4d8502Sjsg 3135fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_UPDATE_QUEUE, 3136fb4d8502Sjsg kfd_ioctl_update_queue, 0), 3137fb4d8502Sjsg 3138fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_EVENT, 3139fb4d8502Sjsg kfd_ioctl_create_event, 0), 3140fb4d8502Sjsg 3141fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DESTROY_EVENT, 3142fb4d8502Sjsg kfd_ioctl_destroy_event, 0), 3143fb4d8502Sjsg 3144fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_EVENT, 3145fb4d8502Sjsg kfd_ioctl_set_event, 0), 3146fb4d8502Sjsg 3147fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_RESET_EVENT, 3148fb4d8502Sjsg kfd_ioctl_reset_event, 0), 3149fb4d8502Sjsg 3150fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_WAIT_EVENTS, 3151fb4d8502Sjsg kfd_ioctl_wait_events, 0), 3152fb4d8502Sjsg 31531bb76ff1Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_REGISTER_DEPRECATED, 3154fb4d8502Sjsg kfd_ioctl_dbg_register, 0), 3155fb4d8502Sjsg 31561bb76ff1Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED, 3157fb4d8502Sjsg kfd_ioctl_dbg_unregister, 0), 3158fb4d8502Sjsg 31591bb76ff1Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED, 3160fb4d8502Sjsg kfd_ioctl_dbg_address_watch, 0), 3161fb4d8502Sjsg 31621bb76ff1Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED, 3163fb4d8502Sjsg kfd_ioctl_dbg_wave_control, 0), 3164fb4d8502Sjsg 3165fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_SCRATCH_BACKING_VA, 3166fb4d8502Sjsg kfd_ioctl_set_scratch_backing_va, 0), 3167fb4d8502Sjsg 3168fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_TILE_CONFIG, 3169fb4d8502Sjsg kfd_ioctl_get_tile_config, 0), 3170fb4d8502Sjsg 3171fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_TRAP_HANDLER, 3172fb4d8502Sjsg kfd_ioctl_set_trap_handler, 0), 3173fb4d8502Sjsg 3174fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_PROCESS_APERTURES_NEW, 3175fb4d8502Sjsg kfd_ioctl_get_process_apertures_new, 0), 3176fb4d8502Sjsg 3177fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_ACQUIRE_VM, 3178fb4d8502Sjsg kfd_ioctl_acquire_vm, 0), 3179fb4d8502Sjsg 3180fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_ALLOC_MEMORY_OF_GPU, 3181fb4d8502Sjsg kfd_ioctl_alloc_memory_of_gpu, 0), 3182fb4d8502Sjsg 3183fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_FREE_MEMORY_OF_GPU, 3184fb4d8502Sjsg kfd_ioctl_free_memory_of_gpu, 0), 3185fb4d8502Sjsg 3186fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_MAP_MEMORY_TO_GPU, 3187fb4d8502Sjsg kfd_ioctl_map_memory_to_gpu, 0), 3188fb4d8502Sjsg 3189fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_UNMAP_MEMORY_FROM_GPU, 3190fb4d8502Sjsg kfd_ioctl_unmap_memory_from_gpu, 0), 3191fb4d8502Sjsg 3192fb4d8502Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_CU_MASK, 3193fb4d8502Sjsg kfd_ioctl_set_cu_mask, 0), 3194fb4d8502Sjsg 3195c349dbc7Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_QUEUE_WAVE_STATE, 3196c349dbc7Sjsg kfd_ioctl_get_queue_wave_state, 0), 3197c349dbc7Sjsg 3198c349dbc7Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_DMABUF_INFO, 3199c349dbc7Sjsg kfd_ioctl_get_dmabuf_info, 0), 3200c349dbc7Sjsg 3201c349dbc7Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_IMPORT_DMABUF, 3202c349dbc7Sjsg kfd_ioctl_import_dmabuf, 0), 3203c349dbc7Sjsg 3204ad8b1aafSjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_ALLOC_QUEUE_GWS, 3205ad8b1aafSjsg kfd_ioctl_alloc_queue_gws, 0), 3206ad8b1aafSjsg 3207ad8b1aafSjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SMI_EVENTS, 3208ad8b1aafSjsg kfd_ioctl_smi_events, 0), 32095ca02815Sjsg 32105ca02815Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SVM, kfd_ioctl_svm, 0), 32115ca02815Sjsg 32125ca02815Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_XNACK_MODE, 32135ca02815Sjsg kfd_ioctl_set_xnack_mode, 0), 32141bb76ff1Sjsg 32151bb76ff1Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_CRIU_OP, 32161bb76ff1Sjsg kfd_ioctl_criu, KFD_IOC_FLAG_CHECKPOINT_RESTORE), 32171bb76ff1Sjsg 32181bb76ff1Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_AVAILABLE_MEMORY, 32191bb76ff1Sjsg kfd_ioctl_get_available_memory, 0), 3220f005ef32Sjsg 3221f005ef32Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_EXPORT_DMABUF, 3222f005ef32Sjsg kfd_ioctl_export_dmabuf, 0), 3223f005ef32Sjsg 3224f005ef32Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_RUNTIME_ENABLE, 3225f005ef32Sjsg kfd_ioctl_runtime_enable, 0), 3226f005ef32Sjsg 3227f005ef32Sjsg AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_TRAP, 3228f005ef32Sjsg kfd_ioctl_set_debug_trap, 0), 3229fb4d8502Sjsg }; 3230fb4d8502Sjsg 3231fb4d8502Sjsg #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) 3232fb4d8502Sjsg 3233fb4d8502Sjsg static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) 3234fb4d8502Sjsg { 3235fb4d8502Sjsg struct kfd_process *process; 3236fb4d8502Sjsg amdkfd_ioctl_t *func; 3237fb4d8502Sjsg const struct amdkfd_ioctl_desc *ioctl = NULL; 3238fb4d8502Sjsg unsigned int nr = _IOC_NR(cmd); 3239fb4d8502Sjsg char stack_kdata[128]; 3240fb4d8502Sjsg char *kdata = NULL; 3241fb4d8502Sjsg unsigned int usize, asize; 3242fb4d8502Sjsg int retcode = -EINVAL; 32431bb76ff1Sjsg bool ptrace_attached = false; 3244fb4d8502Sjsg 3245fb4d8502Sjsg if (nr >= AMDKFD_CORE_IOCTL_COUNT) 3246fb4d8502Sjsg goto err_i1; 3247fb4d8502Sjsg 3248fb4d8502Sjsg if ((nr >= AMDKFD_COMMAND_START) && (nr < AMDKFD_COMMAND_END)) { 3249fb4d8502Sjsg u32 amdkfd_size; 3250fb4d8502Sjsg 3251fb4d8502Sjsg ioctl = &amdkfd_ioctls[nr]; 3252fb4d8502Sjsg 3253fb4d8502Sjsg amdkfd_size = _IOC_SIZE(ioctl->cmd); 3254fb4d8502Sjsg usize = asize = _IOC_SIZE(cmd); 3255fb4d8502Sjsg if (amdkfd_size > asize) 3256fb4d8502Sjsg asize = amdkfd_size; 3257fb4d8502Sjsg 3258fb4d8502Sjsg cmd = ioctl->cmd; 3259fb4d8502Sjsg } else 3260fb4d8502Sjsg goto err_i1; 3261fb4d8502Sjsg 3262c349dbc7Sjsg dev_dbg(kfd_device, "ioctl cmd 0x%x (#0x%x), arg 0x%lx\n", cmd, nr, arg); 3263fb4d8502Sjsg 3264c349dbc7Sjsg /* Get the process struct from the filep. Only the process 3265c349dbc7Sjsg * that opened /dev/kfd can use the file descriptor. Child 3266c349dbc7Sjsg * processes need to create their own KFD device context. 3267c349dbc7Sjsg */ 3268c349dbc7Sjsg process = filep->private_data; 32691bb76ff1Sjsg 32701bb76ff1Sjsg rcu_read_lock(); 32711bb76ff1Sjsg if ((ioctl->flags & KFD_IOC_FLAG_CHECKPOINT_RESTORE) && 32721bb76ff1Sjsg ptrace_parent(process->lead_thread) == current) 32731bb76ff1Sjsg ptrace_attached = true; 32741bb76ff1Sjsg rcu_read_unlock(); 32751bb76ff1Sjsg 32761bb76ff1Sjsg if (process->lead_thread != current->group_leader 32771bb76ff1Sjsg && !ptrace_attached) { 3278c349dbc7Sjsg dev_dbg(kfd_device, "Using KFD FD in wrong process\n"); 3279c349dbc7Sjsg retcode = -EBADF; 3280fb4d8502Sjsg goto err_i1; 3281fb4d8502Sjsg } 3282fb4d8502Sjsg 3283fb4d8502Sjsg /* Do not trust userspace, use our own definition */ 3284fb4d8502Sjsg func = ioctl->func; 3285fb4d8502Sjsg 3286fb4d8502Sjsg if (unlikely(!func)) { 3287fb4d8502Sjsg dev_dbg(kfd_device, "no function\n"); 3288fb4d8502Sjsg retcode = -EINVAL; 3289fb4d8502Sjsg goto err_i1; 3290fb4d8502Sjsg } 3291fb4d8502Sjsg 32921bb76ff1Sjsg /* 32931bb76ff1Sjsg * Versions of docker shipped in Ubuntu 18.xx and 20.xx do not support 32941bb76ff1Sjsg * CAP_CHECKPOINT_RESTORE, so we also allow access if CAP_SYS_ADMIN as CAP_SYS_ADMIN is a 32951bb76ff1Sjsg * more priviledged access. 32961bb76ff1Sjsg */ 32971bb76ff1Sjsg if (unlikely(ioctl->flags & KFD_IOC_FLAG_CHECKPOINT_RESTORE)) { 32981bb76ff1Sjsg if (!capable(CAP_CHECKPOINT_RESTORE) && 32991bb76ff1Sjsg !capable(CAP_SYS_ADMIN)) { 33001bb76ff1Sjsg retcode = -EACCES; 33011bb76ff1Sjsg goto err_i1; 33021bb76ff1Sjsg } 33031bb76ff1Sjsg } 33041bb76ff1Sjsg 3305fb4d8502Sjsg if (cmd & (IOC_IN | IOC_OUT)) { 3306fb4d8502Sjsg if (asize <= sizeof(stack_kdata)) { 3307fb4d8502Sjsg kdata = stack_kdata; 3308fb4d8502Sjsg } else { 3309fb4d8502Sjsg kdata = kmalloc(asize, GFP_KERNEL); 3310fb4d8502Sjsg if (!kdata) { 3311fb4d8502Sjsg retcode = -ENOMEM; 3312fb4d8502Sjsg goto err_i1; 3313fb4d8502Sjsg } 3314fb4d8502Sjsg } 3315fb4d8502Sjsg if (asize > usize) 3316fb4d8502Sjsg memset(kdata + usize, 0, asize - usize); 3317fb4d8502Sjsg } 3318fb4d8502Sjsg 3319fb4d8502Sjsg if (cmd & IOC_IN) { 3320fb4d8502Sjsg if (copy_from_user(kdata, (void __user *)arg, usize) != 0) { 3321fb4d8502Sjsg retcode = -EFAULT; 3322fb4d8502Sjsg goto err_i1; 3323fb4d8502Sjsg } 3324fb4d8502Sjsg } else if (cmd & IOC_OUT) { 3325fb4d8502Sjsg memset(kdata, 0, usize); 3326fb4d8502Sjsg } 3327fb4d8502Sjsg 3328fb4d8502Sjsg retcode = func(filep, process, kdata); 3329fb4d8502Sjsg 3330fb4d8502Sjsg if (cmd & IOC_OUT) 3331fb4d8502Sjsg if (copy_to_user((void __user *)arg, kdata, usize) != 0) 3332fb4d8502Sjsg retcode = -EFAULT; 3333fb4d8502Sjsg 3334fb4d8502Sjsg err_i1: 3335fb4d8502Sjsg if (!ioctl) 3336fb4d8502Sjsg dev_dbg(kfd_device, "invalid ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n", 3337fb4d8502Sjsg task_pid_nr(current), cmd, nr); 3338fb4d8502Sjsg 3339fb4d8502Sjsg if (kdata != stack_kdata) 3340fb4d8502Sjsg kfree(kdata); 3341fb4d8502Sjsg 3342fb4d8502Sjsg if (retcode) 3343c349dbc7Sjsg dev_dbg(kfd_device, "ioctl cmd (#0x%x), arg 0x%lx, ret = %d\n", 3344c349dbc7Sjsg nr, arg, retcode); 3345fb4d8502Sjsg 3346fb4d8502Sjsg return retcode; 3347fb4d8502Sjsg } 3348fb4d8502Sjsg 3349f005ef32Sjsg static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process, 3350c349dbc7Sjsg struct vm_area_struct *vma) 3351c349dbc7Sjsg { 3352c349dbc7Sjsg phys_addr_t address; 3353c349dbc7Sjsg 3354c349dbc7Sjsg if (vma->vm_end - vma->vm_start != PAGE_SIZE) 3355c349dbc7Sjsg return -EINVAL; 3356c349dbc7Sjsg 3357ab5fd4cbSjsg if (PAGE_SIZE > 4096) 3358ab5fd4cbSjsg return -EINVAL; 3359ab5fd4cbSjsg 33601bb76ff1Sjsg address = dev->adev->rmmio_remap.bus_addr; 3361c349dbc7Sjsg 3362f005ef32Sjsg vm_flags_set(vma, VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE | 3363f005ef32Sjsg VM_DONTDUMP | VM_PFNMAP); 3364c349dbc7Sjsg 3365c349dbc7Sjsg vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 3366c349dbc7Sjsg 3367c349dbc7Sjsg pr_debug("pasid 0x%x mapping mmio page\n" 3368c349dbc7Sjsg " target user address == 0x%08llX\n" 3369c349dbc7Sjsg " physical address == 0x%08llX\n" 3370c349dbc7Sjsg " vm_flags == 0x%04lX\n" 3371c349dbc7Sjsg " size == 0x%04lX\n", 3372c349dbc7Sjsg process->pasid, (unsigned long long) vma->vm_start, 3373c349dbc7Sjsg address, vma->vm_flags, PAGE_SIZE); 3374c349dbc7Sjsg 33751bb76ff1Sjsg return io_remap_pfn_range(vma, 3376c349dbc7Sjsg vma->vm_start, 3377c349dbc7Sjsg address >> PAGE_SHIFT, 3378c349dbc7Sjsg PAGE_SIZE, 3379c349dbc7Sjsg vma->vm_page_prot); 3380c349dbc7Sjsg } 3381c349dbc7Sjsg 3382c349dbc7Sjsg 3383fb4d8502Sjsg static int kfd_mmap(struct file *filp, struct vm_area_struct *vma) 3384fb4d8502Sjsg { 3385fb4d8502Sjsg struct kfd_process *process; 3386f005ef32Sjsg struct kfd_node *dev = NULL; 3387c349dbc7Sjsg unsigned long mmap_offset; 3388fb4d8502Sjsg unsigned int gpu_id; 3389fb4d8502Sjsg 3390fb4d8502Sjsg process = kfd_get_process(current); 3391fb4d8502Sjsg if (IS_ERR(process)) 3392fb4d8502Sjsg return PTR_ERR(process); 3393fb4d8502Sjsg 3394c349dbc7Sjsg mmap_offset = vma->vm_pgoff << PAGE_SHIFT; 3395c349dbc7Sjsg gpu_id = KFD_MMAP_GET_GPU_ID(mmap_offset); 3396fb4d8502Sjsg if (gpu_id) 3397fb4d8502Sjsg dev = kfd_device_by_id(gpu_id); 3398fb4d8502Sjsg 3399c349dbc7Sjsg switch (mmap_offset & KFD_MMAP_TYPE_MASK) { 3400fb4d8502Sjsg case KFD_MMAP_TYPE_DOORBELL: 3401fb4d8502Sjsg if (!dev) 3402fb4d8502Sjsg return -ENODEV; 3403fb4d8502Sjsg return kfd_doorbell_mmap(dev, process, vma); 3404fb4d8502Sjsg 3405fb4d8502Sjsg case KFD_MMAP_TYPE_EVENTS: 3406fb4d8502Sjsg return kfd_event_mmap(process, vma); 3407fb4d8502Sjsg 3408fb4d8502Sjsg case KFD_MMAP_TYPE_RESERVED_MEM: 3409fb4d8502Sjsg if (!dev) 3410fb4d8502Sjsg return -ENODEV; 3411fb4d8502Sjsg return kfd_reserved_mem_mmap(dev, process, vma); 3412c349dbc7Sjsg case KFD_MMAP_TYPE_MMIO: 3413c349dbc7Sjsg if (!dev) 3414c349dbc7Sjsg return -ENODEV; 3415c349dbc7Sjsg return kfd_mmio_mmap(dev, process, vma); 3416fb4d8502Sjsg } 3417fb4d8502Sjsg 3418fb4d8502Sjsg return -EFAULT; 3419fb4d8502Sjsg } 3420