All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] Gen7 batch buffer command parser
@ 2014-02-18 18:15 bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 01/13] drm/i915: Refactor shmem pread setup bradley.d.volkin
                   ` (16 more replies)
  0 siblings, 17 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

Certain OpenGL features (e.g. transform feedback, performance monitoring)
require userspace code to submit batches containing commands such as
MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
generations of the hardware will noop these commands in "unsecure" batches
(which includes all userspace batches submitted via i915) even though the
commands may be safe and represent the intended programming model of the device.

This series introduces a software command parser similar in operation to the
command parsing done in hardware for unsecure batches. However, the software
parser allows some operations that would be noop'd by hardware, if the parser
determines the operation is safe, and submits the batch as "secure" to prevent
hardware parsing. Currently the series implements this on IVB and HSW.

The series has one piece of prep work, one patch for the parser logic, and a
handful of patches to fill out the tables which drive the parser. There are
follow-up patches to libdrm and to i-g-t. The i-g-t tests are basic and do not
test all of the commands used by the parser on the assumption that I'm likely
to make the same mistakes in both the parser and the test.

I've previously run the i-g-t gem_* tests, the piglit quick tests, and generally
used Ubuntu 13.10 IVB and HSW systems with the parser running. Aside from a
failure described below, I did not see any regressions.

At this point there are a couple of required/potential improvements.

1) Chained batches. The parser currently allows MI_BATCH_BUFFER_START commands
   in userspace batches without parsing them. The media driver uses chained
   batches, so a solution is required. I'm still working through the
   requirements but don't want to continue delaying the review process for what
   I have so far.
2) Command buffer copy. To avoid CPU modifications to buffers after parsing, and
   to avoid GPU modifications to buffers via EUs or commands in the batch, we
   should copy the userspace batch buffer to memory that userspace does not
   have access to, map it into GGTT, and execute that batch buffer. I have a
   sense of how to do this for 1st-level batches, but it may need changes to
   tie in with the chained batch parsing, so I've again held off.
3) Coherency. I've previously found a coherency issue on VLV when reading the
   batch buffer from the CPU during execbuffer2. Userspace writes the batch via
   pwrite fast path before calling execbuffer2. The parser reads stale data.
   This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
   It's possible that the shmem pread refactoring fixes this, I just have not
   been able to retest due to lack of a VLV system.

v2:
- Significantly reorder series
- Scan secure batches (i.e. I915_EXEC_SECURE)
- Check that parser tables are sorted during init
- Fixed gem_cpu_reloc regression
- HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
- Additional tests

v3:
- Don't actually send batches as secure yet
- Improved documentation and commenting
- Many other small cleanups throughout

Brad Volkin (13):
  drm/i915: Refactor shmem pread setup
  drm/i915: Implement command buffer parsing logic
  drm/i915: Initial command parser table definitions
  drm/i915: Reject privileged commands
  drm/i915: Allow some privileged commands from master
  drm/i915: Add register whitelists for mesa
  drm/i915: Add register whitelist for DRM master
  drm/i915: Enable register whitelist checks
  drm/i915: Reject commands that explicitly generate interrupts
  drm/i915: Enable PPGTT command parser checks
  drm/i915: Reject commands that would store to global HWS page
  drm/i915: Add a CMD_PARSER_VERSION getparam
  drm/i915: Enable command parsing by default

 drivers/gpu/drm/i915/Makefile              |   1 +
 drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_dma.c            |   3 +
 drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
 drivers/gpu/drm/i915/i915_gem.c            |  51 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
 drivers/gpu/drm/i915/i915_params.c         |   5 +
 drivers/gpu/drm/i915/i915_reg.h            |  96 +++
 drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
 drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
 include/uapi/drm/i915_drm.h                |   1 +
 11 files changed, 1216 insertions(+), 14 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c

-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 01/13] drm/i915: Refactor shmem pread setup
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-03-06 12:13   ` Jani Nikula
  2014-02-18 18:15 ` [PATCH 02/13] drm/i915: Implement command buffer parsing logic bradley.d.volkin
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

The command parser is going to need the same synchronization and
setup logic, so factor it out for reuse.

v2: Add a check that the object is backed by shmem

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |  3 +++
 drivers/gpu/drm/i915/i915_gem.c | 51 ++++++++++++++++++++++++++++++-----------
 2 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8c64831..582035b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2097,6 +2097,9 @@ void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
+int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
+				    int *needs_clflush);
+
 int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3618bb0..83990cb 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -326,6 +326,42 @@ __copy_from_user_swizzled(char *gpu_vaddr, int gpu_offset,
 	return 0;
 }
 
+/*
+ * Pins the specified object's pages and synchronizes the object with
+ * GPU accesses. Sets needs_clflush to non-zero if the caller should
+ * flush the object from the CPU cache.
+ */
+int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
+				    int *needs_clflush)
+{
+	int ret;
+
+	*needs_clflush = 0;
+
+	if (!obj->base.filp)
+		return -EINVAL;
+
+	if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) {
+		/* If we're not in the cpu read domain, set ourself into the gtt
+		 * read domain and manually flush cachelines (if required). This
+		 * optimizes for the case when the gpu will dirty the data
+		 * anyway again before the next pread happens. */
+		*needs_clflush = !cpu_cache_is_coherent(obj->base.dev,
+							obj->cache_level);
+		ret = i915_gem_object_wait_rendering(obj, true);
+		if (ret)
+			return ret;
+	}
+
+	ret = i915_gem_object_get_pages(obj);
+	if (ret)
+		return ret;
+
+	i915_gem_object_pin_pages(obj);
+
+	return ret;
+}
+
 /* Per-page copy function for the shmem pread fastpath.
  * Flushes invalid cachelines before reading the target if
  * needs_clflush is set. */
@@ -423,23 +459,10 @@ i915_gem_shmem_pread(struct drm_device *dev,
 
 	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
 
-	if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) {
-		/* If we're not in the cpu read domain, set ourself into the gtt
-		 * read domain and manually flush cachelines (if required). This
-		 * optimizes for the case when the gpu will dirty the data
-		 * anyway again before the next pread happens. */
-		needs_clflush = !cpu_cache_is_coherent(dev, obj->cache_level);
-		ret = i915_gem_object_wait_rendering(obj, true);
-		if (ret)
-			return ret;
-	}
-
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush);
 	if (ret)
 		return ret;
 
-	i915_gem_object_pin_pages(obj);
-
 	offset = args->offset;
 
 	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 02/13] drm/i915: Implement command buffer parsing logic
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 01/13] drm/i915: Refactor shmem pread setup bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-03-06 13:10   ` Jani Nikula
  2014-03-20 12:40   ` Jani Nikula
  2014-02-18 18:15 ` [PATCH 03/13] drm/i915: Initial command parser table definitions bradley.d.volkin
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

The command parser scans batch buffers submitted via execbuffer ioctls before
the driver submits them to hardware. At a high level, it looks for several
things:

1) Commands which are explicitly defined as privileged or which should only be
   used by the kernel driver. The parser generally rejects such commands, with
   the provision that it may allow some from the drm master process.
2) Commands which access registers. To support correct/enhanced userspace
   functionality, particularly certain OpenGL extensions, the parser provides a
   whitelist of registers which userspace may safely access (for both normal and
   drm master processes).
3) Commands which access privileged memory (i.e. GGTT, HWS page, etc). The
   parser always rejects such commands.

See the overview comment in the source for more details.

This patch only implements the logic. Subsequent patches will build the tables
that drive the parser.

v2: Don't set the secure bit if the parser succeeds
Fail harder during init
Makefile cleanup
Kerneldoc cleanup
Clarify module param description
Convert ints to bools in a few places
Move client/subclient defs to i915_reg.h
Remove the bits_count field

OTC-Tracker: AXIA-4631
Change-Id: I50b98c71c6655893291c78a2d1b8954577b37a30
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/Makefile              |   1 +
 drivers/gpu/drm/i915/i915_cmd_parser.c     | 485 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h            |  93 ++++++
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 ++
 drivers/gpu/drm/i915/i915_params.c         |   5 +
 drivers/gpu/drm/i915/i915_reg.h            |  12 +
 drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
 drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 ++
 8 files changed, 648 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4850494..3569122 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -14,6 +14,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  i915_gem_gtt.o \
 	  i915_gem_stolen.o \
 	  i915_gem_tiling.o \
+	  i915_cmd_parser.o \
 	  i915_params.o \
 	  i915_sysfs.o \
 	  i915_trace_points.o \
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
new file mode 100644
index 0000000..7a5756e
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Brad Volkin <bradley.d.volkin@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+
+/**
+ * DOC: i915 batch buffer command parser
+ *
+ * Motivation:
+ * Certain OpenGL features (e.g. transform feedback, performance monitoring)
+ * require userspace code to submit batches containing commands such as
+ * MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
+ * generations of the hardware will noop these commands in "unsecure" batches
+ * (which includes all userspace batches submitted via i915) even though the
+ * commands may be safe and represent the intended programming model of the
+ * device.
+ *
+ * The software command parser is similar in operation to the command parsing
+ * done in hardware for unsecure batches. However, the software parser allows
+ * some operations that would be noop'd by hardware, if the parser determines
+ * the operation is safe, and submits the batch as "secure" to prevent hardware
+ * parsing.
+ *
+ * Threats:
+ * At a high level, the hardware (and software) checks attempt to prevent
+ * granting userspace undue privileges. There are three categories of privilege.
+ *
+ * First, commands which are explicitly defined as privileged or which should
+ * only be used by the kernel driver. The parser generally rejects such
+ * commands, though it may allow some from the drm master process.
+ *
+ * Second, commands which access registers. To support correct/enhanced
+ * userspace functionality, particularly certain OpenGL extensions, the parser
+ * provides a whitelist of registers which userspace may safely access (for both
+ * normal and drm master processes).
+ *
+ * Third, commands which access privileged memory (i.e. GGTT, HWS page, etc).
+ * The parser always rejects such commands.
+ *
+ * The majority of the problematic commands fall in the MI_* range, with only a
+ * few specific commands on each ring (e.g. PIPE_CONTROL and MI_FLUSH_DW).
+ *
+ * Implementation:
+ * Each ring maintains tables of commands and registers which the parser uses in
+ * scanning batch buffers submitted to that ring.
+ *
+ * Since the set of commands that the parser must check for is significantly
+ * smaller than the number of commands supported, the parser tables contain only
+ * those commands required by the parser. This generally works because command
+ * opcode ranges have standard command length encodings. So for commands that
+ * the parser does not need to check, it can easily skip them. This is
+ * implementated via a per-ring length decoding vfunc.
+ *
+ * Unfortunately, there are a number of commands that do not follow the standard
+ * length encoding for their opcode range, primarily amongst the MI_* commands.
+ * To handle this, the parser provides a way to define explicit "skip" entries
+ * in the per-ring command tables.
+ *
+ * Other command table entries map fairly directly to high level categories
+ * mentioned above: rejected, master-only, register whitelist. The parser
+ * implements a number of checks, including the privileged memory checks, via a
+ * general bitmasking mechanism.
+ */
+
+static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
+{
+	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
+	u32 subclient =
+		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
+
+	if (client == INSTR_MI_CLIENT)
+		return 0x3F;
+	else if (client == INSTR_RC_CLIENT) {
+		if (subclient == INSTR_MEDIA_SUBCLIENT)
+			return 0xFFFF;
+		else
+			return 0xFF;
+	}
+
+	DRM_DEBUG_DRIVER("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header);
+	return 0;
+}
+
+static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header)
+{
+	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
+	u32 subclient =
+		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
+
+	if (client == INSTR_MI_CLIENT)
+		return 0x3F;
+	else if (client == INSTR_RC_CLIENT) {
+		if (subclient == INSTR_MEDIA_SUBCLIENT)
+			return 0xFFF;
+		else
+			return 0xFF;
+	}
+
+	DRM_DEBUG_DRIVER("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header);
+	return 0;
+}
+
+static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
+{
+	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
+
+	if (client == INSTR_MI_CLIENT)
+		return 0x3F;
+	else if (client == INSTR_BC_CLIENT)
+		return 0xFF;
+
+	DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
+	return 0;
+}
+
+static void validate_cmds_sorted(struct intel_ring_buffer *ring)
+{
+	int i;
+
+	if (!ring->cmd_tables || ring->cmd_table_count == 0)
+		return;
+
+	for (i = 0; i < ring->cmd_table_count; i++) {
+		const struct drm_i915_cmd_table *table = &ring->cmd_tables[i];
+		u32 previous = 0;
+		int j;
+
+		for (j = 0; j < table->count; j++) {
+			const struct drm_i915_cmd_descriptor *desc =
+				&table->table[i];
+			u32 curr = desc->cmd.value & desc->cmd.mask;
+
+			if (curr < previous)
+				DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
+					  ring->id, i, j, curr, previous);
+
+			previous = curr;
+		}
+	}
+}
+
+static void check_sorted(int ring_id, const u32 *reg_table, int reg_count)
+{
+	int i;
+	u32 previous = 0;
+
+	for (i = 0; i < reg_count; i++) {
+		u32 curr = reg_table[i];
+
+		if (curr < previous)
+			DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
+				  ring_id, i, curr, previous);
+
+		previous = curr;
+	}
+}
+
+static void validate_regs_sorted(struct intel_ring_buffer *ring)
+{
+	check_sorted(ring->id, ring->reg_table, ring->reg_count);
+	check_sorted(ring->id, ring->master_reg_table, ring->master_reg_count);
+}
+
+/**
+ * i915_cmd_parser_init_ring() - set cmd parser related fields for a ringbuffer
+ * @ring: the ringbuffer to initialize
+ *
+ * Optionally initializes fields related to batch buffer command parsing in the
+ * struct intel_ring_buffer based on whether the platform requires software
+ * command parsing.
+ */
+void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
+{
+	if (!IS_GEN7(ring->dev))
+		return;
+
+	switch (ring->id) {
+	case RCS:
+		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
+		break;
+	case VCS:
+		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
+		break;
+	case BCS:
+		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
+		break;
+	case VECS:
+		/* VECS can use the same length_mask function as VCS */
+		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
+		break;
+	default:
+		DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n",
+			  ring->id);
+		BUG();
+	}
+
+	validate_cmds_sorted(ring);
+	validate_regs_sorted(ring);
+}
+
+static const struct drm_i915_cmd_descriptor*
+find_cmd_in_table(const struct drm_i915_cmd_table *table,
+		  u32 cmd_header)
+{
+	int i;
+
+	for (i = 0; i < table->count; i++) {
+		const struct drm_i915_cmd_descriptor *desc = &table->table[i];
+		u32 masked_cmd = desc->cmd.mask & cmd_header;
+		u32 masked_value = desc->cmd.value & desc->cmd.mask;
+
+		if (masked_cmd == masked_value)
+			return desc;
+	}
+
+	return NULL;
+}
+
+/*
+ * Returns a pointer to a descriptor for the command specified by cmd_header.
+ *
+ * The caller must supply space for a default descriptor via the default_desc
+ * parameter. If no descriptor for the specified command exists in the ring's
+ * command parser tables, this function fills in default_desc based on the
+ * ring's default length encoding and returns default_desc.
+ */
+static const struct drm_i915_cmd_descriptor*
+find_cmd(struct intel_ring_buffer *ring,
+	 u32 cmd_header,
+	 struct drm_i915_cmd_descriptor *default_desc)
+{
+	u32 mask;
+	int i;
+
+	for (i = 0; i < ring->cmd_table_count; i++) {
+		const struct drm_i915_cmd_descriptor *desc;
+
+		desc = find_cmd_in_table(&ring->cmd_tables[i], cmd_header);
+		if (desc)
+			return desc;
+	}
+
+	mask = ring->get_cmd_length_mask(cmd_header);
+	if (!mask)
+		return NULL;
+
+	BUG_ON(!default_desc);
+	default_desc->flags = CMD_DESC_SKIP;
+	default_desc->length.mask = mask;
+
+	return default_desc;
+}
+
+static bool valid_reg(const u32 *table, int count, u32 addr)
+{
+	if (table && count != 0) {
+		int i;
+
+		for (i = 0; i < count; i++) {
+			if (table[i] == addr)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+static u32 *vmap_batch(struct drm_i915_gem_object *obj)
+{
+	int i;
+	void *addr = NULL;
+	struct sg_page_iter sg_iter;
+	struct page **pages;
+
+	pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
+	if (pages == NULL) {
+		DRM_DEBUG_DRIVER("Failed to get space for pages\n");
+		goto finish;
+	}
+
+	i = 0;
+	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
+		pages[i] = sg_page_iter_page(&sg_iter);
+		i++;
+	}
+
+	addr = vmap(pages, i, 0, PAGE_KERNEL);
+	if (addr == NULL) {
+		DRM_DEBUG_DRIVER("Failed to vmap pages\n");
+		goto finish;
+	}
+
+finish:
+	if (pages)
+		drm_free_large(pages);
+	return (u32*)addr;
+}
+
+/**
+ * i915_needs_cmd_parser() - should a given ring use software command parsing?
+ * @ring: the ring in question
+ *
+ * Only certain platforms require software batch buffer command parsing, and
+ * only when enabled via module paramter.
+ *
+ * Return: true if the ring requires software command parsing
+ */
+bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
+{
+	/* No command tables indicates a platform without parsing */
+	if (!ring->cmd_tables)
+		return false;
+
+	return (i915.enable_cmd_parser == 1);
+}
+
+#define LENGTH_BIAS 2
+
+/**
+ * i915_parse_cmds() - parse a submitted batch buffer for privilege violations
+ * @ring: the ring on which the batch is to execute
+ * @batch_obj: the batch buffer in question
+ * @batch_start_offset: byte offset in the batch at which execution starts
+ * @is_master: is the submitting process the drm master?
+ *
+ * Parses the specified batch buffer looking for privilege violations as
+ * described in the overview.
+ *
+ * Return: non-zero if the parser finds violations or otherwise fails
+ */
+int i915_parse_cmds(struct intel_ring_buffer *ring,
+		    struct drm_i915_gem_object *batch_obj,
+		    u32 batch_start_offset,
+		    bool is_master)
+{
+	int ret = 0;
+	u32 *cmd, *batch_base, *batch_end;
+	struct drm_i915_cmd_descriptor default_desc = { 0 };
+	int needs_clflush = 0;
+
+	ret = i915_gem_obj_prepare_shmem_read(batch_obj, &needs_clflush);
+	if (ret) {
+		DRM_DEBUG_DRIVER("CMD: failed to prep read\n");
+		return ret;
+	}
+
+	batch_base = vmap_batch(batch_obj);
+	if (!batch_base) {
+		DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n");
+		i915_gem_object_unpin_pages(batch_obj);
+		return -ENOMEM;
+	}
+
+	if (needs_clflush)
+		drm_clflush_virt_range((char *)batch_base, batch_obj->base.size);
+
+	cmd = batch_base + (batch_start_offset / sizeof(*cmd));
+	batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end));
+
+	while (cmd < batch_end) {
+		const struct drm_i915_cmd_descriptor *desc;
+		u32 length;
+
+		if (*cmd == MI_BATCH_BUFFER_END)
+			break;
+
+		desc = find_cmd(ring, *cmd, &default_desc);
+		if (!desc) {
+			DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n",
+					 *cmd);
+			ret = -EINVAL;
+			break;
+		}
+
+		if (desc->flags & CMD_DESC_FIXED)
+			length = desc->length.fixed;
+		else
+			length = ((*cmd & desc->length.mask) + LENGTH_BIAS);
+
+		if ((batch_end - cmd) < length) {
+			DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%ld\n",
+					 *cmd,
+					 length,
+					 batch_end - cmd);
+			ret = -EINVAL;
+			break;
+		}
+
+		if (desc->flags & CMD_DESC_REJECT) {
+			DRM_DEBUG_DRIVER("CMD: Rejected command: 0x%08X\n", *cmd);
+			ret = -EINVAL;
+			break;
+		}
+
+		if ((desc->flags & CMD_DESC_MASTER) && !is_master) {
+			DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n",
+					 *cmd);
+			ret = -EINVAL;
+			break;
+		}
+
+		if (desc->flags & CMD_DESC_REGISTER) {
+			u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
+
+			if (!valid_reg(ring->reg_table,
+				       ring->reg_count, reg_addr)) {
+				if (!is_master ||
+				    !valid_reg(ring->master_reg_table,
+					       ring->master_reg_count,
+					       reg_addr)) {
+					DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
+							 reg_addr,
+							 *cmd,
+							 ring->id);
+					ret = -EINVAL;
+					break;
+				}
+			}
+		}
+
+		if (desc->flags & CMD_DESC_BITMASK) {
+			int i;
+
+			for (i = 0; i < MAX_CMD_DESC_BITMASKS; i++) {
+				u32 dword;
+
+				if (desc->bits[i].mask == 0)
+					break;
+
+				dword = cmd[desc->bits[i].offset] &
+					desc->bits[i].mask;
+
+				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,
+							 desc->bits[i].mask,
+							 desc->bits[i].expected,
+							 dword, ring->id);
+					ret = -EINVAL;
+					break;
+				}
+			}
+
+			if (ret)
+				break;
+		}
+
+		cmd += length;
+	}
+
+	if (cmd >= batch_end) {
+		DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
+		ret = -EINVAL;
+	}
+
+	vunmap(batch_base);
+
+	i915_gem_object_unpin_pages(batch_obj);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 582035b..376472f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1803,6 +1803,90 @@ struct drm_i915_file_private {
 	atomic_t rps_wait_boost;
 };
 
