vc4: Make the object be the return value from vc4_use_bo().
[mesa.git] / src / gallium / drivers / vc4 / kernel / vc4_validate.c
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 /**
25 * Command list validator for VC4.
26 *
27 * The VC4 has no IOMMU between it and system memory. So, a user with
28 * access to execute command lists could escalate privilege by
29 * overwriting system memory (drawing to it as a framebuffer) or
30 * reading system memory it shouldn't (reading it as a texture, or
31 * uniform data, or vertex data).
32 *
33 * This validates command lists to ensure that all accesses are within
34 * the bounds of the GEM objects referenced. It explicitly whitelists
35 * packets, and looks at the offsets in any address fields to make
36 * sure they're constrained within the BOs they reference.
37 *
38 * Note that because of the validation that's happening anyway, this
39 * is where GEM relocation processing happens.
40 */
41
42 #include "vc4_drv.h"
43 #include "vc4_packet.h"
44
45 #define VALIDATE_ARGS \
46 struct vc4_exec_info *exec, \
47 void *validated, \
48 void *untrusted
49
50
51 /** Return the width in pixels of a 64-byte microtile. */
52 static uint32_t
53 utile_width(int cpp)
54 {
55 switch (cpp) {
56 case 1:
57 case 2:
58 return 8;
59 case 4:
60 return 4;
61 case 8:
62 return 2;
63 default:
64 DRM_ERROR("unknown cpp: %d\n", cpp);
65 return 1;
66 }
67 }
68
69 /** Return the height in pixels of a 64-byte microtile. */
70 static uint32_t
71 utile_height(int cpp)
72 {
73 switch (cpp) {
74 case 1:
75 return 8;
76 case 2:
77 case 4:
78 case 8:
79 return 4;
80 default:
81 DRM_ERROR("unknown cpp: %d\n", cpp);
82 return 1;
83 }
84 }
85
86 /**
87 * The texture unit decides what tiling format a particular miplevel is using
88 * this function, so we lay out our miptrees accordingly.
89 */
90 static bool
91 size_is_lt(uint32_t width, uint32_t height, int cpp)
92 {
93 return (width <= 4 * utile_width(cpp) ||
94 height <= 4 * utile_height(cpp));
95 }
96
97 struct drm_gem_cma_object *
98 vc4_use_bo(struct vc4_exec_info *exec,
99 uint32_t hindex,
100 enum vc4_bo_mode mode)
101 {
102 struct drm_gem_cma_object *obj;
103
104 if (hindex >= exec->bo_count) {
105 DRM_ERROR("BO index %d greater than BO count %d\n",
106 hindex, exec->bo_count);
107 return NULL;
108 }
109 obj = exec->bo[hindex].bo;
110
111 if (exec->bo[hindex].mode != mode) {
112 if (exec->bo[hindex].mode == VC4_MODE_UNDECIDED) {
113 exec->bo[hindex].mode = mode;
114 } else {
115 DRM_ERROR("BO index %d reused with mode %d vs %d\n",
116 hindex, exec->bo[hindex].mode, mode);
117 return NULL;
118 }
119 }
120
121 return obj;
122 }
123
124 static struct drm_gem_cma_object *
125 vc4_use_handle(struct vc4_exec_info *exec,
126 uint32_t gem_handles_packet_index,
127 enum vc4_bo_mode mode)
128 {
129 return vc4_use_bo(exec, exec->bo_index[gem_handles_packet_index], mode);
130 }
131
132 static bool
133 validate_bin_pos(struct vc4_exec_info *exec, void *untrusted, uint32_t pos)
134 {
135 /* Note that the untrusted pointer passed to these functions is
136 * incremented past the packet byte.
137 */
138 return (untrusted - 1 == exec->bin_u + pos);
139 }
140
141 static uint32_t
142 gl_shader_rec_size(uint32_t pointer_bits)
143 {
144 uint32_t attribute_count = pointer_bits & 7;
145 bool extended = pointer_bits & 8;
146
147 if (attribute_count == 0)
148 attribute_count = 8;
149
150 if (extended)
151 return 100 + attribute_count * 4;
152 else
153 return 36 + attribute_count * 8;
154 }
155
156 bool
157 vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
158 uint32_t offset, uint8_t tiling_format,
159 uint32_t width, uint32_t height, uint8_t cpp)
160 {
161 uint32_t aligned_width, aligned_height, stride, size;
162 uint32_t utile_w = utile_width(cpp);
163 uint32_t utile_h = utile_height(cpp);
164
165 /* The shaded vertex format stores signed 12.4 fixed point
166 * (-2048,2047) offsets from the viewport center, so we should
167 * never have a render target larger than 4096. The texture
168 * unit can only sample from 2048x2048, so it's even more
169 * restricted. This lets us avoid worrying about overflow in
170 * our math.
171 */
172 if (width > 4096 || height > 4096) {
173 DRM_ERROR("Surface dimesions (%d,%d) too large", width, height);
174 return false;
175 }
176
177 switch (tiling_format) {
178 case VC4_TILING_FORMAT_LINEAR:
179 aligned_width = round_up(width, utile_w);
180 aligned_height = height;
181 break;
182 case VC4_TILING_FORMAT_T:
183 aligned_width = round_up(width, utile_w * 8);
184 aligned_height = round_up(height, utile_h * 8);
185 break;
186 case VC4_TILING_FORMAT_LT:
187 aligned_width = round_up(width, utile_w);
188 aligned_height = round_up(height, utile_h);
189 break;
190 default:
191 DRM_ERROR("buffer tiling %d unsupported\n", tiling_format);
192 return false;
193 }
194
195 stride = aligned_width * cpp;
196 size = stride * aligned_height;
197
198 if (size + offset < size ||
199 size + offset > fbo->base.size) {
200 DRM_ERROR("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %d)\n",
201 width, height,
202 aligned_width, aligned_height,
203 size, offset, fbo->base.size);
204 return false;
205 }
206
207 return true;
208 }
209
210
211 static int
212 validate_flush(VALIDATE_ARGS)
213 {
214 if (!validate_bin_pos(exec, untrusted, exec->args->bin_cl_size - 1)) {
215 DRM_ERROR("Bin CL must end with VC4_PACKET_FLUSH\n");
216 return false;
217 }
218 exec->found_flush = true;
219
220 return 0;
221 }
222
223 static int
224 validate_start_tile_binning(VALIDATE_ARGS)
225 {
226 if (exec->found_start_tile_binning_packet) {
227 DRM_ERROR("Duplicate VC4_PACKET_START_TILE_BINNING\n");
228 return -EINVAL;
229 }
230 exec->found_start_tile_binning_packet = true;
231
232 if (!exec->found_tile_binning_mode_config_packet) {
233 DRM_ERROR("missing VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
234 return -EINVAL;
235 }
236
237 return 0;
238 }
239
240 static int
241 validate_increment_semaphore(VALIDATE_ARGS)
242 {
243 if (!validate_bin_pos(exec, untrusted, exec->args->bin_cl_size - 2)) {
244 DRM_ERROR("Bin CL must end with "
245 "VC4_PACKET_INCREMENT_SEMAPHORE\n");
246 return -EINVAL;
247 }
248 exec->found_increment_semaphore_packet = true;
249
250 return 0;
251 }
252
253 static int
254 validate_indexed_prim_list(VALIDATE_ARGS)
255 {
256 struct drm_gem_cma_object *ib;
257 uint32_t length = *(uint32_t *)(untrusted + 1);
258 uint32_t offset = *(uint32_t *)(untrusted + 5);
259 uint32_t max_index = *(uint32_t *)(untrusted + 9);
260 uint32_t index_size = (*(uint8_t *)(untrusted + 0) >> 4) ? 2 : 1;
261 struct vc4_shader_state *shader_state;
262
263 /* Check overflow condition */
264 if (exec->shader_state_count == 0) {
265 DRM_ERROR("shader state must precede primitives\n");
266 return -EINVAL;
267 }
268 shader_state = &exec->shader_state[exec->shader_state_count - 1];
269
270 if (max_index > shader_state->max_index)
271 shader_state->max_index = max_index;
272
273 ib = vc4_use_handle(exec, 0, VC4_MODE_RENDER);
274 if (!ib)
275 return -EINVAL;
276
277 if (offset > ib->base.size ||
278 (ib->base.size - offset) / index_size < length) {
279 DRM_ERROR("IB access overflow (%d + %d*%d > %d)\n",
280 offset, length, index_size, ib->base.size);
281 return -EINVAL;
282 }
283
284 *(uint32_t *)(validated + 5) = ib->paddr + offset;
285
286 return 0;
287 }
288
289 static int
290 validate_gl_array_primitive(VALIDATE_ARGS)
291 {
292 uint32_t length = *(uint32_t *)(untrusted + 1);
293 uint32_t base_index = *(uint32_t *)(untrusted + 5);
294 uint32_t max_index;
295 struct vc4_shader_state *shader_state;
296
297 /* Check overflow condition */
298 if (exec->shader_state_count == 0) {
299 DRM_ERROR("shader state must precede primitives\n");
300 return -EINVAL;
301 }
302 shader_state = &exec->shader_state[exec->shader_state_count - 1];
303
304 if (length + base_index < length) {
305 DRM_ERROR("primitive vertex count overflow\n");
306 return -EINVAL;
307 }
308 max_index = length + base_index - 1;
309
310 if (max_index > shader_state->max_index)
311 shader_state->max_index = max_index;
312
313 return 0;
314 }
315
316 static int
317 validate_gl_shader_state(VALIDATE_ARGS)
318 {
319 uint32_t i = exec->shader_state_count++;
320
321 if (i >= exec->shader_state_size) {
322 DRM_ERROR("More requests for shader states than declared\n");
323 return -EINVAL;
324 }
325
326 exec->shader_state[i].addr = *(uint32_t *)untrusted;
327 exec->shader_state[i].max_index = 0;
328
329 if (exec->shader_state[i].addr & ~0xf) {
330 DRM_ERROR("high bits set in GL shader rec reference\n");
331 return -EINVAL;
332 }
333
334 *(uint32_t *)validated = (exec->shader_rec_p +
335 exec->shader_state[i].addr);
336
337 exec->shader_rec_p +=
338 roundup(gl_shader_rec_size(exec->shader_state[i].addr), 16);
339
340 return 0;
341 }
342
343 static int
344 validate_tile_binning_config(VALIDATE_ARGS)
345 {
346 struct drm_device *dev = exec->exec_bo->base.dev;
347 uint8_t flags;
348 uint32_t tile_state_size, tile_alloc_size;
349 uint32_t tile_count;
350
351 if (exec->found_tile_binning_mode_config_packet) {
352 DRM_ERROR("Duplicate VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
353 return -EINVAL;
354 }
355 exec->found_tile_binning_mode_config_packet = true;
356
357 exec->bin_tiles_x = *(uint8_t *)(untrusted + 12);
358 exec->bin_tiles_y = *(uint8_t *)(untrusted + 13);
359 tile_count = exec->bin_tiles_x * exec->bin_tiles_y;
360 flags = *(uint8_t *)(untrusted + 14);
361
362 if (exec->bin_tiles_x == 0 ||
363 exec->bin_tiles_y == 0) {
364 DRM_ERROR("Tile binning config of %dx%d too small\n",
365 exec->bin_tiles_x, exec->bin_tiles_y);
366 return -EINVAL;
367 }
368
369 if (flags & (VC4_BIN_CONFIG_DB_NON_MS |
370 VC4_BIN_CONFIG_TILE_BUFFER_64BIT |
371 VC4_BIN_CONFIG_MS_MODE_4X)) {
372 DRM_ERROR("unsupported bining config flags 0x%02x\n", flags);
373 return -EINVAL;
374 }
375
376 /* The tile state data array is 48 bytes per tile, and we put it at
377 * the start of a BO containing both it and the tile alloc.
378 */
379 tile_state_size = 48 * tile_count;
380
381 /* Since the tile alloc array will follow us, align. */
382 exec->tile_alloc_offset = roundup(tile_state_size, 4096);
383
384 *(uint8_t *)(validated + 14) =
385 ((flags & ~(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK |
386 VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_MASK)) |
387 VC4_BIN_CONFIG_AUTO_INIT_TSDA |
388 VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32,
389 VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE) |
390 VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_128,
391 VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE));
392
393 /* Initial block size. */
394 tile_alloc_size = 32 * tile_count;
395
396 /*
397 * The initial allocation gets rounded to the next 256 bytes before
398 * the hardware starts fulfilling further allocations.
399 */
400 tile_alloc_size = roundup(tile_alloc_size, 256);
401
402 /* Add space for the extra allocations. This is what gets used first,
403 * before overflow memory. It must have at least 4096 bytes, but we
404 * want to avoid overflow memory usage if possible.
405 */
406 tile_alloc_size += 1024 * 1024;
407
408 exec->tile_bo = drm_gem_cma_create(dev, exec->tile_alloc_offset +
409 tile_alloc_size);
410 if (!exec->tile_bo)
411 return -ENOMEM;
412 list_addtail(&to_vc4_bo(&exec->tile_bo->base)->unref_head,
413 &exec->unref_list);
414
415 /* tile alloc address. */
416 *(uint32_t *)(validated + 0) = (exec->tile_bo->paddr +
417 exec->tile_alloc_offset);
418 /* tile alloc size. */
419 *(uint32_t *)(validated + 4) = tile_alloc_size;
420 /* tile state address. */
421 *(uint32_t *)(validated + 8) = exec->tile_bo->paddr;
422
423 return 0;
424 }
425
426 static int
427 validate_gem_handles(VALIDATE_ARGS)
428 {
429 memcpy(exec->bo_index, untrusted, sizeof(exec->bo_index));
430 return 0;
431 }
432
433 #define VC4_DEFINE_PACKET(packet, name, func) \
434 [packet] = { packet ## _SIZE, name, func }
435
436 static const struct cmd_info {
437 uint16_t len;
438 const char *name;
439 int (*func)(struct vc4_exec_info *exec, void *validated,
440 void *untrusted);
441 } cmd_info[] = {
442 VC4_DEFINE_PACKET(VC4_PACKET_HALT, "halt", NULL),
443 VC4_DEFINE_PACKET(VC4_PACKET_NOP, "nop", NULL),
444 VC4_DEFINE_PACKET(VC4_PACKET_FLUSH, "flush", validate_flush),
445 VC4_DEFINE_PACKET(VC4_PACKET_FLUSH_ALL, "flush all state", NULL),
446 VC4_DEFINE_PACKET(VC4_PACKET_START_TILE_BINNING, "start tile binning", validate_start_tile_binning),
447 VC4_DEFINE_PACKET(VC4_PACKET_INCREMENT_SEMAPHORE, "increment semaphore", validate_increment_semaphore),
448
449 VC4_DEFINE_PACKET(VC4_PACKET_GL_INDEXED_PRIMITIVE, "Indexed Primitive List", validate_indexed_prim_list),
450
451 VC4_DEFINE_PACKET(VC4_PACKET_GL_ARRAY_PRIMITIVE, "Vertex Array Primitives", validate_gl_array_primitive),
452
453 /* This is only used by clipped primitives (packets 48 and 49), which
454 * we don't support parsing yet.
455 */
456 VC4_DEFINE_PACKET(VC4_PACKET_PRIMITIVE_LIST_FORMAT, "primitive list format", NULL),
457
458 VC4_DEFINE_PACKET(VC4_PACKET_GL_SHADER_STATE, "GL Shader State", validate_gl_shader_state),
459 /* We don't support validating NV shader states. */
460
461 VC4_DEFINE_PACKET(VC4_PACKET_CONFIGURATION_BITS, "configuration bits", NULL),
462 VC4_DEFINE_PACKET(VC4_PACKET_FLAT_SHADE_FLAGS, "flat shade flags", NULL),
463 VC4_DEFINE_PACKET(VC4_PACKET_POINT_SIZE, "point size", NULL),
464 VC4_DEFINE_PACKET(VC4_PACKET_LINE_WIDTH, "line width", NULL),
465 VC4_DEFINE_PACKET(VC4_PACKET_RHT_X_BOUNDARY, "RHT X boundary", NULL),
466 VC4_DEFINE_PACKET(VC4_PACKET_DEPTH_OFFSET, "Depth Offset", NULL),
467 VC4_DEFINE_PACKET(VC4_PACKET_CLIP_WINDOW, "Clip Window", NULL),
468 VC4_DEFINE_PACKET(VC4_PACKET_VIEWPORT_OFFSET, "Viewport Offset", NULL),
469 VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_XY_SCALING, "Clipper XY Scaling", NULL),
470 /* Note: The docs say this was also 105, but it was 106 in the
471 * initial userland code drop.
472 */
473 VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_Z_SCALING, "Clipper Z Scale and Offset", NULL),
474
475 VC4_DEFINE_PACKET(VC4_PACKET_TILE_BINNING_MODE_CONFIG, "tile binning configuration", validate_tile_binning_config),
476
477 VC4_DEFINE_PACKET(VC4_PACKET_GEM_HANDLES, "GEM handles", validate_gem_handles),
478 };
479
480 int
481 vc4_validate_bin_cl(struct drm_device *dev,
482 void *validated,
483 void *unvalidated,
484 struct vc4_exec_info *exec)
485 {
486 uint32_t len = exec->args->bin_cl_size;
487 uint32_t dst_offset = 0;
488 uint32_t src_offset = 0;
489
490 while (src_offset < len) {
491 void *dst_pkt = validated + dst_offset;
492 void *src_pkt = unvalidated + src_offset;
493 u8 cmd = *(uint8_t *)src_pkt;
494 const struct cmd_info *info;
495
496 if (cmd > ARRAY_SIZE(cmd_info)) {
497 DRM_ERROR("0x%08x: packet %d out of bounds\n",
498 src_offset, cmd);
499 return -EINVAL;
500 }
501
502 info = &cmd_info[cmd];
503 if (!info->name) {
504 DRM_ERROR("0x%08x: packet %d invalid\n",
505 src_offset, cmd);
506 return -EINVAL;
507 }
508
509 #if 0
510 DRM_INFO("0x%08x: packet %d (%s) size %d processing...\n",
511 src_offset, cmd, info->name, info->len);
512 #endif
513
514 if (src_offset + info->len > len) {
515 DRM_ERROR("0x%08x: packet %d (%s) length 0x%08x "
516 "exceeds bounds (0x%08x)\n",
517 src_offset, cmd, info->name, info->len,
518 src_offset + len);
519 return -EINVAL;
520 }
521
522 if (cmd != VC4_PACKET_GEM_HANDLES)
523 memcpy(dst_pkt, src_pkt, info->len);
524
525 if (info->func && info->func(exec,
526 dst_pkt + 1,
527 src_pkt + 1)) {
528 DRM_ERROR("0x%08x: packet %d (%s) failed to "
529 "validate\n",
530 src_offset, cmd, info->name);
531 return -EINVAL;
532 }
533
534 src_offset += info->len;
535 /* GEM handle loading doesn't produce HW packets. */
536 if (cmd != VC4_PACKET_GEM_HANDLES)
537 dst_offset += info->len;
538
539 /* When the CL hits halt, it'll stop reading anything else. */
540 if (cmd == VC4_PACKET_HALT)
541 break;
542 }
543
544 exec->ct0ea = exec->ct0ca + dst_offset;
545
546 if (!exec->found_start_tile_binning_packet) {
547 DRM_ERROR("Bin CL missing VC4_PACKET_START_TILE_BINNING\n");
548 return -EINVAL;
549 }
550
551 /* The bin CL must be ended with INCREMENT_SEMAPHORE and FLUSH. The
552 * semaphore is used to trigger the render CL to start up, and the
553 * FLUSH is what caps the bin lists with
554 * VC4_PACKET_RETURN_FROM_SUB_LIST (so they jump back to the main
555 * render CL when they get called to) and actually triggers the queued
556 * semaphore increment.
557 */
558 if (!exec->found_increment_semaphore_packet || !exec->found_flush) {
559 DRM_ERROR("Bin CL missing VC4_PACKET_INCREMENT_SEMAPHORE + "
560 "VC4_PACKET_FLUSH\n");
561 return -EINVAL;
562 }
563
564 return 0;
565 }
566
567 static bool
568 reloc_tex(struct vc4_exec_info *exec,
569 void *uniform_data_u,
570 struct vc4_texture_sample_info *sample,
571 uint32_t texture_handle_index)
572
573 {
574 struct drm_gem_cma_object *tex;
575 uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]);
576 uint32_t p1 = *(uint32_t *)(uniform_data_u + sample->p_offset[1]);
577 uint32_t p2 = (sample->p_offset[2] != ~0 ?
578 *(uint32_t *)(uniform_data_u + sample->p_offset[2]) : 0);
579 uint32_t p3 = (sample->p_offset[3] != ~0 ?
580 *(uint32_t *)(uniform_data_u + sample->p_offset[3]) : 0);
581 uint32_t *validated_p0 = exec->uniforms_v + sample->p_offset[0];
582 uint32_t offset = p0 & VC4_TEX_P0_OFFSET_MASK;
583 uint32_t miplevels = VC4_GET_FIELD(p0, VC4_TEX_P0_MIPLVLS);
584 uint32_t width = VC4_GET_FIELD(p1, VC4_TEX_P1_WIDTH);
585 uint32_t height = VC4_GET_FIELD(p1, VC4_TEX_P1_HEIGHT);
586 uint32_t cpp, tiling_format, utile_w, utile_h;
587 uint32_t i;
588 uint32_t cube_map_stride = 0;
589 enum vc4_texture_data_type type;
590
591 tex = vc4_use_bo(exec, texture_handle_index, VC4_MODE_RENDER);
592 if (!tex)
593 return false;
594
595 if (sample->is_direct) {
596 uint32_t remaining_size = tex->base.size - p0;
597 if (p0 > tex->base.size - 4) {
598 DRM_ERROR("UBO offset greater than UBO size\n");
599 goto fail;
600 }
601 if (p1 > remaining_size - 4) {
602 DRM_ERROR("UBO clamp would allow reads outside of UBO\n");
603 goto fail;
604 }
605 *validated_p0 = tex->paddr + p0;
606 return true;
607 }
608
609 if (width == 0)
610 width = 2048;
611 if (height == 0)
612 height = 2048;
613
614 if (p0 & VC4_TEX_P0_CMMODE_MASK) {
615 if (VC4_GET_FIELD(p2, VC4_TEX_P2_PTYPE) ==
616 VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE)
617 cube_map_stride = p2 & VC4_TEX_P2_CMST_MASK;
618 if (VC4_GET_FIELD(p3, VC4_TEX_P2_PTYPE) ==
619 VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE) {
620 if (cube_map_stride) {
621 DRM_ERROR("Cube map stride set twice\n");
622 goto fail;
623 }
624
625 cube_map_stride = p3 & VC4_TEX_P2_CMST_MASK;
626 }
627 if (!cube_map_stride) {
628 DRM_ERROR("Cube map stride not set\n");
629 goto fail;
630 }
631 }
632
633 type = (VC4_GET_FIELD(p0, VC4_TEX_P0_TYPE) |
634 (VC4_GET_FIELD(p1, VC4_TEX_P1_TYPE4) << 4));
635
636 switch (type) {
637 case VC4_TEXTURE_TYPE_RGBA8888:
638 case VC4_TEXTURE_TYPE_RGBX8888:
639 case VC4_TEXTURE_TYPE_RGBA32R:
640 cpp = 4;
641 break;
642 case VC4_TEXTURE_TYPE_RGBA4444:
643 case VC4_TEXTURE_TYPE_RGBA5551:
644 case VC4_TEXTURE_TYPE_RGB565:
645 case VC4_TEXTURE_TYPE_LUMALPHA:
646 case VC4_TEXTURE_TYPE_S16F:
647 case VC4_TEXTURE_TYPE_S16:
648 cpp = 2;
649 break;
650 case VC4_TEXTURE_TYPE_LUMINANCE:
651 case VC4_TEXTURE_TYPE_ALPHA:
652 case VC4_TEXTURE_TYPE_S8:
653 cpp = 1;
654 break;
655 case VC4_TEXTURE_TYPE_ETC1:
656 case VC4_TEXTURE_TYPE_BW1:
657 case VC4_TEXTURE_TYPE_A4:
658 case VC4_TEXTURE_TYPE_A1:
659 case VC4_TEXTURE_TYPE_RGBA64:
660 case VC4_TEXTURE_TYPE_YUV422R:
661 default:
662 DRM_ERROR("Texture format %d unsupported\n", type);
663 goto fail;
664 }
665 utile_w = utile_width(cpp);
666 utile_h = utile_height(cpp);
667
668 if (type == VC4_TEXTURE_TYPE_RGBA32R) {
669 tiling_format = VC4_TILING_FORMAT_LINEAR;
670 } else {
671 if (size_is_lt(width, height, cpp))
672 tiling_format = VC4_TILING_FORMAT_LT;
673 else
674 tiling_format = VC4_TILING_FORMAT_T;
675 }
676
677 if (!vc4_check_tex_size(exec, tex, offset + cube_map_stride * 5,
678 tiling_format, width, height, cpp)) {
679 goto fail;
680 }
681
682 /* The mipmap levels are stored before the base of the texture. Make
683 * sure there is actually space in the BO.
684 */
685 for (i = 1; i <= miplevels; i++) {
686 uint32_t level_width = max(width >> i, 1u);
687 uint32_t level_height = max(height >> i, 1u);
688 uint32_t aligned_width, aligned_height;
689 uint32_t level_size;
690
691 /* Once the levels get small enough, they drop from T to LT. */
692 if (tiling_format == VC4_TILING_FORMAT_T &&
693 size_is_lt(level_width, level_height, cpp)) {
694 tiling_format = VC4_TILING_FORMAT_LT;
695 }
696
697 switch (tiling_format) {
698 case VC4_TILING_FORMAT_T:
699 aligned_width = round_up(level_width, utile_w * 8);
700 aligned_height = round_up(level_height, utile_h * 8);
701 break;
702 case VC4_TILING_FORMAT_LT:
703 aligned_width = round_up(level_width, utile_w);
704 aligned_height = round_up(level_height, utile_h);
705 break;
706 default:
707 aligned_width = round_up(level_width, utile_w);
708 aligned_height = level_height;
709 break;
710 }
711
712 level_size = aligned_width * cpp * aligned_height;
713
714 if (offset < level_size) {
715 DRM_ERROR("Level %d (%dx%d -> %dx%d) size %db "
716 "overflowed buffer bounds (offset %d)\n",
717 i, level_width, level_height,
718 aligned_width, aligned_height,
719 level_size, offset);
720 goto fail;
721 }
722
723 offset -= level_size;
724 }
725
726 *validated_p0 = tex->paddr + p0;
727
728 return true;
729 fail:
730 DRM_INFO("Texture p0 at %d: 0x%08x\n", sample->p_offset[0], p0);
731 DRM_INFO("Texture p1 at %d: 0x%08x\n", sample->p_offset[1], p1);
732 DRM_INFO("Texture p2 at %d: 0x%08x\n", sample->p_offset[2], p2);
733 DRM_INFO("Texture p3 at %d: 0x%08x\n", sample->p_offset[3], p3);
734 return false;
735 }
736
737 static int
738 validate_gl_shader_rec(struct drm_device *dev,
739 struct vc4_exec_info *exec,
740 struct vc4_shader_state *state)
741 {
742 uint32_t *src_handles;
743 void *pkt_u, *pkt_v;
744 static const uint32_t shader_reloc_offsets[] = {
745 4, /* fs */
746 16, /* vs */
747 28, /* cs */
748 };
749 uint32_t shader_reloc_count = ARRAY_SIZE(shader_reloc_offsets);
750 struct drm_gem_cma_object *bo[shader_reloc_count + 8];
751 uint32_t nr_attributes, nr_relocs, packet_size;
752 int i;
753 struct vc4_validated_shader_info *validated_shader = NULL;
754
755 nr_attributes = state->addr & 0x7;
756 if (nr_attributes == 0)
757 nr_attributes = 8;
758 packet_size = gl_shader_rec_size(state->addr);
759
760 nr_relocs = ARRAY_SIZE(shader_reloc_offsets) + nr_attributes;
761 if (nr_relocs * 4 > exec->shader_rec_size) {
762 DRM_ERROR("overflowed shader recs reading %d handles "
763 "from %d bytes left\n",
764 nr_relocs, exec->shader_rec_size);
765 return -EINVAL;
766 }
767 src_handles = exec->shader_rec_u;
768 exec->shader_rec_u += nr_relocs * 4;
769 exec->shader_rec_size -= nr_relocs * 4;
770
771 if (packet_size > exec->shader_rec_size) {
772 DRM_ERROR("overflowed shader recs copying %db packet "
773 "from %d bytes left\n",
774 packet_size, exec->shader_rec_size);
775 return -EINVAL;
776 }
777 pkt_u = exec->shader_rec_u;
778 pkt_v = exec->shader_rec_v;
779 memcpy(pkt_v, pkt_u, packet_size);
780 exec->shader_rec_u += packet_size;
781 /* Shader recs have to be aligned to 16 bytes (due to the attribute
782 * flags being in the low bytes), so round the next validated shader
783 * rec address up. This should be safe, since we've got so many
784 * relocations in a shader rec packet.
785 */
786 BUG_ON(roundup(packet_size, 16) - packet_size > nr_relocs * 4);
787 exec->shader_rec_v += roundup(packet_size, 16);
788 exec->shader_rec_size -= packet_size;
789
790 for (i = 0; i < shader_reloc_count; i++) {
791 bo[i] = vc4_use_bo(exec, src_handles[i], VC4_MODE_SHADER);
792 if (!bo[i])
793 return false;
794 }
795 for (i = shader_reloc_count; i < nr_relocs; i++) {
796 bo[i] = vc4_use_bo(exec, src_handles[i], VC4_MODE_RENDER);
797 if (!bo[i])
798 return false;
799 }
800
801 for (i = 0; i < shader_reloc_count; i++) {
802 uint32_t o = shader_reloc_offsets[i];
803 uint32_t src_offset = *(uint32_t *)(pkt_u + o);
804 uint32_t *texture_handles_u;
805 void *uniform_data_u;
806 uint32_t tex;
807
808 *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset;
809
810 if (src_offset != 0) {
811 DRM_ERROR("Shaders must be at offset 0 of "
812 "the BO.\n");
813 goto fail;
814 }
815
816 kfree(validated_shader);
817 validated_shader = vc4_validate_shader(bo[i]);
818 if (!validated_shader)
819 goto fail;
820
821 if (validated_shader->uniforms_src_size >
822 exec->uniforms_size) {
823 DRM_ERROR("Uniforms src buffer overflow\n");
824 goto fail;
825 }
826
827 texture_handles_u = exec->uniforms_u;
828 uniform_data_u = (texture_handles_u +
829 validated_shader->num_texture_samples);
830
831 memcpy(exec->uniforms_v, uniform_data_u,
832 validated_shader->uniforms_size);
833
834 for (tex = 0;
835 tex < validated_shader->num_texture_samples;
836 tex++) {
837 if (!reloc_tex(exec,
838 uniform_data_u,
839 &validated_shader->texture_samples[tex],
840 texture_handles_u[tex])) {
841 goto fail;
842 }
843 }
844
845 *(uint32_t *)(pkt_v + o + 4) = exec->uniforms_p;
846
847 exec->uniforms_u += validated_shader->uniforms_src_size;
848 exec->uniforms_v += validated_shader->uniforms_size;
849 exec->uniforms_p += validated_shader->uniforms_size;
850 }
851
852 for (i = 0; i < nr_attributes; i++) {
853 struct drm_gem_cma_object *vbo =
854 bo[ARRAY_SIZE(shader_reloc_offsets) + i];
855 uint32_t o = 36 + i * 8;
856 uint32_t offset = *(uint32_t *)(pkt_u + o + 0);
857 uint32_t attr_size = *(uint8_t *)(pkt_u + o + 4) + 1;
858 uint32_t stride = *(uint8_t *)(pkt_u + o + 5);
859 uint32_t max_index;
860
861 if (state->addr & 0x8)
862 stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff;
863
864 if (vbo->base.size < offset ||
865 vbo->base.size - offset < attr_size) {
866 DRM_ERROR("BO offset overflow (%d + %d > %d)\n",
867 offset, attr_size, vbo->base.size);
868 return -EINVAL;
869 }
870
871 if (stride != 0) {
872 max_index = ((vbo->base.size - offset - attr_size) /
873 stride);
874 if (state->max_index > max_index) {
875 DRM_ERROR("primitives use index %d out of supplied %d\n",
876 state->max_index, max_index);
877 return -EINVAL;
878 }
879 }
880
881 *(uint32_t *)(pkt_v + o) = vbo->paddr + offset;
882 }
883
884 kfree(validated_shader);
885
886 return 0;
887
888 fail:
889 kfree(validated_shader);
890 return -EINVAL;
891 }
892
893 int
894 vc4_validate_shader_recs(struct drm_device *dev,
895 struct vc4_exec_info *exec)
896 {
897 uint32_t i;
898 int ret = 0;
899
900 for (i = 0; i < exec->shader_state_count; i++) {
901 ret = validate_gl_shader_rec(dev, exec, &exec->shader_state[i]);
902 if (ret)
903 return ret;
904 }
905
906 return ret;
907 }