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 static int virtio_gpu_fence_event_create(struct drm_device *dev, 42 struct drm_file *file, 43 struct virtio_gpu_fence *fence, 44 uint32_t ring_idx) 45 { 46 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 47 struct virtio_gpu_fence_event *e = NULL; 48 int ret; 49 50 if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx))) 51 return 0; 52 53 e = kzalloc(sizeof(*e), GFP_KERNEL); 54 if (!e) 55 return -ENOMEM; 56 57 e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED; 58 e->event.length = sizeof(e->event); 59 60 ret = drm_event_reserve_init(dev, file, &e->base, &e->event); 61 if (ret) 62 goto free; 63 64 fence->e = e; 65 return 0; 66 free: 67 kfree(e); 68 return ret; 69 } 70 71 /* Must be called with &virtio_gpu_fpriv.struct_mutex held. */ 72 static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev, 73 struct virtio_gpu_fpriv *vfpriv) 74 { 75 char dbgname[TASK_COMM_LEN]; 76 77 get_task_comm(dbgname, current); 78 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, 79 vfpriv->context_init, strlen(dbgname), 80 dbgname); 81 82 vfpriv->context_created = true; 83 } 84 85 void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file) 86 { 87 struct virtio_gpu_device *vgdev = dev->dev_private; 88 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 89 90 mutex_lock(&vfpriv->context_lock); 91 if (vfpriv->context_created) 92 goto out_unlock; 93 94 virtio_gpu_create_context_locked(vgdev, vfpriv); 95 96 out_unlock: 97 mutex_unlock(&vfpriv->context_lock); 98 } 99 100 static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data, 101 struct drm_file *file) 102 { 103 struct virtio_gpu_device *vgdev = dev->dev_private; 104 struct drm_virtgpu_map *virtio_gpu_map = data; 105 106 return virtio_gpu_mode_dumb_mmap(file, vgdev->ddev, 107 virtio_gpu_map->handle, 108 &virtio_gpu_map->offset); 109 } 110 111 /* 112 * Usage of execbuffer: 113 * Relocations need to take into account the full VIRTIO_GPUDrawable size. 114 * However, the command as passed from user space must *not* contain the initial 115 * VIRTIO_GPUReleaseInfo struct (first XXX bytes) 116 */ 117 static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, 118 struct drm_file *file) 119 { 120 struct drm_virtgpu_execbuffer *exbuf = data; 121 struct virtio_gpu_device *vgdev = dev->dev_private; 122 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 123 struct virtio_gpu_fence *out_fence; 124 int ret; 125 uint32_t *bo_handles = NULL; 126 void __user *user_bo_handles = NULL; 127 struct virtio_gpu_object_array *buflist = NULL; 128 struct sync_file *sync_file; 129 int in_fence_fd = exbuf->fence_fd; 130 int out_fence_fd = -1; 131 void *buf; 132 uint64_t fence_ctx; 133 uint32_t ring_idx; 134 135 fence_ctx = vgdev->fence_drv.context; 136 ring_idx = 0; 137 138 if (vgdev->has_virgl_3d == false) 139 return -ENOSYS; 140 141 if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS)) 142 return -EINVAL; 143 144 if ((exbuf->flags & VIRTGPU_EXECBUF_RING_IDX)) { 145 if (exbuf->ring_idx >= vfpriv->num_rings) 146 return -EINVAL; 147 148 if (!vfpriv->base_fence_ctx) 149 return -EINVAL; 150 151 fence_ctx = vfpriv->base_fence_ctx; 152 ring_idx = exbuf->ring_idx; 153 } 154 155 exbuf->fence_fd = -1; 156 157 virtio_gpu_create_context(dev, file); 158 if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) { 159 struct dma_fence *in_fence; 160 161 in_fence = sync_file_get_fence(in_fence_fd); 162 163 if (!in_fence) 164 return -EINVAL; 165 166 /* 167 * Wait if the fence is from a foreign context, or if the fence 168 * array contains any fence from a foreign context. 169 */ 170 ret = 0; 171 if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx)) 172 ret = dma_fence_wait(in_fence, true); 173 174 dma_fence_put(in_fence); 175 if (ret) 176 return ret; 177 } 178 179 if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) { 180 out_fence_fd = get_unused_fd_flags(O_CLOEXEC); 181 if (out_fence_fd < 0) 182 return out_fence_fd; 183 } 184 185 if (exbuf->num_bo_handles) { 186 bo_handles = kvmalloc_array(exbuf->num_bo_handles, 187 sizeof(uint32_t), GFP_KERNEL); 188 if (!bo_handles) { 189 ret = -ENOMEM; 190 goto out_unused_fd; 191 } 192 193 user_bo_handles = u64_to_user_ptr(exbuf->bo_handles); 194 if (copy_from_user(bo_handles, user_bo_handles, 195 exbuf->num_bo_handles * sizeof(uint32_t))) { 196 ret = -EFAULT; 197 goto out_unused_fd; 198 } 199 200 buflist = virtio_gpu_array_from_handles(file, bo_handles, 201 exbuf->num_bo_handles); 202 if (!buflist) { 203 ret = -ENOENT; 204 goto out_unused_fd; 205 } 206 kvfree(bo_handles); 207 bo_handles = NULL; 208 } 209 210 buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size); 211 if (IS_ERR(buf)) { 212 ret = PTR_ERR(buf); 213 goto out_unused_fd; 214 } 215 216 if (buflist) { 217 ret = virtio_gpu_array_lock_resv(buflist); 218 if (ret) 219 goto out_memdup; 220 } 221 222 out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx); 223 if(!out_fence) { 224 ret = -ENOMEM; 225 goto out_unresv; 226 } 227 228 ret = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx); 229 if (ret) 230 goto out_unresv; 231 232 if (out_fence_fd >= 0) { 233 sync_file = sync_file_create(&out_fence->f); 234 if (!sync_file) { 235 dma_fence_put(&out_fence->f); 236 ret = -ENOMEM; 237 goto out_unresv; 238 } 239 240 exbuf->fence_fd = out_fence_fd; 241 fd_install(out_fence_fd, sync_file->file); 242 } 243 244 virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, 245 vfpriv->ctx_id, buflist, out_fence); 246 dma_fence_put(&out_fence->f); 247 virtio_gpu_notify(vgdev); 248 return 0; 249 250 out_unresv: 251 if (buflist) 252 virtio_gpu_array_unlock_resv(buflist); 253 out_memdup: 254 kvfree(buf); 255 out_unused_fd: 256 kvfree(bo_handles); 257 if (buflist) 258 virtio_gpu_array_put_free(buflist); 259 260 if (out_fence_fd >= 0) 261 put_unused_fd(out_fence_fd); 262 263 return ret; 264 } 265 266 static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, 267 struct drm_file *file) 268 { 269 struct virtio_gpu_device *vgdev = dev->dev_private; 270 struct drm_virtgpu_getparam *param = data; 271 int value; 272 273 switch (param->param) { 274 case VIRTGPU_PARAM_3D_FEATURES: 275 value = vgdev->has_virgl_3d ? 1 : 0; 276 break; 277 case VIRTGPU_PARAM_CAPSET_QUERY_FIX: 278 value = 1; 279 break; 280 case VIRTGPU_PARAM_RESOURCE_BLOB: 281 value = vgdev->has_resource_blob ? 1 : 0; 282 break; 283 case VIRTGPU_PARAM_HOST_VISIBLE: 284 value = vgdev->has_host_visible ? 1 : 0; 285 break; 286 case VIRTGPU_PARAM_CROSS_DEVICE: 287 value = vgdev->has_resource_assign_uuid ? 1 : 0; 288 break; 289 case VIRTGPU_PARAM_CONTEXT_INIT: 290 value = vgdev->has_context_init ? 1 : 0; 291 break; 292 case VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs: 293 value = vgdev->capset_id_mask; 294 break; 295 default: 296 return -EINVAL; 297 } 298 if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int))) 299 return -EFAULT; 300 301 return 0; 302 } 303 304 static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, 305 struct drm_file *file) 306 { 307 struct virtio_gpu_device *vgdev = dev->dev_private; 308 struct drm_virtgpu_resource_create *rc = data; 309 struct virtio_gpu_fence *fence; 310 int ret; 311 struct virtio_gpu_object *qobj; 312 struct drm_gem_object *obj; 313 uint32_t handle = 0; 314 struct virtio_gpu_object_params params = { 0 }; 315 316 if (vgdev->has_virgl_3d) { 317 virtio_gpu_create_context(dev, file); 318 params.virgl = true; 319 params.target = rc->target; 320 params.bind = rc->bind; 321 params.depth = rc->depth; 322 params.array_size = rc->array_size; 323 params.last_level = rc->last_level; 324 params.nr_samples = rc->nr_samples; 325 params.flags = rc->flags; 326 } else { 327 if (rc->depth > 1) 328 return -EINVAL; 329 if (rc->nr_samples > 1) 330 return -EINVAL; 331 if (rc->last_level > 1) 332 return -EINVAL; 333 if (rc->target != 2) 334 return -EINVAL; 335 if (rc->array_size > 1) 336 return -EINVAL; 337 } 338 339 params.format = rc->format; 340 params.width = rc->width; 341 params.height = rc->height; 342 params.size = rc->size; 343 /* allocate a single page size object */ 344 if (params.size == 0) 345 params.size = PAGE_SIZE; 346 347 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0); 348 if (!fence) 349 return -ENOMEM; 350 ret = virtio_gpu_object_create(vgdev, ¶ms, &qobj, fence); 351 dma_fence_put(&fence->f); 352 if (ret < 0) 353 return ret; 354 obj = &qobj->base.base; 355 356 ret = drm_gem_handle_create(file, obj, &handle); 357 if (ret) { 358 drm_gem_object_release(obj); 359 return ret; 360 } 361 362 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */ 363 rc->bo_handle = handle; 364 365 /* 366 * The handle owns the reference now. But we must drop our 367 * remaining reference *after* we no longer need to dereference 368 * the obj. Otherwise userspace could guess the handle and 369 * race closing it from another thread. 370 */ 371 drm_gem_object_put(obj); 372 373 return 0; 374 } 375 376 static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data, 377 struct drm_file *file) 378 { 379 struct drm_virtgpu_resource_info *ri = data; 380 struct drm_gem_object *gobj = NULL; 381 struct virtio_gpu_object *qobj = NULL; 382 383 gobj = drm_gem_object_lookup(file, ri->bo_handle); 384 if (gobj == NULL) 385 return -ENOENT; 386 387 qobj = gem_to_virtio_gpu_obj(gobj); 388 389 ri->size = qobj->base.base.size; 390 ri->res_handle = qobj->hw_res_handle; 391 if (qobj->host3d_blob || qobj->guest_blob) 392 ri->blob_mem = qobj->blob_mem; 393 394 drm_gem_object_put(gobj); 395 return 0; 396 } 397 398 static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, 399 void *data, 400 struct drm_file *file) 401 { 402 struct virtio_gpu_device *vgdev = dev->dev_private; 403 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 404 struct drm_virtgpu_3d_transfer_from_host *args = data; 405 struct virtio_gpu_object *bo; 406 struct virtio_gpu_object_array *objs; 407 struct virtio_gpu_fence *fence; 408 int ret; 409 u32 offset = args->offset; 410 411 if (vgdev->has_virgl_3d == false) 412 return -ENOSYS; 413 414 virtio_gpu_create_context(dev, file); 415 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); 416 if (objs == NULL) 417 return -ENOENT; 418 419 bo = gem_to_virtio_gpu_obj(objs->objs[0]); 420 if (bo->guest_blob && !bo->host3d_blob) { 421 ret = -EINVAL; 422 goto err_put_free; 423 } 424 425 if (!bo->host3d_blob && (args->stride || args->layer_stride)) { 426 ret = -EINVAL; 427 goto err_put_free; 428 } 429 430 ret = virtio_gpu_array_lock_resv(objs); 431 if (ret != 0) 432 goto err_put_free; 433 434 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0); 435 if (!fence) { 436 ret = -ENOMEM; 437 goto err_unlock; 438 } 439 440 virtio_gpu_cmd_transfer_from_host_3d 441 (vgdev, vfpriv->ctx_id, offset, args->level, args->stride, 442 args->layer_stride, &args->box, objs, fence); 443 dma_fence_put(&fence->f); 444 virtio_gpu_notify(vgdev); 445 return 0; 446 447 err_unlock: 448 virtio_gpu_array_unlock_resv(objs); 449 err_put_free: 450 virtio_gpu_array_put_free(objs); 451 return ret; 452 } 453 454 static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, 455 struct drm_file *file) 456 { 457 struct virtio_gpu_device *vgdev = dev->dev_private; 458 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 459 struct drm_virtgpu_3d_transfer_to_host *args = data; 460 struct virtio_gpu_object *bo; 461 struct virtio_gpu_object_array *objs; 462 struct virtio_gpu_fence *fence; 463 int ret; 464 u32 offset = args->offset; 465 466 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); 467 if (objs == NULL) 468 return -ENOENT; 469 470 bo = gem_to_virtio_gpu_obj(objs->objs[0]); 471 if (bo->guest_blob && !bo->host3d_blob) { 472 ret = -EINVAL; 473 goto err_put_free; 474 } 475 476 if (!vgdev->has_virgl_3d) { 477 virtio_gpu_cmd_transfer_to_host_2d 478 (vgdev, offset, 479 args->box.w, args->box.h, args->box.x, args->box.y, 480 objs, NULL); 481 } else { 482 virtio_gpu_create_context(dev, file); 483 484 if (!bo->host3d_blob && (args->stride || args->layer_stride)) { 485 ret = -EINVAL; 486 goto err_put_free; 487 } 488 489 ret = virtio_gpu_array_lock_resv(objs); 490 if (ret != 0) 491 goto err_put_free; 492 493 ret = -ENOMEM; 494 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 495 0); 496 if (!fence) 497 goto err_unlock; 498 499 virtio_gpu_cmd_transfer_to_host_3d 500 (vgdev, 501 vfpriv ? vfpriv->ctx_id : 0, offset, args->level, 502 args->stride, args->layer_stride, &args->box, objs, 503 fence); 504 dma_fence_put(&fence->f); 505 } 506 virtio_gpu_notify(vgdev); 507 return 0; 508 509 err_unlock: 510 virtio_gpu_array_unlock_resv(objs); 511 err_put_free: 512 virtio_gpu_array_put_free(objs); 513 return ret; 514 } 515 516 static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data, 517 struct drm_file *file) 518 { 519 struct drm_virtgpu_3d_wait *args = data; 520 struct drm_gem_object *obj; 521 long timeout = 15 * HZ; 522 int ret; 523 524 obj = drm_gem_object_lookup(file, args->handle); 525 if (obj == NULL) 526 return -ENOENT; 527 528 if (args->flags & VIRTGPU_WAIT_NOWAIT) { 529 ret = dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ); 530 } else { 531 ret = dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ, 532 true, timeout); 533 } 534 if (ret == 0) 535 ret = -EBUSY; 536 else if (ret > 0) 537 ret = 0; 538 539 drm_gem_object_put(obj); 540 return ret; 541 } 542 543 static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, 544 void *data, struct drm_file *file) 545 { 546 struct virtio_gpu_device *vgdev = dev->dev_private; 547 struct drm_virtgpu_get_caps *args = data; 548 unsigned size, host_caps_size; 549 int i; 550 int found_valid = -1; 551 int ret; 552 struct virtio_gpu_drv_cap_cache *cache_ent; 553 void *ptr; 554 555 if (vgdev->num_capsets == 0) 556 return -ENOSYS; 557 558 /* don't allow userspace to pass 0 */ 559 if (args->size == 0) 560 return -EINVAL; 561 562 spin_lock(&vgdev->display_info_lock); 563 for (i = 0; i < vgdev->num_capsets; i++) { 564 if (vgdev->capsets[i].id == args->cap_set_id) { 565 if (vgdev->capsets[i].max_version >= args->cap_set_ver) { 566 found_valid = i; 567 break; 568 } 569 } 570 } 571 572 if (found_valid == -1) { 573 spin_unlock(&vgdev->display_info_lock); 574 return -EINVAL; 575 } 576 577 host_caps_size = vgdev->capsets[found_valid].max_size; 578 /* only copy to user the minimum of the host caps size or the guest caps size */ 579 size = min(args->size, host_caps_size); 580 581 list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { 582 if (cache_ent->id == args->cap_set_id && 583 cache_ent->version == args->cap_set_ver) { 584 spin_unlock(&vgdev->display_info_lock); 585 goto copy_exit; 586 } 587 } 588 spin_unlock(&vgdev->display_info_lock); 589 590 /* not in cache - need to talk to hw */ 591 ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, 592 &cache_ent); 593 if (ret) 594 return ret; 595 virtio_gpu_notify(vgdev); 596 597 copy_exit: 598 ret = wait_event_timeout(vgdev->resp_wq, 599 atomic_read(&cache_ent->is_valid), 5 * HZ); 600 if (!ret) 601 return -EBUSY; 602 603 /* is_valid check must proceed before copy of the cache entry. */ 604 smp_rmb(); 605 606 ptr = cache_ent->caps_cache; 607 608 if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size)) 609 return -EFAULT; 610 611 return 0; 612 } 613 614 static int verify_blob(struct virtio_gpu_device *vgdev, 615 struct virtio_gpu_fpriv *vfpriv, 616 struct virtio_gpu_object_params *params, 617 struct drm_virtgpu_resource_create_blob *rc_blob, 618 bool *guest_blob, bool *host3d_blob) 619 { 620 if (!vgdev->has_resource_blob) 621 return -EINVAL; 622 623 if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK) 624 return -EINVAL; 625 626 if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { 627 if (!vgdev->has_resource_assign_uuid) 628 return -EINVAL; 629 } 630 631 switch (rc_blob->blob_mem) { 632 case VIRTGPU_BLOB_MEM_GUEST: 633 *guest_blob = true; 634 break; 635 case VIRTGPU_BLOB_MEM_HOST3D_GUEST: 636 *guest_blob = true; 637 fallthrough; 638 case VIRTGPU_BLOB_MEM_HOST3D: 639 *host3d_blob = true; 640 break; 641 default: 642 return -EINVAL; 643 } 644 645 if (*host3d_blob) { 646 if (!vgdev->has_virgl_3d) 647 return -EINVAL; 648 649 /* Must be dword aligned. */ 650 if (rc_blob->cmd_size % 4 != 0) 651 return -EINVAL; 652 653 params->ctx_id = vfpriv->ctx_id; 654 params->blob_id = rc_blob->blob_id; 655 } else { 656 if (rc_blob->blob_id != 0) 657 return -EINVAL; 658 659 if (rc_blob->cmd_size != 0) 660 return -EINVAL; 661 } 662 663 params->blob_mem = rc_blob->blob_mem; 664 params->size = rc_blob->size; 665 params->blob = true; 666 params->blob_flags = rc_blob->blob_flags; 667 return 0; 668 } 669 670 static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, 671 void *data, 672 struct drm_file *file) 673 { 674 int ret = 0; 675 uint32_t handle = 0; 676 bool guest_blob = false; 677 bool host3d_blob = false; 678 struct drm_gem_object *obj; 679 struct virtio_gpu_object *bo; 680 struct virtio_gpu_object_params params = { 0 }; 681 struct virtio_gpu_device *vgdev = dev->dev_private; 682 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 683 struct drm_virtgpu_resource_create_blob *rc_blob = data; 684 685 if (verify_blob(vgdev, vfpriv, ¶ms, rc_blob, 686 &guest_blob, &host3d_blob)) 687 return -EINVAL; 688 689 if (vgdev->has_virgl_3d) 690 virtio_gpu_create_context(dev, file); 691 692 if (rc_blob->cmd_size) { 693 void *buf; 694 695 buf = memdup_user(u64_to_user_ptr(rc_blob->cmd), 696 rc_blob->cmd_size); 697 698 if (IS_ERR(buf)) 699 return PTR_ERR(buf); 700 701 virtio_gpu_cmd_submit(vgdev, buf, rc_blob->cmd_size, 702 vfpriv->ctx_id, NULL, NULL); 703 } 704 705 if (guest_blob) 706 ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL); 707 else if (!guest_blob && host3d_blob) 708 ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo); 709 else 710 return -EINVAL; 711 712 if (ret < 0) 713 return ret; 714 715 bo->guest_blob = guest_blob; 716 bo->host3d_blob = host3d_blob; 717 bo->blob_mem = rc_blob->blob_mem; 718 bo->blob_flags = rc_blob->blob_flags; 719 720 obj = &bo->base.base; 721 if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { 722 ret = virtio_gpu_resource_assign_uuid(vgdev, bo); 723 if (ret) { 724 drm_gem_object_release(obj); 725 return ret; 726 } 727 } 728 729 ret = drm_gem_handle_create(file, obj, &handle); 730 if (ret) { 731 drm_gem_object_release(obj); 732 return ret; 733 } 734 735 rc_blob->res_handle = bo->hw_res_handle; 736 rc_blob->bo_handle = handle; 737 738 /* 739 * The handle owns the reference now. But we must drop our 740 * remaining reference *after* we no longer need to dereference 741 * the obj. Otherwise userspace could guess the handle and 742 * race closing it from another thread. 743 */ 744 drm_gem_object_put(obj); 745 746 return 0; 747 } 748 749 static int virtio_gpu_context_init_ioctl(struct drm_device *dev, 750 void *data, struct drm_file *file) 751 { 752 int ret = 0; 753 uint32_t num_params, i, param, value; 754 uint64_t valid_ring_mask; 755 size_t len; 756 struct drm_virtgpu_context_set_param *ctx_set_params = NULL; 757 struct virtio_gpu_device *vgdev = dev->dev_private; 758 struct virtio_gpu_fpriv *vfpriv = file->driver_priv; 759 struct drm_virtgpu_context_init *args = data; 760 761 num_params = args->num_params; 762 len = num_params * sizeof(struct drm_virtgpu_context_set_param); 763 764 if (!vgdev->has_context_init || !vgdev->has_virgl_3d) 765 return -EINVAL; 766 767 /* Number of unique parameters supported at this time. */ 768 if (num_params > 3) 769 return -EINVAL; 770 771 ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params), 772 len); 773 774 if (IS_ERR(ctx_set_params)) 775 return PTR_ERR(ctx_set_params); 776 777 mutex_lock(&vfpriv->context_lock); 778 if (vfpriv->context_created) { 779 ret = -EEXIST; 780 goto out_unlock; 781 } 782 783 for (i = 0; i < num_params; i++) { 784 param = ctx_set_params[i].param; 785 value = ctx_set_params[i].value; 786 787 switch (param) { 788 case VIRTGPU_CONTEXT_PARAM_CAPSET_ID: 789 if (value > MAX_CAPSET_ID) { 790 ret = -EINVAL; 791 goto out_unlock; 792 } 793 794 if ((vgdev->capset_id_mask & (1ULL << value)) == 0) { 795 ret = -EINVAL; 796 goto out_unlock; 797 } 798 799 /* Context capset ID already set */ 800 if (vfpriv->context_init & 801 VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) { 802 ret = -EINVAL; 803 goto out_unlock; 804 } 805 806 vfpriv->context_init |= value; 807 break; 808 case VIRTGPU_CONTEXT_PARAM_NUM_RINGS: 809 if (vfpriv->base_fence_ctx) { 810 ret = -EINVAL; 811 goto out_unlock; 812 } 813 814 if (value > MAX_RINGS) { 815 ret = -EINVAL; 816 goto out_unlock; 817 } 818 819 vfpriv->base_fence_ctx = dma_fence_context_alloc(value); 820 vfpriv->num_rings = value; 821 break; 822 case VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK: 823 if (vfpriv->ring_idx_mask) { 824 ret = -EINVAL; 825 goto out_unlock; 826 } 827 828 vfpriv->ring_idx_mask = value; 829 break; 830 default: 831 ret = -EINVAL; 832 goto out_unlock; 833 } 834 } 835 836 if (vfpriv->ring_idx_mask) { 837 valid_ring_mask = 0; 838 for (i = 0; i < vfpriv->num_rings; i++) 839 valid_ring_mask |= 1ULL << i; 840 841 if (~valid_ring_mask & vfpriv->ring_idx_mask) { 842 ret = -EINVAL; 843 goto out_unlock; 844 } 845 } 846 847 virtio_gpu_create_context_locked(vgdev, vfpriv); 848 virtio_gpu_notify(vgdev); 849 850 out_unlock: 851 mutex_unlock(&vfpriv->context_lock); 852 kfree(ctx_set_params); 853 return ret; 854 } 855 856 struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { 857 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, 858 DRM_RENDER_ALLOW), 859 860 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, 861 DRM_RENDER_ALLOW), 862 863 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, 864 DRM_RENDER_ALLOW), 865 866 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, 867 virtio_gpu_resource_create_ioctl, 868 DRM_RENDER_ALLOW), 869 870 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, 871 DRM_RENDER_ALLOW), 872 873 /* make transfer async to the main ring? - no sure, can we 874 * thread these in the underlying GL 875 */ 876 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, 877 virtio_gpu_transfer_from_host_ioctl, 878 DRM_RENDER_ALLOW), 879 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, 880 virtio_gpu_transfer_to_host_ioctl, 881 DRM_RENDER_ALLOW), 882 883 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, 884 DRM_RENDER_ALLOW), 885 886 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, 887 DRM_RENDER_ALLOW), 888 889 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB, 890 virtio_gpu_resource_create_blob_ioctl, 891 DRM_RENDER_ALLOW), 892 893 DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl, 894 DRM_RENDER_ALLOW), 895 }; 896