+/*
+ * A command that requires special handling by the command parser.
+ */
+struct drm_i915_cmd_descriptor {
+	/*
+	 * Flags describing how the command parser processes the command.
+	 *
+	 * CMD_DESC_FIXED: The command has a fixed length if this is set,
+	 *                 a length mask if not set
+	 * CMD_DESC_SKIP: The command is allowed but does not follow the
+	 *                standard length encoding for the opcode range in
+	 *                which it falls
+	 * CMD_DESC_REJECT: The command is never allowed
+	 * CMD_DESC_REGISTER: The command should be checked against the
+	 *                    register whitelist for the appropriate ring
+	 * CMD_DESC_MASTER: The command is allowed if the submitting process
+	 *                  is the DRM master
+	 */
+	u32 flags;
+#define CMD_DESC_FIXED    (1<<0)
+#define CMD_DESC_SKIP     (1<<1)
+#define CMD_DESC_REJECT   (1<<2)
+#define CMD_DESC_REGISTER (1<<3)
+#define CMD_DESC_BITMASK  (1<<4)
+#define CMD_DESC_MASTER   (1<<5)
+
+	/*
+	 * The command's unique identification bits and the bitmask to get them.
+	 * This isn't strictly the opcode field as defined in the spec and may
+	 * also include type, subtype, and/or subop fields.
+	 */
+	struct {
+		u32 value;
+		u32 mask;
+	} cmd;
+
+	/*
+	 * The command's length. The command is either fixed length (i.e. does
+	 * not include a length field) or has a length field mask. The flag
+	 * CMD_DESC_FIXED indicates a fixed length. Otherwise, the command has
+	 * a length mask. All command entries in a command table must include
+	 * length information.
+	 */
+	union {
+		u32 fixed;
+		u32 mask;
+	} length;
+
+	/*
+	 * Describes where to find a register address in the command to check
+	 * against the ring's register whitelist. Only valid if flags has the
+	 * CMD_DESC_REGISTER bit set.
+	 */
+	struct {
+		u32 offset;
+		u32 mask;
+	} reg;
+
+#define MAX_CMD_DESC_BITMASKS 3
+	/*
+	 * Describes command checks where a particular dword is masked and
+	 * 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. Only entries where mask is non-zero
+	 * are valid.
+	 */
+	struct {
+		u32 offset;
+		u32 mask;
+		u32 expected;
+	} bits[MAX_CMD_DESC_BITMASKS];
+};
+
+/*
+ * A table of commands requiring special handling by the command parser.
+ *
+ * Each ring has an array of tables. Each table consists of an array of command
+ * descriptors, which must be sorted with command opcodes in ascending order.
+ */
+struct drm_i915_cmd_table {
+	const struct drm_i915_cmd_descriptor *table;
+	int count;
+};
+
 #define INTEL_INFO(dev)	(&to_i915(dev)->info)
 
 #define IS_I830(dev)		((dev)->pdev->device == 0x3577)
@@ -1965,6 +2049,7 @@ struct i915_params {
 	int enable_pc8;
 	int pc8_timeout;
 	int invert_brightness;
+	int enable_cmd_parser;
 	/* leave bools at the end to not create holes */
 	bool enable_hangcheck;
 	bool fastboot;
@@ -2490,6 +2575,14 @@ void i915_destroy_error_state(struct drm_device *dev);
 void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
 const char *i915_cache_level_str(int type);
 
+/* i915_cmd_parser.c */
+void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring);
+bool i915_needs_cmd_parser(struct intel_ring_buffer *ring);
+int i915_parse_cmds(struct intel_ring_buffer *ring,
+		    struct drm_i915_gem_object *batch_obj,
+		    u32 batch_start_offset,
+		    bool is_master);
+
 /* i915_suspend.c */
 extern int i915_save_state(struct drm_device *dev);
 extern int i915_restore_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d7229ad..3851a1b 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1182,6 +1182,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	}
 	batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
 
+	if (i915_needs_cmd_parser(ring)) {
+		ret = i915_parse_cmds(ring,
+				      batch_obj,
+				      args->batch_start_offset,
+				      file->is_master);
+		if (ret)
+			goto err;
+
+		/*
+		 * XXX: Actually do this when enabling batch copy...
+		 *
+		 * Set the DISPATCH_SECURE bit to remove the NON_SECURE bit
+		 * from MI_BATCH_BUFFER_START commands issued in the
+		 * dispatch_execbuffer implementations. We specifically don't
+		 * want that set when the command parser is enabled.
+		 */
+	}
+
 	/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
 	 * batch" bit. Hence we need to pin secure batches into the global gtt.
 	 * hsw should have this fixed, but bdw mucks it up again. */
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 3b48258..aba0b9b 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -48,6 +48,7 @@ struct i915_params i915 __read_mostly = {
 	.reset = true,
 	.invert_brightness = 0,
 	.disable_display = 0,
+	.enable_cmd_parser = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -157,3 +158,7 @@ MODULE_PARM_DESC(invert_brightness,
 
 module_param_named(disable_display, i915.disable_display, bool, 0600);
 MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
+
+module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
+MODULE_PARM_DESC(enable_cmd_parser,
+		"Enable command parsing (1=enabled, 0=disabled [default])");
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2f564ce..e14dfda 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -175,6 +175,18 @@
 #define VGA_CR_DATA_CGA 0x3d5
 
 /*
+ * Instruction field definitions used by the command parser
+ */
+#define INSTR_CLIENT_SHIFT      29
+#define INSTR_CLIENT_MASK       0xE0000000
+#define   INSTR_MI_CLIENT       0x0
+#define   INSTR_BC_CLIENT       0x2
+#define   INSTR_RC_CLIENT       0x3
+#define INSTR_SUBCLIENT_SHIFT   27
+#define INSTR_SUBCLIENT_MASK    0x18000000
+#define   INSTR_MEDIA_SUBCLIENT 0x2
+
+/*
  * Memory interface instructions used by the kernel
  */
 #define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index b340c75..7bff5ef 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1388,6 +1388,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 	if (IS_I830(ring->dev) || IS_845G(ring->dev))
 		ring->effective_size -= 128;
 
+	i915_cmd_parser_init_ring(ring);
+
 	return 0;
 
 err_unmap:
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 08b91c6..09af920 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -164,6 +164,38 @@ struct  intel_ring_buffer {
 		u32 gtt_offset;
 		volatile u32 *cpu_page;
 	} scratch;
+
+	/*
+	 * Tables of commands the command parser needs to know about
+	 * for this ring.
+	 */
+	const struct drm_i915_cmd_table *cmd_tables;
+	int cmd_table_count;
+
+	/*
+	 * Table of registers allowed in commands that read/write registers.
+	 */
+	const u32 *reg_table;
+	int reg_count;
+
+	/*
+	 * Table of registers allowed in commands that read/write registers, but
+	 * only from the DRM master.
+	 */
+	const u32 *master_reg_table;
+	int master_reg_count;
+
+	/*
+	 * Returns the bitmask for the length field of the specified command.
+	 * Return 0 for an unrecognized/invalid command.
+	 *
+	 * If the command parser finds an entry for a command in the ring's
+	 * cmd_tables, it gets the command's length based on the table entry.
+	 * If not, it calls this function to determine the per-ring length field
+	 * encoding for the command (i.e. certain opcode ranges use certain bits
+	 * to encode the command length in the header).
+	 */
+	u32 (*get_cmd_length_mask)(u32 cmd_header);
 };
 
 static inline bool
-- 
1.8.3.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 03/13] drm/i915: Initial command parser table definitions
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 01/13] drm/i915: Refactor shmem pread setup bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 02/13] drm/i915: Implement command buffer parsing logic bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-03-06 13:12   ` Jani Nikula
  2014-02-18 18:15 ` [PATCH 04/13] drm/i915: Reject privileged commands bradley.d.volkin
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

Add command tables defining irregular length commands for each ring.
This requires a few new command opcode definitions.

v2: Whitespace adjustment in command definitions, sparse fix for !F

OTC-Tracker: AXIA-4631
Change-Id: I064bceb457e15f46928058352afe76d918c58ef5
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 157 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h        |  46 ++++++++++
 2 files changed, 203 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 7a5756e..12241e8 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -86,6 +86,148 @@
  * general bitmasking mechanism.
  */
 
+#define STD_MI_OPCODE_MASK  0xFF800000
+#define STD_3D_OPCODE_MASK  0xFFFF0000
+#define STD_2D_OPCODE_MASK  0xFFC00000
+#define STD_MFX_OPCODE_MASK 0xFFFF0000
+
+#define CMD(op, opm, f, lm, fl, ...)				\
+	{							\
+		.flags = (fl) | ((f) ? CMD_DESC_FIXED : 0),	\
+		.cmd = { (op), (opm) }, 			\
+		.length = { (lm) },				\
+		__VA_ARGS__					\
+	}
+
+/* Convenience macros to compress the tables */
+#define SMI STD_MI_OPCODE_MASK
+#define S3D STD_3D_OPCODE_MASK
+#define S2D STD_2D_OPCODE_MASK
+#define SMFX STD_MFX_OPCODE_MASK
+#define F true
+#define S CMD_DESC_SKIP
+#define R CMD_DESC_REJECT
+#define W CMD_DESC_REGISTER
+#define B CMD_DESC_BITMASK
+#define M CMD_DESC_MASTER
+
+/*            Command                          Mask   Fixed Len   Action
+	      ---------------------------------------------------------- */
+static const struct drm_i915_cmd_descriptor common_cmds[] = {
+	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
+	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
+	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
+	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
+	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
+	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
+};
+
+static const struct drm_i915_cmd_descriptor render_cmds[] = {
+	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
+	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
+	CMD(  PIPELINE_SELECT,                  S3D,    F,  1,      S  ),
+	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
+	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
+};
+
+static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
+	CMD(  MI_SET_PREDICATE,                 SMI,    F,  1,      S  ),
+	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
+	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
+	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
+	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_VS,  S3D,   !F,  0x7FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_PS,  S3D,   !F,  0x7FF,  S  ),
+
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,  S3D,   !F,  0x1FF,  S  ),
+};
+
+static const struct drm_i915_cmd_descriptor video_cmds[] = {
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+	/*
+	 * MFX_WAIT doesn't fit the way we handle length for most commands.
+	 * It has a length field but it uses a non-standard length bias.
+	 * It is always 1 dword though, so just treat it as fixed length.
+	 */
+	CMD(  MFX_WAIT,                         SMFX,   F,  1,      S  ),
+};
+
+static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+};
+
+static const struct drm_i915_cmd_descriptor blt_cmds[] = {
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
+	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
+	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
+};
+
+#undef CMD
+#undef SMI
+#undef S3D
+#undef S2D
+#undef SMFX
+#undef F
+#undef S
+#undef R
+#undef W
+#undef B
+#undef M
+
+static const struct drm_i915_cmd_table gen7_render_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ render_cmds, ARRAY_SIZE(render_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_render_ring_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ render_cmds, ARRAY_SIZE(render_cmds) },
+	{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
+};
+
+static const struct drm_i915_cmd_table gen7_video_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ video_cmds, ARRAY_SIZE(video_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_vebox_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ vecs_cmds, ARRAY_SIZE(vecs_cmds) },
+};
+
+static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
+};
+
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
 {
 	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
@@ -200,15 +342,30 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 
 	switch (ring->id) {
 	case RCS:
+		if (IS_HASWELL(ring->dev)) {
+			ring->cmd_tables = hsw_render_ring_cmds;
+			ring->cmd_table_count =
+				ARRAY_SIZE(hsw_render_ring_cmds);
+		} else {
+			ring->cmd_tables = gen7_render_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
+		}
+
 		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 		break;
 	case VCS:
+		ring->cmd_tables = gen7_video_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
 	case BCS:
+		ring->cmd_tables = gen7_blt_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
 		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
+		ring->cmd_tables = hsw_vebox_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
 		/* VECS can use the same length_mask function as VCS */
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e14dfda..3f0b414 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -347,6 +347,52 @@
 #define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
 
+/*
+ * Commands used only by the command parser
+ */
+#define MI_SET_PREDICATE        MI_INSTR(0x01, 0)
+#define MI_ARB_CHECK            MI_INSTR(0x05, 0)
+#define MI_RS_CONTROL           MI_INSTR(0x06, 0)
+#define MI_URB_ATOMIC_ALLOC     MI_INSTR(0x09, 0)
+#define MI_PREDICATE            MI_INSTR(0x0C, 0)
+#define MI_RS_CONTEXT           MI_INSTR(0x0F, 0)
+#define MI_TOPOLOGY_FILTER      MI_INSTR(0x0D, 0)
+#define MI_URB_CLEAR            MI_INSTR(0x19, 0)
+#define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
+#define MI_CLFLUSH              MI_INSTR(0x27, 0)
+#define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
+#define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
+#define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 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))
+#define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
+#define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
+#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16))
+#define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16))
+#define GFX_OP_3DSTATE_SO_DECL_LIST \
+	((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16))
+
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))
+
+#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))
+
+#define COLOR_BLT     ((0x2<<29)|(0x40<<22))
+#define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
 
 /*
  * Reset registers
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 04/13] drm/i915: Reject privileged commands
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (2 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 03/13] drm/i915: Initial command parser table definitions bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 05/13] drm/i915: Allow some privileged commands from master bradley.d.volkin
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

The spec defines most of these commands as privileged. A few others,
like the semaphore mbox command and some display commands, are also
reserved for the driver's use. Subsequent patches relax some of
these restrictions.

v2: Rebased

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 54 ++++++++++++++++++++++++----------
 drivers/gpu/drm/i915/i915_reg.h        |  1 +
 2 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 12241e8..90bbb6d 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -116,27 +116,27 @@
 static const struct drm_i915_cmd_descriptor common_cmds[] = {
 	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
 	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
-	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      S  ),
+	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      R  ),
 	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
 	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
 	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
-	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   S  ),
-	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   S  ),
-	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   S  ),
-	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   S  ),
-	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
 };
 
 static const struct drm_i915_cmd_descriptor render_cmds[] = {
 	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
-	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
 	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
 	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
-	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
-	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
-	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
@@ -151,7 +151,9 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
 	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
 	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
 	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
-	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
 	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
 	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
@@ -166,8 +168,9 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
 };
 
 static const struct drm_i915_cmd_descriptor video_cmds[] = {
-	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 	/*
 	 * MFX_WAIT doesn't fit the way we handle length for most commands.
@@ -178,18 +181,25 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
 };
 
 static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
-	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 };
 
 static const struct drm_i915_cmd_descriptor blt_cmds[] = {
-	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
 	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
 	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
 };
 
+static const struct drm_i915_cmd_descriptor hsw_blt_cmds[] = {
+	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
+};
+
 #undef CMD
 #undef SMI
 #undef S3D
@@ -228,6 +238,12 @@ static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
 	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
 };
 
+static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
+	{ hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) },
+};
+
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
 {
 	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
@@ -359,8 +375,14 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
 	case BCS:
-		ring->cmd_tables = gen7_blt_cmds;
-		ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
+		if (IS_HASWELL(ring->dev)) {
+			ring->cmd_tables = hsw_blt_ring_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds);
+		} else {
+			ring->cmd_tables = gen7_blt_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
+		}
+
 		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 3f0b414..23be06a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -357,6 +357,7 @@
 #define MI_PREDICATE            MI_INSTR(0x0C, 0)
 #define MI_RS_CONTEXT           MI_INSTR(0x0F, 0)
 #define MI_TOPOLOGY_FILTER      MI_INSTR(0x0D, 0)
+#define MI_LOAD_SCAN_LINES_EXCL MI_INSTR(0x13, 0)
 #define MI_URB_CLEAR            MI_INSTR(0x19, 0)
 #define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
 #define MI_CLFLUSH              MI_INSTR(0x27, 0)
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 05/13] drm/i915: Allow some privileged commands from master
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (3 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 04/13] drm/i915: Reject privileged commands bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 06/13] drm/i915: Add register whitelists for mesa bradley.d.volkin
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

The Intel DDX uses these to implement scanline waits in the X server.

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 90bbb6d..cf03ba6 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -116,7 +116,7 @@
 static const struct drm_i915_cmd_descriptor common_cmds[] = {
 	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
 	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
-	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      R  ),
+	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      M  ),
 	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
 	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
 	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
@@ -151,7 +151,7 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
 	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
 	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
 	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
-	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   M  ),
 	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
 	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
@@ -196,7 +196,7 @@ static const struct drm_i915_cmd_descriptor blt_cmds[] = {
 };
 
 static const struct drm_i915_cmd_descriptor hsw_blt_cmds[] = {
-	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   M  ),
 	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
 };
 
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 06/13] drm/i915: Add register whitelists for mesa
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (4 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 05/13] drm/i915: Allow some privileged commands from master bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 07/13] drm/i915: Add register whitelist for DRM master bradley.d.volkin
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

These registers are currently used by mesa for blitting,
transform feedback extensions, and performance monitoring
extensions.

v2: REG64 macro

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 45 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h        | 20 +++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index cf03ba6..4347a30 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -244,6 +244,45 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
 	{ hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) },
 };
 
+/*
+ * Register whitelists, sorted by increasing register offset.
+ *
+ * Some registers that userspace accesses are 64 bits. The register
+ * access commands only allow 32-bit accesses. Hence, we have to include
+ * entries for both halves of the 64-bit registers.
+ */
+
+/* Convenience macro for adding 64-bit registers */
+#define REG64(addr) (addr), (addr + sizeof(u32))
+
+static const u32 gen7_render_regs[] = {
+	REG64(HS_INVOCATION_COUNT),
+	REG64(DS_INVOCATION_COUNT),
+	REG64(IA_VERTICES_COUNT),
+	REG64(IA_PRIMITIVES_COUNT),
+	REG64(VS_INVOCATION_COUNT),
+	REG64(GS_INVOCATION_COUNT),
+	REG64(GS_PRIMITIVES_COUNT),
+	REG64(CL_INVOCATION_COUNT),
+	REG64(CL_PRIMITIVES_COUNT),
+	REG64(PS_INVOCATION_COUNT),
+	REG64(PS_DEPTH_COUNT),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)),
+	REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)),
+	GEN7_SO_WRITE_OFFSET(0),
+	GEN7_SO_WRITE_OFFSET(1),
+	GEN7_SO_WRITE_OFFSET(2),
+	GEN7_SO_WRITE_OFFSET(3),
+};
+
+static const u32 gen7_blt_regs[] = {
+	BCS_SWCTRL,
+};
+
+#undef REG64
+
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
 {
 	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
@@ -367,6 +406,9 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 			ring->cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
 		}
 
+		ring->reg_table = gen7_render_regs;
+		ring->reg_count = ARRAY_SIZE(gen7_render_regs);
+
 		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 		break;
 	case VCS:
@@ -383,6 +425,9 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 			ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
 		}
 
+		ring->reg_table = gen7_blt_regs;
+		ring->reg_count = ARRAY_SIZE(gen7_blt_regs);
+
 		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 23be06a..1f2aeba 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -396,6 +396,26 @@
 #define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
 
 /*
+ * Registers used only by the command parser
+ */
+#define BCS_SWCTRL 0x22200
+
+#define HS_INVOCATION_COUNT 0x2300
+#define DS_INVOCATION_COUNT 0x2308
+#define IA_VERTICES_COUNT   0x2310
+#define IA_PRIMITIVES_COUNT 0x2318
+#define VS_INVOCATION_COUNT 0x2320
+#define GS_INVOCATION_COUNT 0x2328
+#define GS_PRIMITIVES_COUNT 0x2330
+#define CL_INVOCATION_COUNT 0x2338
+#define CL_PRIMITIVES_COUNT 0x2340
+#define PS_INVOCATION_COUNT 0x2348
+#define PS_DEPTH_COUNT      0x2350
+
+/* There are the 4 64-bit counter registers, one for each stream output */
+#define GEN7_SO_NUM_PRIMS_WRITTEN(n) (0x5200 + (n) * 8)
+
+/*
  * Reset registers
  */
 #define DEBUG_RESET_I830		0x6070
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 07/13] drm/i915: Add register whitelist for DRM master
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (5 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 06/13] drm/i915: Add register whitelists for mesa bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 08/13] drm/i915: Enable register whitelist checks bradley.d.volkin
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

These are used to implement scanline waits in the X server.

v2: Use #defines instead of magic numbers

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 29 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h        |  6 ++++++
 2 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 4347a30..353e5cf 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -281,6 +281,19 @@ static const u32 gen7_blt_regs[] = {
 	BCS_SWCTRL,
 };
 
+static const u32 ivb_master_regs[] = {
+	FORCEWAKE_MT,
+	DERRMR,
+	GEN7_PIPE_DE_LOAD_SL(PIPE_A),
+	GEN7_PIPE_DE_LOAD_SL(PIPE_B),
+	GEN7_PIPE_DE_LOAD_SL(PIPE_C),
+};
+
+static const u32 hsw_master_regs[] = {
+	FORCEWAKE_MT,
+	DERRMR,
+};
+
 #undef REG64
 
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
@@ -409,6 +422,14 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 		ring->reg_table = gen7_render_regs;
 		ring->reg_count = ARRAY_SIZE(gen7_render_regs);
 
+		if (IS_HASWELL(ring->dev)) {
+			ring->master_reg_table = hsw_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+		} else {
+			ring->master_reg_table = ivb_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+		}
+
 		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 		break;
 	case VCS:
@@ -428,6 +449,14 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 		ring->reg_table = gen7_blt_regs;
 		ring->reg_count = ARRAY_SIZE(gen7_blt_regs);
 
+		if (IS_HASWELL(ring->dev)) {
+			ring->master_reg_table = hsw_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+		} else {
+			ring->master_reg_table = ivb_master_regs;
+			ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+		}
+
 		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1f2aeba..87523df 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -415,6 +415,12 @@
 /* There are the 4 64-bit counter registers, one for each stream output */
 #define GEN7_SO_NUM_PRIMS_WRITTEN(n) (0x5200 + (n) * 8)
 
+#define _GEN7_PIPEA_DE_LOAD_SL	0x70068
+#define _GEN7_PIPEB_DE_LOAD_SL	0x71068
+#define GEN7_PIPE_DE_LOAD_SL(pipe) _PIPE(pipe, \
+					 _GEN7_PIPEA_DE_LOAD_SL, \
+					 _GEN7_PIPEB_DE_LOAD_SL)
+
 /*
  * Reset registers
  */
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 08/13] drm/i915: Enable register whitelist checks
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (6 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 07/13] drm/i915: Add register whitelist for DRM master bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 09/13] drm/i915: Reject commands that explicitly generate interrupts bradley.d.volkin
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

MI_STORE_REGISTER_MEM, MI_LOAD_REGISTER_MEM, and MI_LOAD_REGISTER_IMM
commands allow userspace access to registers. Only certain registers
should be allowed for such access, so enable checking for those commands.
Each ring gets its own register whitelist.

MI_LOAD_REGISTER_REG on HSW also allows register access but is currently
unused by userspace components. Leave it rejected.

PIPE_CONTROL and MEDIA_VFE_STATE allow register access based on certain
bits being set. Reject those as well.

v2: trailing commas, rebased

