vc4: Fix things to validate more than one shader state in a submit.
authorEric Anholt <eric@anholt.net>
Wed, 23 Jul 2014 03:10:01 +0000 (20:10 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 11 Aug 2014 21:45:28 +0000 (14:45 -0700)
src/gallium/drivers/vc4/vc4_simulator.c
src/gallium/drivers/vc4/vc4_simulator_validate.c
src/gallium/drivers/vc4/vc4_simulator_validate.h

index 0dada68791162537242ef363a1ff94d8d85ff0ce..879a1a3802bb440127cf52fceb414d1db8ddfdcc 100644 (file)
@@ -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);
index a67e2345b11446e27859d882b1479845beaf949c..d393517c414d951dbadbde1801f2699c385f0862 100644 (file)
        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;
index 885a754a9d56a6b00cbb6e234cf92b255f2cb253..28dd2f65e703bf2fecc87c7571588a71be990de0 100644 (file)
@@ -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,