void *validated, \
void *untrusted
-
/** Return the width in pixels of a 64-byte microtile. */
static uint32_t
utile_width(int cpp)
if (size + offset < size ||
size + offset > fbo->base.size) {
- DRM_ERROR("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %d)\n",
+ DRM_ERROR("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %zd)\n",
width, height,
aligned_width, aligned_height,
size, offset, fbo->base.size);
return true;
}
-
static int
validate_flush(VALIDATE_ARGS)
{
if (offset > ib->base.size ||
(ib->base.size - offset) / index_size < length) {
- DRM_ERROR("IB access overflow (%d + %d*%d > %d)\n",
+ DRM_ERROR("IB access overflow (%d + %d*%d > %zd)\n",
offset, length, index_size, ib->base.size);
return -EINVAL;
}
return 0;
}
-#define VC4_DEFINE_PACKET(packet, name, func) \
- [packet] = { packet ## _SIZE, name, func }
+#define VC4_DEFINE_PACKET(packet, func) \
+ [packet] = { packet ## _SIZE, #packet, func }
static const struct cmd_info {
uint16_t len;
int (*func)(struct vc4_exec_info *exec, void *validated,
void *untrusted);
} cmd_info[] = {
- VC4_DEFINE_PACKET(VC4_PACKET_HALT, "halt", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_NOP, "nop", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_FLUSH, "flush", validate_flush),
- VC4_DEFINE_PACKET(VC4_PACKET_FLUSH_ALL, "flush all state", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_START_TILE_BINNING, "start tile binning", validate_start_tile_binning),
- VC4_DEFINE_PACKET(VC4_PACKET_INCREMENT_SEMAPHORE, "increment semaphore", validate_increment_semaphore),
-
- VC4_DEFINE_PACKET(VC4_PACKET_GL_INDEXED_PRIMITIVE, "Indexed Primitive List", validate_indexed_prim_list),
-
- VC4_DEFINE_PACKET(VC4_PACKET_GL_ARRAY_PRIMITIVE, "Vertex Array Primitives", validate_gl_array_primitive),
-
- /* This is only used by clipped primitives (packets 48 and 49), which
- * we don't support parsing yet.
- */
- VC4_DEFINE_PACKET(VC4_PACKET_PRIMITIVE_LIST_FORMAT, "primitive list format", NULL),
-
- VC4_DEFINE_PACKET(VC4_PACKET_GL_SHADER_STATE, "GL Shader State", validate_gl_shader_state),
- /* We don't support validating NV shader states. */
-
- VC4_DEFINE_PACKET(VC4_PACKET_CONFIGURATION_BITS, "configuration bits", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_FLAT_SHADE_FLAGS, "flat shade flags", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_POINT_SIZE, "point size", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_LINE_WIDTH, "line width", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_RHT_X_BOUNDARY, "RHT X boundary", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_DEPTH_OFFSET, "Depth Offset", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_CLIP_WINDOW, "Clip Window", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_VIEWPORT_OFFSET, "Viewport Offset", NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_XY_SCALING, "Clipper XY Scaling", NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_HALT, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_NOP, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_FLUSH, validate_flush),
+ VC4_DEFINE_PACKET(VC4_PACKET_FLUSH_ALL, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_START_TILE_BINNING,
+ validate_start_tile_binning),
+ VC4_DEFINE_PACKET(VC4_PACKET_INCREMENT_SEMAPHORE,
+ validate_increment_semaphore),
+
+ VC4_DEFINE_PACKET(VC4_PACKET_GL_INDEXED_PRIMITIVE,
+ validate_indexed_prim_list),
+ VC4_DEFINE_PACKET(VC4_PACKET_GL_ARRAY_PRIMITIVE,
+ validate_gl_array_primitive),
+
+ VC4_DEFINE_PACKET(VC4_PACKET_PRIMITIVE_LIST_FORMAT, NULL),
+
+ VC4_DEFINE_PACKET(VC4_PACKET_GL_SHADER_STATE, validate_gl_shader_state),
+
+ VC4_DEFINE_PACKET(VC4_PACKET_CONFIGURATION_BITS, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_FLAT_SHADE_FLAGS, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_POINT_SIZE, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_LINE_WIDTH, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_RHT_X_BOUNDARY, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_DEPTH_OFFSET, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_CLIP_WINDOW, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_VIEWPORT_OFFSET, NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_XY_SCALING, NULL),
/* Note: The docs say this was also 105, but it was 106 in the
* initial userland code drop.
*/
- VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_Z_SCALING, "Clipper Z Scale and Offset", NULL),
+ VC4_DEFINE_PACKET(VC4_PACKET_CLIPPER_Z_SCALING, NULL),
- VC4_DEFINE_PACKET(VC4_PACKET_TILE_BINNING_MODE_CONFIG, "tile binning configuration", validate_tile_binning_config),
+ VC4_DEFINE_PACKET(VC4_PACKET_TILE_BINNING_MODE_CONFIG,
+ validate_tile_binning_config),
- VC4_DEFINE_PACKET(VC4_PACKET_GEM_HANDLES, "GEM handles", validate_gem_handles),
+ VC4_DEFINE_PACKET(VC4_PACKET_GEM_HANDLES, validate_gem_handles),
};
int
return -EINVAL;
}
-#if 0
- DRM_INFO("0x%08x: packet %d (%s) size %d processing...\n",
- src_offset, cmd, info->name, info->len);
-#endif
-
if (src_offset + info->len > len) {
DRM_ERROR("0x%08x: packet %d (%s) length 0x%08x "
"exceeds bounds (0x%08x)\n",
if (info->func && info->func(exec,
dst_pkt + 1,
src_pkt + 1)) {
- DRM_ERROR("0x%08x: packet %d (%s) failed to "
- "validate\n",
+ DRM_ERROR("0x%08x: packet %d (%s) failed to validate\n",
src_offset, cmd, info->name);
return -EINVAL;
}
if (sample->is_direct) {
uint32_t remaining_size = tex->base.size - p0;
+
if (p0 > tex->base.size - 4) {
DRM_ERROR("UBO offset greater than UBO size\n");
goto fail;
}
if (p1 > remaining_size - 4) {
- DRM_ERROR("UBO clamp would allow reads outside of UBO\n");
+ DRM_ERROR("UBO clamp would allow reads "
+ "outside of UBO\n");
goto fail;
}
*validated_p0 = tex->paddr + p0;
max_index = ((vbo->base.size - offset - attr_size) /
stride);
if (state->max_index > max_index) {
- DRM_ERROR("primitives use index %d out of supplied %d\n",
+ DRM_ERROR("primitives use index %d out of "
+ "supplied %d\n",
state->max_index, max_index);
return -EINVAL;
}
/**
* DOC: Shader validator for VC4.
*
- * The VC4 has no IOMMU between it and system memory. So, a user with access
- * to execute shaders could escalate privilege by overwriting system memory
- * (using the VPM write address register in the general-purpose DMA mode) or
- * reading system memory it shouldn't (reading it as a texture, or uniform
- * data, or vertex data).
+ * The VC4 has no IOMMU between it and system memory, so a user with
+ * access to execute shaders could escalate privilege by overwriting
+ * system memory (using the VPM write address register in the
+ * general-purpose DMA mode) or reading system memory it shouldn't
+ * (reading it as a texture, or uniform data, or vertex data).
*
- * This walks over a shader starting from some offset within a BO, ensuring
- * that its accesses are appropriately bounded, and recording how many texture
- * accesses are made and where so that we can do relocations for them in the
+ * This walks over a shader BO, ensuring that its accesses are
+ * appropriately bounded, and recording how many texture accesses are
+ * made and where so that we can do relocations for them in the
* uniform stream.
- *
- * The kernel API has shaders stored in user-mapped BOs. The BOs will be
- * forcibly unmapped from the process before validation, and any cache of
- * validated state will be flushed if the mapping is faulted back in.
- *
- * Storing the shaders in BOs means that the validation process will be slow
- * due to uncached reads, but since shaders are long-lived and shader BOs are
- * never actually modified, this shouldn't be a problem.
*/
#include "vc4_drv.h"
else
return waddr;
} else if (waddr <= QPU_W_ACC3) {
-
return 64 + waddr - QPU_W_ACC0;
} else {
return ~0;
uint32_t raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);
uint32_t raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);
- if (add_a == QPU_MUX_A) {
+ if (add_a == QPU_MUX_A)
return raddr_a;
- } else if (add_a == QPU_MUX_B && sig != QPU_SIG_SMALL_IMM) {
+ else if (add_a == QPU_MUX_B && sig != QPU_SIG_SMALL_IMM)
return 32 + raddr_b;
- } else if (add_a <= QPU_MUX_R3) {
+ else if (add_a <= QPU_MUX_R3)
return 64 + add_a;
- } else {
+ else
return ~0;
- }
}
static bool
}
static bool
-record_validated_texture_sample(struct vc4_validated_shader_info *validated_shader,
- struct vc4_shader_validation_state *validation_state,
- int tmu)
+record_texture_sample(struct vc4_validated_shader_info *validated_shader,
+ struct vc4_shader_validation_state *validation_state,
+ int tmu)
{
uint32_t s = validated_shader->num_texture_samples;
int i;
validated_shader->uniforms_size += 4;
if (submit) {
- if (!record_validated_texture_sample(validated_shader,
- validation_state, tmu)) {
+ if (!record_texture_sample(validated_shader,
+ validation_state, tmu)) {
return false;
}
}
static bool
-check_register_write(uint64_t inst,
- struct vc4_validated_shader_info *validated_shader,
- struct vc4_shader_validation_state *validation_state,
- bool is_mul)
+check_reg_write(uint64_t inst,
+ struct vc4_validated_shader_info *validated_shader,
+ struct vc4_shader_validation_state *validation_state,
+ bool is_mul)
{
uint32_t waddr = (is_mul ?
QPU_GET_FIELD(inst, QPU_WADDR_MUL) :
return true;
case QPU_W_TLB_STENCIL_SETUP:
- return true;
+ return true;
}
return true;
}
validation_state->live_max_clamp_regs[lri_add] = true;
- } if (op_add == QPU_A_MIN) {
+ } else if (op_add == QPU_A_MIN) {
/* Track live clamps of a value clamped to a minimum of 0 and
* a maximum of some uniform's offset.
*/
return false;
}
- ok = (check_register_write(inst, validated_shader, validation_state, false) &&
- check_register_write(inst, validated_shader, validation_state, true));
+ ok = (check_reg_write(inst, validated_shader, validation_state,
+ false) &&
+ check_reg_write(inst, validated_shader, validation_state,
+ true));
track_live_clamps(inst, validated_shader, validation_state);
shader = shader_obj->vaddr;
max_ip = shader_obj->base.size / sizeof(uint64_t);
- validated_shader = kcalloc(sizeof(*validated_shader), 1, GFP_KERNEL);
+ validated_shader = kcalloc(1, sizeof(*validated_shader), GFP_KERNEL);
if (!validated_shader)
return NULL;
if (ip == max_ip) {
DRM_ERROR("shader failed to terminate before "
- "shader BO end at %d\n",
+ "shader BO end at %zd\n",
shader_obj->base.size);
goto fail;
}
return validated_shader;
fail:
- kfree(validated_shader);
+ if (validated_shader) {
+ kfree(validated_shader->texture_samples);
+ kfree(validated_shader);
+ }
return NULL;
}