OTC-Tracker: AXIA-4631
Change-Id: Ie614a2f0eb2e5917de809e5a17957175d24cc44f
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 21 ++++++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h        |  3 +++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 353e5cf..4f14a24 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -122,9 +122,12 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
 	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
 	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   R  ),
-	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   R  ),
-	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   R  ),
-	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   R  ),
+	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   W,
+	      .reg = { .offset = 1, .mask = 0x007FFFFC }               ),
+	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_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
 };
 
@@ -141,9 +144,21 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 	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,
+	      .bits = {{
+			.offset = 2,
+			.mask = MEDIA_VFE_STATE_MMIO_ACCESS_MASK,
+			.expected = 0,
+	      }},						       ),
 	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
 	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
 	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_PIPE_CONTROL(5),           S3D,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 1,
+			.mask = PIPE_CONTROL_MMIO_WRITE,
+			.expected = 0,
+	      }},						       ),
 };
 
 static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 87523df..11cca96 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -330,6 +330,7 @@
 #define   DISPLAY_PLANE_B           (1<<20)
 #define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
 #define   PIPE_CONTROL_GLOBAL_GTT_IVB			(1<<24) /* gen7+ */
+#define   PIPE_CONTROL_MMIO_WRITE			(1<<23)
 #define   PIPE_CONTROL_CS_STALL				(1<<20)
 #define   PIPE_CONTROL_TLB_INVALIDATE			(1<<18)
 #define   PIPE_CONTROL_QW_WRITE				(1<<14)
@@ -370,6 +371,8 @@
 
 #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))
+#define MEDIA_VFE_STATE                ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16))
+#define  MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18)
 #define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
 #define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
 #define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 09/13] drm/i915: Reject commands that explicitly generate interrupts
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (7 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 08/13] drm/i915: Enable register whitelist checks bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 10/13] drm/i915: Enable PPGTT command parser checks bradley.d.volkin
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

The driver leaves most interrupts masked during normal operation,
so there would have to be additional work to enable userspace to
safely request/receive an interrupt.

v2: trailing commas, rebased

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 22 ++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_reg.h        |  1 +
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 4f14a24..0351df1 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -115,7 +115,7 @@
 	      ---------------------------------------------------------- */
 static const struct drm_i915_cmd_descriptor common_cmds[] = {
 	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
-	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
+	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      R  ),
 	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      M  ),
 	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
 	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
@@ -156,7 +156,7 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
 	CMD(  GFX_OP_PIPE_CONTROL(5),           S3D,   !F,  0xFF,   B,
 	      .bits = {{
 			.offset = 1,
-			.mask = PIPE_CONTROL_MMIO_WRITE,
+			.mask = (PIPE_CONTROL_MMIO_WRITE | PIPE_CONTROL_NOTIFY),
 			.expected = 0,
 	      }},						       ),
 };
@@ -186,6 +186,12 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_FLUSH_DW_NOTIFY,
+			.expected = 0,
+	      }},						       ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 	/*
 	 * MFX_WAIT doesn't fit the way we handle length for most commands.
@@ -199,6 +205,12 @@ static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_FLUSH_DW_NOTIFY,
+			.expected = 0,
+	      }},						       ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 };
 
@@ -206,6 +218,12 @@ static const struct drm_i915_cmd_descriptor blt_cmds[] = {
 	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
+	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_FLUSH_DW_NOTIFY,
+			.expected = 0,
+	      }},						       ),
 	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
 	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
 };
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 11cca96..e6dd7e9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -269,6 +269,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_NOTIFY		(1<<8)
 #define   MI_INVALIDATE_BSD		(1<<7)
 #define   MI_FLUSH_DW_USE_GTT		(1<<2)
 #define   MI_FLUSH_DW_USE_PPGTT		(0<<2)
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 10/13] drm/i915: Enable PPGTT command parser checks
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (8 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 09/13] drm/i915: Reject commands that explicitly generate interrupts bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-03-06 13:17   ` Jani Nikula
  2014-02-18 18:15 ` [PATCH 11/13] drm/i915: Reject commands that would store to global HWS page bradley.d.volkin
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

Various commands that access memory have a bit to determine whether
the graphics address specified in the command should use the GGTT or
PPGTT for translation. These checks ensure that the bit indicates
PPGTT translation.

Most of these checks use the existing bit-checking infrastructure.
The PIPE_CONTROL and MI_FLUSH_DW commands, however, are multi-function
commands. The GGTT/PPGTT bit is only relevant for certain uses of the
command. As such, this change also extends the bit-checking code to
include a "condition" mask and offset. If the condition mask is non-zero
then the parser only performs the bit check when the bits specified by
the condition mask/offset are also non-zero.

NOTE: At this point in the series PPGTT must be enabled for the parser
to work correctly. If it's not enabled, userspace will not be setting
the PPGTT bits the way the parser requires. VLV is the only platform
where this is a problem, so at this point, we disable parsing for VLV.

v2: whitespace and trailing commas fixes, rebased

OTC-Tracker: AXIA-4631
Change-Id: I3f4c76b6734f1956ec47e698230f97d0998ff92b
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 128 ++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h        |   6 ++
 drivers/gpu/drm/i915/i915_reg.h        |   6 ++
 3 files changed, 129 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 0351df1..1528549 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -124,10 +124,20 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
 	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_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,
+	      }},						       ),
+	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   W | B,
+	      .reg = { .offset = 1, .mask = 0x007FFFFC },
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
 	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
 };
 
@@ -139,9 +149,31 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
 	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
 	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
-	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
-	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
+	      .bits = {{
+			.offset = 1,
+			.mask = MI_REPORT_PERF_COUNT_GGTT,
+			.expected = 0,
+	      }},						       ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
 	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,
@@ -158,6 +190,13 @@ 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,
 	      }},						       ),
 };
 
@@ -184,15 +223,32 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
 
 static const struct drm_i915_cmd_descriptor video_cmds[] = {
 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
-	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
 	      .bits = {{
 			.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,
+	      }},						       ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
 	      }},						       ),
-	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 	/*
 	 * MFX_WAIT doesn't fit the way we handle length for most commands.
 	 * It has a length field but it uses a non-standard length bias.
@@ -203,26 +259,55 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
 
 static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
-	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
+	      }},						       ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
 	      .bits = {{
 			.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,
+	      }},						       ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
+	      .bits = {{
+			.offset = 0,
+			.mask = MI_GLOBAL_GTT,
+			.expected = 0,
 	      }},						       ),
-	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
 };
 
 static const struct drm_i915_cmd_descriptor blt_cmds[] = {
 	CMD(  MI_DISPLAY_FLIP,                  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,
+	      }},						       ),
 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
 	      .bits = {{
 			.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,
 	      }},						       ),
 	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
 	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
@@ -617,10 +702,21 @@ finish:
  */
 bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
 {
+	drm_i915_private_t *dev_priv =
+		(drm_i915_private_t *)ring->dev->dev_private;
+
 	/* No command tables indicates a platform without parsing */
 	if (!ring->cmd_tables)
 		return false;
 
+	/*
+	 * XXX: VLV is Gen7 and therefore has cmd_tables, but has PPGTT
+	 * disabled. That will cause all of the parser's PPGTT checks to
+	 * fail. For now, disable parsing when PPGTT is off.
+	 */
+	if (!dev_priv->mm.aliasing_ppgtt)
+		return false;
+
 	return (i915.enable_cmd_parser == 1);
 }
 
@@ -737,6 +833,16 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
 				if (desc->bits[i].mask == 0)
 					break;
 
+				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;
+				}
+
 				dword = cmd[desc->bits[i].offset] &
 					desc->bits[i].mask;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 376472f..27a48d9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1868,11 +1868,17 @@ struct drm_i915_cmd_descriptor {
 	 * the expected value, the parser rejects it. Only valid if flags has
 	 * the CMD_DESC_BITMASK bit set. Only entries where mask is non-zero
 	 * are valid.
+	 *
+	 * 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];
 };
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e6dd7e9..e683b31 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -190,6 +190,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)
@@ -269,6 +271,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)
@@ -335,6 +338,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+ */
@@ -363,6 +367,8 @@
 #define MI_URB_CLEAR            MI_INSTR(0x19, 0)
 #define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
 #define MI_CLFLUSH              MI_INSTR(0x27, 0)
+#define MI_REPORT_PERF_COUNT    MI_INSTR(0x28, 0)
+#define   MI_REPORT_PERF_COUNT_GGTT (1<<0)
 #define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
 #define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
 #define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 0)
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 11/13] drm/i915: Reject commands that would store to global HWS page
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (9 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 10/13] drm/i915: Enable PPGTT command parser checks bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 12/13] drm/i915: Add a CMD_PARSER_VERSION getparam bradley.d.volkin
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

PIPE_CONTROL and MI_FLUSH_DW have bits that would write to the
hardware status page. The driver stores request tracking info
there, so don't let userspace overwrite it.

v2: trailing comma fix, rebased

Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 24 +++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_reg.h        |  1 +
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 1528549..f9aa01a 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -193,7 +193,8 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
 	      },
 	      {
 			.offset = 1,
-		        .mask = PIPE_CONTROL_GLOBAL_GTT_IVB,
+		        .mask = (PIPE_CONTROL_GLOBAL_GTT_IVB |
+				 PIPE_CONTROL_STORE_DATA_INDEX),
 			.expected = 0,
 			.condition_offset = 1,
 			.condition_mask = PIPE_CONTROL_POST_SYNC_OP_MASK,
@@ -242,6 +243,13 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
 			.expected = 0,
 			.condition_offset = 0,
 			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      },
+	      {
+			.offset = 0,
+			.mask = MI_FLUSH_DW_STORE_INDEX,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
 	      }},						       ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
 	      .bits = {{
@@ -278,6 +286,13 @@ static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
 			.expected = 0,
 			.condition_offset = 0,
 			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      },
+	      {
+			.offset = 0,
+			.mask = MI_FLUSH_DW_STORE_INDEX,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
 	      }},						       ),
 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
 	      .bits = {{
@@ -308,6 +323,13 @@ static const struct drm_i915_cmd_descriptor blt_cmds[] = {
 			.expected = 0,
 			.condition_offset = 0,
 			.condition_mask = MI_FLUSH_DW_OP_MASK,
+	      },
+	      {
+			.offset = 0,
+			.mask = MI_FLUSH_DW_STORE_INDEX,
+			.expected = 0,
+			.condition_offset = 0,
+			.condition_mask = MI_FLUSH_DW_OP_MASK,
 	      }},						       ),
 	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
 	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e683b31..46db649 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -335,6 +335,7 @@
 #define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
 #define   PIPE_CONTROL_GLOBAL_GTT_IVB			(1<<24) /* gen7+ */
 #define   PIPE_CONTROL_MMIO_WRITE			(1<<23)
+#define   PIPE_CONTROL_STORE_DATA_INDEX			(1<<21)
 #define   PIPE_CONTROL_CS_STALL				(1<<20)
 #define   PIPE_CONTROL_TLB_INVALIDATE			(1<<18)
 #define   PIPE_CONTROL_QW_WRITE				(1<<14)
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 12/13] drm/i915: Add a CMD_PARSER_VERSION getparam
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (10 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 11/13] drm/i915: Reject commands that would store to global HWS page bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-02-18 18:15 ` [PATCH 13/13] drm/i915: Enable command parsing by default bradley.d.volkin
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

So userspace can query the kernel for command parser support.

v2: Add i915_cmd_parser_get_version(), history log, and kerneldoc

OTC-Tracker: AXIA-4631
Change-Id: I58af650db9f6753c2dcac9c54ab432fd31db302f
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 19 +++++++++++++++++++
 drivers/gpu/drm/i915/i915_dma.c        |  3 +++
 drivers/gpu/drm/i915/i915_drv.h        |  1 +
 include/uapi/drm/i915_drm.h            |  1 +
 4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index f9aa01a..23c8174 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -897,3 +897,22 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
 
 	return ret;
 }
+
+/**
+ * i915_cmd_parser_get_version() - get the cmd parser version number
+ *
+ * The cmd parser maintains a simple increasing integer version number suitable
+ * for passing to userspace clients to determine what operations are permitted.
+ *
+ * Return: the current version number of the cmd parser
+ */
+int i915_cmd_parser_get_version(void)
+{
+	/*
+	 * Command parser version history
+	 *
+	 * 1. Initial version. Checks batches and reports violations, but leaves
+	 *    hardware parsing enabled (so does not allow new use cases).
+	 */
+	return 1;
+}
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 7688abc..14875f5 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1017,6 +1017,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_HANDLE_LUT:
 		value = 1;
 		break;
+	case I915_PARAM_CMD_PARSER_VERSION:
+		value = i915_cmd_parser_get_version();
+		break;
 	default:
 		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 27a48d9..6294d61 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2582,6 +2582,7 @@ void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
 const char *i915_cache_level_str(int type);
 
 /* i915_cmd_parser.c */
+int i915_cmd_parser_get_version(void);
 void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring);
 bool i915_needs_cmd_parser(struct intel_ring_buffer *ring);
 int i915_parse_cmds(struct intel_ring_buffer *ring,
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 126bfaa..8a3e4ef00 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -337,6 +337,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_EXEC_NO_RELOC	 25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
 #define I915_PARAM_HAS_WT     	 	 27
+#define I915_PARAM_CMD_PARSER_VERSION	 28
 
 typedef struct drm_i915_getparam {
 	int param;
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 13/13] drm/i915: Enable command parsing by default
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (11 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 12/13] drm/i915: Add a CMD_PARSER_VERSION getparam bradley.d.volkin
@ 2014-02-18 18:15 ` bradley.d.volkin
  2014-03-04 17:21 ` [PATCH 00/13] Gen7 batch buffer command parser Volkin, Bradley D
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: bradley.d.volkin @ 2014-02-18 18:15 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

v2: rebased

OTC-Tracker: AXIA-4631
Change-Id: I6747457e1fe7494bd42787af51198fcba398ad78
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_params.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index aba0b9b..9e394bc 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -48,7 +48,7 @@ struct i915_params i915 __read_mostly = {
 	.reset = true,
 	.invert_brightness = 0,
 	.disable_display = 0,
-	.enable_cmd_parser = 0,
+	.enable_cmd_parser = 1,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -161,4 +161,4 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
 
 module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
 MODULE_PARM_DESC(enable_cmd_parser,
-		"Enable command parsing (1=enabled, 0=disabled [default])");
+		"Enable command parsing (1=enabled [default], 0=disabled)");
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (12 preceding siblings ...)
  2014-02-18 18:15 ` [PATCH 13/13] drm/i915: Enable command parsing by default bradley.d.volkin
@ 2014-03-04 17:21 ` Volkin, Bradley D
  2014-03-05 10:46 ` Daniel Vetter
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-04 17:21 UTC (permalink / raw)
  To: jani.nikula, daniel; +Cc: intel-gfx

Daniel, Jani,

I think I managed to send this while you were both out and I'm sure it got
buried. Can you take a look? I think this rev addresses all of the current
comments.

Thanks,
Brad

On Tue, Feb 18, 2014 at 10:15:44AM -0800, Volkin, Bradley D wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
> 
> Certain OpenGL features (e.g. transform feedback, performance monitoring)
> require userspace code to submit batches containing commands such as
> MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> generations of the hardware will noop these commands in "unsecure" batches
> (which includes all userspace batches submitted via i915) even though the
> commands may be safe and represent the intended programming model of the device.
> 
> This series introduces a software command parser similar in operation to the
> command parsing done in hardware for unsecure batches. However, the software
> parser allows some operations that would be noop'd by hardware, if the parser
> determines the operation is safe, and submits the batch as "secure" to prevent
> hardware parsing. Currently the series implements this on IVB and HSW.
> 
> The series has one piece of prep work, one patch for the parser logic, and a
> handful of patches to fill out the tables which drive the parser. There are
> follow-up patches to libdrm and to i-g-t. The i-g-t tests are basic and do not
> test all of the commands used by the parser on the assumption that I'm likely
> to make the same mistakes in both the parser and the test.
> 
> I've previously run the i-g-t gem_* tests, the piglit quick tests, and generally
> used Ubuntu 13.10 IVB and HSW systems with the parser running. Aside from a
> failure described below, I did not see any regressions.
> 
> At this point there are a couple of required/potential improvements.
> 
> 1) Chained batches. The parser currently allows MI_BATCH_BUFFER_START commands
>    in userspace batches without parsing them. The media driver uses chained
>    batches, so a solution is required. I'm still working through the
>    requirements but don't want to continue delaying the review process for what
>    I have so far.
> 2) Command buffer copy. To avoid CPU modifications to buffers after parsing, and
>    to avoid GPU modifications to buffers via EUs or commands in the batch, we
>    should copy the userspace batch buffer to memory that userspace does not
>    have access to, map it into GGTT, and execute that batch buffer. I have a
>    sense of how to do this for 1st-level batches, but it may need changes to
>    tie in with the chained batch parsing, so I've again held off.
> 3) Coherency. I've previously found a coherency issue on VLV when reading the
>    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
>    pwrite fast path before calling execbuffer2. The parser reads stale data.
>    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
>    It's possible that the shmem pread refactoring fixes this, I just have not
>    been able to retest due to lack of a VLV system.
> 
> v2:
> - Significantly reorder series
> - Scan secure batches (i.e. I915_EXEC_SECURE)
> - Check that parser tables are sorted during init
> - Fixed gem_cpu_reloc regression
> - HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
> - Additional tests
> 
> v3:
> - Don't actually send batches as secure yet
> - Improved documentation and commenting
> - Many other small cleanups throughout
> 
> Brad Volkin (13):
>   drm/i915: Refactor shmem pread setup
>   drm/i915: Implement command buffer parsing logic
>   drm/i915: Initial command parser table definitions
>   drm/i915: Reject privileged commands
>   drm/i915: Allow some privileged commands from master
>   drm/i915: Add register whitelists for mesa
>   drm/i915: Add register whitelist for DRM master
>   drm/i915: Enable register whitelist checks
>   drm/i915: Reject commands that explicitly generate interrupts
>   drm/i915: Enable PPGTT command parser checks
>   drm/i915: Reject commands that would store to global HWS page
>   drm/i915: Add a CMD_PARSER_VERSION getparam
>   drm/i915: Enable command parsing by default
> 
>  drivers/gpu/drm/i915/Makefile              |   1 +
>  drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_dma.c            |   3 +
>  drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
>  drivers/gpu/drm/i915/i915_gem.c            |  51 +-
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
>  drivers/gpu/drm/i915/i915_params.c         |   5 +
>  drivers/gpu/drm/i915/i915_reg.h            |  96 +++
>  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
>  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
>  include/uapi/drm/i915_drm.h                |   1 +
>  11 files changed, 1216 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
> 
> -- 
> 1.8.3.2
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (13 preceding siblings ...)
  2014-03-04 17:21 ` [PATCH 00/13] Gen7 batch buffer command parser Volkin, Bradley D
@ 2014-03-05 10:46 ` Daniel Vetter
  2014-03-05 16:59   ` Volkin, Bradley D
  2014-03-11 12:41 ` Jani Nikula
  2014-03-20 14:43 ` Jani Nikula
  16 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:46 UTC (permalink / raw)
  To: bradley.d.volkin; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 10:15:44AM -0800, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
> 
> Certain OpenGL features (e.g. transform feedback, performance monitoring)
> require userspace code to submit batches containing commands such as
> MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> generations of the hardware will noop these commands in "unsecure" batches
> (which includes all userspace batches submitted via i915) even though the
> commands may be safe and represent the intended programming model of the device.
> 
> This series introduces a software command parser similar in operation to the
> command parsing done in hardware for unsecure batches. However, the software
> parser allows some operations that would be noop'd by hardware, if the parser
> determines the operation is safe, and submits the batch as "secure" to prevent
> hardware parsing. Currently the series implements this on IVB and HSW.
> 
> The series has one piece of prep work, one patch for the parser logic, and a
> handful of patches to fill out the tables which drive the parser. There are
> follow-up patches to libdrm and to i-g-t. The i-g-t tests are basic and do not
> test all of the commands used by the parser on the assumption that I'm likely
> to make the same mistakes in both the parser and the test.
> 
> I've previously run the i-g-t gem_* tests, the piglit quick tests, and generally
> used Ubuntu 13.10 IVB and HSW systems with the parser running. Aside from a
> failure described below, I did not see any regressions.
> 
> At this point there are a couple of required/potential improvements.
> 
> 1) Chained batches. The parser currently allows MI_BATCH_BUFFER_START commands
>    in userspace batches without parsing them. The media driver uses chained
>    batches, so a solution is required. I'm still working through the
>    requirements but don't want to continue delaying the review process for what
>    I have so far.
> 2) Command buffer copy. To avoid CPU modifications to buffers after parsing, and
>    to avoid GPU modifications to buffers via EUs or commands in the batch, we
>    should copy the userspace batch buffer to memory that userspace does not
>    have access to, map it into GGTT, and execute that batch buffer. I have a
>    sense of how to do this for 1st-level batches, but it may need changes to
>    tie in with the chained batch parsing, so I've again held off.
> 3) Coherency. I've previously found a coherency issue on VLV when reading the
>    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
>    pwrite fast path before calling execbuffer2. The parser reads stale data.
>    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
>    It's possible that the shmem pread refactoring fixes this, I just have not
>    been able to retest due to lack of a VLV system.

Is it still true that we need to test this on vlv? The shmem_pread path
really should have fixed this ... Otherwise I think this looks ready to go
in, I'll pester Jani for the review.

Thanks, Daniel

> 
> v2:
> - Significantly reorder series
> - Scan secure batches (i.e. I915_EXEC_SECURE)
> - Check that parser tables are sorted during init
> - Fixed gem_cpu_reloc regression
> - HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
> - Additional tests
> 
> v3:
> - Don't actually send batches as secure yet
> - Improved documentation and commenting
> - Many other small cleanups throughout
> 
> Brad Volkin (13):
>   drm/i915: Refactor shmem pread setup
>   drm/i915: Implement command buffer parsing logic
>   drm/i915: Initial command parser table definitions
>   drm/i915: Reject privileged commands
>   drm/i915: Allow some privileged commands from master
>   drm/i915: Add register whitelists for mesa
>   drm/i915: Add register whitelist for DRM master
>   drm/i915: Enable register whitelist checks
>   drm/i915: Reject commands that explicitly generate interrupts
>   drm/i915: Enable PPGTT command parser checks
>   drm/i915: Reject commands that would store to global HWS page
>   drm/i915: Add a CMD_PARSER_VERSION getparam
>   drm/i915: Enable command parsing by default
> 
>  drivers/gpu/drm/i915/Makefile              |   1 +
>  drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_dma.c            |   3 +
>  drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
>  drivers/gpu/drm/i915/i915_gem.c            |  51 +-
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
>  drivers/gpu/drm/i915/i915_params.c         |   5 +
>  drivers/gpu/drm/i915/i915_reg.h            |  96 +++
>  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
>  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
>  include/uapi/drm/i915_drm.h                |   1 +
>  11 files changed, 1216 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
> 
> -- 
> 1.8.3.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-05 10:46 ` Daniel Vetter
@ 2014-03-05 16:59   ` Volkin, Bradley D
  2014-03-05 17:14     ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-05 16:59 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Mar 05, 2014 at 02:46:35AM -0800, Daniel Vetter wrote:
> On Tue, Feb 18, 2014 at 10:15:44AM -0800, bradley.d.volkin@intel.com wrote:
> > From: Brad Volkin <bradley.d.volkin@intel.com>
> > 3) Coherency. I've previously found a coherency issue on VLV when reading the
> >    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
> >    pwrite fast path before calling execbuffer2. The parser reads stale data.
> >    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
> >    It's possible that the shmem pread refactoring fixes this, I just have not
> >    been able to retest due to lack of a VLV system.
> 
> Is it still true that we need to test this on vlv? The shmem_pread path
> really should have fixed this ... Otherwise I think this looks ready to go
> in, I'll pester Jani for the review.

Yes, I still don't have a system to test on.

Brad

> 
> Thanks, Daniel
> 
> > 
> > v2:
> > - Significantly reorder series
> > - Scan secure batches (i.e. I915_EXEC_SECURE)
> > - Check that parser tables are sorted during init
> > - Fixed gem_cpu_reloc regression
> > - HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
> > - Additional tests
> > 
> > v3:
> > - Don't actually send batches as secure yet
> > - Improved documentation and commenting
> > - Many other small cleanups throughout
> > 
> > Brad Volkin (13):
> >   drm/i915: Refactor shmem pread setup
> >   drm/i915: Implement command buffer parsing logic
> >   drm/i915: Initial command parser table definitions
> >   drm/i915: Reject privileged commands
> >   drm/i915: Allow some privileged commands from master
> >   drm/i915: Add register whitelists for mesa
> >   drm/i915: Add register whitelist for DRM master
> >   drm/i915: Enable register whitelist checks
> >   drm/i915: Reject commands that explicitly generate interrupts
> >   drm/i915: Enable PPGTT command parser checks
> >   drm/i915: Reject commands that would store to global HWS page
> >   drm/i915: Add a CMD_PARSER_VERSION getparam
> >   drm/i915: Enable command parsing by default
> > 
> >  drivers/gpu/drm/i915/Makefile              |   1 +
> >  drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/i915_dma.c            |   3 +
> >  drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
> >  drivers/gpu/drm/i915/i915_gem.c            |  51 +-
> >  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
> >  drivers/gpu/drm/i915/i915_params.c         |   5 +
> >  drivers/gpu/drm/i915/i915_reg.h            |  96 +++
> >  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
> >  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
> >  include/uapi/drm/i915_drm.h                |   1 +
> >  11 files changed, 1216 insertions(+), 14 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
> > 
> > -- 
> > 1.8.3.2
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-05 16:59   ` Volkin, Bradley D
@ 2014-03-05 17:14     ` Daniel Vetter
  2014-03-05 17:45       ` Volkin, Bradley D
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2014-03-05 17:14 UTC (permalink / raw)
  To: Volkin, Bradley D; +Cc: intel-gfx

