aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c74
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
2 files changed, 48 insertions, 31 deletions
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 9605ff8f2fcd..5fc49bbcdb9d 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -123,7 +123,7 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
123 CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ), 123 CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ),
124 CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ), 124 CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ),
125 CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, 125 CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W,
126 .reg = { .offset = 1, .mask = 0x007FFFFC } ), 126 .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ),
127 CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B, 127 CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B,
128 .reg = { .offset = 1, .mask = 0x007FFFFC }, 128 .reg = { .offset = 1, .mask = 0x007FFFFC },
129 .bits = {{ 129 .bits = {{
@@ -934,7 +934,7 @@ bool i915_needs_cmd_parser(struct intel_engine_cs *ring)
934 934
935static bool check_cmd(const struct intel_engine_cs *ring, 935static bool check_cmd(const struct intel_engine_cs *ring,
936 const struct drm_i915_cmd_descriptor *desc, 936 const struct drm_i915_cmd_descriptor *desc,
937 const u32 *cmd, 937 const u32 *cmd, u32 length,
938 const bool is_master, 938 const bool is_master,
939 bool *oacontrol_set) 939 bool *oacontrol_set)
940{ 940{
@@ -950,38 +950,49 @@ static bool check_cmd(const struct intel_engine_cs *ring,
950 } 950 }
951 951
952 if (desc->flags & CMD_DESC_REGISTER) { 952 if (desc->flags & CMD_DESC_REGISTER) {
953 u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
954
955 /* 953 /*
956 * OACONTROL requires some special handling for writes. We 954 * Get the distance between individual register offset
957 * want to make sure that any batch which enables OA also 955 * fields if the command can perform more than one
958 * disables it before the end of the batch. The goal is to 956 * access at a time.
959 * prevent one process from snooping on the perf data from
960 * another process. To do that, we need to check the value
961 * that will be written to the register. Hence, limit
962 * OACONTROL writes to only MI_LOAD_REGISTER_IMM commands.
963 */ 957 */
964 if (reg_addr == OACONTROL) { 958 const u32 step = desc->reg.step ? desc->reg.step : length;
965 if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { 959 u32 offset;
966 DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); 960
967 return false; 961 for (offset = desc->reg.offset; offset < length;
962 offset += step) {
963 const u32 reg_addr = cmd[offset] & desc->reg.mask;
964
965 /*
966 * OACONTROL requires some special handling for
967 * writes. We want to make sure that any batch which
968 * enables OA also disables it before the end of the
969 * batch. The goal is to prevent one process from
970 * snooping on the perf data from another process. To do
971 * that, we need to check the value that will be written
972 * to the register. Hence, limit OACONTROL writes to
973 * only MI_LOAD_REGISTER_IMM commands.
974 */
975 if (reg_addr == OACONTROL) {
976 if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
977 DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
978 return false;
979 }
980
981 if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1))
982 *oacontrol_set = (cmd[offset + 1] != 0);
968 } 983 }
969 984
970 if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) 985 if (!valid_reg(ring->reg_table,
971 *oacontrol_set = (cmd[2] != 0); 986 ring->reg_count, reg_addr)) {
972 } 987 if (!is_master ||
973 988 !valid_reg(ring->master_reg_table,
974 if (!valid_reg(ring->reg_table, 989 ring->master_reg_count,
975 ring->reg_count, reg_addr)) { 990 reg_addr)) {
976 if (!is_master || 991 DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
977 !valid_reg(ring->master_reg_table, 992 reg_addr, *cmd,
978 ring->master_reg_count, 993 ring->id);
979 reg_addr)) { 994 return false;
980 DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", 995 }
981 reg_addr,
982 *cmd,
983 ring->id);
984 return false;
985 } 996 }
986 } 997 }
987 } 998 }
@@ -1105,7 +1116,8 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
1105 break; 1116 break;
1106 } 1117 }
1107 1118
1108 if (!check_cmd(ring, desc, cmd, is_master, &oacontrol_set)) { 1119 if (!check_cmd(ring, desc, cmd, length, is_master,
1120 &oacontrol_set)) {
1109 ret = -EINVAL; 1121 ret = -EINVAL;
1110 break; 1122 break;
1111 } 1123 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 72f5a3f9dbf2..542fac628b28 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2300,10 +2300,15 @@ struct drm_i915_cmd_descriptor {
2300 * Describes where to find a register address in the command to check 2300 * Describes where to find a register address in the command to check
2301 * against the ring's register whitelist. Only valid if flags has the 2301 * against the ring's register whitelist. Only valid if flags has the
2302 * CMD_DESC_REGISTER bit set. 2302 * CMD_DESC_REGISTER bit set.
2303 *
2304 * A non-zero step value implies that the command may access multiple
2305 * registers in sequence (e.g. LRI), in that case step gives the
2306 * distance in dwords between individual offset fields.
2303 */ 2307 */
2304 struct { 2308 struct {
2305 u32 offset; 2309 u32 offset;
2306 u32 mask; 2310 u32 mask;
2311 u32 step;
2307 } reg; 2312 } reg;
2308 2313
2309#define MAX_CMD_DESC_BITMASKS 3 2314#define MAX_CMD_DESC_BITMASKS 3