Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. static bool
  98. vc4_use_bo(struct vc4_exec_info *exec,
  99.            uint32_t hindex,
  100.            enum vc4_bo_mode mode,
  101.            struct drm_gem_cma_object **obj)
  102. {
  103.         *obj = NULL;
  104.  
  105.         if (hindex >= exec->bo_count) {
  106.                 DRM_ERROR("BO index %d greater than BO count %d\n",
  107.                           hindex, exec->bo_count);
  108.                 return false;
  109.         }
  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 false;
  118.                 }
  119.         }
  120.  
  121.         *obj = exec->bo[hindex].bo;
  122.         return true;
  123. }
  124.  
  125. static bool
  126. vc4_use_handle(struct vc4_exec_info *exec,
  127.                uint32_t gem_handles_packet_index,
  128.                enum vc4_bo_mode mode,
  129.                struct drm_gem_cma_object **obj)
  130. {
  131.         return vc4_use_bo(exec, exec->bo_index[gem_handles_packet_index],
  132.                           mode, obj);
  133. }
  134.  
  135. static uint32_t
  136. gl_shader_rec_size(uint32_t pointer_bits)
  137. {
  138.         uint32_t attribute_count = pointer_bits & 7;
  139.         bool extended = pointer_bits & 8;
  140.  
  141.         if (attribute_count == 0)
  142.                 attribute_count = 8;
  143.  
  144.         if (extended)
  145.                 return 100 + attribute_count * 4;
  146.         else
  147.                 return 36 + attribute_count * 8;
  148. }
  149.  
  150. static bool
  151. check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
  152.                uint32_t offset, uint8_t tiling_format,
  153.                uint32_t width, uint32_t height, uint8_t cpp)
  154. {
  155.         uint32_t aligned_width, aligned_height, stride, size;
  156.         uint32_t utile_w = utile_width(cpp);
  157.         uint32_t utile_h = utile_height(cpp);
  158.  
  159.         /* The values are limited by the packet/texture parameter bitfields,
  160.          * so we don't need to worry as much about integer overflow.
  161.          */
  162.         BUG_ON(width > 65535);
  163.         BUG_ON(height > 65535);
  164.  
  165.         switch (tiling_format) {
  166.         case VC4_TILING_FORMAT_LINEAR:
  167.                 aligned_width = roundup(width, utile_w);
  168.                 aligned_height = height;
  169.                 break;
  170.         case VC4_TILING_FORMAT_T:
  171.                 aligned_width = roundup(width, utile_w * 8);
  172.                 aligned_height = roundup(height, utile_h * 8);
  173.                 break;
  174.         case VC4_TILING_FORMAT_LT:
  175.                 aligned_width = roundup(width, utile_w);
  176.                 aligned_height = roundup(height, utile_h);
  177.                 break;
  178.         default:
  179.                 DRM_ERROR("buffer tiling %d unsupported\n", tiling_format);
  180.                 return false;
  181.         }
  182.  
  183.         stride = aligned_width * cpp;
  184.  
  185.         if (INT_MAX / stride < aligned_height) {
  186.                 DRM_ERROR("Overflow in fbo size (%dx%d -> %dx%d)\n",
  187.                           width, height,
  188.                           aligned_width, aligned_height);
  189.                 return false;
  190.         }
  191.         size = stride * aligned_height;
  192.  
  193.         if (size + offset < size ||
  194.             size + offset > fbo->base.size) {
  195.                 DRM_ERROR("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %d)\n",
  196.                           width, height,
  197.                           aligned_width, aligned_height,
  198.                           size, offset, fbo->base.size);
  199.                 return false;
  200.         }
  201.  
  202.         return true;
  203. }
  204.  
  205. static int
  206. validate_flush_all(VALIDATE_ARGS)
  207. {
  208.         if (exec->found_increment_semaphore_packet) {
  209.                 DRM_ERROR("VC4_PACKET_FLUSH_ALL after "
  210.                           "VC4_PACKET_INCREMENT_SEMAPHORE\n");
  211.                 return -EINVAL;
  212.         }
  213.  
  214.         return 0;
  215. }
  216.  
  217. static int
  218. validate_start_tile_binning(VALIDATE_ARGS)
  219. {
  220.         if (exec->found_start_tile_binning_packet) {
  221.                 DRM_ERROR("Duplicate VC4_PACKET_START_TILE_BINNING\n");
  222.                 return -EINVAL;
  223.         }
  224.         exec->found_start_tile_binning_packet = true;
  225.  
  226.         if (!exec->found_tile_binning_mode_config_packet) {
  227.                 DRM_ERROR("missing VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
  228.                 return -EINVAL;
  229.         }
  230.  
  231.         return 0;
  232. }
  233.  
  234. static int
  235. validate_increment_semaphore(VALIDATE_ARGS)
  236. {
  237.         if (exec->found_increment_semaphore_packet) {
  238.                 DRM_ERROR("Duplicate VC4_PACKET_INCREMENT_SEMAPHORE\n");
  239.                 return -EINVAL;
  240.         }
  241.         exec->found_increment_semaphore_packet = true;
  242.  
  243.         /* Once we've found the semaphore increment, there should be one FLUSH
  244.          * then the end of the command list.  The FLUSH actually triggers the
  245.          * increment, so we only need to make sure there
  246.          */
  247.  
  248.         return 0;
  249. }
  250.  
  251. static int
  252. validate_wait_on_semaphore(VALIDATE_ARGS)
  253. {
  254.         if (exec->found_wait_on_semaphore_packet) {
  255.                 DRM_ERROR("Duplicate VC4_PACKET_WAIT_ON_SEMAPHORE\n");
  256.                 return -EINVAL;
  257.         }
  258.         exec->found_wait_on_semaphore_packet = true;
  259.  
  260.         if (!exec->found_increment_semaphore_packet) {
  261.                 DRM_ERROR("VC4_PACKET_WAIT_ON_SEMAPHORE without "
  262.                           "VC4_PACKET_INCREMENT_SEMAPHORE\n");
  263.                 return -EINVAL;
  264.         }
  265.  
  266.         return 0;
  267. }
  268.  
  269. static int
  270. validate_branch_to_sublist(VALIDATE_ARGS)
  271. {
  272.         struct drm_gem_cma_object *target;
  273.         uint32_t offset;
  274.  
  275.         if (!vc4_use_handle(exec, 0, VC4_MODE_TILE_ALLOC, &target))
  276.                 return -EINVAL;
  277.  
  278.         if (target != exec->tile_alloc_bo) {
  279.                 DRM_ERROR("Jumping to BOs other than tile alloc unsupported\n");
  280.                 return -EINVAL;
  281.         }
  282.  
  283.         if (!exec->found_wait_on_semaphore_packet) {
  284.                 DRM_ERROR("Jumping to tile alloc before binning finished.\n");
  285.                 return -EINVAL;
  286.         }
  287.  
  288.         offset = *(uint32_t *)(untrusted + 0);
  289.         if (offset % exec->tile_alloc_init_block_size ||
  290.             offset / exec->tile_alloc_init_block_size >=
  291.             exec->bin_tiles_x * exec->bin_tiles_y) {
  292.                 DRM_ERROR("VC4_PACKET_BRANCH_TO_SUB_LIST must jump to initial "
  293.                           "tile allocation space.\n");
  294.                 return -EINVAL;
  295.         }
  296.  
  297.         *(uint32_t *)(validated + 0) = target->paddr + offset;
  298.  
  299.         return 0;
  300. }
  301.  
  302. /**
  303.  * validate_loadstore_tile_buffer_general() - Validation for
  304.  * VC4_PACKET_LOAD_TILE_BUFFER_GENERAL and
  305.  * VC4_PACKET_STORE_TILE_BUFFER_GENERAL.
  306.  *
  307.  * The two packets are nearly the same, except for the TLB-clearing management
  308.  * bits not being present for loads.  Additionally, while stores are executed
  309.  * immediately (using the current tile coordinates), loads are queued to be
  310.  * executed when the tile coordinates packet occurs.
  311.  *
  312.  * Note that coordinates packets are validated to be within the declared
  313.  * bin_x/y, which themselves are verified to match the rendering-configuration
  314.  * FB width and height (which the hardware uses to clip loads and stores).
  315.  */
  316. static int
  317. validate_loadstore_tile_buffer_general(VALIDATE_ARGS)
  318. {
  319.         uint32_t packet_b0 = *(uint8_t *)(untrusted + 0);
  320.         uint32_t packet_b1 = *(uint8_t *)(untrusted + 1);
  321.         struct drm_gem_cma_object *fbo;
  322.         uint32_t buffer_type = packet_b0 & 0xf;
  323.         uint32_t untrusted_address, offset, cpp;
  324.  
  325.         switch (buffer_type) {
  326.         case VC4_LOADSTORE_TILE_BUFFER_NONE:
  327.                 return 0;
  328.         case VC4_LOADSTORE_TILE_BUFFER_COLOR:
  329.                 if ((packet_b1 & VC4_LOADSTORE_TILE_BUFFER_MASK) ==
  330.                     VC4_LOADSTORE_TILE_BUFFER_RGBA8888) {
  331.                         cpp = 4;
  332.                 } else {
  333.                         cpp = 2;
  334.                 }
  335.                 break;
  336.  
  337.         case VC4_LOADSTORE_TILE_BUFFER_Z:
  338.         case VC4_LOADSTORE_TILE_BUFFER_ZS:
  339.                 cpp = 4;
  340.                 break;
  341.  
  342.         default:
  343.                 DRM_ERROR("Load/store type %d unsupported\n", buffer_type);
  344.                 return -EINVAL;
  345.         }
  346.  
  347.         if (!vc4_use_handle(exec, 0, VC4_MODE_RENDER, &fbo))
  348.                 return -EINVAL;
  349.  
  350.         untrusted_address = *(uint32_t *)(untrusted + 2);
  351.         offset = untrusted_address & ~0xf;
  352.  
  353.         if (!check_tex_size(exec, fbo, offset,
  354.                             ((packet_b0 &
  355.                               VC4_LOADSTORE_TILE_BUFFER_FORMAT_MASK) >>
  356.                              VC4_LOADSTORE_TILE_BUFFER_FORMAT_SHIFT),
  357.                             exec->fb_width, exec->fb_height, cpp)) {
  358.                 return -EINVAL;
  359.         }
  360.  
  361.         *(uint32_t *)(validated + 2) = (offset + fbo->paddr +
  362.                                         (untrusted_address & 0xf));
  363.  
  364.         return 0;
  365. }
  366.  
  367. static int
  368. validate_indexed_prim_list(VALIDATE_ARGS)
  369. {
  370.         struct drm_gem_cma_object *ib;
  371.         uint32_t length = *(uint32_t *)(untrusted + 1);
  372.         uint32_t offset = *(uint32_t *)(untrusted + 5);
  373.         uint32_t max_index = *(uint32_t *)(untrusted + 9);
  374.         uint32_t index_size = (*(uint8_t *)(untrusted + 0) >> 4) ? 2 : 1;
  375.         struct vc4_shader_state *shader_state;
  376.  
  377.         if (exec->found_increment_semaphore_packet) {
  378.                 DRM_ERROR("Drawing after VC4_PACKET_INCREMENT_SEMAPHORE\n");
  379.                 return -EINVAL;
  380.         }
  381.  
  382.         /* Check overflow condition */
  383.         if (exec->shader_state_count == 0) {
  384.                 DRM_ERROR("shader state must precede primitives\n");
  385.                 return -EINVAL;
  386.         }
  387.         shader_state = &exec->shader_state[exec->shader_state_count - 1];
  388.  
  389.         if (max_index > shader_state->max_index)
  390.                 shader_state->max_index = max_index;
  391.  
  392.         if (!vc4_use_handle(exec, 0, VC4_MODE_RENDER, &ib))
  393.                 return -EINVAL;
  394.  
  395.         if (offset > ib->base.size ||
  396.             (ib->base.size - offset) / index_size < length) {
  397.                 DRM_ERROR("IB access overflow (%d + %d*%d > %d)\n",
  398.                           offset, length, index_size, ib->base.size);
  399.                 return -EINVAL;
  400.         }
  401.  
  402.         *(uint32_t *)(validated + 5) = ib->paddr + offset;
  403.  
  404.         return 0;
  405. }
  406.  
  407. static int
  408. validate_gl_array_primitive(VALIDATE_ARGS)
  409. {
  410.         uint32_t length = *(uint32_t *)(untrusted + 1);
  411.         uint32_t base_index = *(uint32_t *)(untrusted + 5);
  412.         uint32_t max_index;
  413.         struct vc4_shader_state *shader_state;
  414.  
  415.         if (exec->found_increment_semaphore_packet) {
  416.                 DRM_ERROR("Drawing after VC4_PACKET_INCREMENT_SEMAPHORE\n");
  417.                 return -EINVAL;
  418.         }
  419.  
  420.         /* Check overflow condition */
  421.         if (exec->shader_state_count == 0) {
  422.                 DRM_ERROR("shader state must precede primitives\n");
  423.                 return -EINVAL;
  424.         }
  425.         shader_state = &exec->shader_state[exec->shader_state_count - 1];
  426.  
  427.         if (length + base_index < length) {
  428.                 DRM_ERROR("primitive vertex count overflow\n");
  429.                 return -EINVAL;
  430.         }
  431.         max_index = length + base_index - 1;
  432.  
  433.         if (max_index > shader_state->max_index)
  434.                 shader_state->max_index = max_index;
  435.  
  436.         return 0;
  437. }
  438.  
  439. static int
  440. validate_gl_shader_state(VALIDATE_ARGS)
  441. {
  442.         uint32_t i = exec->shader_state_count++;
  443.  
  444.         if (i >= exec->shader_state_size) {
  445.                 DRM_ERROR("More requests for shader states than declared\n");
  446.                 return -EINVAL;
  447.         }
  448.  
  449.         exec->shader_state[i].packet = VC4_PACKET_GL_SHADER_STATE;
  450.         exec->shader_state[i].addr = *(uint32_t *)untrusted;
  451.         exec->shader_state[i].max_index = 0;
  452.  
  453.         if (exec->shader_state[i].addr & ~0xf) {
  454.                 DRM_ERROR("high bits set in GL shader rec reference\n");
  455.                 return -EINVAL;
  456.         }
  457.  
  458.         *(uint32_t *)validated = (exec->shader_rec_p +
  459.                                   exec->shader_state[i].addr);
  460.  
  461.         exec->shader_rec_p +=
  462.                 roundup(gl_shader_rec_size(exec->shader_state[i].addr), 16);
  463.  
  464.         return 0;
  465. }
  466.  
  467. static int
  468. validate_nv_shader_state(VALIDATE_ARGS)
  469. {
  470.         uint32_t i = exec->shader_state_count++;
  471.  
  472.         if (i >= exec->shader_state_size) {
  473.                 DRM_ERROR("More requests for shader states than declared\n");
  474.                 return -EINVAL;
  475.         }
  476.  
  477.         exec->shader_state[i].packet = VC4_PACKET_NV_SHADER_STATE;
  478.         exec->shader_state[i].addr = *(uint32_t *)untrusted;
  479.  
  480.         if (exec->shader_state[i].addr & 15) {
  481.                 DRM_ERROR("NV shader state address 0x%08x misaligned\n",
  482.                           exec->shader_state[i].addr);
  483.                 return -EINVAL;
  484.         }
  485.  
  486.         *(uint32_t *)validated = (exec->shader_state[i].addr +
  487.                                   exec->shader_rec_p);
  488.  
  489.         return 0;
  490. }
  491.  
  492. static int
  493. validate_tile_binning_config(VALIDATE_ARGS)
  494. {
  495.         struct drm_gem_cma_object *tile_allocation;
  496.         struct drm_gem_cma_object *tile_state_data_array;
  497.         uint8_t flags;
  498.         uint32_t tile_allocation_size;
  499.  
  500.         if (!vc4_use_handle(exec, 0, VC4_MODE_TILE_ALLOC, &tile_allocation) ||
  501.             !vc4_use_handle(exec, 1, VC4_MODE_TSDA, &tile_state_data_array))
  502.                 return -EINVAL;
  503.  
  504.         if (exec->found_tile_binning_mode_config_packet) {
  505.                 DRM_ERROR("Duplicate VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
  506.                 return -EINVAL;
  507.         }
  508.         exec->found_tile_binning_mode_config_packet = true;
  509.  
  510.         exec->bin_tiles_x = *(uint8_t *)(untrusted + 12);
  511.         exec->bin_tiles_y = *(uint8_t *)(untrusted + 13);
  512.         flags = *(uint8_t *)(untrusted + 14);
  513.  
  514.         if (exec->bin_tiles_x == 0 ||
  515.             exec->bin_tiles_y == 0) {
  516.                 DRM_ERROR("Tile binning config of %dx%d too small\n",
  517.                           exec->bin_tiles_x, exec->bin_tiles_y);
  518.                 return -EINVAL;
  519.         }
  520.  
  521.         /* Our validation relies on the user not getting to set up their own
  522.          * tile state/tile allocation BO contents.
  523.          */
  524.         if (!(flags & VC4_BIN_CONFIG_AUTO_INIT_TSDA)) {
  525.                 DRM_ERROR("binning config missing "
  526.                           "VC4_BIN_CONFIG_AUTO_INIT_TSDA\n");
  527.                 return -EINVAL;
  528.         }
  529.  
  530.         if (flags & (VC4_BIN_CONFIG_DB_NON_MS |
  531.                      VC4_BIN_CONFIG_TILE_BUFFER_64BIT |
  532.                      VC4_BIN_CONFIG_MS_MODE_4X)) {
  533.                 DRM_ERROR("unsupported bining config flags 0x%02x\n", flags);
  534.                 return -EINVAL;
  535.         }
  536.  
  537.         if (*(uint32_t *)(untrusted + 0) != 0) {
  538.                 DRM_ERROR("tile allocation offset != 0 unsupported\n");
  539.                 return -EINVAL;
  540.         }
  541.         tile_allocation_size = *(uint32_t *)(untrusted + 4);
  542.         if (tile_allocation_size > tile_allocation->base.size) {
  543.                 DRM_ERROR("tile allocation size %d > BO size %d\n",
  544.                           tile_allocation_size, tile_allocation->base.size);
  545.                 return -EINVAL;
  546.         }
  547.         *(uint32_t *)validated = tile_allocation->paddr;
  548.         exec->tile_alloc_bo = tile_allocation;
  549.  
  550.         exec->tile_alloc_init_block_size = 1 << (5 + ((flags >> 5) & 3));
  551.         if (exec->bin_tiles_x * exec->bin_tiles_y *
  552.             exec->tile_alloc_init_block_size > tile_allocation_size) {
  553.                 DRM_ERROR("tile init exceeds tile alloc size (%d vs %d)\n",
  554.                           exec->bin_tiles_x * exec->bin_tiles_y *
  555.                           exec->tile_alloc_init_block_size,
  556.                           tile_allocation_size);
  557.                 return -EINVAL;
  558.         }
  559.         if (*(uint32_t *)(untrusted + 8) != 0) {
  560.                 DRM_ERROR("TSDA offset != 0 unsupported\n");
  561.                 return -EINVAL;
  562.         }
  563.         if (exec->bin_tiles_x * exec->bin_tiles_y * 48 >
  564.             tile_state_data_array->base.size) {
  565.                 DRM_ERROR("TSDA of %db too small for %dx%d bin config\n",
  566.                           tile_state_data_array->base.size,
  567.                           exec->bin_tiles_x, exec->bin_tiles_y);
  568.         }
  569.         *(uint32_t *)(validated + 8) = tile_state_data_array->paddr;
  570.  
  571.         return 0;
  572. }
  573.  
  574. static int
  575. validate_tile_rendering_mode_config(VALIDATE_ARGS)
  576. {
  577.         struct drm_gem_cma_object *fbo;
  578.         uint32_t flags, offset, cpp;
  579.  
  580.         if (exec->found_tile_rendering_mode_config_packet) {
  581.                 DRM_ERROR("Duplicate VC4_PACKET_TILE_RENDERING_MODE_CONFIG\n");
  582.                 return -EINVAL;
  583.         }
  584.         exec->found_tile_rendering_mode_config_packet = true;
  585.  
  586.         if (!vc4_use_handle(exec, 0, VC4_MODE_RENDER, &fbo))
  587.                 return -EINVAL;
  588.  
  589.         exec->fb_width = *(uint16_t *)(untrusted + 4);
  590.         exec->fb_height = *(uint16_t *)(untrusted + 6);
  591.  
  592.         flags = *(uint16_t *)(untrusted + 8);
  593.         if ((flags & VC4_RENDER_CONFIG_FORMAT_MASK) ==
  594.             VC4_RENDER_CONFIG_FORMAT_RGBA8888) {
  595.                 cpp = 4;
  596.         } else {
  597.                 cpp = 2;
  598.         }
  599.  
  600.         offset = *(uint32_t *)untrusted;
  601.         if (!check_tex_size(exec, fbo, offset,
  602.                             ((flags &
  603.                               VC4_RENDER_CONFIG_MEMORY_FORMAT_MASK) >>
  604.                              VC4_RENDER_CONFIG_MEMORY_FORMAT_SHIFT),
  605.                             exec->fb_width, exec->fb_height, cpp)) {
  606.                 return -EINVAL;
  607.         }
  608.  
  609.         *(uint32_t *)validated = fbo->paddr + offset;
  610.  
  611.         return 0;
  612. }
  613.  
  614. static int
  615. validate_tile_coordinates(VALIDATE_ARGS)
  616. {
  617.         uint8_t tile_x = *(uint8_t *)(untrusted + 0);
  618.         uint8_t tile_y = *(uint8_t *)(untrusted + 1);
  619.  
  620.         if (tile_x * 64 >= exec->fb_width || tile_y * 64 >= exec->fb_height) {
  621.                 DRM_ERROR("Tile coordinates %d,%d > render config %dx%d\n",
  622.                           tile_x, tile_y, exec->fb_width, exec->fb_height);
  623.                 return -EINVAL;
  624.         }
  625.  
  626.         return 0;
  627. }
  628.  
  629. static int
  630. validate_gem_handles(VALIDATE_ARGS)
  631. {
  632.         memcpy(exec->bo_index, untrusted, sizeof(exec->bo_index));
  633.         return 0;
  634. }
  635.  
  636. static const struct cmd_info {
  637.         bool bin;
  638.         bool render;
  639.         uint16_t len;
  640.         const char *name;
  641.         int (*func)(struct vc4_exec_info *exec, void *validated,
  642.                     void *untrusted);
  643. } cmd_info[] = {
  644.         [VC4_PACKET_HALT] = { 1, 1, 1, "halt", NULL },
  645.         [VC4_PACKET_NOP] = { 1, 1, 1, "nop", NULL },
  646.         [VC4_PACKET_FLUSH] = { 1, 1, 1, "flush", NULL },
  647.         [VC4_PACKET_FLUSH_ALL] = { 1, 0, 1, "flush all state", validate_flush_all },
  648.         [VC4_PACKET_START_TILE_BINNING] = { 1, 0, 1, "start tile binning", validate_start_tile_binning },
  649.         [VC4_PACKET_INCREMENT_SEMAPHORE] = { 1, 0, 1, "increment semaphore", validate_increment_semaphore },
  650.         [VC4_PACKET_WAIT_ON_SEMAPHORE] = { 0, 1, 1, "wait on semaphore", validate_wait_on_semaphore },
  651.         /* BRANCH_TO_SUB_LIST is actually supported in the binner as well, but
  652.          * we only use it from the render CL in order to jump into the tile
  653.          * allocation BO.
  654.          */
  655.         [VC4_PACKET_BRANCH_TO_SUB_LIST] = { 0, 1, 5, "branch to sublist", validate_branch_to_sublist },
  656.         [VC4_PACKET_STORE_MS_TILE_BUFFER] = { 0, 1, 1, "store MS resolved tile color buffer", NULL },
  657.         [VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF] = { 0, 1, 1, "store MS resolved tile color buffer and EOF", NULL },
  658.  
  659.         [VC4_PACKET_STORE_TILE_BUFFER_GENERAL] = { 0, 1, 7, "Store Tile Buffer General", validate_loadstore_tile_buffer_general },
  660.         [VC4_PACKET_LOAD_TILE_BUFFER_GENERAL] = { 0, 1, 7, "Load Tile Buffer General", validate_loadstore_tile_buffer_general },
  661.  
  662.         [VC4_PACKET_GL_INDEXED_PRIMITIVE] = { 1, 1, 14, "Indexed Primitive List", validate_indexed_prim_list },
  663.  
  664.         [VC4_PACKET_GL_ARRAY_PRIMITIVE] = { 1, 1, 10, "Vertex Array Primitives", validate_gl_array_primitive },
  665.  
  666.         /* This is only used by clipped primitives (packets 48 and 49), which
  667.          * we don't support parsing yet.
  668.          */
  669.         [VC4_PACKET_PRIMITIVE_LIST_FORMAT] = { 1, 1, 2, "primitive list format", NULL },
  670.  
  671.         [VC4_PACKET_GL_SHADER_STATE] = { 1, 1, 5, "GL Shader State", validate_gl_shader_state },
  672.         [VC4_PACKET_NV_SHADER_STATE] = { 1, 1, 5, "NV Shader State", validate_nv_shader_state },
  673.  
  674.         [VC4_PACKET_CONFIGURATION_BITS] = { 1, 1, 4, "configuration bits", NULL },
  675.         [VC4_PACKET_FLAT_SHADE_FLAGS] = { 1, 1, 5, "flat shade flags", NULL },
  676.         [VC4_PACKET_POINT_SIZE] = { 1, 1, 5, "point size", NULL },
  677.         [VC4_PACKET_LINE_WIDTH] = { 1, 1, 5, "line width", NULL },
  678.         [VC4_PACKET_RHT_X_BOUNDARY] = { 1, 1, 3, "RHT X boundary", NULL },
  679.         [VC4_PACKET_DEPTH_OFFSET] = { 1, 1, 5, "Depth Offset", NULL },
  680.         [VC4_PACKET_CLIP_WINDOW] = { 1, 1, 9, "Clip Window", NULL },
  681.         [VC4_PACKET_VIEWPORT_OFFSET] = { 1, 1, 5, "Viewport Offset", NULL },
  682.         [VC4_PACKET_CLIPPER_XY_SCALING] = { 1, 1, 9, "Clipper XY Scaling", NULL },
  683.         /* Note: The docs say this was also 105, but it was 106 in the
  684.          * initial userland code drop.
  685.          */
  686.         [VC4_PACKET_CLIPPER_Z_SCALING] = { 1, 1, 9, "Clipper Z Scale and Offset", NULL },
  687.  
  688.         [VC4_PACKET_TILE_BINNING_MODE_CONFIG] = { 1, 0, 16, "tile binning configuration", validate_tile_binning_config },
  689.  
  690.         [VC4_PACKET_TILE_RENDERING_MODE_CONFIG] = { 0, 1, 11, "tile rendering mode configuration", validate_tile_rendering_mode_config},
  691.  
  692.         [VC4_PACKET_CLEAR_COLORS] = { 0, 1, 14, "Clear Colors", NULL },
  693.  
  694.         [VC4_PACKET_TILE_COORDINATES] = { 0, 1, 3, "Tile Coordinates", validate_tile_coordinates },
  695.  
  696.         [VC4_PACKET_GEM_HANDLES] = { 1, 1, 9, "GEM handles", validate_gem_handles },
  697. };
  698.  
  699. int
  700. vc4_validate_cl(struct drm_device *dev,
  701.                 void *validated,
  702.                 void *unvalidated,
  703.                 uint32_t len,
  704.                 bool is_bin,
  705.                 bool has_bin,
  706.                 struct vc4_exec_info *exec)
  707. {
  708.         uint32_t dst_offset = 0;
  709.         uint32_t src_offset = 0;
  710.  
  711.         while (src_offset < len) {
  712.                 void *dst_pkt = validated + dst_offset;
  713.                 void *src_pkt = unvalidated + src_offset;
  714.                 u8 cmd = *(uint8_t *)src_pkt;
  715.                 const struct cmd_info *info;
  716.  
  717.                 if (cmd > ARRAY_SIZE(cmd_info)) {
  718.                         DRM_ERROR("0x%08x: packet %d out of bounds\n",
  719.                                   src_offset, cmd);
  720.                         return -EINVAL;
  721.                 }
  722.  
  723.                 info = &cmd_info[cmd];
  724.                 if (!info->name) {
  725.                         DRM_ERROR("0x%08x: packet %d invalid\n",
  726.                                   src_offset, cmd);
  727.                         return -EINVAL;
  728.                 }
  729.  
  730. #if 0
  731.                 DRM_INFO("0x%08x: packet %d (%s) size %d processing...\n",
  732.                          src_offset, cmd, info->name, info->len);
  733. #endif
  734.  
  735.                 if ((is_bin && !info->bin) ||
  736.                     (!is_bin && !info->render)) {
  737.                         DRM_ERROR("0x%08x: packet %d (%s) invalid for %s\n",
  738.                                   src_offset, cmd, info->name,
  739.                                   is_bin ? "binner" : "render");
  740.                         return -EINVAL;
  741.                 }
  742.  
  743.                 if (src_offset + info->len > len) {
  744.                         DRM_ERROR("0x%08x: packet %d (%s) length 0x%08x "
  745.                                   "exceeds bounds (0x%08x)\n",
  746.                                   src_offset, cmd, info->name, info->len,
  747.                                   src_offset + len);
  748.                         return -EINVAL;
  749.                 }
  750.  
  751.                 if (cmd != VC4_PACKET_GEM_HANDLES)
  752.                         memcpy(dst_pkt, src_pkt, info->len);
  753.  
  754.                 if (info->func && info->func(exec,
  755.                                              dst_pkt + 1,
  756.                                              src_pkt + 1)) {
  757.                         DRM_ERROR("0x%08x: packet %d (%s) failed to "
  758.                                   "validate\n",
  759.                                   src_offset, cmd, info->name);
  760.                         return -EINVAL;
  761.                 }
  762.  
  763.                 src_offset += info->len;
  764.                 /* GEM handle loading doesn't produce HW packets. */
  765.                 if (cmd != VC4_PACKET_GEM_HANDLES)
  766.                         dst_offset += info->len;
  767.  
  768.                 /* When the CL hits halt, it'll stop reading anything else. */
  769.                 if (cmd == VC4_PACKET_HALT)
  770.                         break;
  771.         }
  772.  
  773.         if (is_bin) {
  774.                 exec->ct0ea = exec->ct0ca + dst_offset;
  775.  
  776.                 if (has_bin && !exec->found_start_tile_binning_packet) {
  777.                         DRM_ERROR("Bin CL missing VC4_PACKET_START_TILE_BINNING\n");
  778.                         return -EINVAL;
  779.                 }
  780.         } else {
  781.                 if (!exec->found_tile_rendering_mode_config_packet) {
  782.                         DRM_ERROR("Render CL missing VC4_PACKET_TILE_RENDERING_MODE_CONFIG\n");
  783.                         return -EINVAL;
  784.                 }
  785.  
  786.                 /* Make sure that they actually consumed the semaphore
  787.                  * increment from the bin CL.  Otherwise a later submit would
  788.                  * have render execute immediately.
  789.                  */
  790.                 if (exec->found_wait_on_semaphore_packet != has_bin) {
  791.                         DRM_ERROR("Render CL %s VC4_PACKET_WAIT_ON_SEMAPHORE\n",
  792.                                   exec->found_wait_on_semaphore_packet ?
  793.                                   "has" : "missing");
  794.                         return -EINVAL;
  795.                 }
  796.                 exec->ct1ea = exec->ct1ca + dst_offset;
  797.         }
  798.  
  799.         return 0;
  800. }
  801.  
  802. static bool
  803. reloc_tex(struct vc4_exec_info *exec,
  804.           void *uniform_data_u,
  805.           struct vc4_texture_sample_info *sample,
  806.           uint32_t texture_handle_index)
  807.  
  808. {
  809.         struct drm_gem_cma_object *tex;
  810.         uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]);
  811.         uint32_t p1 = *(uint32_t *)(uniform_data_u + sample->p_offset[1]);
  812.         uint32_t p2 = (sample->p_offset[2] != ~0 ?
  813.                        *(uint32_t *)(uniform_data_u + sample->p_offset[2]) : 0);
  814.         uint32_t p3 = (sample->p_offset[3] != ~0 ?
  815.                        *(uint32_t *)(uniform_data_u + sample->p_offset[3]) : 0);
  816.         uint32_t *validated_p0 = exec->uniforms_v + sample->p_offset[0];
  817.         uint32_t offset = p0 & ~0xfff;
  818.         uint32_t miplevels = (p0 & 15);
  819.         uint32_t width = (p1 >> 8) & 2047;
  820.         uint32_t height = (p1 >> 20) & 2047;
  821.         uint32_t cpp, tiling_format, utile_w, utile_h;
  822.         uint32_t i;
  823.         uint32_t cube_map_stride = 0;
  824.         enum vc4_texture_data_type type;
  825.  
  826.         if (!vc4_use_bo(exec, texture_handle_index, VC4_MODE_RENDER, &tex))
  827.                 return false;
  828.  
  829.         if (sample->is_direct) {
  830.                 uint32_t remaining_size = tex->base.size - p0;
  831.                 if (p0 > tex->base.size - 4) {
  832.                         DRM_ERROR("UBO offset greater than UBO size\n");
  833.                         return false;
  834.                 }
  835.                 if (p1 > remaining_size - 4) {
  836.                         DRM_ERROR("UBO clamp would allow reads outside of UBO\n");
  837.                         return false;
  838.                 }
  839.                 *validated_p0 = tex->paddr + p0;
  840.                 return true;
  841.         }
  842.  
  843.         if (width == 0)
  844.                 width = 2048;
  845.         if (height == 0)
  846.                 height = 2048;
  847.  
  848.         if (p0 & (1 << 9)) {
  849.                 if ((p2 & (3 << 30)) == (1 << 30))
  850.                         cube_map_stride = p2 & 0x3ffff000;
  851.                 if ((p3 & (3 << 30)) == (1 << 30)) {
  852.                         if (cube_map_stride) {
  853.                                 DRM_ERROR("Cube map stride set twice\n");
  854.                                 return false;
  855.                         }
  856.  
  857.                         cube_map_stride = p3 & 0x3ffff000;
  858.                 }
  859.                 if (!cube_map_stride) {
  860.                         DRM_ERROR("Cube map stride not set\n");
  861.                         return false;
  862.                 }
  863.         }
  864.  
  865.         type = ((p0 >> 4) & 15) | ((p1 >> 31) << 4);
  866.  
  867.         switch (type) {
  868.         case VC4_TEXTURE_TYPE_RGBA8888:
  869.         case VC4_TEXTURE_TYPE_RGBX8888:
  870.         case VC4_TEXTURE_TYPE_RGBA32R:
  871.                 cpp = 4;
  872.                 break;
  873.         case VC4_TEXTURE_TYPE_RGBA4444:
  874.         case VC4_TEXTURE_TYPE_RGBA5551:
  875.         case VC4_TEXTURE_TYPE_RGB565:
  876.         case VC4_TEXTURE_TYPE_LUMALPHA:
  877.         case VC4_TEXTURE_TYPE_S16F:
  878.         case VC4_TEXTURE_TYPE_S16:
  879.                 cpp = 2;
  880.                 break;
  881.         case VC4_TEXTURE_TYPE_LUMINANCE:
  882.         case VC4_TEXTURE_TYPE_ALPHA:
  883.         case VC4_TEXTURE_TYPE_S8:
  884.                 cpp = 1;
  885.                 break;
  886.         case VC4_TEXTURE_TYPE_ETC1:
  887.         case VC4_TEXTURE_TYPE_BW1:
  888.         case VC4_TEXTURE_TYPE_A4:
  889.         case VC4_TEXTURE_TYPE_A1:
  890.         case VC4_TEXTURE_TYPE_RGBA64:
  891.         case VC4_TEXTURE_TYPE_YUV422R:
  892.         default:
  893.                 DRM_ERROR("Texture format %d unsupported\n", type);
  894.                 return false;
  895.         }
  896.         utile_w = utile_width(cpp);
  897.         utile_h = utile_height(cpp);
  898.  
  899.         if (type == VC4_TEXTURE_TYPE_RGBA32R) {
  900.                 tiling_format = VC4_TILING_FORMAT_LINEAR;
  901.         } else {
  902.                 if (size_is_lt(width, height, cpp))
  903.                         tiling_format = VC4_TILING_FORMAT_LT;
  904.                 else
  905.                         tiling_format = VC4_TILING_FORMAT_T;
  906.         }
  907.  
  908.         if (!check_tex_size(exec, tex, offset + cube_map_stride * 5,
  909.                             tiling_format, width, height, cpp)) {
  910.                 return false;
  911.         }
  912.  
  913.         /* The mipmap levels are stored before the base of the texture.  Make
  914.          * sure there is actually space in the BO.
  915.          */
  916.         for (i = 1; i <= miplevels; i++) {
  917.                 uint32_t level_width = max(width >> i, 1u);
  918.                 uint32_t level_height = max(height >> i, 1u);
  919.                 uint32_t aligned_width, aligned_height;
  920.                 uint32_t level_size;
  921.  
  922.                 /* Once the levels get small enough, they drop from T to LT. */
  923.                 if (tiling_format == VC4_TILING_FORMAT_T &&
  924.                     size_is_lt(level_width, level_height, cpp)) {
  925.                         tiling_format = VC4_TILING_FORMAT_LT;
  926.                 }
  927.  
  928.                 switch (tiling_format) {
  929.                 case VC4_TILING_FORMAT_T:
  930.                         aligned_width = roundup(level_width, utile_w * 8);
  931.                         aligned_height = roundup(level_height, utile_h * 8);
  932.                         break;
  933.                 case VC4_TILING_FORMAT_LT:
  934.                         aligned_width = roundup(level_width, utile_w);
  935.                         aligned_height = roundup(level_height, utile_h);
  936.                         break;
  937.                 default:
  938.                         aligned_width = roundup(level_width, utile_w);
  939.                         aligned_height = level_height;
  940.                         break;
  941.                 }
  942.  
  943.                 level_size = aligned_width * cpp * aligned_height;
  944.  
  945.                 if (offset < level_size) {
  946.                         DRM_ERROR("Level %d (%dx%d -> %dx%d) size %db "
  947.                                   "overflowed buffer bounds (offset %d)\n",
  948.                                   i, level_width, level_height,
  949.                                   aligned_width, aligned_height,
  950.                                   level_size, offset);
  951.                         return false;
  952.                 }
  953.  
  954.                 offset -= level_size;
  955.         }
  956.  
  957.         *validated_p0 = tex->paddr + p0;
  958.  
  959.         return true;
  960. }
  961.  
  962. static int
  963. validate_shader_rec(struct drm_device *dev,
  964.                     struct vc4_exec_info *exec,
  965.                     struct vc4_shader_state *state)
  966. {
  967.         uint32_t *src_handles;
  968.         void *pkt_u, *pkt_v;
  969.         enum shader_rec_reloc_type {
  970.                 RELOC_CODE,
  971.                 RELOC_VBO,
  972.         };
  973.         struct shader_rec_reloc {
  974.                 enum shader_rec_reloc_type type;
  975.                 uint32_t offset;
  976.         };
  977.         static const struct shader_rec_reloc gl_relocs[] = {
  978.                 { RELOC_CODE, 4 },  /* fs */
  979.                 { RELOC_CODE, 16 }, /* vs */
  980.                 { RELOC_CODE, 28 }, /* cs */
  981.         };
  982.         static const struct shader_rec_reloc nv_relocs[] = {
  983.                 { RELOC_CODE, 4 }, /* fs */
  984.                 { RELOC_VBO, 12 }
  985.         };
  986.         const struct shader_rec_reloc *relocs;
  987.         struct drm_gem_cma_object *bo[ARRAY_SIZE(gl_relocs) + 8];
  988.         uint32_t nr_attributes = 0, nr_fixed_relocs, nr_relocs, packet_size;
  989.         int i;
  990.         struct vc4_validated_shader_info *validated_shader = NULL;
  991.  
  992.         if (state->packet == VC4_PACKET_NV_SHADER_STATE) {
  993.                 relocs = nv_relocs;
  994.                 nr_fixed_relocs = ARRAY_SIZE(nv_relocs);
  995.  
  996.                 packet_size = 16;
  997.         } else {
  998.                 relocs = gl_relocs;
  999.                 nr_fixed_relocs = ARRAY_SIZE(gl_relocs);
  1000.  
  1001.                 nr_attributes = state->addr & 0x7;
  1002.                 if (nr_attributes == 0)
  1003.                         nr_attributes = 8;
  1004.                 packet_size = gl_shader_rec_size(state->addr);
  1005.         }
  1006.         nr_relocs = nr_fixed_relocs + nr_attributes;
  1007.  
  1008.         if (nr_relocs * 4 > exec->shader_rec_size) {
  1009.                 DRM_ERROR("overflowed shader recs reading %d handles "
  1010.                           "from %d bytes left\n",
  1011.                           nr_relocs, exec->shader_rec_size);
  1012.                 return -EINVAL;
  1013.         }
  1014.         src_handles = exec->shader_rec_u;
  1015.         exec->shader_rec_u += nr_relocs * 4;
  1016.         exec->shader_rec_size -= nr_relocs * 4;
  1017.  
  1018.         if (packet_size > exec->shader_rec_size) {
  1019.                 DRM_ERROR("overflowed shader recs copying %db packet "
  1020.                           "from %d bytes left\n",
  1021.                           packet_size, exec->shader_rec_size);
  1022.                 return -EINVAL;
  1023.         }
  1024.         pkt_u = exec->shader_rec_u;
  1025.         pkt_v = exec->shader_rec_v;
  1026.         memcpy(pkt_v, pkt_u, packet_size);
  1027.         exec->shader_rec_u += packet_size;
  1028.         /* Shader recs have to be aligned to 16 bytes (due to the attribute
  1029.          * flags being in the low bytes), so round the next validated shader
  1030.          * rec address up.  This should be safe, since we've got so many
  1031.          * relocations in a shader rec packet.
  1032.          */
  1033.         BUG_ON(roundup(packet_size, 16) - packet_size > nr_relocs * 4);
  1034.         exec->shader_rec_v += roundup(packet_size, 16);
  1035.         exec->shader_rec_size -= packet_size;
  1036.  
  1037.         for (i = 0; i < nr_relocs; i++) {
  1038.                 enum vc4_bo_mode mode;
  1039.  
  1040.                 if (i < nr_fixed_relocs && relocs[i].type == RELOC_CODE)
  1041.                         mode = VC4_MODE_SHADER;
  1042.                 else
  1043.                         mode = VC4_MODE_RENDER;
  1044.  
  1045.                 if (!vc4_use_bo(exec, src_handles[i], mode, &bo[i])) {
  1046.                         return false;
  1047.                 }
  1048.         }
  1049.  
  1050.         for (i = 0; i < nr_fixed_relocs; i++) {
  1051.                 uint32_t o = relocs[i].offset;
  1052.                 uint32_t src_offset = *(uint32_t *)(pkt_u + o);
  1053.                 uint32_t *texture_handles_u;
  1054.                 void *uniform_data_u;
  1055.                 uint32_t tex;
  1056.  
  1057.                 *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset;
  1058.  
  1059.                 switch (relocs[i].type) {
  1060.                 case RELOC_CODE:
  1061.                         if (src_offset != 0) {
  1062.                                 DRM_ERROR("Shaders must be at offset 0 of "
  1063.                                           "the BO.\n");
  1064.                                 goto fail;
  1065.                         }
  1066.  
  1067.                         kfree(validated_shader);
  1068.                         validated_shader = vc4_validate_shader(bo[i]);
  1069.                         if (!validated_shader)
  1070.                                 goto fail;
  1071.  
  1072.                         if (validated_shader->uniforms_src_size >
  1073.                             exec->uniforms_size) {
  1074.                                 DRM_ERROR("Uniforms src buffer overflow\n");
  1075.                                 goto fail;
  1076.                         }
  1077.  
  1078.                         texture_handles_u = exec->uniforms_u;
  1079.                         uniform_data_u = (texture_handles_u +
  1080.                                           validated_shader->num_texture_samples);
  1081.  
  1082.                         memcpy(exec->uniforms_v, uniform_data_u,
  1083.                                validated_shader->uniforms_size);
  1084.  
  1085.                         for (tex = 0;
  1086.                              tex < validated_shader->num_texture_samples;
  1087.                              tex++) {
  1088.                                 if (!reloc_tex(exec,
  1089.                                                uniform_data_u,
  1090.                                                &validated_shader->texture_samples[tex],
  1091.                                                texture_handles_u[tex])) {
  1092.                                         goto fail;
  1093.                                 }
  1094.                         }
  1095.  
  1096.                         *(uint32_t *)(pkt_v + o + 4) = exec->uniforms_p;
  1097.  
  1098.                         exec->uniforms_u += validated_shader->uniforms_src_size;
  1099.                         exec->uniforms_v += validated_shader->uniforms_size;
  1100.                         exec->uniforms_p += validated_shader->uniforms_size;
  1101.  
  1102.                         break;
  1103.  
  1104.                 case RELOC_VBO:
  1105.                         break;
  1106.                 }
  1107.         }
  1108.  
  1109.         for (i = 0; i < nr_attributes; i++) {
  1110.                 struct drm_gem_cma_object *vbo = bo[nr_fixed_relocs + i];
  1111.                 uint32_t o = 36 + i * 8;
  1112.                 uint32_t offset = *(uint32_t *)(pkt_u + o + 0);
  1113.                 uint32_t attr_size = *(uint8_t *)(pkt_u + o + 4) + 1;
  1114.                 uint32_t stride = *(uint8_t *)(pkt_u + o + 5);
  1115.                 uint32_t max_index;
  1116.  
  1117.                 if (state->addr & 0x8)
  1118.                         stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff;
  1119.  
  1120.                 if (vbo->base.size < offset ||
  1121.                     vbo->base.size - offset < attr_size) {
  1122.                         DRM_ERROR("BO offset overflow (%d + %d > %d)\n",
  1123.                                   offset, attr_size, vbo->base.size);
  1124.                         return -EINVAL;
  1125.                 }
  1126.  
  1127.                 if (stride != 0) {
  1128.                         max_index = ((vbo->base.size - offset - attr_size) /
  1129.                                      stride);
  1130.                         if (state->max_index > max_index) {
  1131.                                 DRM_ERROR("primitives use index %d out of supplied %d\n",
  1132.                                           state->max_index, max_index);
  1133.                                 return -EINVAL;
  1134.                         }
  1135.                 }
  1136.  
  1137.                 *(uint32_t *)(pkt_v + o) = vbo->paddr + offset;
  1138.         }
  1139.  
  1140.         kfree(validated_shader);
  1141.  
  1142.         return 0;
  1143.  
  1144. fail:
  1145.         kfree(validated_shader);
  1146.         return -EINVAL;
  1147. }
  1148.  
  1149. int
  1150. vc4_validate_shader_recs(struct drm_device *dev,
  1151.                          struct vc4_exec_info *exec)
  1152. {
  1153.         uint32_t i;
  1154.         int ret = 0;
  1155.  
  1156.         for (i = 0; i < exec->shader_state_count; i++) {
  1157.                 ret = validate_shader_rec(dev, exec, &exec->shader_state[i]);
  1158.                 if (ret)
  1159.                         return ret;
  1160.         }
  1161.  
  1162.         return ret;
  1163. }
  1164.