On Wed, Mar 05, 2014 at 08:59:56AM -0800, Volkin, Bradley D wrote:
> On Wed, Mar 05, 2014 at 02:46:35AM -0800, Daniel Vetter wrote:
> > On Tue, Feb 18, 2014 at 10:15:44AM -0800, bradley.d.volkin@intel.com wrote:
> > > From: Brad Volkin <bradley.d.volkin@intel.com>
> > > 3) Coherency. I've previously found a coherency issue on VLV when reading the
> > >    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
> > >    pwrite fast path before calling execbuffer2. The parser reads stale data.
> > >    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
> > >    It's possible that the shmem pread refactoring fixes this, I just have not
> > >    been able to retest due to lack of a VLV system.
> > 
> > Is it still true that we need to test this on vlv? The shmem_pread path
> > really should have fixed this ... Otherwise I think this looks ready to go
> > in, I'll pester Jani for the review.
> 
> Yes, I still don't have a system to test on.

Steal one? I guess we'll notice when our QA runs all this stuff on theirs
;-)

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-05 17:14     ` Daniel Vetter
@ 2014-03-05 17:45       ` Volkin, Bradley D
  0 siblings, 0 replies; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-05 17:45 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Mar 05, 2014 at 09:14:38AM -0800, Daniel Vetter wrote:
> On Wed, Mar 05, 2014 at 08:59:56AM -0800, Volkin, Bradley D wrote:
> > On Wed, Mar 05, 2014 at 02:46:35AM -0800, Daniel Vetter wrote:
> > > On Tue, Feb 18, 2014 at 10:15:44AM -0800, bradley.d.volkin@intel.com wrote:
> > > > From: Brad Volkin <bradley.d.volkin@intel.com>
> > > > 3) Coherency. I've previously found a coherency issue on VLV when reading the
> > > >    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
> > > >    pwrite fast path before calling execbuffer2. The parser reads stale data.
> > > >    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
> > > >    It's possible that the shmem pread refactoring fixes this, I just have not
> > > >    been able to retest due to lack of a VLV system.
> > > 
> > > Is it still true that we need to test this on vlv? The shmem_pread path
> > > really should have fixed this ... Otherwise I think this looks ready to go
> > > in, I'll pester Jani for the review.
> > 
> > Yes, I still don't have a system to test on.
> 
> Steal one? I guess we'll notice when our QA runs all this stuff on theirs
> ;-)

It's not stealing if I give it back :)

Anyhow, sorry, the note isn't totally clear. It shouldn't be a problem for now because
the parser is still disabled on VLV (and platforms with ppgtt disabled in general). I
will look into retesting this though.

Brad

> 
> Cheers, Daniel
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/13] drm/i915: Refactor shmem pread setup
  2014-02-18 18:15 ` [PATCH 01/13] drm/i915: Refactor shmem pread setup bradley.d.volkin
@ 2014-03-06 12:13   ` Jani Nikula
  0 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2014-03-06 12:13 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx

On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> The command parser is going to need the same synchronization and
> setup logic, so factor it out for reuse.
>
> v2: Add a check that the object is backed by shmem
>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h |  3 +++
>  drivers/gpu/drm/i915/i915_gem.c | 51 ++++++++++++++++++++++++++++++-----------
>  2 files changed, 40 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 8c64831..582035b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2097,6 +2097,9 @@ void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
>  void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
>  void i915_gem_lastclose(struct drm_device *dev);
>  
> +int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
> +				    int *needs_clflush);
> +
>  int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
>  static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
>  {
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 3618bb0..83990cb 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -326,6 +326,42 @@ __copy_from_user_swizzled(char *gpu_vaddr, int gpu_offset,
>  	return 0;
>  }
>  
> +/*
> + * Pins the specified object's pages and synchronizes the object with
> + * GPU accesses. Sets needs_clflush to non-zero if the caller should
> + * flush the object from the CPU cache.
> + */
> +int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj,
> +				    int *needs_clflush)
> +{
> +	int ret;
> +
> +	*needs_clflush = 0;
> +
> +	if (!obj->base.filp)
> +		return -EINVAL;
> +
> +	if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) {
> +		/* If we're not in the cpu read domain, set ourself into the gtt
> +		 * read domain and manually flush cachelines (if required). This
> +		 * optimizes for the case when the gpu will dirty the data
> +		 * anyway again before the next pread happens. */
> +		*needs_clflush = !cpu_cache_is_coherent(obj->base.dev,
> +							obj->cache_level);
> +		ret = i915_gem_object_wait_rendering(obj, true);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = i915_gem_object_get_pages(obj);
> +	if (ret)
> +		return ret;
> +
> +	i915_gem_object_pin_pages(obj);
> +
> +	return ret;
> +}
> +
>  /* Per-page copy function for the shmem pread fastpath.
>   * Flushes invalid cachelines before reading the target if
>   * needs_clflush is set. */
> @@ -423,23 +459,10 @@ i915_gem_shmem_pread(struct drm_device *dev,
>  
>  	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
>  
> -	if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) {
> -		/* If we're not in the cpu read domain, set ourself into the gtt
> -		 * read domain and manually flush cachelines (if required). This
> -		 * optimizes for the case when the gpu will dirty the data
> -		 * anyway again before the next pread happens. */
> -		needs_clflush = !cpu_cache_is_coherent(dev, obj->cache_level);
> -		ret = i915_gem_object_wait_rendering(obj, true);
> -		if (ret)
> -			return ret;
> -	}
> -
> -	ret = i915_gem_object_get_pages(obj);
> +	ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush);
>  	if (ret)
>  		return ret;
>  
> -	i915_gem_object_pin_pages(obj);
> -
>  	offset = args->offset;
>  
>  	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
> -- 
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/13] drm/i915: Implement command buffer parsing logic
  2014-02-18 18:15 ` [PATCH 02/13] drm/i915: Implement command buffer parsing logic bradley.d.volkin
@ 2014-03-06 13:10   ` Jani Nikula
  2014-03-06 21:07     ` Daniel Vetter
  2014-03-20 12:40   ` Jani Nikula
  1 sibling, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2014-03-06 13:10 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx

On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> The command parser scans batch buffers submitted via execbuffer ioctls before
> the driver submits them to hardware. At a high level, it looks for several
> things:
>
> 1) Commands which are explicitly defined as privileged or which should only be
>    used by the kernel driver. The parser generally rejects such commands, with
>    the provision that it may allow some from the drm master process.
> 2) Commands which access registers. To support correct/enhanced userspace
>    functionality, particularly certain OpenGL extensions, the parser provides a
>    whitelist of registers which userspace may safely access (for both normal and
>    drm master processes).
> 3) Commands which access privileged memory (i.e. GGTT, HWS page, etc). The
>    parser always rejects such commands.
>
> See the overview comment in the source for more details.
>
> This patch only implements the logic. Subsequent patches will build the tables
> that drive the parser.
>
> v2: Don't set the secure bit if the parser succeeds
> Fail harder during init
> Makefile cleanup
> Kerneldoc cleanup
> Clarify module param description
> Convert ints to bools in a few places
> Move client/subclient defs to i915_reg.h
> Remove the bits_count field
>
> OTC-Tracker: AXIA-4631
> Change-Id: I50b98c71c6655893291c78a2d1b8954577b37a30
> Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile              |   1 +
>  drivers/gpu/drm/i915/i915_cmd_parser.c     | 485 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h            |  93 ++++++
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 ++
>  drivers/gpu/drm/i915/i915_params.c         |   5 +
>  drivers/gpu/drm/i915/i915_reg.h            |  12 +
>  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
>  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 ++
>  8 files changed, 648 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 4850494..3569122 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -14,6 +14,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
>  	  i915_gem_gtt.o \
>  	  i915_gem_stolen.o \
>  	  i915_gem_tiling.o \
> +	  i915_cmd_parser.o \
>  	  i915_params.o \
>  	  i915_sysfs.o \
>  	  i915_trace_points.o \
> diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> new file mode 100644
> index 0000000..7a5756e
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> @@ -0,0 +1,485 @@
> +/*
> + * Copyright © 2013 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *    Brad Volkin <bradley.d.volkin@intel.com>
> + *
> + */
> +
> +#include "i915_drv.h"
> +
> +/**
> + * DOC: i915 batch buffer command parser
> + *
> + * Motivation:
> + * Certain OpenGL features (e.g. transform feedback, performance monitoring)
> + * require userspace code to submit batches containing commands such as
> + * MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> + * generations of the hardware will noop these commands in "unsecure" batches
> + * (which includes all userspace batches submitted via i915) even though the
> + * commands may be safe and represent the intended programming model of the
> + * device.
> + *
> + * The software command parser is similar in operation to the command parsing
> + * done in hardware for unsecure batches. However, the software parser allows
> + * some operations that would be noop'd by hardware, if the parser determines
> + * the operation is safe, and submits the batch as "secure" to prevent hardware
> + * parsing.
> + *
> + * Threats:
> + * At a high level, the hardware (and software) checks attempt to prevent
> + * granting userspace undue privileges. There are three categories of privilege.
> + *
> + * First, commands which are explicitly defined as privileged or which should
> + * only be used by the kernel driver. The parser generally rejects such
> + * commands, though it may allow some from the drm master process.
> + *
> + * Second, commands which access registers. To support correct/enhanced
> + * userspace functionality, particularly certain OpenGL extensions, the parser
> + * provides a whitelist of registers which userspace may safely access (for both
> + * normal and drm master processes).
> + *
> + * Third, commands which access privileged memory (i.e. GGTT, HWS page, etc).
> + * The parser always rejects such commands.
> + *
> + * The majority of the problematic commands fall in the MI_* range, with only a
> + * few specific commands on each ring (e.g. PIPE_CONTROL and MI_FLUSH_DW).
> + *
> + * Implementation:
> + * Each ring maintains tables of commands and registers which the parser uses in
> + * scanning batch buffers submitted to that ring.
> + *
> + * Since the set of commands that the parser must check for is significantly
> + * smaller than the number of commands supported, the parser tables contain only
> + * those commands required by the parser. This generally works because command
> + * opcode ranges have standard command length encodings. So for commands that
> + * the parser does not need to check, it can easily skip them. This is
> + * implementated via a per-ring length decoding vfunc.
> + *
> + * Unfortunately, there are a number of commands that do not follow the standard
> + * length encoding for their opcode range, primarily amongst the MI_* commands.
> + * To handle this, the parser provides a way to define explicit "skip" entries
> + * in the per-ring command tables.
> + *
> + * Other command table entries map fairly directly to high level categories
> + * mentioned above: rejected, master-only, register whitelist. The parser
> + * implements a number of checks, including the privileged memory checks, via a
> + * general bitmasking mechanism.
> + */
> +
> +static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
> +{
> +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> +	u32 subclient =
> +		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
> +
> +	if (client == INSTR_MI_CLIENT)
> +		return 0x3F;
> +	else if (client == INSTR_RC_CLIENT) {
> +		if (subclient == INSTR_MEDIA_SUBCLIENT)
> +			return 0xFFFF;
> +		else
> +			return 0xFF;
> +	}
> +
> +	DRM_DEBUG_DRIVER("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header);
> +	return 0;
> +}
> +
> +static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header)
> +{
> +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> +	u32 subclient =
> +		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
> +
> +	if (client == INSTR_MI_CLIENT)
> +		return 0x3F;
> +	else if (client == INSTR_RC_CLIENT) {
> +		if (subclient == INSTR_MEDIA_SUBCLIENT)
> +			return 0xFFF;
> +		else
> +			return 0xFF;
> +	}
> +
> +	DRM_DEBUG_DRIVER("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header);
> +	return 0;
> +}
> +
> +static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
> +{
> +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> +
> +	if (client == INSTR_MI_CLIENT)
> +		return 0x3F;
> +	else if (client == INSTR_BC_CLIENT)
> +		return 0xFF;
> +
> +	DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
> +	return 0;
> +}
> +
> +static void validate_cmds_sorted(struct intel_ring_buffer *ring)
> +{
> +	int i;
> +
> +	if (!ring->cmd_tables || ring->cmd_table_count == 0)
> +		return;
> +
> +	for (i = 0; i < ring->cmd_table_count; i++) {
> +		const struct drm_i915_cmd_table *table = &ring->cmd_tables[i];
> +		u32 previous = 0;
> +		int j;
> +
> +		for (j = 0; j < table->count; j++) {
> +			const struct drm_i915_cmd_descriptor *desc =
> +				&table->table[i];
> +			u32 curr = desc->cmd.value & desc->cmd.mask;
> +
> +			if (curr < previous)
> +				DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
> +					  ring->id, i, j, curr, previous);
> +
> +			previous = curr;
> +		}
> +	}
> +}
> +
> +static void check_sorted(int ring_id, const u32 *reg_table, int reg_count)
> +{
> +	int i;
> +	u32 previous = 0;
> +
> +	for (i = 0; i < reg_count; i++) {
> +		u32 curr = reg_table[i];
> +
> +		if (curr < previous)
> +			DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
> +				  ring_id, i, curr, previous);
> +
> +		previous = curr;
> +	}
> +}
> +
> +static void validate_regs_sorted(struct intel_ring_buffer *ring)
> +{
> +	check_sorted(ring->id, ring->reg_table, ring->reg_count);
> +	check_sorted(ring->id, ring->master_reg_table, ring->master_reg_count);
> +}
> +
> +/**
> + * i915_cmd_parser_init_ring() - set cmd parser related fields for a ringbuffer
> + * @ring: the ringbuffer to initialize
> + *
> + * Optionally initializes fields related to batch buffer command parsing in the
> + * struct intel_ring_buffer based on whether the platform requires software
> + * command parsing.
> + */
> +void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
> +{
> +	if (!IS_GEN7(ring->dev))
> +		return;
> +
> +	switch (ring->id) {
> +	case RCS:
> +		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
> +		break;
> +	case VCS:
> +		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
> +		break;
> +	case BCS:
> +		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
> +		break;
> +	case VECS:
> +		/* VECS can use the same length_mask function as VCS */
> +		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
> +		break;
> +	default:
> +		DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n",
> +			  ring->id);
> +		BUG();
> +	}
> +
> +	validate_cmds_sorted(ring);
> +	validate_regs_sorted(ring);

