1 /* 2 * Copyright 2014 Broadcom 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24 #ifdef USE_VC4_SIMULATOR 25 26 #include "vc4_drv.h" 27 28 /* 29 * Copies in the user's binning command list and generates the validated bin 30 * CL, along with associated data (shader records, uniforms). 31 */ 32 static int 33 vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) 34 { 35 struct drm_vc4_submit_cl *args = exec->args; 36 void *temp = NULL; 37 void *bin; 38 int ret = 0; 39 uint32_t bin_offset = 0; 40 uint32_t shader_rec_offset = roundup(bin_offset + args->bin_cl_size, 41 16); 42 uint32_t uniforms_offset = shader_rec_offset + args->shader_rec_size; 43 uint32_t exec_size = uniforms_offset + args->uniforms_size; 44 uint32_t temp_size = exec_size + (sizeof(struct vc4_shader_state) * 45 args->shader_rec_count); 46 47 if (uniforms_offset < shader_rec_offset || 48 exec_size < uniforms_offset || 49 args->shader_rec_count >= (UINT_MAX / 50 sizeof(struct vc4_shader_state)) || 51 temp_size < exec_size) { 52 DRM_ERROR("overflow in exec arguments\n"); 53 goto fail; 54 } 55 56 /* Allocate space where we'll store the copied in user command lists 57 * and shader records. 58 * 59 * We don't just copy directly into the BOs because we need to 60 * read the contents back for validation, and I think the 61 * bo->vaddr is uncached access. 62 */ 63 temp = kmalloc(temp_size, GFP_KERNEL); 64 if (!temp) { 65 DRM_ERROR("Failed to allocate storage for copying " 66 "in bin/render CLs.\n"); 67 ret = -ENOMEM; 68 goto fail; 69 } 70 bin = temp + bin_offset; 71 exec->shader_rec_u = temp + shader_rec_offset; 72 exec->uniforms_u = temp + uniforms_offset; 73 exec->shader_state = temp + exec_size; 74 exec->shader_state_size = args->shader_rec_count; 75 76 ret = copy_from_user(bin, 77 (void __user *)(uintptr_t)args->bin_cl, 78 args->bin_cl_size); 79 if (ret) { 80 DRM_ERROR("Failed to copy in bin cl\n"); 81 goto fail; 82 } 83 84 ret = copy_from_user(exec->shader_rec_u, 85 (void __user *)(uintptr_t)args->shader_rec, 86 args->shader_rec_size); 87 if (ret) { 88 DRM_ERROR("Failed to copy in shader recs\n"); 89 goto fail; 90 } 91 92 ret = copy_from_user(exec->uniforms_u, 93 (void __user *)(uintptr_t)args->uniforms, 94 args->uniforms_size); 95 if (ret) { 96 DRM_ERROR("Failed to copy in uniforms cl\n"); 97 goto fail; 98 } 99 100 exec->exec_bo = drm_gem_cma_create(dev, exec_size); 101 #if 0 102 if (IS_ERR(exec->exec_bo)) { 103 DRM_ERROR("Couldn't allocate BO for exec\n"); 104 ret = PTR_ERR(exec->exec_bo); 105 exec->exec_bo = NULL; 106 goto fail; 107 } 108 #endif 109 110 list_addtail(&to_vc4_bo(&exec->exec_bo->base)->unref_head, 111 &exec->unref_list); 112 113 exec->ct0ca = exec->exec_bo->paddr + bin_offset; 114 115 exec->bin_u = bin; 116 117 exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset; 118 exec->shader_rec_p = exec->exec_bo->paddr + shader_rec_offset; 119 exec->shader_rec_size = args->shader_rec_size; 120 121 exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset; 122 exec->uniforms_p = exec->exec_bo->paddr + uniforms_offset; 123 exec->uniforms_size = args->uniforms_size; 124 125 ret = vc4_validate_bin_cl(dev, 126 exec->exec_bo->vaddr + bin_offset, 127 bin, 128 exec); 129 if (ret) 130 goto fail; 131 132 ret = vc4_validate_shader_recs(dev, exec); 133 134 fail: 135 kfree(temp); 136 return ret; 137 } 138 139 int 140 vc4_cl_validate(struct drm_device *dev, struct vc4_exec_info *exec) 141 { 142 struct drm_vc4_submit_cl *args = exec->args; 143 int ret = 0; 144 145 if (args->color_write.bits & VC4_RENDER_CONFIG_MS_MODE_4X) { 146 exec->tile_width = 32; 147 exec->tile_height = 32; 148 } else { 149 exec->tile_width = 64; 150 exec->tile_height = 64; 151 } 152 153 if (exec->args->bin_cl_size != 0) { 154 ret = vc4_get_bcl(dev, exec); 155 if (ret) 156 goto fail; 157 } else { 158 exec->ct0ca = exec->ct0ea = 0; 159 } 160 161 ret = vc4_get_rcl(dev, exec); 162 if (ret) 163 goto fail; 164 165 fail: 166 return ret; 167 } 168 169 #endif /* USE_VC4_SIMULATOR */ 170