@@ -61,15 +61,33 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
CMD( MI_REPORT_HEAD, SMI, F, 1, S ),
CMD( MI_SUSPEND_FLUSH, SMI, F, 1, S ),
CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ),
- CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3FF, S ),
+ CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3FF, B,
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ),
CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W,
.reg = { .offset = 1, .mask = 0x007FFFFC } ),
CMD( MI_UPDATE_GTT, SMI, !F, 0xFF, R ),
- CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W,
- .reg = { .offset = 1, .mask = 0x007FFFFC } ),
- CMD( MI_LOAD_REGISTER_MEM, SMI, !F, 0xFF, W,
- .reg = { .offset = 1, .mask = 0x007FFFFC } ),
+ CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B,
+ .reg = { .offset = 1, .mask = 0x007FFFFC },
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
+ CMD( MI_LOAD_REGISTER_MEM, SMI, !F, 0xFF, W | B,
+ .reg = { .offset = 1, .mask = 0x007FFFFC },
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
CMD( MI_BATCH_BUFFER_START, SMI, !F, 0xFF, S ),
};
@@ -79,7 +97,20 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
CMD( MI_DISPLAY_FLIP, SMI, !F, 0xFF, R ),
CMD( MI_PREDICATE, SMI, F, 1, S ),
CMD( MI_TOPOLOGY_FILTER, SMI, F, 1, S ),
- CMD( MI_CLFLUSH, SMI, !F, 0x3FF, S ),
+ CMD( MI_CLFLUSH, SMI, !F, 0x3FF, B,
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
+ CMD( MI_CONDITIONAL_BATCH_BUFFER_END, SMI, !F, 0xFF, B,
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
CMD( GFX_OP_3DSTATE_VF_STATISTICS, S3D, F, 1, S ),
CMD( PIPELINE_SELECT, S3D, F, 1, S ),
CMD( MEDIA_VFE_STATE, S3D, !F, 0xFFFF, B,
@@ -97,8 +128,15 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
.offset = 1,
.mask = (PIPE_CONTROL_MMIO_WRITE | PIPE_CONTROL_NOTIFY),
.expected = 0
+ },
+ {
+ .offset = 1,
+ .mask = PIPE_CONTROL_GLOBAL_GTT_IVB,
+ .expected = 0,
+ .condition_offset = 1,
+ .condition_mask = PIPE_CONTROL_POST_SYNC_OP_MASK
}},
- .bits_count = 1 ),
+ .bits_count = 2 ),
};
static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
@@ -122,8 +160,22 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
.offset = 0,
.mask = MI_FLUSH_DW_NOTIFY,
.expected = 0
+ },
+ {
+ .offset = 1,
+ .mask = MI_FLUSH_DW_USE_GTT,
+ .expected = 0,
+ .condition_offset = 0,
+ .condition_mask = MI_FLUSH_DW_OP_MASK
}},
- .bits_count = 1 ),
+ .bits_count = 2 ),
+ CMD( MI_CONDITIONAL_BATCH_BUFFER_END, SMI, !F, 0xFF, B,
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
CMD( MFX_WAIT, SMFX, !F, 0x3F, S ),
};
@@ -133,8 +185,22 @@ static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
.offset = 0,
.mask = MI_FLUSH_DW_NOTIFY,
.expected = 0
+ },
+ {
+ .offset = 1,
+ .mask = MI_FLUSH_DW_USE_GTT,
+ .expected = 0,
+ .condition_offset = 0,
+ .condition_mask = MI_FLUSH_DW_OP_MASK
}},
- .bits_count = 1 ),
+ .bits_count = 2 ),
+ CMD( MI_CONDITIONAL_BATCH_BUFFER_END, SMI, !F, 0xFF, B,
+ .bits = {{
+ .offset = 0,
+ .mask = MI_GLOBAL_GTT,
+ .expected = 0
+ }},
+ .bits_count = 1 ),
};
static const struct drm_i915_cmd_descriptor blt_cmds[] = {
@@ -144,8 +210,15 @@ static const struct drm_i915_cmd_descriptor blt_cmds[] = {
.offset = 0,
.mask = MI_FLUSH_DW_NOTIFY,
.expected = 0
+ },
+ {
+ .offset = 1,
+ .mask = MI_FLUSH_DW_USE_GTT,
+ .expected = 0,
+ .condition_offset = 0,
+ .condition_mask = MI_FLUSH_DW_OP_MASK
}},
- .bits_count = 1 ),
+ .bits_count = 2 ),
CMD( COLOR_BLT, S2D, !F, 0x3F, S ),
CMD( SRC_COPY_BLT, S2D, !F, 0x3F, S ),
};
@@ -422,6 +495,13 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
int ret = 0;
u32 *cmd, *batch_base, *batch_end;
struct drm_i915_cmd_descriptor default_desc = { 0 };
+ drm_i915_private_t *dev_priv =
+ (drm_i915_private_t *)ring->dev->dev_private;
+
+ /* XXX: this breaks VLV, which is Gen7, but no PPGTT
+ * Replace with better checks for when to call i915_parse_cmds?
+ */
+ WARN_ON(!dev_priv->mm.aliasing_ppgtt);
/* No command tables currently indicates a platform without parsing */
if (!ring->cmd_tables)
@@ -490,6 +570,16 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
u32 dword = cmd[desc->bits[i].offset] &
desc->bits[i].mask;
+ if (desc->bits[i].condition_mask != 0) {
+ u32 offset =
+ desc->bits[i].condition_offset;
+ u32 condition = cmd[offset] &
+ desc->bits[i].condition_mask;
+
+ if (condition == 0)
+ continue;
+ }
+
if (dword != desc->bits[i].expected) {
DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (ring=%d)\n",
*cmd,
@@ -1792,11 +1792,17 @@ struct drm_i915_cmd_descriptor {
* compared against an expected value. If the command does not match
* the expected value, the parser rejects it. Only valid if flags has
* the CMD_DESC_BITMASK bit set.
+ *
+ * If the check specifies a non-zero condition_mask then the parser
+ * only performs the check when the bits specified by condition_mask
+ * are non-zero.
*/
struct {
u32 offset;
u32 mask;
u32 expected;
+ u32 condition_offset;
+ u32 condition_mask;
} bits[MAX_CMD_DESC_BITMASKS];
/** Number of valid entries in the bits array */
int bits_count;
@@ -178,6 +178,8 @@
* Memory interface instructions used by the kernel
*/
#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+/* Many MI commands use bit 22 of the header dword for GGTT vs PPGTT */
+#define MI_GLOBAL_GTT (1<<22)
#define MI_NOOP MI_INSTR(0, 0)
#define MI_USER_INTERRUPT MI_INSTR(0x02, 0)
@@ -240,6 +242,7 @@
#define MI_FLUSH_DW_STORE_INDEX (1<<21)
#define MI_INVALIDATE_TLB (1<<18)
#define MI_FLUSH_DW_OP_STOREDW (1<<14)
+#define MI_FLUSH_DW_OP_MASK (3<<14)
#define MI_FLUSH_DW_NOTIFY (1<<8)
#define MI_INVALIDATE_BSD (1<<7)
#define MI_FLUSH_DW_USE_GTT (1<<2)
@@ -323,6 +326,7 @@
#define PIPE_CONTROL_CS_STALL (1<<20)
#define PIPE_CONTROL_TLB_INVALIDATE (1<<18)
#define PIPE_CONTROL_QW_WRITE (1<<14)
+#define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14)
#define PIPE_CONTROL_DEPTH_STALL (1<<13)
#define PIPE_CONTROL_WRITE_FLUSH (1<<12)
#define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */
@@ -354,6 +358,7 @@
#define MI_LOAD_REGISTER_REG MI_INSTR(0x2A, 0)
#define MI_LOAD_URB_MEM MI_INSTR(0x2C, 0)
#define MI_STORE_URB_MEM MI_INSTR(0x2D, 0)
+#define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0)
#define PIPELINE_SELECT ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16))
#define GFX_OP_3DSTATE_VF_STATISTICS ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16))