So if you come to rely on the tables being sorted later on, I'd like the
above functions to return whether everything was okay or not, and BUG()
here if not. This can be a follow-up, and *must* be added before doing
anything that really requires the tables to be sorted.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +}
> +
> +static const struct drm_i915_cmd_descriptor*
> +find_cmd_in_table(const struct drm_i915_cmd_table *table,
> +		  u32 cmd_header)
> +{
> +	int i;
> +
> +	for (i = 0; i < table->count; i++) {
> +		const struct drm_i915_cmd_descriptor *desc = &table->table[i];
> +		u32 masked_cmd = desc->cmd.mask & cmd_header;
> +		u32 masked_value = desc->cmd.value & desc->cmd.mask;
> +
> +		if (masked_cmd == masked_value)
> +			return desc;
> +	}
> +
> +	return NULL;
> +}
> +
> +/*
> + * Returns a pointer to a descriptor for the command specified by cmd_header.
> + *
> + * The caller must supply space for a default descriptor via the default_desc
> + * parameter. If no descriptor for the specified command exists in the ring's
> + * command parser tables, this function fills in default_desc based on the
> + * ring's default length encoding and returns default_desc.
> + */
> +static const struct drm_i915_cmd_descriptor*
> +find_cmd(struct intel_ring_buffer *ring,
> +	 u32 cmd_header,
> +	 struct drm_i915_cmd_descriptor *default_desc)
> +{
> +	u32 mask;
> +	int i;
> +
> +	for (i = 0; i < ring->cmd_table_count; i++) {
> +		const struct drm_i915_cmd_descriptor *desc;
> +
> +		desc = find_cmd_in_table(&ring->cmd_tables[i], cmd_header);
> +		if (desc)
> +			return desc;
> +	}
> +
> +	mask = ring->get_cmd_length_mask(cmd_header);
> +	if (!mask)
> +		return NULL;
> +
> +	BUG_ON(!default_desc);
> +	default_desc->flags = CMD_DESC_SKIP;
> +	default_desc->length.mask = mask;
> +
> +	return default_desc;
> +}
> +
> +static bool valid_reg(const u32 *table, int count, u32 addr)
> +{
> +	if (table && count != 0) {
> +		int i;
> +
> +		for (i = 0; i < count; i++) {
> +			if (table[i] == addr)
> +				return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static u32 *vmap_batch(struct drm_i915_gem_object *obj)
> +{
> +	int i;
> +	void *addr = NULL;
> +	struct sg_page_iter sg_iter;
> +	struct page **pages;
> +
> +	pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
> +	if (pages == NULL) {
> +		DRM_DEBUG_DRIVER("Failed to get space for pages\n");
> +		goto finish;
> +	}
> +
> +	i = 0;
> +	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
> +		pages[i] = sg_page_iter_page(&sg_iter);
> +		i++;
> +	}
> +
> +	addr = vmap(pages, i, 0, PAGE_KERNEL);
> +	if (addr == NULL) {
> +		DRM_DEBUG_DRIVER("Failed to vmap pages\n");
> +		goto finish;
> +	}
> +
> +finish:
> +	if (pages)
> +		drm_free_large(pages);
> +	return (u32*)addr;
> +}
> +
> +/**
> + * i915_needs_cmd_parser() - should a given ring use software command parsing?
> + * @ring: the ring in question
> + *
> + * Only certain platforms require software batch buffer command parsing, and
> + * only when enabled via module paramter.
> + *
> + * Return: true if the ring requires software command parsing
> + */
> +bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
> +{
> +	/* No command tables indicates a platform without parsing */
> +	if (!ring->cmd_tables)
> +		return false;
> +
> +	return (i915.enable_cmd_parser == 1);
> +}
> +
> +#define LENGTH_BIAS 2
> +
> +/**
> + * i915_parse_cmds() - parse a submitted batch buffer for privilege violations
> + * @ring: the ring on which the batch is to execute
> + * @batch_obj: the batch buffer in question
> + * @batch_start_offset: byte offset in the batch at which execution starts
> + * @is_master: is the submitting process the drm master?
> + *
> + * Parses the specified batch buffer looking for privilege violations as
> + * described in the overview.
> + *
> + * Return: non-zero if the parser finds violations or otherwise fails
> + */
> +int i915_parse_cmds(struct intel_ring_buffer *ring,
> +		    struct drm_i915_gem_object *batch_obj,
> +		    u32 batch_start_offset,
> +		    bool is_master)
> +{
> +	int ret = 0;
> +	u32 *cmd, *batch_base, *batch_end;
> +	struct drm_i915_cmd_descriptor default_desc = { 0 };
> +	int needs_clflush = 0;
> +
> +	ret = i915_gem_obj_prepare_shmem_read(batch_obj, &needs_clflush);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("CMD: failed to prep read\n");
> +		return ret;
> +	}
> +
> +	batch_base = vmap_batch(batch_obj);
> +	if (!batch_base) {
> +		DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n");
> +		i915_gem_object_unpin_pages(batch_obj);
> +		return -ENOMEM;
> +	}
> +
> +	if (needs_clflush)
> +		drm_clflush_virt_range((char *)batch_base, batch_obj->base.size);
> +
> +	cmd = batch_base + (batch_start_offset / sizeof(*cmd));
> +	batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end));
> +
> +	while (cmd < batch_end) {
> +		const struct drm_i915_cmd_descriptor *desc;
> +		u32 length;
> +
> +		if (*cmd == MI_BATCH_BUFFER_END)
> +			break;
> +
> +		desc = find_cmd(ring, *cmd, &default_desc);
> +		if (!desc) {
> +			DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n",
> +					 *cmd);
> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		if (desc->flags & CMD_DESC_FIXED)
> +			length = desc->length.fixed;
> +		else
> +			length = ((*cmd & desc->length.mask) + LENGTH_BIAS);
> +
> +		if ((batch_end - cmd) < length) {
> +			DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%ld\n",
> +					 *cmd,
> +					 length,
> +					 batch_end - cmd);
> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		if (desc->flags & CMD_DESC_REJECT) {
> +			DRM_DEBUG_DRIVER("CMD: Rejected command: 0x%08X\n", *cmd);
> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		if ((desc->flags & CMD_DESC_MASTER) && !is_master) {
> +			DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n",
> +					 *cmd);
> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		if (desc->flags & CMD_DESC_REGISTER) {
> +			u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
> +
> +			if (!valid_reg(ring->reg_table,
> +				       ring->reg_count, reg_addr)) {
> +				if (!is_master ||
> +				    !valid_reg(ring->master_reg_table,
> +					       ring->master_reg_count,
> +					       reg_addr)) {
> +					DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
> +							 reg_addr,
> +							 *cmd,
> +							 ring->id);
> +					ret = -EINVAL;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (desc->flags & CMD_DESC_BITMASK) {
> +			int i;
> +
> +			for (i = 0; i < MAX_CMD_DESC_BITMASKS; i++) {
> +				u32 dword;
> +
> +				if (desc->bits[i].mask == 0)
> +					break;
> +
> +				dword = cmd[desc->bits[i].offset] &
> +					desc->bits[i].mask;
> +
> +				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,
> +							 desc->bits[i].mask,
> +							 desc->bits[i].expected,
> +							 dword, ring->id);
> +					ret = -EINVAL;
> +					break;
> +				}
> +			}
> +
> +			if (ret)
> +				break;
> +		}
> +
> +		cmd += length;
> +	}
> +
> +	if (cmd >= batch_end) {
> +		DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
> +		ret = -EINVAL;
> +	}
> +
> +	vunmap(batch_base);
> +
> +	i915_gem_object_unpin_pages(batch_obj);
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 582035b..376472f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1803,6 +1803,90 @@ struct drm_i915_file_private {
>  	atomic_t rps_wait_boost;
>  };
>  
> +/*
> + * A command that requires special handling by the command parser.
> + */
> +struct drm_i915_cmd_descriptor {
> +	/*
> +	 * Flags describing how the command parser processes the command.
> +	 *
> +	 * CMD_DESC_FIXED: The command has a fixed length if this is set,
> +	 *                 a length mask if not set
> +	 * CMD_DESC_SKIP: The command is allowed but does not follow the
> +	 *                standard length encoding for the opcode range in
> +	 *                which it falls
> +	 * CMD_DESC_REJECT: The command is never allowed
> +	 * CMD_DESC_REGISTER: The command should be checked against the
> +	 *                    register whitelist for the appropriate ring
> +	 * CMD_DESC_MASTER: The command is allowed if the submitting process
> +	 *                  is the DRM master
> +	 */
> +	u32 flags;
> +#define CMD_DESC_FIXED    (1<<0)
> +#define CMD_DESC_SKIP     (1<<1)
> +#define CMD_DESC_REJECT   (1<<2)
> +#define CMD_DESC_REGISTER (1<<3)
> +#define CMD_DESC_BITMASK  (1<<4)
> +#define CMD_DESC_MASTER   (1<<5)
> +
> +	/*
> +	 * The command's unique identification bits and the bitmask to get them.
> +	 * This isn't strictly the opcode field as defined in the spec and may
> +	 * also include type, subtype, and/or subop fields.
> +	 */
> +	struct {
> +		u32 value;
> +		u32 mask;
> +	} cmd;
> +
> +	/*
> +	 * The command's length. The command is either fixed length (i.e. does
> +	 * not include a length field) or has a length field mask. The flag
> +	 * CMD_DESC_FIXED indicates a fixed length. Otherwise, the command has
> +	 * a length mask. All command entries in a command table must include
> +	 * length information.
> +	 */
> +	union {
> +		u32 fixed;
> +		u32 mask;
> +	} length;
> +
> +	/*
> +	 * Describes where to find a register address in the command to check
> +	 * against the ring's register whitelist. Only valid if flags has the
> +	 * CMD_DESC_REGISTER bit set.
> +	 */
> +	struct {
> +		u32 offset;
> +		u32 mask;
> +	} reg;
> +
> +#define MAX_CMD_DESC_BITMASKS 3
> +	/*
> +	 * Describes command checks where a particular dword is masked and
> +	 * 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. Only entries where mask is non-zero
> +	 * are valid.
> +	 */
> +	struct {
> +		u32 offset;
> +		u32 mask;
> +		u32 expected;
> +	} bits[MAX_CMD_DESC_BITMASKS];
> +};
> +
> +/*
> + * A table of commands requiring special handling by the command parser.
> + *
> + * Each ring has an array of tables. Each table consists of an array of command
> + * descriptors, which must be sorted with command opcodes in ascending order.
> + */
> +struct drm_i915_cmd_table {
> +	const struct drm_i915_cmd_descriptor *table;
> +	int count;
> +};
> +
>  #define INTEL_INFO(dev)	(&to_i915(dev)->info)
>  
>  #define IS_I830(dev)		((dev)->pdev->device == 0x3577)
> @@ -1965,6 +2049,7 @@ struct i915_params {
>  	int enable_pc8;
>  	int pc8_timeout;
>  	int invert_brightness;
> +	int enable_cmd_parser;
>  	/* leave bools at the end to not create holes */
>  	bool enable_hangcheck;
>  	bool fastboot;
> @@ -2490,6 +2575,14 @@ void i915_destroy_error_state(struct drm_device *dev);
>  void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone);
>  const char *i915_cache_level_str(int type);
>  
> +/* i915_cmd_parser.c */
> +void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring);
> +bool i915_needs_cmd_parser(struct intel_ring_buffer *ring);
> +int i915_parse_cmds(struct intel_ring_buffer *ring,
> +		    struct drm_i915_gem_object *batch_obj,
> +		    u32 batch_start_offset,
> +		    bool is_master);
> +
>  /* i915_suspend.c */
>  extern int i915_save_state(struct drm_device *dev);
>  extern int i915_restore_state(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index d7229ad..3851a1b 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -1182,6 +1182,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  	}
>  	batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
>  
> +	if (i915_needs_cmd_parser(ring)) {
> +		ret = i915_parse_cmds(ring,
> +				      batch_obj,
> +				      args->batch_start_offset,
> +				      file->is_master);
> +		if (ret)
> +			goto err;
> +
> +		/*
> +		 * XXX: Actually do this when enabling batch copy...
> +		 *
> +		 * Set the DISPATCH_SECURE bit to remove the NON_SECURE bit
> +		 * from MI_BATCH_BUFFER_START commands issued in the
> +		 * dispatch_execbuffer implementations. We specifically don't
> +		 * want that set when the command parser is enabled.
> +		 */
> +	}
> +
>  	/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
>  	 * batch" bit. Hence we need to pin secure batches into the global gtt.
>  	 * hsw should have this fixed, but bdw mucks it up again. */
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index 3b48258..aba0b9b 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -48,6 +48,7 @@ struct i915_params i915 __read_mostly = {
>  	.reset = true,
>  	.invert_brightness = 0,
>  	.disable_display = 0,
> +	.enable_cmd_parser = 0,
>  };
>  
>  module_param_named(modeset, i915.modeset, int, 0400);
> @@ -157,3 +158,7 @@ MODULE_PARM_DESC(invert_brightness,
>  
>  module_param_named(disable_display, i915.disable_display, bool, 0600);
>  MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
> +
> +module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
> +MODULE_PARM_DESC(enable_cmd_parser,
> +		"Enable command parsing (1=enabled, 0=disabled [default])");
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2f564ce..e14dfda 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -175,6 +175,18 @@
>  #define VGA_CR_DATA_CGA 0x3d5
>  
>  /*
> + * Instruction field definitions used by the command parser
> + */
> +#define INSTR_CLIENT_SHIFT      29
> +#define INSTR_CLIENT_MASK       0xE0000000
> +#define   INSTR_MI_CLIENT       0x0
> +#define   INSTR_BC_CLIENT       0x2
> +#define   INSTR_RC_CLIENT       0x3
> +#define INSTR_SUBCLIENT_SHIFT   27
> +#define INSTR_SUBCLIENT_MASK    0x18000000
> +#define   INSTR_MEDIA_SUBCLIENT 0x2
> +
> +/*
>   * Memory interface instructions used by the kernel
>   */
>  #define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index b340c75..7bff5ef 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -1388,6 +1388,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,
>  	if (IS_I830(ring->dev) || IS_845G(ring->dev))
>  		ring->effective_size -= 128;
>  
> +	i915_cmd_parser_init_ring(ring);
> +
>  	return 0;
>  
>  err_unmap:
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index 08b91c6..09af920 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -164,6 +164,38 @@ struct  intel_ring_buffer {
>  		u32 gtt_offset;
>  		volatile u32 *cpu_page;
>  	} scratch;
> +
> +	/*
> +	 * Tables of commands the command parser needs to know about
> +	 * for this ring.
> +	 */
> +	const struct drm_i915_cmd_table *cmd_tables;
> +	int cmd_table_count;
> +
> +	/*
> +	 * Table of registers allowed in commands that read/write registers.
> +	 */
> +	const u32 *reg_table;
> +	int reg_count;
> +
> +	/*
> +	 * Table of registers allowed in commands that read/write registers, but
> +	 * only from the DRM master.
> +	 */
> +	const u32 *master_reg_table;
> +	int master_reg_count;
> +
> +	/*
> +	 * Returns the bitmask for the length field of the specified command.
> +	 * Return 0 for an unrecognized/invalid command.
> +	 *
> +	 * If the command parser finds an entry for a command in the ring's
> +	 * cmd_tables, it gets the command's length based on the table entry.
> +	 * If not, it calls this function to determine the per-ring length field
> +	 * encoding for the command (i.e. certain opcode ranges use certain bits
> +	 * to encode the command length in the header).
> +	 */
> +	u32 (*get_cmd_length_mask)(u32 cmd_header);
>  };
>  
>  static inline bool
> -- 
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 03/13] drm/i915: Initial command parser table definitions
  2014-02-18 18:15 ` [PATCH 03/13] drm/i915: Initial command parser table definitions bradley.d.volkin
@ 2014-03-06 13:12   ` Jani Nikula
  0 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2014-03-06 13:12 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx

On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> Add command tables defining irregular length commands for each ring.
> This requires a few new command opcode definitions.
>
> v2: Whitespace adjustment in command definitions, sparse fix for !F

Apart from the table contents,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> OTC-Tracker: AXIA-4631
> Change-Id: I064bceb457e15f46928058352afe76d918c58ef5
> Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_cmd_parser.c | 157 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h        |  46 ++++++++++
>  2 files changed, 203 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> index 7a5756e..12241e8 100644
> --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> @@ -86,6 +86,148 @@
>   * general bitmasking mechanism.
>   */
>  
> +#define STD_MI_OPCODE_MASK  0xFF800000
> +#define STD_3D_OPCODE_MASK  0xFFFF0000
> +#define STD_2D_OPCODE_MASK  0xFFC00000
> +#define STD_MFX_OPCODE_MASK 0xFFFF0000
> +
> +#define CMD(op, opm, f, lm, fl, ...)				\
> +	{							\
> +		.flags = (fl) | ((f) ? CMD_DESC_FIXED : 0),	\
> +		.cmd = { (op), (opm) }, 			\
> +		.length = { (lm) },				\
> +		__VA_ARGS__					\
> +	}
> +
> +/* Convenience macros to compress the tables */
> +#define SMI STD_MI_OPCODE_MASK
> +#define S3D STD_3D_OPCODE_MASK
> +#define S2D STD_2D_OPCODE_MASK
> +#define SMFX STD_MFX_OPCODE_MASK
> +#define F true
> +#define S CMD_DESC_SKIP
> +#define R CMD_DESC_REJECT
> +#define W CMD_DESC_REGISTER
> +#define B CMD_DESC_BITMASK
> +#define M CMD_DESC_MASTER
> +
> +/*            Command                          Mask   Fixed Len   Action
> +	      ---------------------------------------------------------- */
> +static const struct drm_i915_cmd_descriptor common_cmds[] = {
> +	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
> +	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
> +	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      S  ),
> +	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
> +	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
> +	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
> +	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor render_cmds[] = {
> +	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
> +	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
> +	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
> +	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
> +	CMD(  PIPELINE_SELECT,                  S3D,    F,  1,      S  ),
> +	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
> +	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
> +	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
> +	CMD(  MI_SET_PREDICATE,                 SMI,    F,  1,      S  ),
> +	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
> +	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
> +	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_VS,  S3D,   !F,  0x7FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_PS,  S3D,   !F,  0x7FF,  S  ),
> +
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,  S3D,   !F,  0x1FF,  S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor video_cmds[] = {
> +	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +	/*
> +	 * MFX_WAIT doesn't fit the way we handle length for most commands.
> +	 * It has a length field but it uses a non-standard length bias.
> +	 * It is always 1 dword though, so just treat it as fixed length.
> +	 */
> +	CMD(  MFX_WAIT,                         SMFX,   F,  1,      S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
> +	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor blt_cmds[] = {
> +	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
> +	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
> +	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
> +};
> +
> +#undef CMD
> +#undef SMI
> +#undef S3D
> +#undef S2D
> +#undef SMFX
> +#undef F
> +#undef S
> +#undef R
> +#undef W
> +#undef B
> +#undef M
> +
> +static const struct drm_i915_cmd_table gen7_render_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ render_cmds, ARRAY_SIZE(render_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table hsw_render_ring_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ render_cmds, ARRAY_SIZE(render_cmds) },
> +	{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table gen7_video_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ video_cmds, ARRAY_SIZE(video_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table hsw_vebox_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ vecs_cmds, ARRAY_SIZE(vecs_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
> +};
> +
>  static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
>  {
>  	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> @@ -200,15 +342,30 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
>  
>  	switch (ring->id) {
>  	case RCS:
> +		if (IS_HASWELL(ring->dev)) {
> +			ring->cmd_tables = hsw_render_ring_cmds;
> +			ring->cmd_table_count =
> +				ARRAY_SIZE(hsw_render_ring_cmds);
> +		} else {
> +			ring->cmd_tables = gen7_render_cmds;
> +			ring->cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
> +		}
> +
>  		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
>  		break;
>  	case VCS:
> +		ring->cmd_tables = gen7_video_cmds;
> +		ring->cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
>  		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
>  		break;
>  	case BCS:
> +		ring->cmd_tables = gen7_blt_cmds;
> +		ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
>  		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
>  		break;
>  	case VECS:
> +		ring->cmd_tables = hsw_vebox_cmds;
> +		ring->cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
>  		/* VECS can use the same length_mask function as VCS */
>  		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
>  		break;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index e14dfda..3f0b414 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -347,6 +347,52 @@
>  #define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
>  #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
>  
> +/*
> + * Commands used only by the command parser
> + */
> +#define MI_SET_PREDICATE        MI_INSTR(0x01, 0)
> +#define MI_ARB_CHECK            MI_INSTR(0x05, 0)
> +#define MI_RS_CONTROL           MI_INSTR(0x06, 0)
> +#define MI_URB_ATOMIC_ALLOC     MI_INSTR(0x09, 0)
> +#define MI_PREDICATE            MI_INSTR(0x0C, 0)
> +#define MI_RS_CONTEXT           MI_INSTR(0x0F, 0)
> +#define MI_TOPOLOGY_FILTER      MI_INSTR(0x0D, 0)
> +#define MI_URB_CLEAR            MI_INSTR(0x19, 0)
> +#define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
> +#define MI_CLFLUSH              MI_INSTR(0x27, 0)
> +#define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
> +#define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
> +#define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 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))
> +#define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
> +#define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
> +#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16))
> +#define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16))
> +#define GFX_OP_3DSTATE_SO_DECL_LIST \
> +	((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16))
> +
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))
> +
> +#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))
> +
> +#define COLOR_BLT     ((0x2<<29)|(0x40<<22))
> +#define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
>  
>  /*
>   * Reset registers
> -- 
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 10/13] drm/i915: Enable PPGTT command parser checks
  2014-02-18 18:15 ` [PATCH 10/13] drm/i915: Enable PPGTT command parser checks bradley.d.volkin
@ 2014-03-06 13:17   ` Jani Nikula
  2014-03-06 21:32     ` Volkin, Bradley D
  0 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2014-03-06 13:17 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx

On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> Various commands that access memory have a bit to determine whether
> the graphics address specified in the command should use the GGTT or
> PPGTT for translation. These checks ensure that the bit indicates
> PPGTT translation.
>
> Most of these checks use the existing bit-checking infrastructure.
> The PIPE_CONTROL and MI_FLUSH_DW commands, however, are multi-function
> commands. The GGTT/PPGTT bit is only relevant for certain uses of the
> command. As such, this change also extends the bit-checking code to
> include a "condition" mask and offset. If the condition mask is non-zero
> then the parser only performs the bit check when the bits specified by
> the condition mask/offset are also non-zero.
>
> NOTE: At this point in the series PPGTT must be enabled for the parser
> to work correctly. If it's not enabled, userspace will not be setting
> the PPGTT bits the way the parser requires. VLV is the only platform
> where this is a problem, so at this point, we disable parsing for VLV.
>
> v2: whitespace and trailing commas fixes, rebased
>
> OTC-Tracker: AXIA-4631
> Change-Id: I3f4c76b6734f1956ec47e698230f97d0998ff92b
> Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_cmd_parser.c | 128 ++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/i915_drv.h        |   6 ++
>  drivers/gpu/drm/i915/i915_reg.h        |   6 ++
>  3 files changed, 129 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> index 0351df1..1528549 100644
> --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> @@ -124,10 +124,20 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
>  	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_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,
> +	      }},						       ),
> +	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   W | B,
> +	      .reg = { .offset = 1, .mask = 0x007FFFFC },
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
> +	      }},						       ),
>  	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
>  };
>  
> @@ -139,9 +149,31 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
>  	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
>  	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
>  	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
> +	      }},						       ),
>  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
> -	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
> -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
> +	      }},						       ),
> +	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
> +	      .bits = {{
> +			.offset = 1,
> +			.mask = MI_REPORT_PERF_COUNT_GGTT,
> +			.expected = 0,
> +	      }},						       ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
> +	      }},						       ),
>  	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,
> @@ -158,6 +190,13 @@ 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,
>  	      }},						       ),
>  };
>  
> @@ -184,15 +223,32 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
>  
>  static const struct drm_i915_cmd_descriptor video_cmds[] = {
>  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
> +	      }},						       ),
>  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
>  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
>  	      .bits = {{
>  			.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,
> +	      }},						       ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
>  	      }},						       ),
> -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
>  	/*
>  	 * MFX_WAIT doesn't fit the way we handle length for most commands.
>  	 * It has a length field but it uses a non-standard length bias.
> @@ -203,26 +259,55 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
>  
>  static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
>  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
> +	      }},						       ),
>  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
>  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
>  	      .bits = {{
>  			.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,
> +	      }},						       ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> +	      .bits = {{
> +			.offset = 0,
> +			.mask = MI_GLOBAL_GTT,
> +			.expected = 0,
>  	      }},						       ),
> -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
>  };
>  
>  static const struct drm_i915_cmd_descriptor blt_cmds[] = {
>  	CMD(  MI_DISPLAY_FLIP,                  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,
> +	      }},						       ),
>  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
>  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
>  	      .bits = {{
>  			.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,
>  	      }},						       ),
>  	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
>  	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
> @@ -617,10 +702,21 @@ finish:
>   */
>  bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
>  {
> +	drm_i915_private_t *dev_priv =
> +		(drm_i915_private_t *)ring->dev->dev_private;

Make that:

	struct drm_i915_private *dev_priv = ring->dev->dev_private;


> +
>  	/* No command tables indicates a platform without parsing */
>  	if (!ring->cmd_tables)
>  		return false;
>  
> +	/*
> +	 * XXX: VLV is Gen7 and therefore has cmd_tables, but has PPGTT
> +	 * disabled. That will cause all of the parser's PPGTT checks to
> +	 * fail. For now, disable parsing when PPGTT is off.
> +	 */
> +	if (!dev_priv->mm.aliasing_ppgtt)
> +		return false;
> +
>  	return (i915.enable_cmd_parser == 1);
>  }
>  
> @@ -737,6 +833,16 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
>  				if (desc->bits[i].mask == 0)
>  					break;
>  
> +				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;
> +				}
> +
>  				dword = cmd[desc->bits[i].offset] &
>  					desc->bits[i].mask;
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 376472f..27a48d9 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1868,11 +1868,17 @@ struct drm_i915_cmd_descriptor {
>  	 * the expected value, the parser rejects it. Only valid if flags has
>  	 * the CMD_DESC_BITMASK bit set. Only entries where mask is non-zero
>  	 * are valid.
> +	 *
> +	 * 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];
>  };
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index e6dd7e9..e683b31 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -190,6 +190,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)
> @@ -269,6 +271,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)
> @@ -335,6 +338,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+ */
> @@ -363,6 +367,8 @@
>  #define MI_URB_CLEAR            MI_INSTR(0x19, 0)
>  #define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
>  #define MI_CLFLUSH              MI_INSTR(0x27, 0)
> +#define MI_REPORT_PERF_COUNT    MI_INSTR(0x28, 0)
> +#define   MI_REPORT_PERF_COUNT_GGTT (1<<0)
>  #define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
>  #define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
>  #define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 0)
> -- 
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/13] drm/i915: Implement command buffer parsing logic
  2014-03-06 13:10   ` Jani Nikula
@ 2014-03-06 21:07     ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2014-03-06 21:07 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Mar 06, 2014 at 03:10:50PM +0200, Jani Nikula wrote:
> On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> > From: Brad Volkin <bradley.d.volkin@intel.com>
> >
> > The command parser scans batch buffers submitted via execbuffer ioctls before
> > the driver submits them to hardware. At a high level, it looks for several
> > things:
> >
> > 1) Commands which are explicitly defined as privileged or which should only be
> >    used by the kernel driver. The parser generally rejects such commands, with
> >    the provision that it may allow some from the drm master process.
> > 2) Commands which access registers. To support correct/enhanced userspace
> >    functionality, particularly certain OpenGL extensions, the parser provides a
> >    whitelist of registers which userspace may safely access (for both normal and
> >    drm master processes).
> > 3) Commands which access privileged memory (i.e. GGTT, HWS page, etc). The
> >    parser always rejects such commands.
> >
> > See the overview comment in the source for more details.
> >
> > This patch only implements the logic. Subsequent patches will build the tables
> > that drive the parser.
> >
> > v2: Don't set the secure bit if the parser succeeds
> > Fail harder during init
> > Makefile cleanup
> > Kerneldoc cleanup
> > Clarify module param description
> > Convert ints to bools in a few places
> > Move client/subclient defs to i915_reg.h
> > Remove the bits_count field
> >
> > OTC-Tracker: AXIA-4631
> > Change-Id: I50b98c71c6655893291c78a2d1b8954577b37a30
> > Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> > ---
> >  drivers/gpu/drm/i915/Makefile              |   1 +
> >  drivers/gpu/drm/i915/i915_cmd_parser.c     | 485 +++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/i915_drv.h            |  93 ++++++
> >  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 ++
> >  drivers/gpu/drm/i915/i915_params.c         |   5 +
> >  drivers/gpu/drm/i915/i915_reg.h            |  12 +
> >  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
> >  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 ++
> >  8 files changed, 648 insertions(+)
> >  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
> >
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index 4850494..3569122 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -14,6 +14,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
> >  	  i915_gem_gtt.o \
> >  	  i915_gem_stolen.o \
> >  	  i915_gem_tiling.o \
> > +	  i915_cmd_parser.o \
> >  	  i915_params.o \
> >  	  i915_sysfs.o \
> >  	  i915_trace_points.o \
> > diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > new file mode 100644
> > index 0000000..7a5756e
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > @@ -0,0 +1,485 @@
> > +/*
> > + * Copyright © 2013 Intel Corporation
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a
> > + * copy of this software and associated documentation files (the "Software"),
> > + * to deal in the Software without restriction, including without limitation
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> > + * and/or sell copies of the Software, and to permit persons to whom the
> > + * Software is furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice (including the next
> > + * paragraph) shall be included in all copies or substantial portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + *
> > + * Authors:
> > + *    Brad Volkin <bradley.d.volkin@intel.com>
> > + *
> > + */
> > +
> > +#include "i915_drv.h"
> > +
> > +/**
> > + * DOC: i915 batch buffer command parser
> > + *
> > + * Motivation:
> > + * Certain OpenGL features (e.g. transform feedback, performance monitoring)
> > + * require userspace code to submit batches containing commands such as
> > + * MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> > + * generations of the hardware will noop these commands in "unsecure" batches
> > + * (which includes all userspace batches submitted via i915) even though the
> > + * commands may be safe and represent the intended programming model of the
> > + * device.
> > + *
> > + * The software command parser is similar in operation to the command parsing
> > + * done in hardware for unsecure batches. However, the software parser allows
> > + * some operations that would be noop'd by hardware, if the parser determines
> > + * the operation is safe, and submits the batch as "secure" to prevent hardware
> > + * parsing.
> > + *
> > + * Threats:
> > + * At a high level, the hardware (and software) checks attempt to prevent
> > + * granting userspace undue privileges. There are three categories of privilege.
> > + *
> > + * First, commands which are explicitly defined as privileged or which should
> > + * only be used by the kernel driver. The parser generally rejects such
> > + * commands, though it may allow some from the drm master process.
> > + *
> > + * Second, commands which access registers. To support correct/enhanced
> > + * userspace functionality, particularly certain OpenGL extensions, the parser
> > + * provides a whitelist of registers which userspace may safely access (for both
> > + * normal and drm master processes).
> > + *
> > + * Third, commands which access privileged memory (i.e. GGTT, HWS page, etc).
> > + * The parser always rejects such commands.
> > + *
> > + * The majority of the problematic commands fall in the MI_* range, with only a
> > + * few specific commands on each ring (e.g. PIPE_CONTROL and MI_FLUSH_DW).
> > + *
> > + * Implementation:
> > + * Each ring maintains tables of commands and registers which the parser uses in
> > + * scanning batch buffers submitted to that ring.
> > + *
> > + * Since the set of commands that the parser must check for is significantly
> > + * smaller than the number of commands supported, the parser tables contain only
> > + * those commands required by the parser. This generally works because command
> > + * opcode ranges have standard command length encodings. So for commands that
> > + * the parser does not need to check, it can easily skip them. This is
> > + * implementated via a per-ring length decoding vfunc.
> > + *
> > + * Unfortunately, there are a number of commands that do not follow the standard
> > + * length encoding for their opcode range, primarily amongst the MI_* commands.
> > + * To handle this, the parser provides a way to define explicit "skip" entries
> > + * in the per-ring command tables.
> > + *
> > + * Other command table entries map fairly directly to high level categories
> > + * mentioned above: rejected, master-only, register whitelist. The parser
> > + * implements a number of checks, including the privileged memory checks, via a
> > + * general bitmasking mechanism.
> > + */
> > +
> > +static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
> > +{
> > +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> > +	u32 subclient =
> > +		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
> > +
> > +	if (client == INSTR_MI_CLIENT)
> > +		return 0x3F;
> > +	else if (client == INSTR_RC_CLIENT) {
> > +		if (subclient == INSTR_MEDIA_SUBCLIENT)
> > +			return 0xFFFF;
> > +		else
> > +			return 0xFF;
> > +	}
> > +
> > +	DRM_DEBUG_DRIVER("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header);
> > +	return 0;
> > +}
> > +
> > +static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header)
> > +{
> > +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> > +	u32 subclient =
> > +		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
> > +
> > +	if (client == INSTR_MI_CLIENT)
> > +		return 0x3F;
> > +	else if (client == INSTR_RC_CLIENT) {
> > +		if (subclient == INSTR_MEDIA_SUBCLIENT)
> > +			return 0xFFF;
> > +		else
> > +			return 0xFF;
> > +	}
> > +
> > +	DRM_DEBUG_DRIVER("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header);
> > +	return 0;
> > +}
> > +
> > +static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
> > +{
> > +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> > +
> > +	if (client == INSTR_MI_CLIENT)
> > +		return 0x3F;
> > +	else if (client == INSTR_BC_CLIENT)
> > +		return 0xFF;
> > +
> > +	DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
> > +	return 0;
> > +}
> > +
> > +static void validate_cmds_sorted(struct intel_ring_buffer *ring)
> > +{
> > +	int i;
> > +
> > +	if (!ring->cmd_tables || ring->cmd_table_count == 0)
> > +		return;
> > +
> > +	for (i = 0; i < ring->cmd_table_count; i++) {
> > +		const struct drm_i915_cmd_table *table = &ring->cmd_tables[i];
> > +		u32 previous = 0;
> > +		int j;
> > +
> > +		for (j = 0; j < table->count; j++) {
> > +			const struct drm_i915_cmd_descriptor *desc =
> > +				&table->table[i];
> > +			u32 curr = desc->cmd.value & desc->cmd.mask;
> > +
> > +			if (curr < previous)
> > +				DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
> > +					  ring->id, i, j, curr, previous);
> > +
> > +			previous = curr;
> > +		}
> > +	}
> > +}
> > +
> > +static void check_sorted(int ring_id, const u32 *reg_table, int reg_count)
> > +{
> > +	int i;
> > +	u32 previous = 0;
> > +
> > +	for (i = 0; i < reg_count; i++) {
> > +		u32 curr = reg_table[i];
> > +
> > +		if (curr < previous)
> > +			DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
> > +				  ring_id, i, curr, previous);
> > +
> > +		previous = curr;
> > +	}
> > +}
> > +
> > +static void validate_regs_sorted(struct intel_ring_buffer *ring)
> > +{
> > +	check_sorted(ring->id, ring->reg_table, ring->reg_count);
> > +	check_sorted(ring->id, ring->master_reg_table, ring->master_reg_count);
> > +}
> > +
> > +/**
> > + * i915_cmd_parser_init_ring() - set cmd parser related fields for a ringbuffer
> > + * @ring: the ringbuffer to initialize
> > + *
> > + * Optionally initializes fields related to batch buffer command parsing in the
> > + * struct intel_ring_buffer based on whether the platform requires software
> > + * command parsing.
> > + */
> > +void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
> > +{
> > +	if (!IS_GEN7(ring->dev))
> > +		return;
> > +
> > +	switch (ring->id) {
> > +	case RCS:
> > +		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
> > +		break;
> > +	case VCS:
> > +		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
> > +		break;
> > +	case BCS:
> > +		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
> > +		break;
> > +	case VECS:
> > +		/* VECS can use the same length_mask function as VCS */
> > +		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
> > +		break;
> > +	default:
> > +		DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n",
> > +			  ring->id);
> > +		BUG();
> > +	}
> > +
> > +	validate_cmds_sorted(ring);
> > +	validate_regs_sorted(ring);
> 
> So if you come to rely on the tables being sorted later on, I'd like the
> above functions to return whether everything was okay or not, and BUG()
> here if not. This can be a follow-up, and *must* be added before doing
> anything that really requires the tables to be sorted.
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>

Merged the first 2 patches from this series, thanks.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 10/13] drm/i915: Enable PPGTT command parser checks
  2014-03-06 13:17   ` Jani Nikula
