summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2014-07-22 20:10:01 -0700
committerEric Anholt <[email protected]>2014-08-11 14:45:28 -0700
commit2b16b3d75fa9350e358e80a4189d4f592c7394d4 (patch)
treec11917dbe393d252290cf7170fba376bd196a7bc /src/gallium/drivers/vc4
parenta8f2bf0f51222a96a49dfb3d6f9b36d3e54d08cd (diff)
vc4: Fix things to validate more than one shader state in a submit.
Diffstat (limited to 'src/gallium/drivers/vc4')
-rw-r--r--src/gallium/drivers/vc4/vc4_simulator.c17
-rw-r--r--src/gallium/drivers/vc4/vc4_simulator_validate.c111
-rw-r--r--src/gallium/drivers/vc4/vc4_simulator_validate.h17
3 files changed, 78 insertions, 67 deletions
diff --git a/src/gallium/drivers/vc4/vc4_simulator.c b/src/gallium/drivers/vc4/vc4_simulator.c
index 0dada687911..879a1a3802b 100644
--- a/src/gallium/drivers/vc4/vc4_simulator.c
+++ b/src/gallium/drivers/vc4/vc4_simulator.c
@@ -105,7 +105,7 @@ vc4_cl_validate(struct drm_device *dev, struct exec_info *exec)
{
struct drm_vc4_submit_cl *args = exec->args;
void *temp = NULL;
- void *bin, *render, *shader_rec;
+ void *bin, *render;
int ret = 0;
uint32_t bin_offset = 0;
uint32_t render_offset = bin_offset + args->bin_cl_len;
@@ -142,7 +142,7 @@ vc4_cl_validate(struct drm_device *dev, struct exec_info *exec)
}
bin = temp + bin_offset;
render = temp + render_offset;
- shader_rec = temp + shader_rec_offset;
+ exec->shader_rec_u = temp + shader_rec_offset;
exec->uniforms_u = temp + uniforms_offset;
exec->shader_state = temp + exec_size;
exec->shader_state_size = args->shader_record_count;
@@ -159,7 +159,7 @@ vc4_cl_validate(struct drm_device *dev, struct exec_info *exec)
goto fail;
}
- ret = copy_from_user(shader_rec, args->shader_records,
+ ret = copy_from_user(exec->shader_rec_u, args->shader_records,
args->shader_record_len);
if (ret) {
DRM_ERROR("Failed to copy in shader recs\n");
@@ -187,7 +187,10 @@ vc4_cl_validate(struct drm_device *dev, struct exec_info *exec)
exec->ct0ea = exec->ct0ca + args->bin_cl_len;
exec->ct1ca = exec->exec_bo->paddr + render_offset;
exec->ct1ea = exec->ct1ca + args->render_cl_len;
- exec->shader_paddr = exec->exec_bo->paddr + shader_rec_offset;
+
+ exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset;
+ exec->shader_rec_p = exec->exec_bo->paddr + shader_rec_offset;
+ exec->shader_rec_size = args->shader_record_len;
exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset;
exec->uniforms_p = exec->exec_bo->paddr + uniforms_offset;
@@ -211,11 +214,7 @@ vc4_cl_validate(struct drm_device *dev, struct exec_info *exec)
if (ret)
goto fail;
- ret = vc4_validate_shader_recs(dev,
- exec->exec_bo->vaddr + shader_rec_offset,
- shader_rec,
- args->shader_record_len,
- exec);
+ ret = vc4_validate_shader_recs(dev, exec);
fail:
kfree(temp);
diff --git a/src/gallium/drivers/vc4/vc4_simulator_validate.c b/src/gallium/drivers/vc4/vc4_simulator_validate.c
index a67e2345b11..d393517c414 100644
--- a/src/gallium/drivers/vc4/vc4_simulator_validate.c
+++ b/src/gallium/drivers/vc4/vc4_simulator_validate.c
@@ -47,6 +47,18 @@
void *validated, \
void *untrusted
+static uint32_t
+gl_shader_rec_size(uint32_t pointer_bits)
+{
+ uint32_t attribute_count = pointer_bits & 7;
+ bool extended = pointer_bits & 8;
+
+ if (attribute_count == 0)
+ attribute_count = 8;
+
+ return 36 + attribute_count * (extended ? 12 : 8);
+}
+
static int
validate_branch_to_sublist(VALIDATE_ARGS)
{
@@ -123,8 +135,15 @@ validate_gl_shader_state(VALIDATE_ARGS)
exec->shader_state[i].packet = VC4_PACKET_GL_SHADER_STATE;
exec->shader_state[i].addr = *(uint32_t *)untrusted;
- *(uint32_t *)validated = exec->shader_state[i].addr +
- exec->shader_paddr;
+ if (exec->shader_state[i].addr & ~0xf) {
+ DRM_ERROR("high bits set in GL shader rec reference\n");
+ return -EINVAL;
+ }
+
+ *(uint32_t *)validated = (exec->shader_rec_p +
+ exec->shader_state[i].addr);
+
+ exec->shader_rec_p += gl_shader_rec_size(exec->shader_state[i].addr);
return 0;
}
@@ -148,8 +167,8 @@ validate_nv_shader_state(VALIDATE_ARGS)
return -EINVAL;
}
- *(uint32_t *)validated =
- exec->shader_state[i].addr + exec->shader_paddr;
+ *(uint32_t *)validated = (exec->shader_state[i].addr +
+ exec->shader_rec_p);
return 0;
}
@@ -374,14 +393,10 @@ reloc_tex(struct exec_info *exec,
static int
validate_shader_rec(struct drm_device *dev,
struct exec_info *exec,
- void *validated,
- void *unvalidated,
- uint32_t len,
struct vc4_shader_state *state)
{
- uint32_t *src_handles = unvalidated;
- void *src_pkt;
- void *dst_pkt = validated;
+ uint32_t *src_handles;
+ void *pkt_u, *pkt_v;
enum shader_rec_reloc_type {
RELOC_CODE,
RELOC_VBO,
@@ -401,35 +416,49 @@ validate_shader_rec(struct drm_device *dev,
};
const struct shader_rec_reloc *relocs;
struct drm_gem_cma_object *bo[ARRAY_SIZE(gl_relocs) + 8];
- uint32_t nr_attributes = 0, nr_relocs, packet_size;
+ uint32_t nr_attributes = 0, nr_fixed_relocs, nr_relocs, packet_size;
int i;
struct vc4_validated_shader_info *validated_shader = NULL;
if (state->packet == VC4_PACKET_NV_SHADER_STATE) {
relocs = nv_relocs;
- nr_relocs = ARRAY_SIZE(nv_relocs);
+ nr_fixed_relocs = ARRAY_SIZE(nv_relocs);
packet_size = 16;
} else {
relocs = gl_relocs;
- nr_relocs = ARRAY_SIZE(gl_relocs);
+ nr_fixed_relocs = ARRAY_SIZE(gl_relocs);
nr_attributes = state->addr & 0x7;
if (nr_attributes == 0)
nr_attributes = 8;
- packet_size = 36 + nr_attributes * 8;
+ packet_size = gl_shader_rec_size(state->addr);
+ }
+ nr_relocs = nr_fixed_relocs + nr_attributes;
+
+ if (nr_relocs * 4 > exec->shader_rec_size) {
+ DRM_ERROR("overflowed shader recs reading %d handles "
+ "from %d bytes left\n",
+ nr_relocs, exec->shader_rec_size);
+ return -EINVAL;
}
- if ((nr_relocs + nr_attributes) * 4 + packet_size > len) {
- DRM_ERROR("overflowed shader packet read "
- "(handles %d, packet %d, len %d)\n",
- (nr_relocs + nr_attributes) * 4, packet_size, len);
+ src_handles = exec->shader_rec_u;
+ exec->shader_rec_u += nr_relocs * 4;
+ exec->shader_rec_size -= nr_relocs * 4;
+
+ if (packet_size > exec->shader_rec_size) {
+ DRM_ERROR("overflowed shader recs copying %db packet "
+ "from %d bytes left\n",
+ packet_size, exec->shader_rec_size);
return -EINVAL;
}
+ pkt_u = exec->shader_rec_u;
+ pkt_v = exec->shader_rec_v;
+ memcpy(pkt_v, pkt_u, packet_size);
+ exec->shader_rec_u += packet_size;
+ exec->shader_rec_v += packet_size;
- src_pkt = unvalidated + 4 * (nr_relocs + nr_attributes);
- memcpy(dst_pkt, src_pkt, packet_size);
-
- for (i = 0; i < nr_relocs + nr_attributes; i++) {
+ for (i = 0; i < nr_relocs; i++) {
if (src_handles[i] >= exec->bo_count) {
DRM_ERROR("shader rec bo index %d > %d\n",
src_handles[i], exec->bo_count);
@@ -438,14 +467,15 @@ validate_shader_rec(struct drm_device *dev,
bo[i] = exec->bo[src_handles[i]];
}
- for (i = 0; i < nr_relocs; i++) {
+ for (i = 0; i < nr_fixed_relocs; i++) {
uint32_t o = relocs[i].offset;
- uint32_t src_offset = *(uint32_t *)(src_pkt + o);
- *(uint32_t *)(dst_pkt + o) = bo[i]->paddr + src_offset;
+ uint32_t src_offset = *(uint32_t *)(pkt_u + o);
uint32_t *texture_handles_u;
void *uniform_data_u;
uint32_t tex;
+ *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset;
+
switch (relocs[i].type) {
case RELOC_CODE:
kfree(validated_shader);
@@ -478,7 +508,7 @@ validate_shader_rec(struct drm_device *dev,
}
}
- *(uint32_t *)(dst_pkt + o + 4) = exec->uniforms_p;
+ *(uint32_t *)(pkt_v + o + 4) = exec->uniforms_p;
exec->uniforms_u += validated_shader->uniforms_src_size;
exec->uniforms_v += validated_shader->uniforms_size;
@@ -494,8 +524,8 @@ validate_shader_rec(struct drm_device *dev,
for (i = 0; i < nr_attributes; i++) {
/* XXX: validation */
uint32_t o = 36 + i * 8;
- *(uint32_t *)(dst_pkt + o) =
- bo[nr_relocs + i]->paddr + *(uint32_t *)(src_pkt + o);
+ *(uint32_t *)(pkt_v + o) = (bo[nr_fixed_relocs + i]->paddr +
+ *(uint32_t *)(pkt_u + o));
}
kfree(validated_shader);
@@ -509,38 +539,15 @@ fail:
int
vc4_validate_shader_recs(struct drm_device *dev,
- void *validated,
- void *unvalidated,
- uint32_t len,
struct exec_info *exec)
{
- uint32_t dst_offset = 0;
- uint32_t src_offset = 0;
uint32_t i;
int ret = 0;
for (i = 0; i < exec->shader_state_count; i++) {
- if ((exec->shader_state[i].addr & ~0xf) !=
- (validated - exec->exec_bo->vaddr -
- (exec->shader_paddr - exec->exec_bo->paddr))) {
- DRM_ERROR("unexpected shader rec offset: "
- "0x%08x vs 0x%08x\n",
- exec->shader_state[i].addr & ~0xf,
- (int)(validated -
- exec->exec_bo->vaddr -
- (exec->shader_paddr -
- exec->exec_bo->paddr)));
- return -EINVAL;
- }
-
- ret = validate_shader_rec(dev, exec,
- validated + dst_offset,
- unvalidated + src_offset,
- len - src_offset,
- &exec->shader_state[i]);
+ ret = validate_shader_rec(dev, exec, &exec->shader_state[i]);
if (ret)
return ret;
- /* XXX: incr dst/src offset */
}
return ret;
diff --git a/src/gallium/drivers/vc4/vc4_simulator_validate.h b/src/gallium/drivers/vc4/vc4_simulator_validate.h
index 885a754a9d5..28dd2f65e70 100644
--- a/src/gallium/drivers/vc4/vc4_simulator_validate.h
+++ b/src/gallium/drivers/vc4/vc4_simulator_validate.h
@@ -114,7 +114,16 @@ struct exec_info {
*/
uint32_t ct0ca, ct0ea;
uint32_t ct1ca, ct1ea;
- uint32_t shader_paddr;
+
+ /* Pointers to the shader recs. These paddr gets incremented as CL
+ * packets are relocated in validate_gl_shader_state, and the vaddrs
+ * (u and v) get incremented and size decremented as the shader recs
+ * themselves are validated.
+ */
+ void *shader_rec_u;
+ void *shader_rec_v;
+ uint32_t shader_rec_p;
+ uint32_t shader_rec_size;
/* Pointers to the uniform data. These pointers are incremented, and
* size decremented, as each batch of uniforms is uploaded.
@@ -168,11 +177,7 @@ int vc4_validate_cl(struct drm_device *dev,
bool is_bin,
struct exec_info *exec);
-int vc4_validate_shader_recs(struct drm_device *dev,
- void *validated,
- void *unvalidated,
- uint32_t len,
- struct exec_info *exec);
+int vc4_validate_shader_recs(struct drm_device *dev, struct exec_info *exec);
struct vc4_validated_shader_info *
vc4_validate_shader(struct drm_gem_cma_object *shader_obj,