]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: host: fix 64 bit regops
authorDeepak Nibade <dnibade@nvidia.com>
Tue, 18 Feb 2014 12:57:29 +0000 (18:27 +0530)
committerTerje Bergstrom <tbergstrom@nvidia.com>
Wed, 26 Feb 2014 13:46:37 +0000 (05:46 -0800)
In regops, there is a whitelist of allowed registers. The
whitelisted registers are always considered to be 32-bit.
However, we do not consider 64-bit read/write operations
during whitelist validation.
e.g. if register at 0x400500 is whitelisted, with a 64-bit
read we can also read register at 0x400504 which is not
whitelisted

To fix this, first separate out check_whitelists() function
from validate_reg_op_offset() which does the whitelist
validation of given offset.
Then pass offset to this function to check if it is
whitelisted or not.
If yes and if operation is 64-bit, then pass (offset + 4)
to check_whitelists() to check if next offset is also
whitelisted or not.

Bug 1440107

Change-Id: I9a08cc031e741987f5577d47d32b303ba114ff07
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/368437
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
drivers/video/tegra/host/gk20a/regops_gk20a.c

index 75b98927e46eadd6220171333dee158564fca4cd..7a6d5ed3c83283787c5369ad328ff159c1f16a98 100644 (file)
@@ -549,25 +549,11 @@ static int validate_reg_op_info(struct dbg_session_gk20a *dbg_s,
        return err;
 }
 
-
-/* note: the op here has already been through validate_reg_op_info */
-static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
-                                 struct nvhost_dbg_gpu_reg_op *op)
+static bool check_whitelists(struct dbg_session_gk20a *dbg_s,
+                         struct nvhost_dbg_gpu_reg_op *op, u32 offset)
 {
-       int err;
-       u32 buf_offset_lo, buf_offset_addr, num_offsets, offset;
        bool valid = false;
 
-       op->status = 0;
-       offset = op->offset;
-
-       /* support only 24-bit 4-byte aligned offsets */
-       if (offset & 0xFF000003) {
-               nvhost_err(dbg_s->dev, "invalid regop offset: 0x%x\n", offset);
-               op->status |= REGOP(STATUS_INVALID_OFFSET);
-               return -EINVAL;
-       }
-
        if (op->type == REGOP(TYPE_GLOBAL)) {
                /* search global list */
                valid = !!bsearch(&offset,
@@ -620,6 +606,31 @@ static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
                                      gk20a_qctl_whitelist_count);
        }
 
+       return valid;
+}
+
+/* note: the op here has already been through validate_reg_op_info */
+static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
+                                 struct nvhost_dbg_gpu_reg_op *op)
+{
+       int err;
+       u32 buf_offset_lo, buf_offset_addr, num_offsets, offset;
+       bool valid = false;
+
+       op->status = 0;
+       offset = op->offset;
+
+       /* support only 24-bit 4-byte aligned offsets */
+       if (offset & 0xFF000003) {
+               nvhost_err(dbg_s->dev, "invalid regop offset: 0x%x\n", offset);
+               op->status |= REGOP(STATUS_INVALID_OFFSET);
+               return -EINVAL;
+       }
+
+       valid = check_whitelists(dbg_s, op, offset);
+       if ((op->op == REGOP(READ_64) || op->op == REGOP(WRITE_64)) && valid)
+               valid = check_whitelists(dbg_s, op, offset + 4);
+
        if (valid && (op->type != REGOP(TYPE_GLOBAL))) {
                        err = gr_gk20a_get_ctx_buffer_offsets(dbg_s->g,
                                                              op->offset,