@ 2014-03-06 21:32     ` Volkin, Bradley D
  2014-03-06 21:58       ` Daniel Vetter
  0 siblings, 1 reply; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-06 21:32 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Mar 06, 2014 at 05:17:59AM -0800, Jani Nikula wrote:
> On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> > From: Brad Volkin <bradley.d.volkin@intel.com>
> >
> > Various commands that access memory have a bit to determine whether
> > the graphics address specified in the command should use the GGTT or
> > PPGTT for translation. These checks ensure that the bit indicates
> > PPGTT translation.
> >
> > Most of these checks use the existing bit-checking infrastructure.
> > The PIPE_CONTROL and MI_FLUSH_DW commands, however, are multi-function
> > commands. The GGTT/PPGTT bit is only relevant for certain uses of the
> > command. As such, this change also extends the bit-checking code to
> > include a "condition" mask and offset. If the condition mask is non-zero
> > then the parser only performs the bit check when the bits specified by
> > the condition mask/offset are also non-zero.
> >
> > NOTE: At this point in the series PPGTT must be enabled for the parser
> > to work correctly. If it's not enabled, userspace will not be setting
> > the PPGTT bits the way the parser requires. VLV is the only platform
> > where this is a problem, so at this point, we disable parsing for VLV.
> >
> > v2: whitespace and trailing commas fixes, rebased
> >
> > OTC-Tracker: AXIA-4631
> > Change-Id: I3f4c76b6734f1956ec47e698230f97d0998ff92b
> > Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_cmd_parser.c | 128 ++++++++++++++++++++++++++++++---
> >  drivers/gpu/drm/i915/i915_drv.h        |   6 ++
> >  drivers/gpu/drm/i915/i915_reg.h        |   6 ++
> >  3 files changed, 129 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > index 0351df1..1528549 100644
> > --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> > +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > @@ -124,10 +124,20 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
> >  	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_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,
> > +	      }},						       ),
> > +	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   W | B,
> > +	      .reg = { .offset = 1, .mask = 0x007FFFFC },
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> > +	      }},						       ),
> >  	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
> >  };
> >  
> > @@ -139,9 +149,31 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
> >  	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
> >  	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
> >  	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
> > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> > +	      }},						       ),
> >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
> > -	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
> > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > +	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> > +	      }},						       ),
> > +	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
> > +	      .bits = {{
> > +			.offset = 1,
> > +			.mask = MI_REPORT_PERF_COUNT_GGTT,
> > +			.expected = 0,
> > +	      }},						       ),
> > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> > +	      }},						       ),
> >  	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,
> > @@ -158,6 +190,13 @@ 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,
> >  	      }},						       ),
> >  };
> >  
> > @@ -184,15 +223,32 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
> >  
> >  static const struct drm_i915_cmd_descriptor video_cmds[] = {
> >  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> > -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> > +	      }},						       ),
> >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> >  	      .bits = {{
> >  			.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,
> > +	      }},						       ),
> > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> >  	      }},						       ),
> > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> >  	/*
> >  	 * MFX_WAIT doesn't fit the way we handle length for most commands.
> >  	 * It has a length field but it uses a non-standard length bias.
> > @@ -203,26 +259,55 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
> >  
> >  static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
> >  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> > -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> > +	      }},						       ),
> >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> >  	      .bits = {{
> >  			.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,
> > +	      }},						       ),
> > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > +	      .bits = {{
> > +			.offset = 0,
> > +			.mask = MI_GLOBAL_GTT,
> > +			.expected = 0,
> >  	      }},						       ),
> > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> >  };
> >  
> >  static const struct drm_i915_cmd_descriptor blt_cmds[] = {
> >  	CMD(  MI_DISPLAY_FLIP,                  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,
> > +	      }},						       ),
> >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> >  	      .bits = {{
> >  			.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,
> >  	      }},						       ),
> >  	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
> >  	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
> > @@ -617,10 +702,21 @@ finish:
> >   */
> >  bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
> >  {
> > +	drm_i915_private_t *dev_priv =
> > +		(drm_i915_private_t *)ring->dev->dev_private;
> 
> Make that:
> 
> 	struct drm_i915_private *dev_priv = ring->dev->dev_private;

Is this something that can be fixed up when merging the patch, or
should I fix it up and resend just this one?

Brad

> 
> 
> > +
> >  	/* No command tables indicates a platform without parsing */
> >  	if (!ring->cmd_tables)
> >  		return false;
> >  
> > +	/*
> > +	 * XXX: VLV is Gen7 and therefore has cmd_tables, but has PPGTT
> > +	 * disabled. That will cause all of the parser's PPGTT checks to
> > +	 * fail. For now, disable parsing when PPGTT is off.
> > +	 */
> > +	if (!dev_priv->mm.aliasing_ppgtt)
> > +		return false;
> > +
> >  	return (i915.enable_cmd_parser == 1);
> >  }
> >  
> > @@ -737,6 +833,16 @@ int i915_parse_cmds(struct intel_ring_buffer *ring,
> >  				if (desc->bits[i].mask == 0)
> >  					break;
> >  
> > +				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;
> > +				}
> > +
> >  				dword = cmd[desc->bits[i].offset] &
> >  					desc->bits[i].mask;
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 376472f..27a48d9 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1868,11 +1868,17 @@ struct drm_i915_cmd_descriptor {
> >  	 * the expected value, the parser rejects it. Only valid if flags has
> >  	 * the CMD_DESC_BITMASK bit set. Only entries where mask is non-zero
> >  	 * are valid.
> > +	 *
> > +	 * 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];
> >  };
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index e6dd7e9..e683b31 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -190,6 +190,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)
> > @@ -269,6 +271,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)
> > @@ -335,6 +338,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+ */
> > @@ -363,6 +367,8 @@
> >  #define MI_URB_CLEAR            MI_INSTR(0x19, 0)
> >  #define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
> >  #define MI_CLFLUSH              MI_INSTR(0x27, 0)
> > +#define MI_REPORT_PERF_COUNT    MI_INSTR(0x28, 0)
> > +#define   MI_REPORT_PERF_COUNT_GGTT (1<<0)
> >  #define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
> >  #define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
> >  #define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 0)
> > -- 
> > 1.8.3.2
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 10/13] drm/i915: Enable PPGTT command parser checks
  2014-03-06 21:32     ` Volkin, Bradley D
@ 2014-03-06 21:58       ` Daniel Vetter
  2014-03-06 22:13         ` Volkin, Bradley D
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2014-03-06 21:58 UTC (permalink / raw)
  To: Volkin, Bradley D; +Cc: intel-gfx

On Thu, Mar 06, 2014 at 01:32:48PM -0800, Volkin, Bradley D wrote:
> On Thu, Mar 06, 2014 at 05:17:59AM -0800, Jani Nikula wrote:
> > On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> > > From: Brad Volkin <bradley.d.volkin@intel.com>
> > >
> > > Various commands that access memory have a bit to determine whether
> > > the graphics address specified in the command should use the GGTT or
> > > PPGTT for translation. These checks ensure that the bit indicates
> > > PPGTT translation.
> > >
> > > Most of these checks use the existing bit-checking infrastructure.
> > > The PIPE_CONTROL and MI_FLUSH_DW commands, however, are multi-function
> > > commands. The GGTT/PPGTT bit is only relevant for certain uses of the
> > > command. As such, this change also extends the bit-checking code to
> > > include a "condition" mask and offset. If the condition mask is non-zero
> > > then the parser only performs the bit check when the bits specified by
> > > the condition mask/offset are also non-zero.
> > >
> > > NOTE: At this point in the series PPGTT must be enabled for the parser
> > > to work correctly. If it's not enabled, userspace will not be setting
> > > the PPGTT bits the way the parser requires. VLV is the only platform
> > > where this is a problem, so at this point, we disable parsing for VLV.
> > >
> > > v2: whitespace and trailing commas fixes, rebased
> > >
> > > OTC-Tracker: AXIA-4631
> > > Change-Id: I3f4c76b6734f1956ec47e698230f97d0998ff92b
> > > Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_cmd_parser.c | 128 ++++++++++++++++++++++++++++++---
> > >  drivers/gpu/drm/i915/i915_drv.h        |   6 ++
> > >  drivers/gpu/drm/i915/i915_reg.h        |   6 ++
> > >  3 files changed, 129 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > > index 0351df1..1528549 100644
> > > --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> > > +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > > @@ -124,10 +124,20 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
> > >  	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_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,
> > > +	      }},						       ),
> > > +	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   W | B,
> > > +	      .reg = { .offset = 1, .mask = 0x007FFFFC },
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > >  	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
> > >  };
> > >  
> > > @@ -139,9 +149,31 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
> > >  	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
> > >  	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
> > >  	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
> > > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
> > > -	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
> > > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > > +	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > > +	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
> > > +	      .bits = {{
> > > +			.offset = 1,
> > > +			.mask = MI_REPORT_PERF_COUNT_GGTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > >  	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,
> > > @@ -158,6 +190,13 @@ 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,
> > >  	      }},						       ),
> > >  };
> > >  
> > > @@ -184,15 +223,32 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
> > >  
> > >  static const struct drm_i915_cmd_descriptor video_cmds[] = {
> > >  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> > > -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> > > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> > >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> > >  	      .bits = {{
> > >  			.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,
> > > +	      }},						       ),
> > > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > >  	      }},						       ),
> > > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > >  	/*
> > >  	 * MFX_WAIT doesn't fit the way we handle length for most commands.
> > >  	 * It has a length field but it uses a non-standard length bias.
> > > @@ -203,26 +259,55 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
> > >  
> > >  static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
> > >  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> > > -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> > > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > > +	      }},						       ),
> > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> > >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> > >  	      .bits = {{
> > >  			.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,
> > > +	      }},						       ),
> > > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > > +	      .bits = {{
> > > +			.offset = 0,
> > > +			.mask = MI_GLOBAL_GTT,
> > > +			.expected = 0,
> > >  	      }},						       ),
> > > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > >  };
> > >  
> > >  static const struct drm_i915_cmd_descriptor blt_cmds[] = {
> > >  	CMD(  MI_DISPLAY_FLIP,                  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,
> > > +	      }},						       ),
> > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> > >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> > >  	      .bits = {{
> > >  			.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,
> > >  	      }},						       ),
> > >  	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
> > >  	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
> > > @@ -617,10 +702,21 @@ finish:
> > >   */
> > >  bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
> > >  {
> > > +	drm_i915_private_t *dev_priv =
> > > +		(drm_i915_private_t *)ring->dev->dev_private;
> > 
> > Make that:
> > 
> > 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
> 
> Is this something that can be fixed up when merging the patch, or
> should I fix it up and resend just this one?

I usually do that when merging, at least if it's not too much. Already
applied a small checkpatch appeasement change for your 2nd patch ;-)

BKM is to run scripts/checkpatch.pl before hitting send and working down
the list. Presuming your editor is configured correctly not upsetting
checkpatch should become natural after a few patches though. If not you
need a better editor ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 10/13] drm/i915: Enable PPGTT command parser checks
  2014-03-06 21:58       ` Daniel Vetter
