0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #include "uapi/drm/vc4_drm.h"
0047 #include "vc4_drv.h"
0048 #include "vc4_packet.h"
0049
0050 #define VALIDATE_ARGS \
0051 struct vc4_exec_info *exec, \
0052 void *validated, \
0053 void *untrusted
0054
0055
0056 static uint32_t
0057 utile_width(int cpp)
0058 {
0059 switch (cpp) {
0060 case 1:
0061 case 2:
0062 return 8;
0063 case 4:
0064 return 4;
0065 case 8:
0066 return 2;
0067 default:
0068 DRM_ERROR("unknown cpp: %d\n", cpp);
0069 return 1;
0070 }
0071 }
0072
0073
0074 static uint32_t
0075 utile_height(int cpp)
0076 {
0077 switch (cpp) {
0078 case 1:
0079 return 8;
0080 case 2:
0081 case 4:
0082 case 8:
0083 return 4;
0084 default:
0085 DRM_ERROR("unknown cpp: %d\n", cpp);
0086 return 1;
0087 }
0088 }
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static bool
0099 size_is_lt(uint32_t width, uint32_t height, int cpp)
0100 {
0101 return (width <= 4 * utile_width(cpp) ||
0102 height <= 4 * utile_height(cpp));
0103 }
0104
0105 struct drm_gem_cma_object *
0106 vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex)
0107 {
0108 struct vc4_dev *vc4 = exec->dev;
0109 struct drm_gem_cma_object *obj;
0110 struct vc4_bo *bo;
0111
0112 if (WARN_ON_ONCE(vc4->is_vc5))
0113 return NULL;
0114
0115 if (hindex >= exec->bo_count) {
0116 DRM_DEBUG("BO index %d greater than BO count %d\n",
0117 hindex, exec->bo_count);
0118 return NULL;
0119 }
0120 obj = exec->bo[hindex];
0121 bo = to_vc4_bo(&obj->base);
0122
0123 if (bo->validated_shader) {
0124 DRM_DEBUG("Trying to use shader BO as something other than "
0125 "a shader\n");
0126 return NULL;
0127 }
0128
0129 return obj;
0130 }
0131
0132 static struct drm_gem_cma_object *
0133 vc4_use_handle(struct vc4_exec_info *exec, uint32_t gem_handles_packet_index)
0134 {
0135 return vc4_use_bo(exec, exec->bo_index[gem_handles_packet_index]);
0136 }
0137
0138 static bool
0139 validate_bin_pos(struct vc4_exec_info *exec, void *untrusted, uint32_t pos)
0140 {
0141
0142
0143
0144 return (untrusted - 1 == exec->bin_u + pos);
0145 }
0146
0147 static uint32_t
0148 gl_shader_rec_size(uint32_t pointer_bits)
0149 {
0150 uint32_t attribute_count = pointer_bits & 7;
0151 bool extended = pointer_bits & 8;
0152
0153 if (attribute_count == 0)
0154 attribute_count = 8;
0155
0156 if (extended)
0157 return 100 + attribute_count * 4;
0158 else
0159 return 36 + attribute_count * 8;
0160 }
0161
0162 bool
0163 vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
0164 uint32_t offset, uint8_t tiling_format,
0165 uint32_t width, uint32_t height, uint8_t cpp)
0166 {
0167 struct vc4_dev *vc4 = exec->dev;
0168 uint32_t aligned_width, aligned_height, stride, size;
0169 uint32_t utile_w = utile_width(cpp);
0170 uint32_t utile_h = utile_height(cpp);
0171
0172 if (WARN_ON_ONCE(vc4->is_vc5))
0173 return false;
0174
0175
0176
0177
0178
0179
0180
0181
0182 if (width > 4096 || height > 4096) {
0183 DRM_DEBUG("Surface dimensions (%d,%d) too large",
0184 width, height);
0185 return false;
0186 }
0187
0188 switch (tiling_format) {
0189 case VC4_TILING_FORMAT_LINEAR:
0190 aligned_width = round_up(width, utile_w);
0191 aligned_height = height;
0192 break;
0193 case VC4_TILING_FORMAT_T:
0194 aligned_width = round_up(width, utile_w * 8);
0195 aligned_height = round_up(height, utile_h * 8);
0196 break;
0197 case VC4_TILING_FORMAT_LT:
0198 aligned_width = round_up(width, utile_w);
0199 aligned_height = round_up(height, utile_h);
0200 break;
0201 default:
0202 DRM_DEBUG("buffer tiling %d unsupported\n", tiling_format);
0203 return false;
0204 }
0205
0206 stride = aligned_width * cpp;
0207 size = stride * aligned_height;
0208
0209 if (size + offset < size ||
0210 size + offset > fbo->base.size) {
0211 DRM_DEBUG("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %zd)\n",
0212 width, height,
0213 aligned_width, aligned_height,
0214 size, offset, fbo->base.size);
0215 return false;
0216 }
0217
0218 return true;
0219 }
0220
0221 static int
0222 validate_flush(VALIDATE_ARGS)
0223 {
0224 if (!validate_bin_pos(exec, untrusted, exec->args->bin_cl_size - 1)) {
0225 DRM_DEBUG("Bin CL must end with VC4_PACKET_FLUSH\n");
0226 return -EINVAL;
0227 }
0228 exec->found_flush = true;
0229
0230 return 0;
0231 }
0232
0233 static int
0234 validate_start_tile_binning(VALIDATE_ARGS)
0235 {
0236 if (exec->found_start_tile_binning_packet) {
0237 DRM_DEBUG("Duplicate VC4_PACKET_START_TILE_BINNING\n");
0238 return -EINVAL;
0239 }
0240 exec->found_start_tile_binning_packet = true;
0241
0242 if (!exec->found_tile_binning_mode_config_packet) {
0243 DRM_DEBUG("missing VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
0244 return -EINVAL;
0245 }
0246
0247 return 0;
0248 }
0249
0250 static int
0251 validate_increment_semaphore(VALIDATE_ARGS)
0252 {
0253 if (!validate_bin_pos(exec, untrusted, exec->args->bin_cl_size - 2)) {
0254 DRM_DEBUG("Bin CL must end with "
0255 "VC4_PACKET_INCREMENT_SEMAPHORE\n");
0256 return -EINVAL;
0257 }
0258 exec->found_increment_semaphore_packet = true;
0259
0260 return 0;
0261 }
0262
0263 static int
0264 validate_indexed_prim_list(VALIDATE_ARGS)
0265 {
0266 struct drm_gem_cma_object *ib;
0267 uint32_t length = *(uint32_t *)(untrusted + 1);
0268 uint32_t offset = *(uint32_t *)(untrusted + 5);
0269 uint32_t max_index = *(uint32_t *)(untrusted + 9);
0270 uint32_t index_size = (*(uint8_t *)(untrusted + 0) >> 4) ? 2 : 1;
0271 struct vc4_shader_state *shader_state;
0272
0273
0274 if (exec->shader_state_count == 0) {
0275 DRM_DEBUG("shader state must precede primitives\n");
0276 return -EINVAL;
0277 }
0278 shader_state = &exec->shader_state[exec->shader_state_count - 1];
0279
0280 if (max_index > shader_state->max_index)
0281 shader_state->max_index = max_index;
0282
0283 ib = vc4_use_handle(exec, 0);
0284 if (!ib)
0285 return -EINVAL;
0286
0287 exec->bin_dep_seqno = max(exec->bin_dep_seqno,
0288 to_vc4_bo(&ib->base)->write_seqno);
0289
0290 if (offset > ib->base.size ||
0291 (ib->base.size - offset) / index_size < length) {
0292 DRM_DEBUG("IB access overflow (%d + %d*%d > %zd)\n",
0293 offset, length, index_size, ib->base.size);
0294 return -EINVAL;
0295 }
0296
0297 *(uint32_t *)(validated + 5) = ib->paddr + offset;
0298
0299 return 0;
0300 }
0301
0302 static int
0303 validate_gl_array_primitive(VALIDATE_ARGS)
0304 {
0305 uint32_t length = *(uint32_t *)(untrusted + 1);
0306 uint32_t base_index = *(uint32_t *)(untrusted + 5);
0307 uint32_t max_index;
0308 struct vc4_shader_state *shader_state;
0309
0310
0311 if (exec->shader_state_count == 0) {
0312 DRM_DEBUG("shader state must precede primitives\n");
0313 return -EINVAL;
0314 }
0315 shader_state = &exec->shader_state[exec->shader_state_count - 1];
0316
0317 if (length + base_index < length) {
0318 DRM_DEBUG("primitive vertex count overflow\n");
0319 return -EINVAL;
0320 }
0321 max_index = length + base_index - 1;
0322
0323 if (max_index > shader_state->max_index)
0324 shader_state->max_index = max_index;
0325
0326 return 0;
0327 }
0328
0329 static int
0330 validate_gl_shader_state(VALIDATE_ARGS)
0331 {
0332 uint32_t i = exec->shader_state_count++;
0333
0334 if (i >= exec->shader_state_size) {
0335 DRM_DEBUG("More requests for shader states than declared\n");
0336 return -EINVAL;
0337 }
0338
0339 exec->shader_state[i].addr = *(uint32_t *)untrusted;
0340 exec->shader_state[i].max_index = 0;
0341
0342 if (exec->shader_state[i].addr & ~0xf) {
0343 DRM_DEBUG("high bits set in GL shader rec reference\n");
0344 return -EINVAL;
0345 }
0346
0347 *(uint32_t *)validated = (exec->shader_rec_p +
0348 exec->shader_state[i].addr);
0349
0350 exec->shader_rec_p +=
0351 roundup(gl_shader_rec_size(exec->shader_state[i].addr), 16);
0352
0353 return 0;
0354 }
0355
0356 static int
0357 validate_tile_binning_config(VALIDATE_ARGS)
0358 {
0359 struct drm_device *dev = exec->exec_bo->base.dev;
0360 struct vc4_dev *vc4 = to_vc4_dev(dev);
0361 uint8_t flags;
0362 uint32_t tile_state_size;
0363 uint32_t tile_count, bin_addr;
0364 int bin_slot;
0365
0366 if (exec->found_tile_binning_mode_config_packet) {
0367 DRM_DEBUG("Duplicate VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
0368 return -EINVAL;
0369 }
0370 exec->found_tile_binning_mode_config_packet = true;
0371
0372 exec->bin_tiles_x = *(uint8_t *)(untrusted + 12);
0373 exec->bin_tiles_y = *(uint8_t *)(untrusted + 13);
0374 tile_count = exec->bin_tiles_x * exec->bin_tiles_y;
0375 flags = *(uint8_t *)(untrusted + 14);
0376
0377 if (exec->bin_tiles_x == 0 ||
0378 exec->bin_tiles_y == 0) {
0379 DRM_DEBUG("Tile binning config of %dx%d too small\n",
0380 exec->bin_tiles_x, exec->bin_tiles_y);
0381 return -EINVAL;
0382 }
0383
0384 if (flags & (VC4_BIN_CONFIG_DB_NON_MS |
0385 VC4_BIN_CONFIG_TILE_BUFFER_64BIT)) {
0386 DRM_DEBUG("unsupported binning config flags 0x%02x\n", flags);
0387 return -EINVAL;
0388 }
0389
0390 bin_slot = vc4_v3d_get_bin_slot(vc4);
0391 if (bin_slot < 0) {
0392 if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) {
0393 DRM_ERROR("Failed to allocate binner memory: %d\n",
0394 bin_slot);
0395 }
0396 return bin_slot;
0397 }
0398
0399
0400
0401
0402 exec->bin_slots |= BIT(bin_slot);
0403 bin_addr = vc4->bin_bo->base.paddr + bin_slot * vc4->bin_alloc_size;
0404
0405
0406
0407
0408 tile_state_size = 48 * tile_count;
0409
0410
0411 exec->tile_alloc_offset = bin_addr + roundup(tile_state_size, 4096);
0412
0413 *(uint8_t *)(validated + 14) =
0414 ((flags & ~(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK |
0415 VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_MASK)) |
0416 VC4_BIN_CONFIG_AUTO_INIT_TSDA |
0417 VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32,
0418 VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE) |
0419 VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_128,
0420 VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE));
0421
0422
0423 *(uint32_t *)(validated + 0) = exec->tile_alloc_offset;
0424
0425 *(uint32_t *)(validated + 4) = (bin_addr + vc4->bin_alloc_size -
0426 exec->tile_alloc_offset);
0427
0428 *(uint32_t *)(validated + 8) = bin_addr;
0429
0430 return 0;
0431 }
0432
0433 static int
0434 validate_gem_handles(VALIDATE_ARGS)
0435 {
0436 memcpy(exec->bo_index, untrusted, sizeof(exec->bo_index));
0437 return 0;
0438 }
0439
0440 #define VC4_DEFINE_PACKET(packet, func) \
0441 [packet] = { packet ## _SIZE, #packet, func }
0442
0443 static const struct cmd_info {
0444 uint16_t len;
0445 const char *name;
0446 int (*func)(struct vc4_exec_info *exec, void *validated,
0447 void *untrusted);
0448 } cmd_info[] = {
0449 VC4_DEFINE_PACKET(VC4_PACKET_HALT, NULL),
0450 VC4_DEFINE_PACKET(VC4_PACKET_NOP, NULL),
0451 VC4_DEFINE_PACKET(VC4_PACKET_FLUSH, validate_flush),
0452 VC4_DEFINE_PACKET(VC4_PACKET_FLUSH_ALL, NULL),
0453 VC4_DEFINE_PACKET(VC4_PACKET_START_TILE_BINNING,
0454 validate_start_tile_binning),
0455 VC4_DEFINE_PACKET(VC4_PACKET_INCREMENT_SEMAPHORE,
0456 validate_increment_semaphore),
0457
0458 VC4_DEFINE_PACKET(VC4_PACKET_GL_INDEXED_PRIMITIVE,
0459 validate_indexed_prim_list),
0460 VC4_DEFINE_PACKET(VC4_PACKET_GL_ARRAY_PRIMITIVE,
0461 validate_gl_array_primitive),
0462
0463 VC4_DEFINE_PACKET(VC4_PACKET_PRIMITIVE_LIST_FORMAT, NULL),
0464
0465 VC4_DEFINE_PACKET(VC4_PACKET_GL_SHADER_STATE, validate_gl_shader_state),
0466
0467 VC4_DEFINE_PACKET(VC4_PACKET_CONFIGURATION_BITS, NULL),
0468 VC4_DEFINE_PACKET(VC4_PACKET_FLAT_SHADE_FLAGS, NULL),
0469 VC4_DEFINE_PACKET(VC4_PACKET_POINT_SIZE, NULL),
0470 VC4_DEFINE_PACKET(VC4_PACKET_LINE_WIDTH, NULL),
0471 VC4_DEFINE_PACKET(VC4_PACKET_RHT_X_BOUNDARY, NULL),
0472 VC4_DEFINE_PACKET(VC4_PACKET_DEPTH_OFFSET, NULL),
0473 VC4_DEFINE_PACKET(VC4_PACKET_CLIP_WINDOW, NULL),
0474 VC4_DEFINE_PACKET(VC4_PACKET_VIEWPORT_OFFSET, NULL),
0475 VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_XY_SCALING, NULL),
0476
0477
0478
0479 VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_Z_SCALING, NULL),
0480
0481 VC4_DEFINE_PACKET(VC4_PACKET_TILE_BINNING_MODE_CONFIG,
0482 validate_tile_binning_config),
0483
0484 VC4_DEFINE_PACKET(VC4_PACKET_GEM_HANDLES, validate_gem_handles),
0485 };
0486
0487 int
0488 vc4_validate_bin_cl(struct drm_device *dev,
0489 void *validated,
0490 void *unvalidated,
0491 struct vc4_exec_info *exec)
0492 {
0493 struct vc4_dev *vc4 = to_vc4_dev(dev);
0494 uint32_t len = exec->args->bin_cl_size;
0495 uint32_t dst_offset = 0;
0496 uint32_t src_offset = 0;
0497
0498 if (WARN_ON_ONCE(vc4->is_vc5))
0499 return -ENODEV;
0500
0501 while (src_offset < len) {
0502 void *dst_pkt = validated + dst_offset;
0503 void *src_pkt = unvalidated + src_offset;
0504 u8 cmd = *(uint8_t *)src_pkt;
0505 const struct cmd_info *info;
0506
0507 if (cmd >= ARRAY_SIZE(cmd_info)) {
0508 DRM_DEBUG("0x%08x: packet %d out of bounds\n",
0509 src_offset, cmd);
0510 return -EINVAL;
0511 }
0512
0513 info = &cmd_info[cmd];
0514 if (!info->name) {
0515 DRM_DEBUG("0x%08x: packet %d invalid\n",
0516 src_offset, cmd);
0517 return -EINVAL;
0518 }
0519
0520 if (src_offset + info->len > len) {
0521 DRM_DEBUG("0x%08x: packet %d (%s) length 0x%08x "
0522 "exceeds bounds (0x%08x)\n",
0523 src_offset, cmd, info->name, info->len,
0524 src_offset + len);
0525 return -EINVAL;
0526 }
0527
0528 if (cmd != VC4_PACKET_GEM_HANDLES)
0529 memcpy(dst_pkt, src_pkt, info->len);
0530
0531 if (info->func && info->func(exec,
0532 dst_pkt + 1,
0533 src_pkt + 1)) {
0534 DRM_DEBUG("0x%08x: packet %d (%s) failed to validate\n",
0535 src_offset, cmd, info->name);
0536 return -EINVAL;
0537 }
0538
0539 src_offset += info->len;
0540
0541 if (cmd != VC4_PACKET_GEM_HANDLES)
0542 dst_offset += info->len;
0543
0544
0545 if (cmd == VC4_PACKET_HALT)
0546 break;
0547 }
0548
0549 exec->ct0ea = exec->ct0ca + dst_offset;
0550
0551 if (!exec->found_start_tile_binning_packet) {
0552 DRM_DEBUG("Bin CL missing VC4_PACKET_START_TILE_BINNING\n");
0553 return -EINVAL;
0554 }
0555
0556
0557
0558
0559
0560
0561
0562
0563 if (!exec->found_increment_semaphore_packet || !exec->found_flush) {
0564 DRM_DEBUG("Bin CL missing VC4_PACKET_INCREMENT_SEMAPHORE + "
0565 "VC4_PACKET_FLUSH\n");
0566 return -EINVAL;
0567 }
0568
0569 return 0;
0570 }
0571
0572 static bool
0573 reloc_tex(struct vc4_exec_info *exec,
0574 void *uniform_data_u,
0575 struct vc4_texture_sample_info *sample,
0576 uint32_t texture_handle_index, bool is_cs)
0577 {
0578 struct drm_gem_cma_object *tex;
0579 uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]);
0580 uint32_t p1 = *(uint32_t *)(uniform_data_u + sample->p_offset[1]);
0581 uint32_t p2 = (sample->p_offset[2] != ~0 ?
0582 *(uint32_t *)(uniform_data_u + sample->p_offset[2]) : 0);
0583 uint32_t p3 = (sample->p_offset[3] != ~0 ?
0584 *(uint32_t *)(uniform_data_u + sample->p_offset[3]) : 0);
0585 uint32_t *validated_p0 = exec->uniforms_v + sample->p_offset[0];
0586 uint32_t offset = p0 & VC4_TEX_P0_OFFSET_MASK;
0587 uint32_t miplevels = VC4_GET_FIELD(p0, VC4_TEX_P0_MIPLVLS);
0588 uint32_t width = VC4_GET_FIELD(p1, VC4_TEX_P1_WIDTH);
0589 uint32_t height = VC4_GET_FIELD(p1, VC4_TEX_P1_HEIGHT);
0590 uint32_t cpp, tiling_format, utile_w, utile_h;
0591 uint32_t i;
0592 uint32_t cube_map_stride = 0;
0593 enum vc4_texture_data_type type;
0594
0595 tex = vc4_use_bo(exec, texture_handle_index);
0596 if (!tex)
0597 return false;
0598
0599 if (sample->is_direct) {
0600 uint32_t remaining_size = tex->base.size - p0;
0601
0602 if (p0 > tex->base.size - 4) {
0603 DRM_DEBUG("UBO offset greater than UBO size\n");
0604 goto fail;
0605 }
0606 if (p1 > remaining_size - 4) {
0607 DRM_DEBUG("UBO clamp would allow reads "
0608 "outside of UBO\n");
0609 goto fail;
0610 }
0611 *validated_p0 = tex->paddr + p0;
0612 return true;
0613 }
0614
0615 if (width == 0)
0616 width = 2048;
0617 if (height == 0)
0618 height = 2048;
0619
0620 if (p0 & VC4_TEX_P0_CMMODE_MASK) {
0621 if (VC4_GET_FIELD(p2, VC4_TEX_P2_PTYPE) ==
0622 VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE)
0623 cube_map_stride = p2 & VC4_TEX_P2_CMST_MASK;
0624 if (VC4_GET_FIELD(p3, VC4_TEX_P2_PTYPE) ==
0625 VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE) {
0626 if (cube_map_stride) {
0627 DRM_DEBUG("Cube map stride set twice\n");
0628 goto fail;
0629 }
0630
0631 cube_map_stride = p3 & VC4_TEX_P2_CMST_MASK;
0632 }
0633 if (!cube_map_stride) {
0634 DRM_DEBUG("Cube map stride not set\n");
0635 goto fail;
0636 }
0637 }
0638
0639 type = (VC4_GET_FIELD(p0, VC4_TEX_P0_TYPE) |
0640 (VC4_GET_FIELD(p1, VC4_TEX_P1_TYPE4) << 4));
0641
0642 switch (type) {
0643 case VC4_TEXTURE_TYPE_RGBA8888:
0644 case VC4_TEXTURE_TYPE_RGBX8888:
0645 case VC4_TEXTURE_TYPE_RGBA32R:
0646 cpp = 4;
0647 break;
0648 case VC4_TEXTURE_TYPE_RGBA4444:
0649 case VC4_TEXTURE_TYPE_RGBA5551:
0650 case VC4_TEXTURE_TYPE_RGB565:
0651 case VC4_TEXTURE_TYPE_LUMALPHA:
0652 case VC4_TEXTURE_TYPE_S16F:
0653 case VC4_TEXTURE_TYPE_S16:
0654 cpp = 2;
0655 break;
0656 case VC4_TEXTURE_TYPE_LUMINANCE:
0657 case VC4_TEXTURE_TYPE_ALPHA:
0658 case VC4_TEXTURE_TYPE_S8:
0659 cpp = 1;
0660 break;
0661 case VC4_TEXTURE_TYPE_ETC1:
0662
0663
0664
0665 cpp = 8;
0666 width = (width + 3) >> 2;
0667 height = (height + 3) >> 2;
0668 break;
0669 case VC4_TEXTURE_TYPE_BW1:
0670 case VC4_TEXTURE_TYPE_A4:
0671 case VC4_TEXTURE_TYPE_A1:
0672 case VC4_TEXTURE_TYPE_RGBA64:
0673 case VC4_TEXTURE_TYPE_YUV422R:
0674 default:
0675 DRM_DEBUG("Texture format %d unsupported\n", type);
0676 goto fail;
0677 }
0678 utile_w = utile_width(cpp);
0679 utile_h = utile_height(cpp);
0680
0681 if (type == VC4_TEXTURE_TYPE_RGBA32R) {
0682 tiling_format = VC4_TILING_FORMAT_LINEAR;
0683 } else {
0684 if (size_is_lt(width, height, cpp))
0685 tiling_format = VC4_TILING_FORMAT_LT;
0686 else
0687 tiling_format = VC4_TILING_FORMAT_T;
0688 }
0689
0690 if (!vc4_check_tex_size(exec, tex, offset + cube_map_stride * 5,
0691 tiling_format, width, height, cpp)) {
0692 goto fail;
0693 }
0694
0695
0696
0697
0698 for (i = 1; i <= miplevels; i++) {
0699 uint32_t level_width = max(width >> i, 1u);
0700 uint32_t level_height = max(height >> i, 1u);
0701 uint32_t aligned_width, aligned_height;
0702 uint32_t level_size;
0703
0704
0705 if (tiling_format == VC4_TILING_FORMAT_T &&
0706 size_is_lt(level_width, level_height, cpp)) {
0707 tiling_format = VC4_TILING_FORMAT_LT;
0708 }
0709
0710 switch (tiling_format) {
0711 case VC4_TILING_FORMAT_T:
0712 aligned_width = round_up(level_width, utile_w * 8);
0713 aligned_height = round_up(level_height, utile_h * 8);
0714 break;
0715 case VC4_TILING_FORMAT_LT:
0716 aligned_width = round_up(level_width, utile_w);
0717 aligned_height = round_up(level_height, utile_h);
0718 break;
0719 default:
0720 aligned_width = round_up(level_width, utile_w);
0721 aligned_height = level_height;
0722 break;
0723 }
0724
0725 level_size = aligned_width * cpp * aligned_height;
0726
0727 if (offset < level_size) {
0728 DRM_DEBUG("Level %d (%dx%d -> %dx%d) size %db "
0729 "overflowed buffer bounds (offset %d)\n",
0730 i, level_width, level_height,
0731 aligned_width, aligned_height,
0732 level_size, offset);
0733 goto fail;
0734 }
0735
0736 offset -= level_size;
0737 }
0738
0739 *validated_p0 = tex->paddr + p0;
0740
0741 if (is_cs) {
0742 exec->bin_dep_seqno = max(exec->bin_dep_seqno,
0743 to_vc4_bo(&tex->base)->write_seqno);
0744 }
0745
0746 return true;
0747 fail:
0748 DRM_INFO("Texture p0 at %d: 0x%08x\n", sample->p_offset[0], p0);
0749 DRM_INFO("Texture p1 at %d: 0x%08x\n", sample->p_offset[1], p1);
0750 DRM_INFO("Texture p2 at %d: 0x%08x\n", sample->p_offset[2], p2);
0751 DRM_INFO("Texture p3 at %d: 0x%08x\n", sample->p_offset[3], p3);
0752 return false;
0753 }
0754
0755 static int
0756 validate_gl_shader_rec(struct drm_device *dev,
0757 struct vc4_exec_info *exec,
0758 struct vc4_shader_state *state)
0759 {
0760 uint32_t *src_handles;
0761 void *pkt_u, *pkt_v;
0762 static const uint32_t shader_reloc_offsets[] = {
0763 4,
0764 16,
0765 28,
0766 };
0767 uint32_t shader_reloc_count = ARRAY_SIZE(shader_reloc_offsets);
0768 struct drm_gem_cma_object *bo[ARRAY_SIZE(shader_reloc_offsets) + 8];
0769 uint32_t nr_attributes, nr_relocs, packet_size;
0770 int i;
0771
0772 nr_attributes = state->addr & 0x7;
0773 if (nr_attributes == 0)
0774 nr_attributes = 8;
0775 packet_size = gl_shader_rec_size(state->addr);
0776
0777 nr_relocs = ARRAY_SIZE(shader_reloc_offsets) + nr_attributes;
0778 if (nr_relocs * 4 > exec->shader_rec_size) {
0779 DRM_DEBUG("overflowed shader recs reading %d handles "
0780 "from %d bytes left\n",
0781 nr_relocs, exec->shader_rec_size);
0782 return -EINVAL;
0783 }
0784 src_handles = exec->shader_rec_u;
0785 exec->shader_rec_u += nr_relocs * 4;
0786 exec->shader_rec_size -= nr_relocs * 4;
0787
0788 if (packet_size > exec->shader_rec_size) {
0789 DRM_DEBUG("overflowed shader recs copying %db packet "
0790 "from %d bytes left\n",
0791 packet_size, exec->shader_rec_size);
0792 return -EINVAL;
0793 }
0794 pkt_u = exec->shader_rec_u;
0795 pkt_v = exec->shader_rec_v;
0796 memcpy(pkt_v, pkt_u, packet_size);
0797 exec->shader_rec_u += packet_size;
0798
0799
0800
0801
0802
0803 BUG_ON(roundup(packet_size, 16) - packet_size > nr_relocs * 4);
0804 exec->shader_rec_v += roundup(packet_size, 16);
0805 exec->shader_rec_size -= packet_size;
0806
0807 for (i = 0; i < shader_reloc_count; i++) {
0808 if (src_handles[i] > exec->bo_count) {
0809 DRM_DEBUG("Shader handle %d too big\n", src_handles[i]);
0810 return -EINVAL;
0811 }
0812
0813 bo[i] = exec->bo[src_handles[i]];
0814 if (!bo[i])
0815 return -EINVAL;
0816 }
0817 for (i = shader_reloc_count; i < nr_relocs; i++) {
0818 bo[i] = vc4_use_bo(exec, src_handles[i]);
0819 if (!bo[i])
0820 return -EINVAL;
0821 }
0822
0823 if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) !=
0824 to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) {
0825 DRM_DEBUG("Thread mode of CL and FS do not match\n");
0826 return -EINVAL;
0827 }
0828
0829 if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded ||
0830 to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) {
0831 DRM_DEBUG("cs and vs cannot be threaded\n");
0832 return -EINVAL;
0833 }
0834
0835 for (i = 0; i < shader_reloc_count; i++) {
0836 struct vc4_validated_shader_info *validated_shader;
0837 uint32_t o = shader_reloc_offsets[i];
0838 uint32_t src_offset = *(uint32_t *)(pkt_u + o);
0839 uint32_t *texture_handles_u;
0840 void *uniform_data_u;
0841 uint32_t tex, uni;
0842
0843 *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset;
0844
0845 if (src_offset != 0) {
0846 DRM_DEBUG("Shaders must be at offset 0 of "
0847 "the BO.\n");
0848 return -EINVAL;
0849 }
0850
0851 validated_shader = to_vc4_bo(&bo[i]->base)->validated_shader;
0852 if (!validated_shader)
0853 return -EINVAL;
0854
0855 if (validated_shader->uniforms_src_size >
0856 exec->uniforms_size) {
0857 DRM_DEBUG("Uniforms src buffer overflow\n");
0858 return -EINVAL;
0859 }
0860
0861 texture_handles_u = exec->uniforms_u;
0862 uniform_data_u = (texture_handles_u +
0863 validated_shader->num_texture_samples);
0864
0865 memcpy(exec->uniforms_v, uniform_data_u,
0866 validated_shader->uniforms_size);
0867
0868 for (tex = 0;
0869 tex < validated_shader->num_texture_samples;
0870 tex++) {
0871 if (!reloc_tex(exec,
0872 uniform_data_u,
0873 &validated_shader->texture_samples[tex],
0874 texture_handles_u[tex],
0875 i == 2)) {
0876 return -EINVAL;
0877 }
0878 }
0879
0880
0881
0882
0883
0884 for (uni = 0;
0885 uni < validated_shader->num_uniform_addr_offsets;
0886 uni++) {
0887 uint32_t o = validated_shader->uniform_addr_offsets[uni];
0888 ((uint32_t *)exec->uniforms_v)[o] = exec->uniforms_p;
0889 }
0890
0891 *(uint32_t *)(pkt_v + o + 4) = exec->uniforms_p;
0892
0893 exec->uniforms_u += validated_shader->uniforms_src_size;
0894 exec->uniforms_v += validated_shader->uniforms_size;
0895 exec->uniforms_p += validated_shader->uniforms_size;
0896 }
0897
0898 for (i = 0; i < nr_attributes; i++) {
0899 struct drm_gem_cma_object *vbo =
0900 bo[ARRAY_SIZE(shader_reloc_offsets) + i];
0901 uint32_t o = 36 + i * 8;
0902 uint32_t offset = *(uint32_t *)(pkt_u + o + 0);
0903 uint32_t attr_size = *(uint8_t *)(pkt_u + o + 4) + 1;
0904 uint32_t stride = *(uint8_t *)(pkt_u + o + 5);
0905 uint32_t max_index;
0906
0907 exec->bin_dep_seqno = max(exec->bin_dep_seqno,
0908 to_vc4_bo(&vbo->base)->write_seqno);
0909
0910 if (state->addr & 0x8)
0911 stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff;
0912
0913 if (vbo->base.size < offset ||
0914 vbo->base.size - offset < attr_size) {
0915 DRM_DEBUG("BO offset overflow (%d + %d > %zu)\n",
0916 offset, attr_size, vbo->base.size);
0917 return -EINVAL;
0918 }
0919
0920 if (stride != 0) {
0921 max_index = ((vbo->base.size - offset - attr_size) /
0922 stride);
0923 if (state->max_index > max_index) {
0924 DRM_DEBUG("primitives use index %d out of "
0925 "supplied %d\n",
0926 state->max_index, max_index);
0927 return -EINVAL;
0928 }
0929 }
0930
0931 *(uint32_t *)(pkt_v + o) = vbo->paddr + offset;
0932 }
0933
0934 return 0;
0935 }
0936
0937 int
0938 vc4_validate_shader_recs(struct drm_device *dev,
0939 struct vc4_exec_info *exec)
0940 {
0941 struct vc4_dev *vc4 = to_vc4_dev(dev);
0942 uint32_t i;
0943 int ret = 0;
0944
0945 if (WARN_ON_ONCE(vc4->is_vc5))
0946 return -ENODEV;
0947
0948 for (i = 0; i < exec->shader_state_count; i++) {
0949 ret = validate_gl_shader_rec(dev, exec, &exec->shader_state[i]);
0950 if (ret)
0951 return ret;
0952 }
0953
0954 return ret;
0955 }