1 /************************************************************************** 2 * 3 * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include "vmwgfx_drv.h" 29 #include "vmwgfx_resource_priv.h" 30 #include "vmwgfx_binding.h" 31 #include "ttm/ttm_placement.h" 32 33 struct vmw_shader { 34 struct vmw_resource res; 35 SVGA3dShaderType type; 36 uint32_t size; 37 uint8_t num_input_sig; 38 uint8_t num_output_sig; 39 }; 40 41 struct vmw_user_shader { 42 struct ttm_base_object base; 43 struct vmw_shader shader; 44 }; 45 46 struct vmw_dx_shader { 47 struct vmw_resource res; 48 struct vmw_resource *ctx; 49 struct vmw_resource *cotable; 50 u32 id; 51 bool committed; 52 struct list_head cotable_head; 53 }; 54 55 static uint64_t vmw_user_shader_size; 56 static uint64_t vmw_shader_size; 57 static size_t vmw_shader_dx_size; 58 59 static void vmw_user_shader_free(struct vmw_resource *res); 60 static struct vmw_resource * 61 vmw_user_shader_base_to_res(struct ttm_base_object *base); 62 63 static int vmw_gb_shader_create(struct vmw_resource *res); 64 static int vmw_gb_shader_bind(struct vmw_resource *res, 65 struct ttm_validate_buffer *val_buf); 66 static int vmw_gb_shader_unbind(struct vmw_resource *res, 67 bool readback, 68 struct ttm_validate_buffer *val_buf); 69 static int vmw_gb_shader_destroy(struct vmw_resource *res); 70 71 static int vmw_dx_shader_create(struct vmw_resource *res); 72 static int vmw_dx_shader_bind(struct vmw_resource *res, 73 struct ttm_validate_buffer *val_buf); 74 static int vmw_dx_shader_unbind(struct vmw_resource *res, 75 bool readback, 76 struct ttm_validate_buffer *val_buf); 77 static void vmw_dx_shader_commit_notify(struct vmw_resource *res, 78 enum vmw_cmdbuf_res_state state); 79 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type); 80 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type); 81 static uint64_t vmw_user_shader_size; 82 83 static const struct vmw_user_resource_conv user_shader_conv = { 84 .object_type = VMW_RES_SHADER, 85 .base_obj_to_res = vmw_user_shader_base_to_res, 86 .res_free = vmw_user_shader_free 87 }; 88 89 const struct vmw_user_resource_conv *user_shader_converter = 90 &user_shader_conv; 91 92 93 static const struct vmw_res_func vmw_gb_shader_func = { 94 .res_type = vmw_res_shader, 95 .needs_backup = true, 96 .may_evict = true, 97 .type_name = "guest backed shaders", 98 .backup_placement = &vmw_mob_placement, 99 .create = vmw_gb_shader_create, 100 .destroy = vmw_gb_shader_destroy, 101 .bind = vmw_gb_shader_bind, 102 .unbind = vmw_gb_shader_unbind 103 }; 104 105 static const struct vmw_res_func vmw_dx_shader_func = { 106 .res_type = vmw_res_shader, 107 .needs_backup = true, 108 .may_evict = false, 109 .type_name = "dx shaders", 110 .backup_placement = &vmw_mob_placement, 111 .create = vmw_dx_shader_create, 112 /* 113 * The destroy callback is only called with a committed resource on 114 * context destroy, in which case we destroy the cotable anyway, 115 * so there's no need to destroy DX shaders separately. 116 */ 117 .destroy = NULL, 118 .bind = vmw_dx_shader_bind, 119 .unbind = vmw_dx_shader_unbind, 120 .commit_notify = vmw_dx_shader_commit_notify, 121 }; 122 123 /** 124 * Shader management: 125 */ 126 127 static inline struct vmw_shader * 128 vmw_res_to_shader(struct vmw_resource *res) 129 { 130 return container_of(res, struct vmw_shader, res); 131 } 132 133 /** 134 * vmw_res_to_dx_shader - typecast a struct vmw_resource to a 135 * struct vmw_dx_shader 136 * 137 * @res: Pointer to the struct vmw_resource. 138 */ 139 static inline struct vmw_dx_shader * 140 vmw_res_to_dx_shader(struct vmw_resource *res) 141 { 142 return container_of(res, struct vmw_dx_shader, res); 143 } 144 145 static void vmw_hw_shader_destroy(struct vmw_resource *res) 146 { 147 if (likely(res->func->destroy)) 148 (void) res->func->destroy(res); 149 else 150 res->id = -1; 151 } 152 153 154 static int vmw_gb_shader_init(struct vmw_private *dev_priv, 155 struct vmw_resource *res, 156 uint32_t size, 157 uint64_t offset, 158 SVGA3dShaderType type, 159 uint8_t num_input_sig, 160 uint8_t num_output_sig, 161 struct vmw_dma_buffer *byte_code, 162 void (*res_free) (struct vmw_resource *res)) 163 { 164 struct vmw_shader *shader = vmw_res_to_shader(res); 165 int ret; 166 167 ret = vmw_resource_init(dev_priv, res, true, res_free, 168 &vmw_gb_shader_func); 169 170 if (unlikely(ret != 0)) { 171 if (res_free) 172 res_free(res); 173 else 174 kfree(res); 175 return ret; 176 } 177 178 res->backup_size = size; 179 if (byte_code) { 180 res->backup = vmw_dmabuf_reference(byte_code); 181 res->backup_offset = offset; 182 } 183 shader->size = size; 184 shader->type = type; 185 shader->num_input_sig = num_input_sig; 186 shader->num_output_sig = num_output_sig; 187 188 vmw_resource_activate(res, vmw_hw_shader_destroy); 189 return 0; 190 } 191 192 /* 193 * GB shader code: 194 */ 195 196 static int vmw_gb_shader_create(struct vmw_resource *res) 197 { 198 struct vmw_private *dev_priv = res->dev_priv; 199 struct vmw_shader *shader = vmw_res_to_shader(res); 200 int ret; 201 struct { 202 SVGA3dCmdHeader header; 203 SVGA3dCmdDefineGBShader body; 204 } *cmd; 205 206 if (likely(res->id != -1)) 207 return 0; 208 209 ret = vmw_resource_alloc_id(res); 210 if (unlikely(ret != 0)) { 211 DRM_ERROR("Failed to allocate a shader id.\n"); 212 goto out_no_id; 213 } 214 215 if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) { 216 ret = -EBUSY; 217 goto out_no_fifo; 218 } 219 220 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 221 if (unlikely(cmd == NULL)) { 222 DRM_ERROR("Failed reserving FIFO space for shader " 223 "creation.\n"); 224 ret = -ENOMEM; 225 goto out_no_fifo; 226 } 227 228 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER; 229 cmd->header.size = sizeof(cmd->body); 230 cmd->body.shid = res->id; 231 cmd->body.type = shader->type; 232 cmd->body.sizeInBytes = shader->size; 233 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 234 vmw_fifo_resource_inc(dev_priv); 235 236 return 0; 237 238 out_no_fifo: 239 vmw_resource_release_id(res); 240 out_no_id: 241 return ret; 242 } 243 244 static int vmw_gb_shader_bind(struct vmw_resource *res, 245 struct ttm_validate_buffer *val_buf) 246 { 247 struct vmw_private *dev_priv = res->dev_priv; 248 struct { 249 SVGA3dCmdHeader header; 250 SVGA3dCmdBindGBShader body; 251 } *cmd; 252 struct ttm_buffer_object *bo = val_buf->bo; 253 254 BUG_ON(bo->mem.mem_type != VMW_PL_MOB); 255 256 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 257 if (unlikely(cmd == NULL)) { 258 DRM_ERROR("Failed reserving FIFO space for shader " 259 "binding.\n"); 260 return -ENOMEM; 261 } 262 263 cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; 264 cmd->header.size = sizeof(cmd->body); 265 cmd->body.shid = res->id; 266 cmd->body.mobid = bo->mem.start; 267 cmd->body.offsetInBytes = res->backup_offset; 268 res->backup_dirty = false; 269 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 270 271 return 0; 272 } 273 274 static int vmw_gb_shader_unbind(struct vmw_resource *res, 275 bool readback, 276 struct ttm_validate_buffer *val_buf) 277 { 278 struct vmw_private *dev_priv = res->dev_priv; 279 struct { 280 SVGA3dCmdHeader header; 281 SVGA3dCmdBindGBShader body; 282 } *cmd; 283 struct vmw_fence_obj *fence; 284 285 BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB); 286 287 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 288 if (unlikely(cmd == NULL)) { 289 DRM_ERROR("Failed reserving FIFO space for shader " 290 "unbinding.\n"); 291 return -ENOMEM; 292 } 293 294 cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; 295 cmd->header.size = sizeof(cmd->body); 296 cmd->body.shid = res->id; 297 cmd->body.mobid = SVGA3D_INVALID_ID; 298 cmd->body.offsetInBytes = 0; 299 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 300 301 /* 302 * Create a fence object and fence the backup buffer. 303 */ 304 305 (void) vmw_execbuf_fence_commands(NULL, dev_priv, 306 &fence, NULL); 307 308 vmw_fence_single_bo(val_buf->bo, fence); 309 310 if (likely(fence != NULL)) 311 vmw_fence_obj_unreference(&fence); 312 313 return 0; 314 } 315 316 static int vmw_gb_shader_destroy(struct vmw_resource *res) 317 { 318 struct vmw_private *dev_priv = res->dev_priv; 319 struct { 320 SVGA3dCmdHeader header; 321 SVGA3dCmdDestroyGBShader body; 322 } *cmd; 323 324 if (likely(res->id == -1)) 325 return 0; 326 327 mutex_lock(&dev_priv->binding_mutex); 328 vmw_binding_res_list_scrub(&res->binding_head); 329 330 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 331 if (unlikely(cmd == NULL)) { 332 DRM_ERROR("Failed reserving FIFO space for shader " 333 "destruction.\n"); 334 mutex_unlock(&dev_priv->binding_mutex); 335 return -ENOMEM; 336 } 337 338 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER; 339 cmd->header.size = sizeof(cmd->body); 340 cmd->body.shid = res->id; 341 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 342 mutex_unlock(&dev_priv->binding_mutex); 343 vmw_resource_release_id(res); 344 vmw_fifo_resource_dec(dev_priv); 345 346 return 0; 347 } 348 349 /* 350 * DX shader code: 351 */ 352 353 /** 354 * vmw_dx_shader_commit_notify - Notify that a shader operation has been 355 * committed to hardware from a user-supplied command stream. 356 * 357 * @res: Pointer to the shader resource. 358 * @state: Indicating whether a creation or removal has been committed. 359 * 360 */ 361 static void vmw_dx_shader_commit_notify(struct vmw_resource *res, 362 enum vmw_cmdbuf_res_state state) 363 { 364 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 365 struct vmw_private *dev_priv = res->dev_priv; 366 367 if (state == VMW_CMDBUF_RES_ADD) { 368 mutex_lock(&dev_priv->binding_mutex); 369 vmw_cotable_add_resource(shader->cotable, 370 &shader->cotable_head); 371 shader->committed = true; 372 res->id = shader->id; 373 mutex_unlock(&dev_priv->binding_mutex); 374 } else { 375 mutex_lock(&dev_priv->binding_mutex); 376 list_del_init(&shader->cotable_head); 377 shader->committed = false; 378 res->id = -1; 379 mutex_unlock(&dev_priv->binding_mutex); 380 } 381 } 382 383 /** 384 * vmw_dx_shader_unscrub - Have the device reattach a MOB to a DX shader. 385 * 386 * @res: The shader resource 387 * 388 * This function reverts a scrub operation. 389 */ 390 static int vmw_dx_shader_unscrub(struct vmw_resource *res) 391 { 392 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 393 struct vmw_private *dev_priv = res->dev_priv; 394 struct { 395 SVGA3dCmdHeader header; 396 SVGA3dCmdDXBindShader body; 397 } *cmd; 398 399 if (!list_empty(&shader->cotable_head) || !shader->committed) 400 return 0; 401 402 cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), 403 shader->ctx->id); 404 if (unlikely(cmd == NULL)) { 405 DRM_ERROR("Failed reserving FIFO space for shader " 406 "scrubbing.\n"); 407 return -ENOMEM; 408 } 409 410 cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER; 411 cmd->header.size = sizeof(cmd->body); 412 cmd->body.cid = shader->ctx->id; 413 cmd->body.shid = shader->id; 414 cmd->body.mobid = res->backup->base.mem.start; 415 cmd->body.offsetInBytes = res->backup_offset; 416 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 417 418 vmw_cotable_add_resource(shader->cotable, &shader->cotable_head); 419 420 return 0; 421 } 422 423 /** 424 * vmw_dx_shader_create - The DX shader create callback 425 * 426 * @res: The DX shader resource 427 * 428 * The create callback is called as part of resource validation and 429 * makes sure that we unscrub the shader if it's previously been scrubbed. 430 */ 431 static int vmw_dx_shader_create(struct vmw_resource *res) 432 { 433 struct vmw_private *dev_priv = res->dev_priv; 434 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 435 int ret = 0; 436 437 WARN_ON_ONCE(!shader->committed); 438 439 if (!list_empty(&res->mob_head)) { 440 mutex_lock(&dev_priv->binding_mutex); 441 ret = vmw_dx_shader_unscrub(res); 442 mutex_unlock(&dev_priv->binding_mutex); 443 } 444 445 res->id = shader->id; 446 return ret; 447 } 448 449 /** 450 * vmw_dx_shader_bind - The DX shader bind callback 451 * 452 * @res: The DX shader resource 453 * @val_buf: Pointer to the validate buffer. 454 * 455 */ 456 static int vmw_dx_shader_bind(struct vmw_resource *res, 457 struct ttm_validate_buffer *val_buf) 458 { 459 struct vmw_private *dev_priv = res->dev_priv; 460 struct ttm_buffer_object *bo = val_buf->bo; 461 462 BUG_ON(bo->mem.mem_type != VMW_PL_MOB); 463 mutex_lock(&dev_priv->binding_mutex); 464 vmw_dx_shader_unscrub(res); 465 mutex_unlock(&dev_priv->binding_mutex); 466 467 return 0; 468 } 469 470 /** 471 * vmw_dx_shader_scrub - Have the device unbind a MOB from a DX shader. 472 * 473 * @res: The shader resource 474 * 475 * This function unbinds a MOB from the DX shader without requiring the 476 * MOB dma_buffer to be reserved. The driver still considers the MOB bound. 477 * However, once the driver eventually decides to unbind the MOB, it doesn't 478 * need to access the context. 479 */ 480 static int vmw_dx_shader_scrub(struct vmw_resource *res) 481 { 482 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 483 struct vmw_private *dev_priv = res->dev_priv; 484 struct { 485 SVGA3dCmdHeader header; 486 SVGA3dCmdDXBindShader body; 487 } *cmd; 488 489 if (list_empty(&shader->cotable_head)) 490 return 0; 491 492 WARN_ON_ONCE(!shader->committed); 493 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 494 if (unlikely(cmd == NULL)) { 495 DRM_ERROR("Failed reserving FIFO space for shader " 496 "scrubbing.\n"); 497 return -ENOMEM; 498 } 499 500 cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER; 501 cmd->header.size = sizeof(cmd->body); 502 cmd->body.cid = shader->ctx->id; 503 cmd->body.shid = res->id; 504 cmd->body.mobid = SVGA3D_INVALID_ID; 505 cmd->body.offsetInBytes = 0; 506 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 507 res->id = -1; 508 list_del_init(&shader->cotable_head); 509 510 return 0; 511 } 512 513 /** 514 * vmw_dx_shader_unbind - The dx shader unbind callback. 515 * 516 * @res: The shader resource 517 * @readback: Whether this is a readback unbind. Currently unused. 518 * @val_buf: MOB buffer information. 519 */ 520 static int vmw_dx_shader_unbind(struct vmw_resource *res, 521 bool readback, 522 struct ttm_validate_buffer *val_buf) 523 { 524 struct vmw_private *dev_priv = res->dev_priv; 525 struct vmw_fence_obj *fence; 526 int ret; 527 528 BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB); 529 530 mutex_lock(&dev_priv->binding_mutex); 531 ret = vmw_dx_shader_scrub(res); 532 mutex_unlock(&dev_priv->binding_mutex); 533 534 if (ret) 535 return ret; 536 537 (void) vmw_execbuf_fence_commands(NULL, dev_priv, 538 &fence, NULL); 539 vmw_fence_single_bo(val_buf->bo, fence); 540 541 if (likely(fence != NULL)) 542 vmw_fence_obj_unreference(&fence); 543 544 return 0; 545 } 546 547 /** 548 * vmw_dx_shader_cotable_list_scrub - The cotable unbind_func callback for 549 * DX shaders. 550 * 551 * @dev_priv: Pointer to device private structure. 552 * @list: The list of cotable resources. 553 * @readback: Whether the call was part of a readback unbind. 554 * 555 * Scrubs all shader MOBs so that any subsequent shader unbind or shader 556 * destroy operation won't need to swap in the context. 557 */ 558 void vmw_dx_shader_cotable_list_scrub(struct vmw_private *dev_priv, 559 struct list_head *list, 560 bool readback) 561 { 562 struct vmw_dx_shader *entry, *next; 563 564 WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex)); 565 566 list_for_each_entry_safe(entry, next, list, cotable_head) { 567 WARN_ON(vmw_dx_shader_scrub(&entry->res)); 568 if (!readback) 569 entry->committed = false; 570 } 571 } 572 573 /** 574 * vmw_dx_shader_res_free - The DX shader free callback 575 * 576 * @res: The shader resource 577 * 578 * Frees the DX shader resource and updates memory accounting. 579 */ 580 static void vmw_dx_shader_res_free(struct vmw_resource *res) 581 { 582 struct vmw_private *dev_priv = res->dev_priv; 583 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 584 585 vmw_resource_unreference(&shader->cotable); 586 kfree(shader); 587 ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size); 588 } 589 590 /** 591 * vmw_dx_shader_add - Add a shader resource as a command buffer managed 592 * resource. 593 * 594 * @man: The command buffer resource manager. 595 * @ctx: Pointer to the context resource. 596 * @user_key: The id used for this shader. 597 * @shader_type: The shader type. 598 * @list: The list of staged command buffer managed resources. 599 */ 600 int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man, 601 struct vmw_resource *ctx, 602 u32 user_key, 603 SVGA3dShaderType shader_type, 604 struct list_head *list) 605 { 606 struct vmw_dx_shader *shader; 607 struct vmw_resource *res; 608 struct vmw_private *dev_priv = ctx->dev_priv; 609 int ret; 610 611 if (!vmw_shader_dx_size) 612 vmw_shader_dx_size = ttm_round_pot(sizeof(*shader)); 613 614 if (!vmw_shader_id_ok(user_key, shader_type)) 615 return -EINVAL; 616 617 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), vmw_shader_dx_size, 618 false, true); 619 if (ret) { 620 if (ret != -ERESTARTSYS) 621 DRM_ERROR("Out of graphics memory for shader " 622 "creation.\n"); 623 return ret; 624 } 625 626 shader = kmalloc(sizeof(*shader), GFP_KERNEL); 627 if (!shader) { 628 ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size); 629 return -ENOMEM; 630 } 631 632 res = &shader->res; 633 shader->ctx = ctx; 634 shader->cotable = vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER); 635 shader->id = user_key; 636 shader->committed = false; 637 INIT_LIST_HEAD(&shader->cotable_head); 638 ret = vmw_resource_init(dev_priv, res, true, 639 vmw_dx_shader_res_free, &vmw_dx_shader_func); 640 if (ret) 641 goto out_resource_init; 642 643 /* 644 * The user_key name-space is not per shader type for DX shaders, 645 * so when hashing, use a single zero shader type. 646 */ 647 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader, 648 vmw_shader_key(user_key, 0), 649 res, list); 650 if (ret) 651 goto out_resource_init; 652 653 res->id = shader->id; 654 vmw_resource_activate(res, vmw_hw_shader_destroy); 655 656 out_resource_init: 657 vmw_resource_unreference(&res); 658 659 return ret; 660 } 661 662 663 664 /** 665 * User-space shader management: 666 */ 667 668 static struct vmw_resource * 669 vmw_user_shader_base_to_res(struct ttm_base_object *base) 670 { 671 return &(container_of(base, struct vmw_user_shader, base)-> 672 shader.res); 673 } 674 675 static void vmw_user_shader_free(struct vmw_resource *res) 676 { 677 struct vmw_user_shader *ushader = 678 container_of(res, struct vmw_user_shader, shader.res); 679 struct vmw_private *dev_priv = res->dev_priv; 680 681 ttm_base_object_kfree(ushader, base); 682 ttm_mem_global_free(vmw_mem_glob(dev_priv), 683 vmw_user_shader_size); 684 } 685 686 static void vmw_shader_free(struct vmw_resource *res) 687 { 688 struct vmw_shader *shader = vmw_res_to_shader(res); 689 struct vmw_private *dev_priv = res->dev_priv; 690 691 kfree(shader); 692 ttm_mem_global_free(vmw_mem_glob(dev_priv), 693 vmw_shader_size); 694 } 695 696 /** 697 * This function is called when user space has no more references on the 698 * base object. It releases the base-object's reference on the resource object. 699 */ 700 701 static void vmw_user_shader_base_release(struct ttm_base_object **p_base) 702 { 703 struct ttm_base_object *base = *p_base; 704 struct vmw_resource *res = vmw_user_shader_base_to_res(base); 705 706 *p_base = NULL; 707 vmw_resource_unreference(&res); 708 } 709 710 int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, 711 struct drm_file *file_priv) 712 { 713 struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data; 714 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 715 716 return ttm_ref_object_base_unref(tfile, arg->handle, 717 TTM_REF_USAGE); 718 } 719 720 static int vmw_user_shader_alloc(struct vmw_private *dev_priv, 721 struct vmw_dma_buffer *buffer, 722 size_t shader_size, 723 size_t offset, 724 SVGA3dShaderType shader_type, 725 uint8_t num_input_sig, 726 uint8_t num_output_sig, 727 struct ttm_object_file *tfile, 728 u32 *handle) 729 { 730 struct vmw_user_shader *ushader; 731 struct vmw_resource *res, *tmp; 732 int ret; 733 734 /* 735 * Approximate idr memory usage with 128 bytes. It will be limited 736 * by maximum number_of shaders anyway. 737 */ 738 if (unlikely(vmw_user_shader_size == 0)) 739 vmw_user_shader_size = 740 ttm_round_pot(sizeof(struct vmw_user_shader)) + 128; 741 742 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 743 vmw_user_shader_size, 744 false, true); 745 if (unlikely(ret != 0)) { 746 if (ret != -ERESTARTSYS) 747 DRM_ERROR("Out of graphics memory for shader " 748 "creation.\n"); 749 goto out; 750 } 751 752 ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); 753 if (unlikely(ushader == NULL)) { 754 ttm_mem_global_free(vmw_mem_glob(dev_priv), 755 vmw_user_shader_size); 756 ret = -ENOMEM; 757 goto out; 758 } 759 760 res = &ushader->shader.res; 761 ushader->base.shareable = false; 762 ushader->base.tfile = NULL; 763 764 /* 765 * From here on, the destructor takes over resource freeing. 766 */ 767 768 ret = vmw_gb_shader_init(dev_priv, res, shader_size, 769 offset, shader_type, num_input_sig, 770 num_output_sig, buffer, 771 vmw_user_shader_free); 772 if (unlikely(ret != 0)) 773 goto out; 774 775 tmp = vmw_resource_reference(res); 776 ret = ttm_base_object_init(tfile, &ushader->base, false, 777 VMW_RES_SHADER, 778 &vmw_user_shader_base_release, NULL); 779 780 if (unlikely(ret != 0)) { 781 vmw_resource_unreference(&tmp); 782 goto out_err; 783 } 784 785 if (handle) 786 *handle = ushader->base.hash.key; 787 out_err: 788 vmw_resource_unreference(&res); 789 out: 790 return ret; 791 } 792 793 794 static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv, 795 struct vmw_dma_buffer *buffer, 796 size_t shader_size, 797 size_t offset, 798 SVGA3dShaderType shader_type) 799 { 800 struct vmw_shader *shader; 801 struct vmw_resource *res; 802 int ret; 803 804 /* 805 * Approximate idr memory usage with 128 bytes. It will be limited 806 * by maximum number_of shaders anyway. 807 */ 808 if (unlikely(vmw_shader_size == 0)) 809 vmw_shader_size = 810 ttm_round_pot(sizeof(struct vmw_shader)) + 128; 811 812 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 813 vmw_shader_size, 814 false, true); 815 if (unlikely(ret != 0)) { 816 if (ret != -ERESTARTSYS) 817 DRM_ERROR("Out of graphics memory for shader " 818 "creation.\n"); 819 goto out_err; 820 } 821 822 shader = kzalloc(sizeof(*shader), GFP_KERNEL); 823 if (unlikely(shader == NULL)) { 824 ttm_mem_global_free(vmw_mem_glob(dev_priv), 825 vmw_shader_size); 826 ret = -ENOMEM; 827 goto out_err; 828 } 829 830 res = &shader->res; 831 832 /* 833 * From here on, the destructor takes over resource freeing. 834 */ 835 ret = vmw_gb_shader_init(dev_priv, res, shader_size, 836 offset, shader_type, 0, 0, buffer, 837 vmw_shader_free); 838 839 out_err: 840 return ret ? ERR_PTR(ret) : res; 841 } 842 843 844 static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, 845 enum drm_vmw_shader_type shader_type_drm, 846 u32 buffer_handle, size_t size, size_t offset, 847 uint8_t num_input_sig, uint8_t num_output_sig, 848 uint32_t *shader_handle) 849 { 850 struct vmw_private *dev_priv = vmw_priv(dev); 851 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 852 struct vmw_dma_buffer *buffer = NULL; 853 SVGA3dShaderType shader_type; 854 int ret; 855 856 if (buffer_handle != SVGA3D_INVALID_ID) { 857 ret = vmw_user_dmabuf_lookup(tfile, buffer_handle, 858 &buffer, NULL); 859 if (unlikely(ret != 0)) { 860 DRM_ERROR("Could not find buffer for shader " 861 "creation.\n"); 862 return ret; 863 } 864 865 if ((u64)buffer->base.num_pages * PAGE_SIZE < 866 (u64)size + (u64)offset) { 867 DRM_ERROR("Illegal buffer- or shader size.\n"); 868 ret = -EINVAL; 869 goto out_bad_arg; 870 } 871 } 872 873 switch (shader_type_drm) { 874 case drm_vmw_shader_type_vs: 875 shader_type = SVGA3D_SHADERTYPE_VS; 876 break; 877 case drm_vmw_shader_type_ps: 878 shader_type = SVGA3D_SHADERTYPE_PS; 879 break; 880 default: 881 DRM_ERROR("Illegal shader type.\n"); 882 ret = -EINVAL; 883 goto out_bad_arg; 884 } 885 886 ret = ttm_read_lock(&dev_priv->reservation_sem, true); 887 if (unlikely(ret != 0)) 888 goto out_bad_arg; 889 890 ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset, 891 shader_type, num_input_sig, 892 num_output_sig, tfile, shader_handle); 893 894 ttm_read_unlock(&dev_priv->reservation_sem); 895 out_bad_arg: 896 vmw_dmabuf_unreference(&buffer); 897 return ret; 898 } 899 900 /** 901 * vmw_shader_id_ok - Check whether a compat shader user key and 902 * shader type are within valid bounds. 903 * 904 * @user_key: User space id of the shader. 905 * @shader_type: Shader type. 906 * 907 * Returns true if valid false if not. 908 */ 909 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type) 910 { 911 return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16; 912 } 913 914 /** 915 * vmw_shader_key - Compute a hash key suitable for a compat shader. 916 * 917 * @user_key: User space id of the shader. 918 * @shader_type: Shader type. 919 * 920 * Returns a hash key suitable for a command buffer managed resource 921 * manager hash table. 922 */ 923 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type) 924 { 925 return user_key | (shader_type << 20); 926 } 927 928 /** 929 * vmw_shader_remove - Stage a compat shader for removal. 930 * 931 * @man: Pointer to the compat shader manager identifying the shader namespace. 932 * @user_key: The key that is used to identify the shader. The key is 933 * unique to the shader type. 934 * @shader_type: Shader type. 935 * @list: Caller's list of staged command buffer resource actions. 936 */ 937 int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man, 938 u32 user_key, SVGA3dShaderType shader_type, 939 struct list_head *list) 940 { 941 struct vmw_resource *dummy; 942 943 if (!vmw_shader_id_ok(user_key, shader_type)) 944 return -EINVAL; 945 946 return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader, 947 vmw_shader_key(user_key, shader_type), 948 list, &dummy); 949 } 950 951 /** 952 * vmw_compat_shader_add - Create a compat shader and stage it for addition 953 * as a command buffer managed resource. 954 * 955 * @man: Pointer to the compat shader manager identifying the shader namespace. 956 * @user_key: The key that is used to identify the shader. The key is 957 * unique to the shader type. 958 * @bytecode: Pointer to the bytecode of the shader. 959 * @shader_type: Shader type. 960 * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is 961 * to be created with. 962 * @list: Caller's list of staged command buffer resource actions. 963 * 964 */ 965 int vmw_compat_shader_add(struct vmw_private *dev_priv, 966 struct vmw_cmdbuf_res_manager *man, 967 u32 user_key, const void *bytecode, 968 SVGA3dShaderType shader_type, 969 size_t size, 970 struct list_head *list) 971 { 972 struct vmw_dma_buffer *buf; 973 struct ttm_bo_kmap_obj map; 974 bool is_iomem; 975 int ret; 976 struct vmw_resource *res; 977 978 if (!vmw_shader_id_ok(user_key, shader_type)) 979 return -EINVAL; 980 981 /* Allocate and pin a DMA buffer */ 982 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 983 if (unlikely(buf == NULL)) 984 return -ENOMEM; 985 986 ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement, 987 true, vmw_dmabuf_bo_free); 988 if (unlikely(ret != 0)) 989 goto out; 990 991 ret = ttm_bo_reserve(&buf->base, false, true, NULL); 992 if (unlikely(ret != 0)) 993 goto no_reserve; 994 995 /* Map and copy shader bytecode. */ 996 ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT, 997 &map); 998 if (unlikely(ret != 0)) { 999 ttm_bo_unreserve(&buf->base); 1000 goto no_reserve; 1001 } 1002 1003 memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size); 1004 WARN_ON(is_iomem); 1005 1006 ttm_bo_kunmap(&map); 1007 ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true); 1008 WARN_ON(ret != 0); 1009 ttm_bo_unreserve(&buf->base); 1010 1011 res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); 1012 if (unlikely(ret != 0)) 1013 goto no_reserve; 1014 1015 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader, 1016 vmw_shader_key(user_key, shader_type), 1017 res, list); 1018 vmw_resource_unreference(&res); 1019 no_reserve: 1020 vmw_dmabuf_unreference(&buf); 1021 out: 1022 return ret; 1023 } 1024 1025 /** 1026 * vmw_shader_lookup - Look up a compat shader 1027 * 1028 * @man: Pointer to the command buffer managed resource manager identifying 1029 * the shader namespace. 1030 * @user_key: The user space id of the shader. 1031 * @shader_type: The shader type. 1032 * 1033 * Returns a refcounted pointer to a struct vmw_resource if the shader was 1034 * found. An error pointer otherwise. 1035 */ 1036 struct vmw_resource * 1037 vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man, 1038 u32 user_key, 1039 SVGA3dShaderType shader_type) 1040 { 1041 if (!vmw_shader_id_ok(user_key, shader_type)) 1042 return ERR_PTR(-EINVAL); 1043 1044 return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader, 1045 vmw_shader_key(user_key, shader_type)); 1046 } 1047 1048 int vmw_shader_define_ioctl(struct drm_device *dev, void *data, 1049 struct drm_file *file_priv) 1050 { 1051 struct drm_vmw_shader_create_arg *arg = 1052 (struct drm_vmw_shader_create_arg *)data; 1053 1054 return vmw_shader_define(dev, file_priv, arg->shader_type, 1055 arg->buffer_handle, 1056 arg->size, arg->offset, 1057 0, 0, 1058 &arg->shader_handle); 1059 } 1060