1 /* 2 * Copyright (C) 2015 Red Hat, Inc. 3 * All Rights Reserved. 4 * 5 * Authors: 6 * Dave Airlie 7 * Alon Levy 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #include <linux/file.h> 29 #include <linux/sync_file.h> 30 #include <linux/uaccess.h> 31 32 #include <drm/drm_file.h> 33 #include <drm/virtgpu_drm.h> 34 35 #include "virtgpu_drv.h" 36 37 #define VIRTGPU_BLOB_FLAG_USE_MASK (VIRTGPU_BLOB_FLAG_USE_MAPPABLE | \ 38 VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \ 39 VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) 40 41 /* Must be called with &virtio_gpu_fpriv.struct_mutex held. */ 42 static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev, 43 struct virtio_gpu_fpriv *vfpriv) 44 { 45 if (vfpriv->explicit_debug_name) { 46 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, 47 vfpriv->context_init, 48 strlen(vfpriv->debug_name), 49 vfpriv->debug_name); 50 } else { 51 char dbgname[TASK_COMM_LEN]; 52 53 get_task_comm(dbgname, current); 54 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, 55 vfpriv->context_init, strlen(dbgname), 56 dbgname); 57 } 58 59 vfpriv->context_created = true; 60 } 61 62 void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file) 63 { 64 struct virtio_gpu_device *vgdev = dev->dev_private; 65 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 66 67 mutex_lock(&vfpriv->context_lock); 68 if (vfpriv->context_created) 69 goto out_unlock; 70 71 virtio_gpu_create_context_locked(vgdev, vfpriv); 72 73 out_unlock: 74 mutex_unlock(&vfpriv->context_lock); 75 } 76 77 static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data, 78 struct drm_file *file) 79 { 80 struct virtio_gpu_device *vgdev = dev->dev_private; 81 struct drm_virtgpu_map *virtio_gpu_map = data; 82 83 return drm_gem_dumb_map_offset(file, vgdev->ddev, 84 virtio_gpu_map->handle, 85 &virtio_gpu_map->offset); 86 } 87 88 static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, 89 struct drm_file *file) 90 { 91 struct virtio_gpu_device *vgdev = dev->dev_private; 92 struct drm_virtgpu_getparam *param = data; 93 int value; 94 95 switch (param->param) { 96 case VIRTGPU_PARAM_3D_FEATURES: 97 value = vgdev->has_virgl_3d ? 1 : 0; 98 break; 99 case VIRTGPU_PARAM_CAPSET_QUERY_FIX: 100 value = 1; 101 break; 102 case VIRTGPU_PARAM_RESOURCE_BLOB: 103 value = vgdev->has_resource_blob ? 1 : 0; 104 break; 105 case VIRTGPU_PARAM_HOST_VISIBLE: 106 value = vgdev->has_host_visible ? 1 : 0; 107 break; 108 case VIRTGPU_PARAM_CROSS_DEVICE: 109 value = vgdev->has_resource_assign_uuid ? 1 : 0; 110 break; 111 case VIRTGPU_PARAM_CONTEXT_INIT: 112 value = vgdev->has_context_init ? 1 : 0; 113 break; 114 case VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs: 115 value = vgdev->capset_id_mask; 116 break; 117 case VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME: 118 value = vgdev->has_context_init ? 1 : 0; 119 break; 120 case VIRTGPU_PARAM_BLOB_ALIGNMENT: 121 if (!vgdev->has_blob_alignment) 122 return -ENOENT; 123 value = vgdev->blob_alignment; 124 break; 125 default: 126 return -EINVAL; 127 } 128 if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int))) 129 return -EFAULT; 130 131 return 0; 132 } 133 134 static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, 135 struct drm_file *file) 136 { 137 struct virtio_gpu_device *vgdev = dev->dev_private; 138 struct drm_virtgpu_resource_create *rc = data; 139 struct virtio_gpu_fence *fence; 140 int ret; 141 struct virtio_gpu_object *qobj; 142 struct drm_gem_object *obj; 143 uint32_t handle = 0; 144 struct virtio_gpu_object_params params = { 0 }; 145 146 if (vgdev->has_virgl_3d) { 147 virtio_gpu_create_context(dev, file); 148 params.virgl = true; 149 params.target = rc->target; 150 params.bind = rc->bind; 151 params.depth = rc->depth; 152 params.array_size = rc->array_size; 153 params.last_level = rc->last_level; 154 params.nr_samples = rc->nr_samples; 155 params.flags = rc->flags; 156 } else { 157 if (rc->depth > 1) 158 return -EINVAL; 159 if (rc->nr_samples > 1) 160 return -EINVAL; 161 if (rc->last_level > 1) 162 return -EINVAL; 163 if (rc->target != 2) 164 return -EINVAL; 165 if (rc->array_size > 1) 166 return -EINVAL; 167 } 168 169 params.format = rc->format; 170 params.width = rc->width; 171 params.height = rc->height; 172 params.size = rc->size; 173 /* allocate a single page size object */ 174 if (params.size == 0) 175 params.size = PAGE_SIZE; 176 177 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0); 178 if (!fence) 179 return -ENOMEM; 180 ret = virtio_gpu_object_create(vgdev, ¶ms, &qobj, fence); 181 dma_fence_put(&fence->f); 182 if (ret < 0) 183 return ret; 184 obj = &qobj->base.base; 185 186 ret = drm_gem_handle_create(file, obj, &handle); 187 if (ret) { 188 drm_gem_object_put(obj); 189 return ret; 190 } 191 192 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */ 193 rc->bo_handle = handle; 194 195 /* 196 * The handle owns the reference now. But we must drop our 197 * remaining reference *after* we no longer need to dereference 198 * the obj. Otherwise userspace could guess the handle and 199 * race closing it from another thread. 200 */ 201 drm_gem_object_put(obj); 202 203 return 0; 204 } 205 206 static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data, 207 struct drm_file *file) 208 { 209 struct drm_virtgpu_resource_info *ri = data; 210 struct drm_gem_object *gobj = NULL; 211 struct virtio_gpu_object *qobj = NULL; 212 213 gobj = drm_gem_object_lookup(file, ri->bo_handle); 214 if (gobj == NULL) 215 return -ENOENT; 216 217 qobj = gem_to_virtio_gpu_obj(gobj); 218 219 ri->size = qobj->base.base.size; 220 ri->res_handle = qobj->hw_res_handle; 221 if (qobj->host3d_blob || qobj->guest_blob) 222 ri->blob_mem = qobj->blob_mem; 223 224 drm_gem_object_put(gobj); 225 return 0; 226 } 227 228 static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, 229 void *data, 230 struct drm_file *file) 231 { 232 struct virtio_gpu_device *vgdev = dev->dev_private; 233 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 234 struct drm_virtgpu_3d_transfer_from_host *args = data; 235 struct virtio_gpu_object *bo; 236 struct virtio_gpu_object_array *objs; 237 struct virtio_gpu_fence *fence; 238 int ret; 239 u32 offset = args->offset; 240 241 if (vgdev->has_virgl_3d == false) 242 return -ENOSYS; 243 244 virtio_gpu_create_context(dev, file); 245 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); 246 if (objs == NULL) 247 return -ENOENT; 248 249 bo = gem_to_virtio_gpu_obj(objs->objs[0]); 250 if (bo->guest_blob && !bo->host3d_blob) { 251 ret = -EINVAL; 252 goto err_put_free; 253 } 254 255 if (!bo->host3d_blob && (args->stride || args->layer_stride)) { 256 ret = -EINVAL; 257 goto err_put_free; 258 } 259 260 ret = virtio_gpu_array_lock_resv(objs); 261 if (ret != 0) 262 goto err_put_free; 263 264 if (virtio_gpu_is_shmem(bo) && virtio_gpu_use_dma_api(vgdev->vdev)) { 265 /* 266 * The sync on completion restores the whole mapping, so an 267 * earlier transfer has to be done before this one snapshots it. 268 * Otherwise the snapshot predates anything the CPU wrote once 269 * that transfer's fence signalled, and the later sync would 270 * discard it. Nothing can add a fence behind our back here, 271 * since doing so takes the reservation we already hold. 272 * This writes the pages, so it waits as a writer does. READ 273 * usage covers existing readers. 274 */ 275 long wait = dma_resv_wait_timeout(objs->objs[0]->resv, 276 DMA_RESV_USAGE_READ, true, 277 MAX_SCHEDULE_TIMEOUT); 278 279 if (wait < 0) { 280 ret = wait; 281 goto err_unlock; 282 } 283 } 284 285 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0); 286 if (!fence) { 287 ret = -ENOMEM; 288 goto err_unlock; 289 } 290 291 virtio_gpu_cmd_transfer_from_host_3d 292 (vgdev, vfpriv->ctx_id, offset, args->level, args->stride, 293 args->layer_stride, &args->box, objs, fence); 294 dma_fence_put(&fence->f); 295 virtio_gpu_notify(vgdev); 296 return 0; 297 298 err_unlock: 299 virtio_gpu_array_unlock_resv(objs); 300 err_put_free: 301 virtio_gpu_array_put_free(objs); 302 return ret; 303 } 304 305 static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, 306 struct drm_file *file) 307 { 308 struct virtio_gpu_device *vgdev = dev->dev_private; 309 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 310 struct drm_virtgpu_3d_transfer_to_host *args = data; 311 struct virtio_gpu_object *bo; 312 struct virtio_gpu_object_array *objs; 313 struct virtio_gpu_fence *fence; 314 int ret; 315 u32 offset = args->offset; 316 317 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); 318 if (objs == NULL) 319 return -ENOENT; 320 321 bo = gem_to_virtio_gpu_obj(objs->objs[0]); 322 if (bo->guest_blob && !bo->host3d_blob) { 323 ret = -EINVAL; 324 goto err_put_free; 325 } 326 327 if (!vgdev->has_virgl_3d) { 328 virtio_gpu_cmd_transfer_to_host_2d 329 (vgdev, offset, 330 args->box.w, args->box.h, args->box.x, args->box.y, 331 objs, NULL); 332 } else { 333 virtio_gpu_create_context(dev, file); 334 335 if (!bo->host3d_blob && (args->stride || args->layer_stride)) { 336 ret = -EINVAL; 337 goto err_put_free; 338 } 339 340 ret = virtio_gpu_array_lock_resv(objs); 341 if (ret != 0) 342 goto err_put_free; 343 344 /* 345 * A transfer the other way may have queued without yet syncing 346 * its mapping. Pushing the guest pages into it now would 347 * discard what the device wrote there, so wait for that sync: 348 * it runs before the fence it belongs to is signalled. The 349 * flag is only set under this reservation, so it cannot appear 350 * behind our back, and the acquire pairs with the release in 351 * that sync, so finding it clear means the pages it wrote are 352 * visible here too. 353 */ 354 if (smp_load_acquire(&bo->from_host_pending)) { 355 long wait = dma_resv_wait_timeout(objs->objs[0]->resv, 356 DMA_RESV_USAGE_WRITE, 357 true, 358 MAX_SCHEDULE_TIMEOUT); 359 360 if (wait < 0) { 361 ret = wait; 362 goto err_unlock; 363 } 364 } 365 366 ret = -ENOMEM; 367 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 368 0); 369 if (!fence) 370 goto err_unlock; 371 372 virtio_gpu_cmd_transfer_to_host_3d 373 (vgdev, 374 vfpriv ? vfpriv->ctx_id : 0, offset, args->level, 375 args->stride, args->layer_stride, &args->box, objs, 376 fence); 377 dma_fence_put(&fence->f); 378 } 379 virtio_gpu_notify(vgdev); 380 return 0; 381 382 err_unlock: 383 virtio_gpu_array_unlock_resv(objs); 384 err_put_free: 385 virtio_gpu_array_put_free(objs); 386 return ret; 387 } 388 389 static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data, 390 struct drm_file *file) 391 { 392 struct drm_virtgpu_3d_wait *args = data; 393 struct drm_gem_object *obj; 394 long timeout = 15 * HZ; 395 int ret; 396 397 obj = drm_gem_object_lookup(file, args->handle); 398 if (obj == NULL) 399 return -ENOENT; 400 401 if (args->flags & VIRTGPU_WAIT_NOWAIT) { 402 ret = dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ); 403 } else { 404 ret = dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ, 405 true, timeout); 406 } 407 if (ret == 0) 408 ret = -EBUSY; 409 else if (ret > 0) 410 ret = 0; 411 412 drm_gem_object_put(obj); 413 return ret; 414 } 415 416 static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, 417 void *data, struct drm_file *file) 418 { 419 struct virtio_gpu_device *vgdev = dev->dev_private; 420 struct drm_virtgpu_get_caps *args = data; 421 unsigned size, host_caps_size; 422 int i; 423 int found_valid = -1; 424 int ret; 425 struct virtio_gpu_drv_cap_cache *cache_ent; 426 void *ptr; 427 428 if (vgdev->num_capsets == 0) 429 return -ENOSYS; 430 431 /* don't allow userspace to pass 0 */ 432 if (args->size == 0) 433 return -EINVAL; 434 435 spin_lock(&vgdev->display_info_lock); 436 for (i = 0; i < vgdev->num_capsets; i++) { 437 if (vgdev->capsets[i].id == args->cap_set_id) { 438 if (vgdev->capsets[i].max_version >= args->cap_set_ver) { 439 found_valid = i; 440 break; 441 } 442 } 443 } 444 445 if (found_valid == -1) { 446 spin_unlock(&vgdev->display_info_lock); 447 return -EINVAL; 448 } 449 450 host_caps_size = vgdev->capsets[found_valid].max_size; 451 /* only copy to user the minimum of the host caps size or the guest caps size */ 452 size = min(args->size, host_caps_size); 453 454 list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { 455 if (cache_ent->id == args->cap_set_id && 456 cache_ent->version == args->cap_set_ver) { 457 spin_unlock(&vgdev->display_info_lock); 458 goto copy_exit; 459 } 460 } 461 spin_unlock(&vgdev->display_info_lock); 462 463 /* not in cache - need to talk to hw */ 464 ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, 465 &cache_ent); 466 if (ret) 467 return ret; 468 virtio_gpu_notify(vgdev); 469 470 copy_exit: 471 ret = wait_event_timeout(vgdev->resp_wq, 472 atomic_read(&cache_ent->is_valid), 5 * HZ); 473 if (!ret) 474 return -EBUSY; 475 476 /* is_valid check must proceed before copy of the cache entry. */ 477 smp_rmb(); 478 479 ptr = cache_ent->caps_cache; 480 481 if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size)) 482 return -EFAULT; 483 484 return 0; 485 } 486 487 static int verify_blob(struct virtio_gpu_device *vgdev, 488 struct virtio_gpu_fpriv *vfpriv, 489 struct virtio_gpu_object_params *params, 490 struct drm_virtgpu_resource_create_blob *rc_blob, 491 bool *guest_blob, bool *host3d_blob) 492 { 493 if (!vgdev->has_resource_blob) 494 return -EINVAL; 495 496 if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK) 497 return -EINVAL; 498 499 if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { 500 if (!vgdev->has_resource_assign_uuid) 501 return -EINVAL; 502 } 503 504 switch (rc_blob->blob_mem) { 505 case VIRTGPU_BLOB_MEM_GUEST: 506 *guest_blob = true; 507 break; 508 case VIRTGPU_BLOB_MEM_HOST3D_GUEST: 509 *guest_blob = true; 510 fallthrough; 511 case VIRTGPU_BLOB_MEM_HOST3D: 512 *host3d_blob = true; 513 break; 514 default: 515 return -EINVAL; 516 } 517 518 if (*host3d_blob) { 519 if (!vgdev->has_virgl_3d) 520 return -EINVAL; 521 522 /* Must be dword aligned. */ 523 if (rc_blob->cmd_size % 4 != 0) 524 return -EINVAL; 525 526 params->ctx_id = vfpriv->ctx_id; 527 params->blob_id = rc_blob->blob_id; 528 } else { 529 if (rc_blob->blob_id != 0) 530 return -EINVAL; 531 532 if (rc_blob->cmd_size != 0) 533 return -EINVAL; 534 } 535 536 params->blob_mem = rc_blob->blob_mem; 537 params->size = rc_blob->size; 538 params->blob = true; 539 params->blob_flags = rc_blob->blob_flags; 540 params->blob_hints = rc_blob->blob_hints; 541 542 if (vgdev->has_blob_alignment && 543 !IS_ALIGNED(params->size, vgdev->blob_alignment)) 544 return -EINVAL; 545 546 return 0; 547 } 548 549 static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, 550 void *data, 551 struct drm_file *file) 552 { 553 int ret = 0; 554 uint32_t handle = 0; 555 bool guest_blob = false; 556 bool host3d_blob = false; 557 struct drm_gem_object *obj; 558 struct virtio_gpu_object *bo; 559 struct virtio_gpu_object_params params = { 0 }; 560 struct virtio_gpu_device *vgdev = dev->dev_private; 561 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 562 struct drm_virtgpu_resource_create_blob *rc_blob = data; 563 564 if (verify_blob(vgdev, vfpriv, ¶ms, rc_blob, 565 &guest_blob, &host3d_blob)) 566 return -EINVAL; 567 568 if (vgdev->has_virgl_3d) 569 virtio_gpu_create_context(dev, file); 570 571 if (rc_blob->cmd_size) { 572 void *buf; 573 574 buf = memdup_user(u64_to_user_ptr(rc_blob->cmd), 575 rc_blob->cmd_size); 576 577 if (IS_ERR(buf)) 578 return PTR_ERR(buf); 579 580 virtio_gpu_cmd_submit(vgdev, buf, rc_blob->cmd_size, 581 vfpriv->ctx_id, NULL, NULL); 582 } 583 584 if (guest_blob) 585 ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL); 586 else if (!guest_blob && host3d_blob) 587 ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo); 588 else 589 return -EINVAL; 590 591 if (ret < 0) 592 return ret; 593 594 bo->guest_blob = guest_blob; 595 bo->host3d_blob = host3d_blob; 596 bo->blob_mem = rc_blob->blob_mem; 597 bo->blob_flags = rc_blob->blob_flags; 598 599 obj = &bo->base.base; 600 if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { 601 ret = virtio_gpu_resource_assign_uuid(vgdev, bo); 602 if (ret) { 603 drm_gem_object_put(obj); 604 return ret; 605 } 606 } 607 608 ret = drm_gem_handle_create(file, obj, &handle); 609 if (ret) { 610 drm_gem_object_put(obj); 611 return ret; 612 } 613 614 rc_blob->res_handle = bo->hw_res_handle; 615 rc_blob->bo_handle = handle; 616 617 /* 618 * The handle owns the reference now. But we must drop our 619 * remaining reference *after* we no longer need to dereference 620 * the obj. Otherwise userspace could guess the handle and 621 * race closing it from another thread. 622 */ 623 drm_gem_object_put(obj); 624 625 return 0; 626 } 627 628 static int virtio_gpu_context_init_ioctl(struct drm_device *dev, 629 void *data, struct drm_file *file) 630 { 631 int ret = 0; 632 uint32_t num_params, i; 633 uint64_t valid_ring_mask, param, value; 634 size_t len; 635 struct drm_virtgpu_context_set_param *ctx_set_params = NULL; 636 struct virtio_gpu_device *vgdev = dev->dev_private; 637 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 638 struct drm_virtgpu_context_init *args = data; 639 640 num_params = args->num_params; 641 len = num_params * sizeof(struct drm_virtgpu_context_set_param); 642 643 if (!vgdev->has_context_init || !vgdev->has_virgl_3d) 644 return -EINVAL; 645 646 /* Number of unique parameters supported at this time. */ 647 if (num_params > 4) 648 return -EINVAL; 649 650 ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params), 651 len); 652 653 if (IS_ERR(ctx_set_params)) 654 return PTR_ERR(ctx_set_params); 655 656 mutex_lock(&vfpriv->context_lock); 657 if (vfpriv->context_created) { 658 ret = -EEXIST; 659 goto out_unlock; 660 } 661 662 for (i = 0; i < num_params; i++) { 663 param = ctx_set_params[i].param; 664 value = ctx_set_params[i].value; 665 666 switch (param) { 667 case VIRTGPU_CONTEXT_PARAM_CAPSET_ID: 668 if (value > MAX_CAPSET_ID) { 669 ret = -EINVAL; 670 goto out_unlock; 671 } 672 673 if ((vgdev->capset_id_mask & (1ULL << value)) == 0) { 674 ret = -EINVAL; 675 goto out_unlock; 676 } 677 678 /* Context capset ID already set */ 679 if (vfpriv->context_init & 680 VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) { 681 ret = -EINVAL; 682 goto out_unlock; 683 } 684 685 vfpriv->context_init |= value; 686 break; 687 case VIRTGPU_CONTEXT_PARAM_NUM_RINGS: 688 if (vfpriv->base_fence_ctx) { 689 ret = -EINVAL; 690 goto out_unlock; 691 } 692 693 if (value > MAX_RINGS) { 694 ret = -EINVAL; 695 goto out_unlock; 696 } 697 698 vfpriv->base_fence_ctx = dma_fence_context_alloc(value); 699 vfpriv->num_rings = value; 700 break; 701 case VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK: 702 if (vfpriv->ring_idx_mask) { 703 ret = -EINVAL; 704 goto out_unlock; 705 } 706 707 vfpriv->ring_idx_mask = value; 708 break; 709 case VIRTGPU_CONTEXT_PARAM_DEBUG_NAME: 710 if (vfpriv->explicit_debug_name) { 711 ret = -EINVAL; 712 goto out_unlock; 713 } 714 715 ret = strncpy_from_user(vfpriv->debug_name, 716 u64_to_user_ptr(value), 717 DEBUG_NAME_MAX_LEN - 1); 718 if (ret < 0) 719 goto out_unlock; 720 721 vfpriv->explicit_debug_name = true; 722 ret = 0; 723 break; 724 default: 725 ret = -EINVAL; 726 goto out_unlock; 727 } 728 } 729 730 if (vfpriv->ring_idx_mask) { 731 valid_ring_mask = 0; 732 for (i = 0; i < vfpriv->num_rings; i++) 733 valid_ring_mask |= 1ULL << i; 734 735 if (~valid_ring_mask & vfpriv->ring_idx_mask) { 736 ret = -EINVAL; 737 goto out_unlock; 738 } 739 } 740 741 virtio_gpu_create_context_locked(vgdev, vfpriv); 742 virtio_gpu_notify(vgdev); 743 744 out_unlock: 745 mutex_unlock(&vfpriv->context_lock); 746 kfree(ctx_set_params); 747 return ret; 748 } 749 750 struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { 751 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, 752 DRM_RENDER_ALLOW), 753 754 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, 755 DRM_RENDER_ALLOW), 756 757 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, 758 DRM_RENDER_ALLOW), 759 760 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, 761 virtio_gpu_resource_create_ioctl, 762 DRM_RENDER_ALLOW), 763 764 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, 765 DRM_RENDER_ALLOW), 766 767 /* make transfer async to the main ring? - no sure, can we 768 * thread these in the underlying GL 769 */ 770 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, 771 virtio_gpu_transfer_from_host_ioctl, 772 DRM_RENDER_ALLOW), 773 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, 774 virtio_gpu_transfer_to_host_ioctl, 775 DRM_RENDER_ALLOW), 776 777 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, 778 DRM_RENDER_ALLOW), 779 780 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, 781 DRM_RENDER_ALLOW), 782 783 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB, 784 virtio_gpu_resource_create_blob_ioctl, 785 DRM_RENDER_ALLOW), 786 787 DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl, 788 DRM_RENDER_ALLOW), 789 }; 790