@ 2014-03-06 22:13         ` Volkin, Bradley D
  0 siblings, 0 replies; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-06 22:13 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Thu, Mar 06, 2014 at 01:58:09PM -0800, Daniel Vetter wrote:
> On Thu, Mar 06, 2014 at 01:32:48PM -0800, Volkin, Bradley D wrote:
> > On Thu, Mar 06, 2014 at 05:17:59AM -0800, Jani Nikula wrote:
> > > On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> > > > From: Brad Volkin <bradley.d.volkin@intel.com>
> > > >
> > > > Various commands that access memory have a bit to determine whether
> > > > the graphics address specified in the command should use the GGTT or
> > > > PPGTT for translation. These checks ensure that the bit indicates
> > > > PPGTT translation.
> > > >
> > > > Most of these checks use the existing bit-checking infrastructure.
> > > > The PIPE_CONTROL and MI_FLUSH_DW commands, however, are multi-function
> > > > commands. The GGTT/PPGTT bit is only relevant for certain uses of the
> > > > command. As such, this change also extends the bit-checking code to
> > > > include a "condition" mask and offset. If the condition mask is non-zero
> > > > then the parser only performs the bit check when the bits specified by
> > > > the condition mask/offset are also non-zero.
> > > >
> > > > NOTE: At this point in the series PPGTT must be enabled for the parser
> > > > to work correctly. If it's not enabled, userspace will not be setting
> > > > the PPGTT bits the way the parser requires. VLV is the only platform
> > > > where this is a problem, so at this point, we disable parsing for VLV.
> > > >
> > > > v2: whitespace and trailing commas fixes, rebased
> > > >
> > > > OTC-Tracker: AXIA-4631
> > > > Change-Id: I3f4c76b6734f1956ec47e698230f97d0998ff92b
> > > > Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/i915_cmd_parser.c | 128 ++++++++++++++++++++++++++++++---
> > > >  drivers/gpu/drm/i915/i915_drv.h        |   6 ++
> > > >  drivers/gpu/drm/i915/i915_reg.h        |   6 ++
> > > >  3 files changed, 129 insertions(+), 11 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > > > index 0351df1..1528549 100644
> > > > --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> > > > +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > > > @@ -124,10 +124,20 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
> > > >  	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_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,
> > > > +	      }},						       ),
> > > > +	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   W | B,
> > > > +	      .reg = { .offset = 1, .mask = 0x007FFFFC },
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > >  	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
> > > >  };
> > > >  
> > > > @@ -139,9 +149,31 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = {
> > > >  	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
> > > >  	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
> > > >  	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
> > > > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
> > > > -	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
> > > > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > > > +	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > > +	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 1,
> > > > +			.mask = MI_REPORT_PERF_COUNT_GGTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > >  	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,
> > > > @@ -158,6 +190,13 @@ 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,
> > > >  	      }},						       ),
> > > >  };
> > > >  
> > > > @@ -184,15 +223,32 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
> > > >  
> > > >  static const struct drm_i915_cmd_descriptor video_cmds[] = {
> > > >  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> > > > -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> > > > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> > > >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> > > >  	      .bits = {{
> > > >  			.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,
> > > > +	      }},						       ),
> > > > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > >  	      }},						       ),
> > > > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > > >  	/*
> > > >  	 * MFX_WAIT doesn't fit the way we handle length for most commands.
> > > >  	 * It has a length field but it uses a non-standard length bias.
> > > > @@ -203,26 +259,55 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = {
> > > >  
> > > >  static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
> > > >  	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
> > > > -	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> > > > +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > > +	      }},						       ),
> > > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> > > >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> > > >  	      .bits = {{
> > > >  			.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,
> > > > +	      }},						       ),
> > > > +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
> > > > +	      .bits = {{
> > > > +			.offset = 0,
> > > > +			.mask = MI_GLOBAL_GTT,
> > > > +			.expected = 0,
> > > >  	      }},						       ),
> > > > -	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> > > >  };
> > > >  
> > > >  static const struct drm_i915_cmd_descriptor blt_cmds[] = {
> > > >  	CMD(  MI_DISPLAY_FLIP,                  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,
> > > > +	      }},						       ),
> > > >  	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
> > > >  	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
> > > >  	      .bits = {{
> > > >  			.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,
> > > >  	      }},						       ),
> > > >  	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
> > > >  	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
> > > > @@ -617,10 +702,21 @@ finish:
> > > >   */
> > > >  bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
> > > >  {
> > > > +	drm_i915_private_t *dev_priv =
> > > > +		(drm_i915_private_t *)ring->dev->dev_private;
> > > 
> > > Make that:
> > > 
> > > 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
> > 
> > Is this something that can be fixed up when merging the patch, or
> > should I fix it up and resend just this one?
> 
> I usually do that when merging, at least if it's not too much. Already
> applied a small checkpatch appeasement change for your 2nd patch ;-)
> 
> BKM is to run scripts/checkpatch.pl before hitting send and working down
> the list. Presuming your editor is configured correctly not upsetting
> checkpatch should become natural after a few patches though. If not you
> need a better editor ;-)
> -Daniel

Apologies. I think the flaw is that some extra spaces in the tables and log messages
making lines longer than 80 characters drive checkpatch crazy. I'm so used to skimming
over those that I've probably ignored other issues too.

Brad

> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (14 preceding siblings ...)
  2014-03-05 10:46 ` Daniel Vetter
@ 2014-03-11 12:41 ` Jani Nikula
  2014-03-12 18:02   ` Volkin, Bradley D
  2014-03-20 14:43 ` Jani Nikula
  16 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2014-03-11 12:41 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx


Hi Bradley -

I've now rather meticulously reviewed what *is* in the command and
register tables, and didn't spot any obvious errors.

There is still the review of what is *not* in the command and register
tables, but perhaps should be. This is important for two reasons:

1) Any command that should fail that's missing from the tables will
   pass.

2) Any command that has a non-standard length encoding that's missing
   from the tables will confuse the parser. Going out-of-sync with the
   commands may fail a good batch, or, worse, a command that should fail
   may pass.

I'm thinking there's a certain fragility in this. In a sense, it would
be better to whitelist everything, and fail everything else, to err on
the safe side. But I'm guessing that's not really feasible.

Part of the fragility is the immense tediousness of the review... I know
it gets easier with the incremental updates, but this first series is
not fun. (You know, you could have planted a bug to reward me! Or did I
miss it?! ;)


BR,
Jani.


On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> Certain OpenGL features (e.g. transform feedback, performance monitoring)
> require userspace code to submit batches containing commands such as
> MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> generations of the hardware will noop these commands in "unsecure" batches
> (which includes all userspace batches submitted via i915) even though the
> commands may be safe and represent the intended programming model of the device.
>
> This series introduces a software command parser similar in operation to the
> command parsing done in hardware for unsecure batches. However, the software
> parser allows some operations that would be noop'd by hardware, if the parser
> determines the operation is safe, and submits the batch as "secure" to prevent
> hardware parsing. Currently the series implements this on IVB and HSW.
>
> The series has one piece of prep work, one patch for the parser logic, and a
> handful of patches to fill out the tables which drive the parser. There are
> follow-up patches to libdrm and to i-g-t. The i-g-t tests are basic and do not
> test all of the commands used by the parser on the assumption that I'm likely
> to make the same mistakes in both the parser and the test.
>
> I've previously run the i-g-t gem_* tests, the piglit quick tests, and generally
> used Ubuntu 13.10 IVB and HSW systems with the parser running. Aside from a
> failure described below, I did not see any regressions.
>
> At this point there are a couple of required/potential improvements.
>
> 1) Chained batches. The parser currently allows MI_BATCH_BUFFER_START commands
>    in userspace batches without parsing them. The media driver uses chained
>    batches, so a solution is required. I'm still working through the
>    requirements but don't want to continue delaying the review process for what
>    I have so far.
> 2) Command buffer copy. To avoid CPU modifications to buffers after parsing, and
>    to avoid GPU modifications to buffers via EUs or commands in the batch, we
>    should copy the userspace batch buffer to memory that userspace does not
>    have access to, map it into GGTT, and execute that batch buffer. I have a
>    sense of how to do this for 1st-level batches, but it may need changes to
>    tie in with the chained batch parsing, so I've again held off.
> 3) Coherency. I've previously found a coherency issue on VLV when reading the
>    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
>    pwrite fast path before calling execbuffer2. The parser reads stale data.
>    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
>    It's possible that the shmem pread refactoring fixes this, I just have not
>    been able to retest due to lack of a VLV system.
>
> v2:
> - Significantly reorder series
> - Scan secure batches (i.e. I915_EXEC_SECURE)
> - Check that parser tables are sorted during init
> - Fixed gem_cpu_reloc regression
> - HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
> - Additional tests
>
> v3:
> - Don't actually send batches as secure yet
> - Improved documentation and commenting
> - Many other small cleanups throughout
>
> Brad Volkin (13):
>   drm/i915: Refactor shmem pread setup
>   drm/i915: Implement command buffer parsing logic
>   drm/i915: Initial command parser table definitions
>   drm/i915: Reject privileged commands
>   drm/i915: Allow some privileged commands from master
>   drm/i915: Add register whitelists for mesa
>   drm/i915: Add register whitelist for DRM master
>   drm/i915: Enable register whitelist checks
>   drm/i915: Reject commands that explicitly generate interrupts
>   drm/i915: Enable PPGTT command parser checks
>   drm/i915: Reject commands that would store to global HWS page
>   drm/i915: Add a CMD_PARSER_VERSION getparam
>   drm/i915: Enable command parsing by default
>
>  drivers/gpu/drm/i915/Makefile              |   1 +
>  drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_dma.c            |   3 +
>  drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
>  drivers/gpu/drm/i915/i915_gem.c            |  51 +-
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
>  drivers/gpu/drm/i915/i915_params.c         |   5 +
>  drivers/gpu/drm/i915/i915_reg.h            |  96 +++
>  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
>  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
>  include/uapi/drm/i915_drm.h                |   1 +
>  11 files changed, 1216 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
>
> -- 
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-11 12:41 ` Jani Nikula
@ 2014-03-12 18:02   ` Volkin, Bradley D
  0 siblings, 0 replies; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-12 18:02 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Mar 11, 2014 at 05:41:06AM -0700, Jani Nikula wrote:
> 
> Hi Bradley -
> 
> I've now rather meticulously reviewed what *is* in the command and
> register tables, and didn't spot any obvious errors.

Thanks Jani! I know it's a huge pain, so I appreciate you taking the
time for it.

> 
> There is still the review of what is *not* in the command and register
> tables, but perhaps should be. This is important for two reasons:
> 
> 1) Any command that should fail that's missing from the tables will
>    pass.
> 
> 2) Any command that has a non-standard length encoding that's missing
>    from the tables will confuse the parser. Going out-of-sync with the
>    commands may fail a good batch, or, worse, a command that should fail
>    may pass.
> 
> I'm thinking there's a certain fragility in this. In a sense, it would
> be better to whitelist everything, and fail everything else, to err on
> the safe side. But I'm guessing that's not really feasible.

There was some discussion on these issues previously. I think Daniel's
response here covers it.

http://lists.freedesktop.org/archives/intel-gfx/2014-January/039209.html

> 
> Part of the fragility is the immense tediousness of the review... I know
> it gets easier with the incremental updates, but this first series is
> not fun. (You know, you could have planted a bug to reward me! Or did I
> miss it?! ;)

Yes, I'm afraid that I've taken all the fun for myself :p

Brad

> 
> 
> BR,
> Jani.
> 
> 
> On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> > From: Brad Volkin <bradley.d.volkin@intel.com>
> >
> > Certain OpenGL features (e.g. transform feedback, performance monitoring)
> > require userspace code to submit batches containing commands such as
> > MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> > generations of the hardware will noop these commands in "unsecure" batches
> > (which includes all userspace batches submitted via i915) even though the
> > commands may be safe and represent the intended programming model of the device.
> >
> > This series introduces a software command parser similar in operation to the
> > command parsing done in hardware for unsecure batches. However, the software
> > parser allows some operations that would be noop'd by hardware, if the parser
> > determines the operation is safe, and submits the batch as "secure" to prevent
> > hardware parsing. Currently the series implements this on IVB and HSW.
> >
> > The series has one piece of prep work, one patch for the parser logic, and a
> > handful of patches to fill out the tables which drive the parser. There are
> > follow-up patches to libdrm and to i-g-t. The i-g-t tests are basic and do not
> > test all of the commands used by the parser on the assumption that I'm likely
> > to make the same mistakes in both the parser and the test.
> >
> > I've previously run the i-g-t gem_* tests, the piglit quick tests, and generally
> > used Ubuntu 13.10 IVB and HSW systems with the parser running. Aside from a
> > failure described below, I did not see any regressions.
> >
> > At this point there are a couple of required/potential improvements.
> >
> > 1) Chained batches. The parser currently allows MI_BATCH_BUFFER_START commands
> >    in userspace batches without parsing them. The media driver uses chained
> >    batches, so a solution is required. I'm still working through the
> >    requirements but don't want to continue delaying the review process for what
> >    I have so far.
> > 2) Command buffer copy. To avoid CPU modifications to buffers after parsing, and
> >    to avoid GPU modifications to buffers via EUs or commands in the batch, we
> >    should copy the userspace batch buffer to memory that userspace does not
> >    have access to, map it into GGTT, and execute that batch buffer. I have a
> >    sense of how to do this for 1st-level batches, but it may need changes to
> >    tie in with the chained batch parsing, so I've again held off.
> > 3) Coherency. I've previously found a coherency issue on VLV when reading the
> >    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
> >    pwrite fast path before calling execbuffer2. The parser reads stale data.
> >    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
> >    It's possible that the shmem pread refactoring fixes this, I just have not
> >    been able to retest due to lack of a VLV system.
> >
> > v2:
> > - Significantly reorder series
> > - Scan secure batches (i.e. I915_EXEC_SECURE)
> > - Check that parser tables are sorted during init
> > - Fixed gem_cpu_reloc regression
> > - HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
> > - Additional tests
> >
> > v3:
> > - Don't actually send batches as secure yet
> > - Improved documentation and commenting
> > - Many other small cleanups throughout
> >
> > Brad Volkin (13):
> >   drm/i915: Refactor shmem pread setup
> >   drm/i915: Implement command buffer parsing logic
> >   drm/i915: Initial command parser table definitions
> >   drm/i915: Reject privileged commands
> >   drm/i915: Allow some privileged commands from master
> >   drm/i915: Add register whitelists for mesa
> >   drm/i915: Add register whitelist for DRM master
> >   drm/i915: Enable register whitelist checks
> >   drm/i915: Reject commands that explicitly generate interrupts
> >   drm/i915: Enable PPGTT command parser checks
> >   drm/i915: Reject commands that would store to global HWS page
> >   drm/i915: Add a CMD_PARSER_VERSION getparam
> >   drm/i915: Enable command parsing by default
> >
> >  drivers/gpu/drm/i915/Makefile              |   1 +
> >  drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/i915_dma.c            |   3 +
> >  drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
> >  drivers/gpu/drm/i915/i915_gem.c            |  51 +-
> >  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
> >  drivers/gpu/drm/i915/i915_params.c         |   5 +
> >  drivers/gpu/drm/i915/i915_reg.h            |  96 +++
> >  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
> >  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
> >  include/uapi/drm/i915_drm.h                |   1 +
> >  11 files changed, 1216 insertions(+), 14 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
> >
> > -- 
> > 1.8.3.2
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/13] drm/i915: Implement command buffer parsing logic
  2014-02-18 18:15 ` [PATCH 02/13] drm/i915: Implement command buffer parsing logic bradley.d.volkin
  2014-03-06 13:10   ` Jani Nikula
@ 2014-03-20 12:40   ` Jani Nikula
  1 sibling, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2014-03-20 12:40 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx

On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> +static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
> +{
> +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> +	u32 subclient =
> +		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
> +
> +	if (client == INSTR_MI_CLIENT)
> +		return 0x3F;
> +	else if (client == INSTR_RC_CLIENT) {
> +		if (subclient == INSTR_MEDIA_SUBCLIENT)
> +			return 0xFFFF;
> +		else
> +			return 0xFF;
> +	}
> +
> +	DRM_DEBUG_DRIVER("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header);
> +	return 0;
> +}
> +
> +static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header)
> +{
> +	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
> +	u32 subclient =
> +		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
> +
> +	if (client == INSTR_MI_CLIENT)
> +		return 0x3F;
> +	else if (client == INSTR_RC_CLIENT) {
> +		if (subclient == INSTR_MEDIA_SUBCLIENT)
> +			return 0xFFF;

Should this be 0xffff like in gen7_render_get_cmd_length_mask()?

Jani.

> +		else
> +			return 0xFF;
> +	}
> +
> +	DRM_DEBUG_DRIVER("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header);
> +	return 0;
> +}

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
                   ` (15 preceding siblings ...)
  2014-03-11 12:41 ` Jani Nikula
@ 2014-03-20 14:43 ` Jani Nikula
  2014-03-25 13:15   ` Daniel Vetter
  16 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2014-03-20 14:43 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx


Hi Bradley -

Apologies for my procrastination with the review; I don't easily recall
as tedious a review as the command and register tables. And I sure have
reviewed a lot of miserable stuff in the past.

Most infuriatingly, I did not find a single real bug in the code!

I think we'll need to automate some things going forward, for example
listing the non-conforming length encoding with Damien's tools for cross
checking.

There are a few subtle points we need to discuss (separate mails
internally) but all in all this series is:

Reviewed-by: Jani Nikula <jani.nikula@intel.com>



On Tue, 18 Feb 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> Certain OpenGL features (e.g. transform feedback, performance monitoring)
> require userspace code to submit batches containing commands such as
> MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
> generations of the hardware will noop these commands in "unsecure" batches
> (which includes all userspace batches submitted via i915) even though the
> commands may be safe and represent the intended programming model of the device.
>
> This series introduces a software command parser similar in operation to the
> command parsing done in hardware for unsecure batches. However, the software
> parser allows some operations that would be noop'd by hardware, if the parser
> determines the operation is safe, and submits the batch as "secure" to prevent
> hardware parsing. Currently the series implements this on IVB and HSW.
>
> The series has one piece of prep work, one patch for the parser logic, and a
> handful of patches to fill out the tables which drive the parser. There are
> follow-up patches to libdrm and to i-g-t. The i-g-t tests are basic and do not
> test all of the commands used by the parser on the assumption that I'm likely
> to make the same mistakes in both the parser and the test.
>
> I've previously run the i-g-t gem_* tests, the piglit quick tests, and generally
> used Ubuntu 13.10 IVB and HSW systems with the parser running. Aside from a
> failure described below, I did not see any regressions.
>
> At this point there are a couple of required/potential improvements.
>
> 1) Chained batches. The parser currently allows MI_BATCH_BUFFER_START commands
>    in userspace batches without parsing them. The media driver uses chained
>    batches, so a solution is required. I'm still working through the
>    requirements but don't want to continue delaying the review process for what
>    I have so far.
> 2) Command buffer copy. To avoid CPU modifications to buffers after parsing, and
>    to avoid GPU modifications to buffers via EUs or commands in the batch, we
>    should copy the userspace batch buffer to memory that userspace does not
>    have access to, map it into GGTT, and execute that batch buffer. I have a
>    sense of how to do this for 1st-level batches, but it may need changes to
>    tie in with the chained batch parsing, so I've again held off.
> 3) Coherency. I've previously found a coherency issue on VLV when reading the
>    batch buffer from the CPU during execbuffer2. Userspace writes the batch via
>    pwrite fast path before calling execbuffer2. The parser reads stale data.
>    This works fine on IVB and HSW, so I believe it's an LLC vs. non-LLC issue.
>    It's possible that the shmem pread refactoring fixes this, I just have not
>    been able to retest due to lack of a VLV system.
>
> v2:
> - Significantly reorder series
> - Scan secure batches (i.e. I915_EXEC_SECURE)
> - Check that parser tables are sorted during init
> - Fixed gem_cpu_reloc regression
> - HAS_CMD_PARSER -> CMD_PARSER_VERSION getparam
> - Additional tests
>
> v3:
> - Don't actually send batches as secure yet
> - Improved documentation and commenting
> - Many other small cleanups throughout
>
> Brad Volkin (13):
>   drm/i915: Refactor shmem pread setup
>   drm/i915: Implement command buffer parsing logic
>   drm/i915: Initial command parser table definitions
>   drm/i915: Reject privileged commands
>   drm/i915: Allow some privileged commands from master
>   drm/i915: Add register whitelists for mesa
>   drm/i915: Add register whitelist for DRM master
>   drm/i915: Enable register whitelist checks
>   drm/i915: Reject commands that explicitly generate interrupts
>   drm/i915: Enable PPGTT command parser checks
>   drm/i915: Reject commands that would store to global HWS page
>   drm/i915: Add a CMD_PARSER_VERSION getparam
>   drm/i915: Enable command parsing by default
>
>  drivers/gpu/drm/i915/Makefile              |   1 +
>  drivers/gpu/drm/i915/i915_cmd_parser.c     | 918 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_dma.c            |   3 +
>  drivers/gpu/drm/i915/i915_drv.h            | 103 ++++
>  drivers/gpu/drm/i915/i915_gem.c            |  51 +-
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  18 +
>  drivers/gpu/drm/i915/i915_params.c         |   5 +
>  drivers/gpu/drm/i915/i915_reg.h            |  96 +++
>  drivers/gpu/drm/i915/intel_ringbuffer.c    |   2 +
>  drivers/gpu/drm/i915/intel_ringbuffer.h    |  32 +
>  include/uapi/drm/i915_drm.h                |   1 +
>  11 files changed, 1216 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_cmd_parser.c
>
> -- 
> 1.8.3.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-20 14:43 ` Jani Nikula
@ 2014-03-25 13:15   ` Daniel Vetter
  2014-03-25 13:21     ` Jani Nikula
  2014-03-25 19:46     ` Volkin, Bradley D
  0 siblings, 2 replies; 37+ messages in thread
From: Daniel Vetter @ 2014-03-25 13:15 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Mar 20, 2014 at 04:43:05PM +0200, Jani Nikula wrote:
> 
> Hi Bradley -
> 
> Apologies for my procrastination with the review; I don't easily recall
> as tedious a review as the command and register tables. And I sure have
> reviewed a lot of miserable stuff in the past.
> 
> Most infuriatingly, I did not find a single real bug in the code!
> 
> I think we'll need to automate some things going forward, for example
> listing the non-conforming length encoding with Damien's tools for cross
> checking.
> 
> There are a few subtle points we need to discuss (separate mails
> internally) but all in all this series is:
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>

Ok, pulled this one in, thanks a lot for the patches&review. I think it's
time we start to move on with the next bits, the batch copy stuff seams
like a suitable piece. There's still issues with launching the entire
thing in the end, but we can start with the copy infrastructure.

Open issues I see still:

- The littel issue we're discussing internally. Like I've said that one is
  blocking us and needs to be resolved before we can switch to enforcing
  mode.

- Secure batch dispatch is still fubar.

- CodingStyle says: Functions should be a) at most 3 indent levels b) at
  most 3 ansi screens long (i.e. 75 lines). i915_parse_cmds violates both
  metrics pretty deftly. I think a few refactoring patches to extract
  helper functions and structure the flow a bit would be good.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-25 13:15   ` Daniel Vetter
@ 2014-03-25 13:21     ` Jani Nikula
  2014-03-25 19:46     ` Volkin, Bradley D
  1 sibling, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2014-03-25 13:21 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, 25 Mar 2014, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Thu, Mar 20, 2014 at 04:43:05PM +0200, Jani Nikula wrote:
>> 
>> Hi Bradley -
>> 
>> Apologies for my procrastination with the review; I don't easily recall
>> as tedious a review as the command and register tables. And I sure have
>> reviewed a lot of miserable stuff in the past.
>> 
>> Most infuriatingly, I did not find a single real bug in the code!
>> 
>> I think we'll need to automate some things going forward, for example
>> listing the non-conforming length encoding with Damien's tools for cross
>> checking.
>> 
>> There are a few subtle points we need to discuss (separate mails
>> internally) but all in all this series is:
>> 
>> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>
> Ok, pulled this one in, thanks a lot for the patches&review. I think it's
> time we start to move on with the next bits, the batch copy stuff seams
> like a suitable piece. There's still issues with launching the entire
> thing in the end, but we can start with the copy infrastructure.
>
> Open issues I see still:
>
> - The littel issue we're discussing internally. Like I've said that one is
>   blocking us and needs to be resolved before we can switch to enforcing
>   mode.
>
> - Secure batch dispatch is still fubar.
>
> - CodingStyle says: Functions should be a) at most 3 indent levels b) at
>   most 3 ansi screens long (i.e. 75 lines). i915_parse_cmds violates both
>   metrics pretty deftly. I think a few refactoring patches to extract
>   helper functions and structure the flow a bit would be good.

Just extracting the handlers for (desc->flags & CMD_DESC_REGISTER) and
(desc->flags & CMD_DESC_BITMASK) would go a long way.

BR,
Jani.




>
> Cheers, Daniel
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-25 13:15   ` Daniel Vetter
  2014-03-25 13:21     ` Jani Nikula
@ 2014-03-25 19:46     ` Volkin, Bradley D
  2014-03-25 19:53       ` Daniel Vetter
  1 sibling, 1 reply; 37+ messages in thread
From: Volkin, Bradley D @ 2014-03-25 19:46 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, Mar 25, 2014 at 06:15:36AM -0700, Daniel Vetter wrote:
> On Thu, Mar 20, 2014 at 04:43:05PM +0200, Jani Nikula wrote:
> > 
> > Hi Bradley -
> > 
> > Apologies for my procrastination with the review; I don't easily recall
> > as tedious a review as the command and register tables. And I sure have
> > reviewed a lot of miserable stuff in the past.
> > 
> > Most infuriatingly, I did not find a single real bug in the code!
> > 
> > I think we'll need to automate some things going forward, for example
> > listing the non-conforming length encoding with Damien's tools for cross
> > checking.
> > 
> > There are a few subtle points we need to discuss (separate mails
> > internally) but all in all this series is:
> > 
> > Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> Ok, pulled this one in, thanks a lot for the patches&review. I think it's
> time we start to move on with the next bits, the batch copy stuff seams
> like a suitable piece. There's still issues with launching the entire
> thing in the end, but we can start with the copy infrastructure.
> 
> Open issues I see still:
> 
> - The littel issue we're discussing internally. Like I've said that one is
>   blocking us and needs to be resolved before we can switch to enforcing
>   mode.
> 
> - Secure batch dispatch is still fubar.

I'm not sure that this will still impact us once we implement the batch copy
step. I was only using the secure dispatch stuff because it was a convenient
way to get the batch into GGTT. But with the copy step, we could just have
separate code to do that.

> 
> - CodingStyle says: Functions should be a) at most 3 indent levels b) at
>   most 3 ansi screens long (i.e. 75 lines). i915_parse_cmds violates both
>   metrics pretty deftly. I think a few refactoring patches to extract
>   helper functions and structure the flow a bit would be good.

:)

I'll start with a patch to move all of the actual checking logic into a
separate function, with maybe an extra helper for the bitmask checks. That
seems like it should cut the size down sufficiently.

Brad

> 
> Cheers, Daniel
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 00/13] Gen7 batch buffer command parser
  2014-03-25 19:46     ` Volkin, Bradley D
@ 2014-03-25 19:53       ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2014-03-25 19:53 UTC (permalink / raw)
  To: Volkin, Bradley D; +Cc: intel-gfx

On Tue, Mar 25, 2014 at 12:46:37PM -0700, Volkin, Bradley D wrote:
> On Tue, Mar 25, 2014 at 06:15:36AM -0700, Daniel Vetter wrote:
> > - Secure batch dispatch is still fubar.
> 
> I'm not sure that this will still impact us once we implement the batch copy
> step. I was only using the secure dispatch stuff because it was a convenient
> way to get the batch into GGTT. But with the copy step, we could just have
> separate code to do that.

The problem isn't copying or allocating the bo, the issue is running it
with
a) the hw checker disabled
b) not mapped into any ppgtt so hidden from all (unchecked) access and
c) otherwise working like a normal batch.

For that we need to employ the secure batch dispatch code in the execbuf
code. Atm b) is broken for aliasing ppgtt and c) is broken for full ppgtt.
So a bit of blockers for us. But at least broken b) with aliasing ppgtt is
kinda a regression, which means I'll get around to it soonish (before
3.15-rc1 at least).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 03/13] drm/i915: Initial command parser table definitions
  2014-01-29 21:55   ` [PATCH 03/13] drm/i915: Initial command parser table definitions bradley.d.volkin
@ 2014-02-05 14:22     ` Jani Nikula
  0 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2014-02-05 14:22 UTC (permalink / raw)
  To: bradley.d.volkin, intel-gfx


N.B. I'll likely make multiple passes on the patches while reviewing,
for example I did not check any of the #define values here.


On Wed, 29 Jan 2014, bradley.d.volkin@intel.com wrote:
> From: Brad Volkin <bradley.d.volkin@intel.com>
>
> Add command tables defining irregular length commands for each ring.
> This requires a few new command opcode definitions.
>
> OTC-Tracker: AXIA-4631
> Change-Id: I064bceb457e15f46928058352afe76d918c58ef5
> Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_cmd_parser.c | 157 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h        |  46 ++++++++++
>  2 files changed, 203 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
> index 7639dbc..2e27bad 100644
> --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> @@ -27,6 +27,148 @@
>  
>  #include "i915_drv.h"
>  
> +#define STD_MI_OPCODE_MASK  0xFF800000
> +#define STD_3D_OPCODE_MASK  0xFFFF0000
> +#define STD_2D_OPCODE_MASK  0xFFC00000
> +#define STD_MFX_OPCODE_MASK 0xFFFF0000
> +
> +#define CMD(op, opm, f, lm, fl, ...)		\
> +	{					\
> +		.flags = (fl) | (f),		\

Sparse gives me 

drivers/gpu/drm/i915/i915_cmd_parser.c:64:9: warning: dubious: x | !y

for the !F cases (bitwise OR with a logical NOT). I can see it's not a
bug here, but we want to keep those warnings down. Maybe just s/!F/0/ in
the tables? Or make the f argument to CMD a boolean, and make that

	.flags = (fl) | (f ? CMD_DESC_FIXED : 0),

> +		.cmd = { (op), (opm) }, 	\
> +		.length = { (lm) },		\
> +		__VA_ARGS__			\
> +	}
> +
> +/* Convenience macros to compress the tables */
> +#define SMI STD_MI_OPCODE_MASK
> +#define S3D STD_3D_OPCODE_MASK
> +#define S2D STD_2D_OPCODE_MASK
> +#define SMFX STD_MFX_OPCODE_MASK
> +#define F CMD_DESC_FIXED
> +#define S CMD_DESC_SKIP
> +#define R CMD_DESC_REJECT
> +#define W CMD_DESC_REGISTER
> +#define B CMD_DESC_BITMASK
> +#define M CMD_DESC_MASTER
> +
> +/*            Command                          Mask   Fixed Len   Action
> +	      ---------------------------------------------------------- */
> +static const struct drm_i915_cmd_descriptor common_cmds[] = {
> +	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
> +	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
> +	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      S  ),
> +	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
> +	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
> +	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
> +	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor render_cmds[] = {
> +	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
> +	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
> +	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
> +	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
> +	CMD(  PIPELINE_SELECT,                  S3D,    F,  1,      S  ),
> +	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
> +	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
> +	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
> +	CMD(  MI_SET_PREDICATE,                 SMI,    F,  1,      S  ),
> +	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
> +	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
> +	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_VS,  S3D,   !F,  0x7FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_PS,  S3D,   !F,  0x7FF,  S  ),
> +
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,  S3D,   !F,  0x1FF,  S  ),
> +	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,  S3D,   !F,  0x1FF,  S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor video_cmds[] = {
> +	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +	/*
> +	 * MFX_WAIT doesn't fit the way we handle length for most commands.
> +	 * It has a length field but it uses a non-standard length bias.
> +	 * It is always 1 dword though, so just treat it as fixed length.
> +	 */
> +	CMD(  MFX_WAIT,                         SMFX,   F,  1,      S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
> +	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
> +};
> +
> +static const struct drm_i915_cmd_descriptor blt_cmds[] = {
> +	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
> +	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
> +	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
> +	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
> +};
> +
> +#undef CMD
> +#undef SMI
> +#undef S3D
> +#undef S2D
> +#undef SMFX
> +#undef F
> +#undef S
> +#undef R
> +#undef W
> +#undef B
> +#undef M
> +
> +static const struct drm_i915_cmd_table gen7_render_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ render_cmds, ARRAY_SIZE(render_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table hsw_render_ring_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ render_cmds, ARRAY_SIZE(render_cmds) },
> +	{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table gen7_video_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ video_cmds, ARRAY_SIZE(video_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table hsw_vebox_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ vecs_cmds, ARRAY_SIZE(vecs_cmds) },
> +};
> +
> +static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
> +	{ common_cmds, ARRAY_SIZE(common_cmds) },
> +	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
> +};

A thought, if you added an end-of-array cell to all of these tables, I
think a lot of the initialization would be neater. If that seems like
too much trouble for too little gain, feel free to file this in the
bikeshedding bin.

> +
>  #define CLIENT_MASK      0xE0000000
>  #define SUBCLIENT_MASK   0x18000000
>  #define MI_CLIENT        0x00000000
> @@ -146,15 +288,30 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
>  
>  	switch (ring->id) {
>  	case RCS:
> +		if (IS_HASWELL(ring->dev)) {
> +			ring->cmd_tables = hsw_render_ring_cmds;
> +			ring->cmd_table_count =
> +				ARRAY_SIZE(hsw_render_ring_cmds);
> +		} else {
> +			ring->cmd_tables = gen7_render_cmds;
> +			ring->cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
> +		}
> +
>  		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
>  		break;
>  	case VCS:
> +		ring->cmd_tables = gen7_video_cmds;
> +		ring->cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
>  		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
>  		break;
>  	case BCS:
> +		ring->cmd_tables = gen7_blt_cmds;
> +		ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
>  		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
>  		break;
>  	case VECS:
> +		ring->cmd_tables = hsw_vebox_cmds;
> +		ring->cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
>  		/* VECS can use the same length_mask function as VCS */
>  		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
>  		break;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index cbbaf26..13ed6ed 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -336,6 +336,52 @@
>  #define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
>  #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
>  
> +/*
> + * Commands used only by the command parser
> + */
> +#define MI_SET_PREDICATE       MI_INSTR(0x01, 0)
> +#define MI_ARB_CHECK           MI_INSTR(0x05, 0)
> +#define MI_RS_CONTROL          MI_INSTR(0x06, 0)
> +#define MI_URB_ATOMIC_ALLOC    MI_INSTR(0x09, 0)
> +#define MI_PREDICATE           MI_INSTR(0x0C, 0)
> +#define MI_RS_CONTEXT          MI_INSTR(0x0F, 0)
> +#define MI_TOPOLOGY_FILTER     MI_INSTR(0x0D, 0)
> +#define MI_URB_CLEAR           MI_INSTR(0x19, 0)
> +#define MI_UPDATE_GTT          MI_INSTR(0x23, 0)
> +#define MI_CLFLUSH             MI_INSTR(0x27, 0)
> +#define MI_LOAD_REGISTER_MEM   MI_INSTR(0x29, 0)
> +#define MI_LOAD_REGISTER_REG   MI_INSTR(0x2A, 0)
> +#define MI_RS_STORE_DATA_IMM   MI_INSTR(0x2B, 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))
> +#define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
> +#define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
> +#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16))
> +#define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16))
> +#define GFX_OP_3DSTATE_SO_DECL_LIST \
> +	((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16))
> +
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16))
> +#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
> +	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))
> +
> +#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))
> +
> +#define COLOR_BLT     ((0x2<<29)|(0x40<<22))
> +#define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
>  
>  /*
>   * Reset registers
> -- 
> 1.8.5.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 03/13] drm/i915: Initial command parser table definitions
  2014-01-29 21:55 ` [PATCH 00/13] " bradley.d.volkin
@ 2014-01-29 21:55   ` bradley.d.volkin
  2014-02-05 14:22     ` Jani Nikula
  0 siblings, 1 reply; 37+ messages in thread
From: bradley.d.volkin @ 2014-01-29 21:55 UTC (permalink / raw)
  To: intel-gfx

From: Brad Volkin <bradley.d.volkin@intel.com>

Add command tables defining irregular length commands for each ring.
This requires a few new command opcode definitions.

OTC-Tracker: AXIA-4631
Change-Id: I064bceb457e15f46928058352afe76d918c58ef5
Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c | 157 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h        |  46 ++++++++++
 2 files changed, 203 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 7639dbc..2e27bad 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -27,6 +27,148 @@
 
 #include "i915_drv.h"
 
+#define STD_MI_OPCODE_MASK  0xFF800000
+#define STD_3D_OPCODE_MASK  0xFFFF0000
+#define STD_2D_OPCODE_MASK  0xFFC00000
+#define STD_MFX_OPCODE_MASK 0xFFFF0000
+
+#define CMD(op, opm, f, lm, fl, ...)		\
+	{					\
+		.flags = (fl) | (f),		\
+		.cmd = { (op), (opm) }, 	\
+		.length = { (lm) },		\
+		__VA_ARGS__			\
+	}
+
+/* Convenience macros to compress the tables */
+#define SMI STD_MI_OPCODE_MASK
+#define S3D STD_3D_OPCODE_MASK
+#define S2D STD_2D_OPCODE_MASK
+#define SMFX STD_MFX_OPCODE_MASK
+#define F CMD_DESC_FIXED
+#define S CMD_DESC_SKIP
+#define R CMD_DESC_REJECT
+#define W CMD_DESC_REGISTER
+#define B CMD_DESC_BITMASK
+#define M CMD_DESC_MASTER
+
+/*            Command                          Mask   Fixed Len   Action
+	      ---------------------------------------------------------- */
+static const struct drm_i915_cmd_descriptor common_cmds[] = {
+	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
+	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
+	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
+	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
+	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
+	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_REGISTER_MEM(1),         SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_REGISTER_MEM,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
+};
+
+static const struct drm_i915_cmd_descriptor render_cmds[] = {
+	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
+	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  S  ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
+	CMD(  PIPELINE_SELECT,                  S3D,    F,  1,      S  ),
+	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
+	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
+};
+
+static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
+	CMD(  MI_SET_PREDICATE,                 SMI,    F,  1,      S  ),
+	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
+	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
+	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
+	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
+	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_VS,  S3D,   !F,  0x7FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_PS,  S3D,   !F,  0x7FF,  S  ),
+
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,  S3D,   !F,  0x1FF,  S  ),
+	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,  S3D,   !F,  0x1FF,  S  ),
+};
+
+static const struct drm_i915_cmd_descriptor video_cmds[] = {
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+	/*
+	 * MFX_WAIT doesn't fit the way we handle length for most commands.
+	 * It has a length field but it uses a non-standard length bias.
+	 * It is always 1 dword though, so just treat it as fixed length.
+	 */
+	CMD(  MFX_WAIT,                         SMFX,   F,  1,      S  ),
+};
+
+static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
+	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   S  ),
+};
+
+static const struct drm_i915_cmd_descriptor blt_cmds[] = {
+	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   S  ),
+	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
+	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
+	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
+};
+
+#undef CMD
+#undef SMI
+#undef S3D
+#undef S2D
+#undef SMFX
+#undef F
+#undef S
+#undef R
+#undef W
+#undef B
+#undef M
+
+static const struct drm_i915_cmd_table gen7_render_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ render_cmds, ARRAY_SIZE(render_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_render_ring_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ render_cmds, ARRAY_SIZE(render_cmds) },
+	{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
+};
+
+static const struct drm_i915_cmd_table gen7_video_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ video_cmds, ARRAY_SIZE(video_cmds) },
+};
+
+static const struct drm_i915_cmd_table hsw_vebox_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ vecs_cmds, ARRAY_SIZE(vecs_cmds) },
+};
+
+static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
+	{ common_cmds, ARRAY_SIZE(common_cmds) },
+	{ blt_cmds, ARRAY_SIZE(blt_cmds) },
+};
+
 #define CLIENT_MASK      0xE0000000
 #define SUBCLIENT_MASK   0x18000000
 #define MI_CLIENT        0x00000000
@@ -146,15 +288,30 @@ void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 
 	switch (ring->id) {
 	case RCS:
+		if (IS_HASWELL(ring->dev)) {
+			ring->cmd_tables = hsw_render_ring_cmds;
+			ring->cmd_table_count =
+				ARRAY_SIZE(hsw_render_ring_cmds);
+		} else {
+			ring->cmd_tables = gen7_render_cmds;
+			ring->cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
+		}
+
 		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 		break;
 	case VCS:
+		ring->cmd_tables = gen7_video_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
 	case BCS:
+		ring->cmd_tables = gen7_blt_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
 		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
+		ring->cmd_tables = hsw_vebox_cmds;
+		ring->cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
 		/* VECS can use the same length_mask function as VCS */
 		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cbbaf26..13ed6ed 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -336,6 +336,52 @@
 #define   PIPE_CONTROL_DEPTH_CACHE_FLUSH		(1<<0)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
 
+/*
+ * Commands used only by the command parser
+ */
+#define MI_SET_PREDICATE       MI_INSTR(0x01, 0)
+#define MI_ARB_CHECK           MI_INSTR(0x05, 0)
+#define MI_RS_CONTROL          MI_INSTR(0x06, 0)
+#define MI_URB_ATOMIC_ALLOC    MI_INSTR(0x09, 0)
+#define MI_PREDICATE           MI_INSTR(0x0C, 0)
+#define MI_RS_CONTEXT          MI_INSTR(0x0F, 0)
+#define MI_TOPOLOGY_FILTER     MI_INSTR(0x0D, 0)
+#define MI_URB_CLEAR           MI_INSTR(0x19, 0)
+#define MI_UPDATE_GTT          MI_INSTR(0x23, 0)
+#define MI_CLFLUSH             MI_INSTR(0x27, 0)
+#define MI_LOAD_REGISTER_MEM   MI_INSTR(0x29, 0)
+#define MI_LOAD_REGISTER_REG   MI_INSTR(0x2A, 0)
+#define MI_RS_STORE_DATA_IMM   MI_INSTR(0x2B, 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))
+#define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
+#define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
+#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16))
+#define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16))
+#define GFX_OP_3DSTATE_SO_DECL_LIST \
+	((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16))
+
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16))
+#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
+	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))
+
+#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))
+
+#define COLOR_BLT     ((0x2<<29)|(0x40<<22))
+#define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))
 
 /*
  * Reset registers
-- 
1.8.5.2

^ permalink raw reply related	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2014-03-25 19:53 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-18 18:15 [PATCH 00/13] Gen7 batch buffer command parser bradley.d.volkin
2014-02-18 18:15 ` [PATCH 01/13] drm/i915: Refactor shmem pread setup bradley.d.volkin
2014-03-06 12:13   ` Jani Nikula
2014-02-18 18:15 ` [PATCH 02/13] drm/i915: Implement command buffer parsing logic bradley.d.volkin
2014-03-06 13:10   ` Jani Nikula
2014-03-06 21:07     ` Daniel Vetter
2014-03-20 12:40   ` Jani Nikula
2014-02-18 18:15 ` [PATCH 03/13] drm/i915: Initial command parser table definitions bradley.d.volkin
2014-03-06 13:12   ` Jani Nikula
2014-02-18 18:15 ` [PATCH 04/13] drm/i915: Reject privileged commands bradley.d.volkin
2014-02-18 18:15 ` [PATCH 05/13] drm/i915: Allow some privileged commands from master bradley.d.volkin
2014-02-18 18:15 ` [PATCH 06/13] drm/i915: Add register whitelists for mesa bradley.d.volkin
2014-02-18 18:15 ` [PATCH 07/13] drm/i915: Add register whitelist for DRM master bradley.d.volkin
2014-02-18 18:15 ` [PATCH 08/13] drm/i915: Enable register whitelist checks bradley.d.volkin
2014-02-18 18:15 ` [PATCH 09/13] drm/i915: Reject commands that explicitly generate interrupts bradley.d.volkin
2014-02-18 18:15 ` [PATCH 10/13] drm/i915: Enable PPGTT command parser checks bradley.d.volkin
2014-03-06 13:17   ` Jani Nikula
2014-03-06 21:32     ` Volkin, Bradley D
2014-03-06 21:58       ` Daniel Vetter
2014-03-06 22:13         ` Volkin, Bradley D
2014-02-18 18:15 ` [PATCH 11/13] drm/i915: Reject commands that would store to global HWS page bradley.d.volkin
2014-02-18 18:15 ` [PATCH 12/13] drm/i915: Add a CMD_PARSER_VERSION getparam bradley.d.volkin
2014-02-18 18:15 ` [PATCH 13/13] drm/i915: Enable command parsing by default bradley.d.volkin
2014-03-04 17:21 ` [PATCH 00/13] Gen7 batch buffer command parser Volkin, Bradley D
2014-03-05 10:46 ` Daniel Vetter
2014-03-05 16:59   ` Volkin, Bradley D
2014-03-05 17:14     ` Daniel Vetter
2014-03-05 17:45       ` Volkin, Bradley D
2014-03-11 12:41 ` Jani Nikula
2014-03-12 18:02   ` Volkin, Bradley D
2014-03-20 14:43 ` Jani Nikula
2014-03-25 13:15   ` Daniel Vetter
2014-03-25 13:21     ` Jani Nikula
2014-03-25 19:46     ` Volkin, Bradley D
2014-03-25 19:53       ` Daniel Vetter
  -- strict thread matches above, loose matches on Subject: below --
2013-11-26 16:51 [RFC 00/22] " bradley.d.volkin
2014-01-29 21:55 ` [PATCH 00/13] " bradley.d.volkin
2014-01-29 21:55   ` [PATCH 03/13] drm/i915: Initial command parser table definitions bradley.d.volkin
2014-02-05 14:22     ` Jani Nikula

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.