Home | History | Annotate | Line # | Download | only in i915
      1  1.28  riastrad /*	$NetBSD: i915_cmd_parser.c,v 1.28 2021/12/19 12:25:37 riastradh Exp $	*/
      2   1.5  riastrad 
      3   1.1  riastrad /*
      4   1.1  riastrad  * Copyright  2013 Intel Corporation
      5   1.1  riastrad  *
      6   1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      7   1.1  riastrad  * copy of this software and associated documentation files (the "Software"),
      8   1.1  riastrad  * to deal in the Software without restriction, including without limitation
      9   1.1  riastrad  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10   1.1  riastrad  * and/or sell copies of the Software, and to permit persons to whom the
     11   1.1  riastrad  * Software is furnished to do so, subject to the following conditions:
     12   1.1  riastrad  *
     13   1.1  riastrad  * The above copyright notice and this permission notice (including the next
     14   1.1  riastrad  * paragraph) shall be included in all copies or substantial portions of the
     15   1.1  riastrad  * Software.
     16   1.1  riastrad  *
     17   1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18   1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19   1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20   1.1  riastrad  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21   1.1  riastrad  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22   1.1  riastrad  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     23   1.1  riastrad  * IN THE SOFTWARE.
     24   1.1  riastrad  *
     25   1.1  riastrad  * Authors:
     26   1.1  riastrad  *    Brad Volkin <bradley.d.volkin (at) intel.com>
     27   1.1  riastrad  *
     28   1.1  riastrad  */
     29   1.1  riastrad 
     30   1.5  riastrad #include <sys/cdefs.h>
     31  1.28  riastrad __KERNEL_RCSID(0, "$NetBSD: i915_cmd_parser.c,v 1.28 2021/12/19 12:25:37 riastradh Exp $");
     32  1.27  riastrad 
     33  1.27  riastrad #include <linux/bitmap.h>
     34  1.23  riastrad 
     35  1.23  riastrad #include "gt/intel_engine.h"
     36   1.5  riastrad 
     37   1.1  riastrad #include "i915_drv.h"
     38  1.23  riastrad #include "i915_memcpy.h"
     39   1.1  riastrad 
     40   1.1  riastrad /**
     41   1.5  riastrad  * DOC: batch buffer command parser
     42   1.1  riastrad  *
     43   1.1  riastrad  * Motivation:
     44   1.1  riastrad  * Certain OpenGL features (e.g. transform feedback, performance monitoring)
     45   1.1  riastrad  * require userspace code to submit batches containing commands such as
     46   1.1  riastrad  * MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
     47   1.1  riastrad  * generations of the hardware will noop these commands in "unsecure" batches
     48   1.1  riastrad  * (which includes all userspace batches submitted via i915) even though the
     49   1.1  riastrad  * commands may be safe and represent the intended programming model of the
     50   1.1  riastrad  * device.
     51   1.1  riastrad  *
     52   1.1  riastrad  * The software command parser is similar in operation to the command parsing
     53   1.1  riastrad  * done in hardware for unsecure batches. However, the software parser allows
     54   1.1  riastrad  * some operations that would be noop'd by hardware, if the parser determines
     55   1.1  riastrad  * the operation is safe, and submits the batch as "secure" to prevent hardware
     56   1.1  riastrad  * parsing.
     57   1.1  riastrad  *
     58   1.1  riastrad  * Threats:
     59   1.1  riastrad  * At a high level, the hardware (and software) checks attempt to prevent
     60   1.1  riastrad  * granting userspace undue privileges. There are three categories of privilege.
     61   1.1  riastrad  *
     62   1.1  riastrad  * First, commands which are explicitly defined as privileged or which should
     63  1.19      maya  * only be used by the kernel driver. The parser rejects such commands
     64   1.1  riastrad  *
     65   1.1  riastrad  * Second, commands which access registers. To support correct/enhanced
     66   1.1  riastrad  * userspace functionality, particularly certain OpenGL extensions, the parser
     67  1.19      maya  * provides a whitelist of registers which userspace may safely access
     68   1.1  riastrad  *
     69   1.1  riastrad  * Third, commands which access privileged memory (i.e. GGTT, HWS page, etc).
     70   1.1  riastrad  * The parser always rejects such commands.
     71   1.1  riastrad  *
     72   1.1  riastrad  * The majority of the problematic commands fall in the MI_* range, with only a
     73  1.23  riastrad  * few specific commands on each engine (e.g. PIPE_CONTROL and MI_FLUSH_DW).
     74   1.1  riastrad  *
     75   1.1  riastrad  * Implementation:
     76  1.23  riastrad  * Each engine maintains tables of commands and registers which the parser
     77  1.23  riastrad  * uses in scanning batch buffers submitted to that engine.
     78   1.1  riastrad  *
     79   1.1  riastrad  * Since the set of commands that the parser must check for is significantly
     80   1.1  riastrad  * smaller than the number of commands supported, the parser tables contain only
     81   1.1  riastrad  * those commands required by the parser. This generally works because command
     82   1.1  riastrad  * opcode ranges have standard command length encodings. So for commands that
     83   1.1  riastrad  * the parser does not need to check, it can easily skip them. This is
     84  1.23  riastrad  * implemented via a per-engine length decoding vfunc.
     85   1.1  riastrad  *
     86   1.1  riastrad  * Unfortunately, there are a number of commands that do not follow the standard
     87   1.1  riastrad  * length encoding for their opcode range, primarily amongst the MI_* commands.
     88   1.1  riastrad  * To handle this, the parser provides a way to define explicit "skip" entries
     89  1.23  riastrad  * in the per-engine command tables.
     90   1.1  riastrad  *
     91   1.1  riastrad  * Other command table entries map fairly directly to high level categories
     92  1.19      maya  * mentioned above: rejected, register whitelist. The parser implements a number
     93  1.19      maya  * of checks, including the privileged memory checks, via a general bitmasking
     94  1.19      maya  * mechanism.
     95   1.1  riastrad  */
     96   1.1  riastrad 
     97  1.23  riastrad /*
     98  1.23  riastrad  * A command that requires special handling by the command parser.
     99  1.23  riastrad  */
    100  1.23  riastrad struct drm_i915_cmd_descriptor {
    101  1.23  riastrad 	/*
    102  1.23  riastrad 	 * Flags describing how the command parser processes the command.
    103  1.23  riastrad 	 *
    104  1.23  riastrad 	 * CMD_DESC_FIXED: The command has a fixed length if this is set,
    105  1.23  riastrad 	 *                 a length mask if not set
    106  1.23  riastrad 	 * CMD_DESC_SKIP: The command is allowed but does not follow the
    107  1.23  riastrad 	 *                standard length encoding for the opcode range in
    108  1.23  riastrad 	 *                which it falls
    109  1.23  riastrad 	 * CMD_DESC_REJECT: The command is never allowed
    110  1.23  riastrad 	 * CMD_DESC_REGISTER: The command should be checked against the
    111  1.23  riastrad 	 *                    register whitelist for the appropriate ring
    112  1.23  riastrad 	 */
    113  1.23  riastrad 	u32 flags;
    114  1.23  riastrad #define CMD_DESC_FIXED    (1<<0)
    115  1.23  riastrad #define CMD_DESC_SKIP     (1<<1)
    116  1.23  riastrad #define CMD_DESC_REJECT   (1<<2)
    117  1.23  riastrad #define CMD_DESC_REGISTER (1<<3)
    118  1.23  riastrad #define CMD_DESC_BITMASK  (1<<4)
    119  1.23  riastrad 
    120  1.23  riastrad 	/*
    121  1.23  riastrad 	 * The command's unique identification bits and the bitmask to get them.
    122  1.23  riastrad 	 * This isn't strictly the opcode field as defined in the spec and may
    123  1.23  riastrad 	 * also include type, subtype, and/or subop fields.
    124  1.23  riastrad 	 */
    125  1.23  riastrad 	struct {
    126  1.23  riastrad 		u32 value;
    127  1.23  riastrad 		u32 mask;
    128  1.23  riastrad 	} cmd;
    129  1.23  riastrad 
    130  1.23  riastrad 	/*
    131  1.23  riastrad 	 * The command's length. The command is either fixed length (i.e. does
    132  1.23  riastrad 	 * not include a length field) or has a length field mask. The flag
    133  1.23  riastrad 	 * CMD_DESC_FIXED indicates a fixed length. Otherwise, the command has
    134  1.23  riastrad 	 * a length mask. All command entries in a command table must include
    135  1.23  riastrad 	 * length information.
    136  1.23  riastrad 	 */
    137  1.23  riastrad 	union {
    138  1.23  riastrad 		u32 fixed;
    139  1.23  riastrad 		u32 mask;
    140  1.23  riastrad 	} length;
    141  1.23  riastrad 
    142  1.23  riastrad 	/*
    143  1.23  riastrad 	 * Describes where to find a register address in the command to check
    144  1.23  riastrad 	 * against the ring's register whitelist. Only valid if flags has the
    145  1.23  riastrad 	 * CMD_DESC_REGISTER bit set.
    146  1.23  riastrad 	 *
    147  1.23  riastrad 	 * A non-zero step value implies that the command may access multiple
    148  1.23  riastrad 	 * registers in sequence (e.g. LRI), in that case step gives the
    149  1.23  riastrad 	 * distance in dwords between individual offset fields.
    150  1.23  riastrad 	 */
    151  1.23  riastrad 	struct {
    152  1.23  riastrad 		u32 offset;
    153  1.23  riastrad 		u32 mask;
    154  1.23  riastrad 		u32 step;
    155  1.23  riastrad 	} reg;
    156  1.23  riastrad 
    157  1.23  riastrad #define MAX_CMD_DESC_BITMASKS 3
    158  1.23  riastrad 	/*
    159  1.23  riastrad 	 * Describes command checks where a particular dword is masked and
    160  1.23  riastrad 	 * compared against an expected value. If the command does not match
    161  1.23  riastrad 	 * the expected value, the parser rejects it. Only valid if flags has
    162  1.23  riastrad 	 * the CMD_DESC_BITMASK bit set. Only entries where mask is non-zero
    163  1.23  riastrad 	 * are valid.
    164  1.23  riastrad 	 *
    165  1.23  riastrad 	 * If the check specifies a non-zero condition_mask then the parser
    166  1.23  riastrad 	 * only performs the check when the bits specified by condition_mask
    167  1.23  riastrad 	 * are non-zero.
    168  1.23  riastrad 	 */
    169  1.23  riastrad 	struct {
    170  1.23  riastrad 		u32 offset;
    171  1.23  riastrad 		u32 mask;
    172  1.23  riastrad 		u32 expected;
    173  1.23  riastrad 		u32 condition_offset;
    174  1.23  riastrad 		u32 condition_mask;
    175  1.23  riastrad 	} bits[MAX_CMD_DESC_BITMASKS];
    176  1.23  riastrad };
    177  1.23  riastrad 
    178  1.23  riastrad /*
    179  1.23  riastrad  * A table of commands requiring special handling by the command parser.
    180  1.23  riastrad  *
    181  1.23  riastrad  * Each engine has an array of tables. Each table consists of an array of
    182  1.23  riastrad  * command descriptors, which must be sorted with command opcodes in
    183  1.23  riastrad  * ascending order.
    184  1.23  riastrad  */
    185  1.23  riastrad struct drm_i915_cmd_table {
    186  1.23  riastrad 	const struct drm_i915_cmd_descriptor *table;
    187  1.23  riastrad 	int count;
    188  1.23  riastrad };
    189  1.23  riastrad 
    190  1.23  riastrad #define STD_MI_OPCODE_SHIFT  (32 - 9)
    191  1.23  riastrad #define STD_3D_OPCODE_SHIFT  (32 - 16)
    192  1.23  riastrad #define STD_2D_OPCODE_SHIFT  (32 - 10)
    193  1.23  riastrad #define STD_MFX_OPCODE_SHIFT (32 - 16)
    194  1.23  riastrad #define MIN_OPCODE_SHIFT 16
    195   1.5  riastrad 
    196   1.5  riastrad #define CMD(op, opm, f, lm, fl, ...)				\
    197   1.5  riastrad 	{							\
    198   1.5  riastrad 		.flags = (fl) | ((f) ? CMD_DESC_FIXED : 0),	\
    199  1.23  riastrad 		.cmd = { (op & ~0u << (opm)), ~0u << (opm) },	\
    200   1.5  riastrad 		.length = { (lm) },				\
    201   1.5  riastrad 		__VA_ARGS__					\
    202   1.5  riastrad 	}
    203   1.5  riastrad 
    204   1.5  riastrad /* Convenience macros to compress the tables */
    205  1.23  riastrad #define SMI STD_MI_OPCODE_SHIFT
    206  1.23  riastrad #define S3D STD_3D_OPCODE_SHIFT
    207  1.23  riastrad #define S2D STD_2D_OPCODE_SHIFT
    208  1.23  riastrad #define SMFX STD_MFX_OPCODE_SHIFT
    209   1.5  riastrad #define F true
    210   1.5  riastrad #define S CMD_DESC_SKIP
    211   1.5  riastrad #define R CMD_DESC_REJECT
    212   1.5  riastrad #define W CMD_DESC_REGISTER
    213   1.5  riastrad #define B CMD_DESC_BITMASK
    214   1.5  riastrad 
    215   1.5  riastrad /*            Command                          Mask   Fixed Len   Action
    216   1.5  riastrad 	      ---------------------------------------------------------- */
    217  1.19      maya static const struct drm_i915_cmd_descriptor gen7_common_cmds[] = {
    218   1.5  riastrad 	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
    219   1.5  riastrad 	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      R  ),
    220  1.19      maya 	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      R  ),
    221   1.5  riastrad 	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
    222   1.5  riastrad 	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
    223   1.5  riastrad 	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
    224   1.5  riastrad 	CMD(  MI_SEMAPHORE_MBOX,                SMI,   !F,  0xFF,   R  ),
    225   1.5  riastrad 	CMD(  MI_STORE_DWORD_INDEX,             SMI,   !F,  0xFF,   R  ),
    226   1.5  riastrad 	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   W,
    227   1.5  riastrad 	      .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 }    ),
    228   1.5  riastrad 	CMD(  MI_STORE_REGISTER_MEM,            SMI,    F,  3,     W | B,
    229   1.5  riastrad 	      .reg = { .offset = 1, .mask = 0x007FFFFC },
    230   1.5  riastrad 	      .bits = {{
    231   1.5  riastrad 			.offset = 0,
    232   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    233   1.5  riastrad 			.expected = 0,
    234   1.5  riastrad 	      }},						       ),
    235   1.5  riastrad 	CMD(  MI_LOAD_REGISTER_MEM,             SMI,    F,  3,     W | B,
    236   1.5  riastrad 	      .reg = { .offset = 1, .mask = 0x007FFFFC },
    237   1.5  riastrad 	      .bits = {{
    238   1.5  riastrad 			.offset = 0,
    239   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    240   1.5  riastrad 			.expected = 0,
    241   1.5  riastrad 	      }},						       ),
    242   1.5  riastrad 	/*
    243   1.5  riastrad 	 * MI_BATCH_BUFFER_START requires some special handling. It's not
    244   1.5  riastrad 	 * really a 'skip' action but it doesn't seem like it's worth adding
    245  1.23  riastrad 	 * a new action. See intel_engine_cmd_parser().
    246   1.5  riastrad 	 */
    247   1.5  riastrad 	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ),
    248   1.5  riastrad };
    249   1.5  riastrad 
    250  1.19      maya static const struct drm_i915_cmd_descriptor gen7_render_cmds[] = {
    251   1.5  riastrad 	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
    252   1.5  riastrad 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
    253   1.5  riastrad 	CMD(  MI_PREDICATE,                     SMI,    F,  1,      S  ),
    254   1.5  riastrad 	CMD(  MI_TOPOLOGY_FILTER,               SMI,    F,  1,      S  ),
    255   1.5  riastrad 	CMD(  MI_SET_APPID,                     SMI,    F,  1,      S  ),
    256   1.5  riastrad 	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
    257   1.5  riastrad 	CMD(  MI_SET_CONTEXT,                   SMI,   !F,  0xFF,   R  ),
    258   1.5  riastrad 	CMD(  MI_URB_CLEAR,                     SMI,   !F,  0xFF,   S  ),
    259   1.5  riastrad 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3F,   B,
    260   1.5  riastrad 	      .bits = {{
    261   1.5  riastrad 			.offset = 0,
    262   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    263   1.5  riastrad 			.expected = 0,
    264   1.5  riastrad 	      }},						       ),
    265   1.5  riastrad 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0xFF,   R  ),
    266   1.5  riastrad 	CMD(  MI_CLFLUSH,                       SMI,   !F,  0x3FF,  B,
    267   1.5  riastrad 	      .bits = {{
    268   1.5  riastrad 			.offset = 0,
    269   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    270   1.5  riastrad 			.expected = 0,
    271   1.5  riastrad 	      }},						       ),
    272   1.5  riastrad 	CMD(  MI_REPORT_PERF_COUNT,             SMI,   !F,  0x3F,   B,
    273   1.5  riastrad 	      .bits = {{
    274   1.5  riastrad 			.offset = 1,
    275   1.5  riastrad 			.mask = MI_REPORT_PERF_COUNT_GGTT,
    276   1.5  riastrad 			.expected = 0,
    277   1.5  riastrad 	      }},						       ),
    278   1.5  riastrad 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
    279   1.5  riastrad 	      .bits = {{
    280   1.5  riastrad 			.offset = 0,
    281   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    282   1.5  riastrad 			.expected = 0,
    283   1.5  riastrad 	      }},						       ),
    284   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_VF_STATISTICS,     S3D,    F,  1,      S  ),
    285   1.5  riastrad 	CMD(  PIPELINE_SELECT,                  S3D,    F,  1,      S  ),
    286   1.5  riastrad 	CMD(  MEDIA_VFE_STATE,			S3D,   !F,  0xFFFF, B,
    287   1.5  riastrad 	      .bits = {{
    288   1.5  riastrad 			.offset = 2,
    289   1.5  riastrad 			.mask = MEDIA_VFE_STATE_MMIO_ACCESS_MASK,
    290   1.5  riastrad 			.expected = 0,
    291   1.5  riastrad 	      }},						       ),
    292   1.5  riastrad 	CMD(  GPGPU_OBJECT,                     S3D,   !F,  0xFF,   S  ),
    293   1.5  riastrad 	CMD(  GPGPU_WALKER,                     S3D,   !F,  0xFF,   S  ),
    294   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_SO_DECL_LIST,      S3D,   !F,  0x1FF,  S  ),
    295   1.5  riastrad 	CMD(  GFX_OP_PIPE_CONTROL(5),           S3D,   !F,  0xFF,   B,
    296   1.5  riastrad 	      .bits = {{
    297   1.5  riastrad 			.offset = 1,
    298   1.5  riastrad 			.mask = (PIPE_CONTROL_MMIO_WRITE | PIPE_CONTROL_NOTIFY),
    299   1.5  riastrad 			.expected = 0,
    300   1.5  riastrad 	      },
    301   1.5  riastrad 	      {
    302   1.5  riastrad 			.offset = 1,
    303   1.5  riastrad 		        .mask = (PIPE_CONTROL_GLOBAL_GTT_IVB |
    304   1.5  riastrad 				 PIPE_CONTROL_STORE_DATA_INDEX),
    305   1.5  riastrad 			.expected = 0,
    306   1.5  riastrad 			.condition_offset = 1,
    307   1.5  riastrad 			.condition_mask = PIPE_CONTROL_POST_SYNC_OP_MASK,
    308   1.5  riastrad 	      }},						       ),
    309   1.5  riastrad };
    310   1.5  riastrad 
    311   1.5  riastrad static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = {
    312   1.5  riastrad 	CMD(  MI_SET_PREDICATE,                 SMI,    F,  1,      S  ),
    313   1.5  riastrad 	CMD(  MI_RS_CONTROL,                    SMI,    F,  1,      S  ),
    314   1.5  riastrad 	CMD(  MI_URB_ATOMIC_ALLOC,              SMI,    F,  1,      S  ),
    315   1.5  riastrad 	CMD(  MI_SET_APPID,                     SMI,    F,  1,      S  ),
    316   1.5  riastrad 	CMD(  MI_RS_CONTEXT,                    SMI,    F,  1,      S  ),
    317  1.19      maya 	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   R  ),
    318   1.5  riastrad 	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
    319  1.23  riastrad 	CMD(  MI_LOAD_REGISTER_REG,             SMI,   !F,  0xFF,   W,
    320  1.23  riastrad 	      .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 }    ),
    321   1.5  riastrad 	CMD(  MI_RS_STORE_DATA_IMM,             SMI,   !F,  0xFF,   S  ),
    322   1.5  riastrad 	CMD(  MI_LOAD_URB_MEM,                  SMI,   !F,  0xFF,   S  ),
    323   1.5  riastrad 	CMD(  MI_STORE_URB_MEM,                 SMI,   !F,  0xFF,   S  ),
    324   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_VS,  S3D,   !F,  0x7FF,  S  ),
    325   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_DX9_CONSTANTF_PS,  S3D,   !F,  0x7FF,  S  ),
    326   1.5  riastrad 
    327   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,  S3D,   !F,  0x1FF,  S  ),
    328   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,  S3D,   !F,  0x1FF,  S  ),
    329   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,  S3D,   !F,  0x1FF,  S  ),
    330   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,  S3D,   !F,  0x1FF,  S  ),
    331   1.5  riastrad 	CMD(  GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,  S3D,   !F,  0x1FF,  S  ),
    332   1.5  riastrad };
    333   1.5  riastrad 
    334  1.19      maya static const struct drm_i915_cmd_descriptor gen7_video_cmds[] = {
    335   1.5  riastrad 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
    336   1.5  riastrad 	CMD(  MI_SET_APPID,                     SMI,    F,  1,      S  ),
    337   1.5  riastrad 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
    338   1.5  riastrad 	      .bits = {{
    339   1.5  riastrad 			.offset = 0,
    340   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    341   1.5  riastrad 			.expected = 0,
    342   1.5  riastrad 	      }},						       ),
    343   1.5  riastrad 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
    344   1.5  riastrad 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
    345   1.5  riastrad 	      .bits = {{
    346   1.5  riastrad 			.offset = 0,
    347   1.5  riastrad 			.mask = MI_FLUSH_DW_NOTIFY,
    348   1.5  riastrad 			.expected = 0,
    349   1.5  riastrad 	      },
    350   1.5  riastrad 	      {
    351   1.5  riastrad 			.offset = 1,
    352   1.5  riastrad 			.mask = MI_FLUSH_DW_USE_GTT,
    353   1.5  riastrad 			.expected = 0,
    354   1.5  riastrad 			.condition_offset = 0,
    355   1.5  riastrad 			.condition_mask = MI_FLUSH_DW_OP_MASK,
    356   1.5  riastrad 	      },
    357   1.5  riastrad 	      {
    358   1.5  riastrad 			.offset = 0,
    359   1.5  riastrad 			.mask = MI_FLUSH_DW_STORE_INDEX,
    360   1.5  riastrad 			.expected = 0,
    361   1.5  riastrad 			.condition_offset = 0,
    362   1.5  riastrad 			.condition_mask = MI_FLUSH_DW_OP_MASK,
    363   1.5  riastrad 	      }},						       ),
    364   1.5  riastrad 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
    365   1.5  riastrad 	      .bits = {{
    366   1.5  riastrad 			.offset = 0,
    367   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    368   1.5  riastrad 			.expected = 0,
    369   1.5  riastrad 	      }},						       ),
    370   1.5  riastrad 	/*
    371   1.5  riastrad 	 * MFX_WAIT doesn't fit the way we handle length for most commands.
    372   1.5  riastrad 	 * It has a length field but it uses a non-standard length bias.
    373   1.5  riastrad 	 * It is always 1 dword though, so just treat it as fixed length.
    374   1.5  riastrad 	 */
    375   1.5  riastrad 	CMD(  MFX_WAIT,                         SMFX,   F,  1,      S  ),
    376   1.5  riastrad };
    377   1.5  riastrad 
    378  1.19      maya static const struct drm_i915_cmd_descriptor gen7_vecs_cmds[] = {
    379   1.5  riastrad 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      R  ),
    380   1.5  riastrad 	CMD(  MI_SET_APPID,                     SMI,    F,  1,      S  ),
    381   1.5  riastrad 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0xFF,   B,
    382   1.5  riastrad 	      .bits = {{
    383   1.5  riastrad 			.offset = 0,
    384   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    385   1.5  riastrad 			.expected = 0,
    386   1.5  riastrad 	      }},						       ),
    387   1.5  riastrad 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
    388   1.5  riastrad 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
    389   1.5  riastrad 	      .bits = {{
    390   1.5  riastrad 			.offset = 0,
    391   1.5  riastrad 			.mask = MI_FLUSH_DW_NOTIFY,
    392   1.5  riastrad 			.expected = 0,
    393   1.5  riastrad 	      },
    394   1.5  riastrad 	      {
    395   1.5  riastrad 			.offset = 1,
    396   1.5  riastrad 			.mask = MI_FLUSH_DW_USE_GTT,
    397   1.5  riastrad 			.expected = 0,
    398   1.5  riastrad 			.condition_offset = 0,
    399   1.5  riastrad 			.condition_mask = MI_FLUSH_DW_OP_MASK,
    400   1.5  riastrad 	      },
    401   1.5  riastrad 	      {
    402   1.5  riastrad 			.offset = 0,
    403   1.5  riastrad 			.mask = MI_FLUSH_DW_STORE_INDEX,
    404   1.5  riastrad 			.expected = 0,
    405   1.5  riastrad 			.condition_offset = 0,
    406   1.5  riastrad 			.condition_mask = MI_FLUSH_DW_OP_MASK,
    407   1.5  riastrad 	      }},						       ),
    408   1.5  riastrad 	CMD(  MI_CONDITIONAL_BATCH_BUFFER_END,  SMI,   !F,  0xFF,   B,
    409   1.5  riastrad 	      .bits = {{
    410   1.5  riastrad 			.offset = 0,
    411   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    412   1.5  riastrad 			.expected = 0,
    413   1.5  riastrad 	      }},						       ),
    414   1.5  riastrad };
    415   1.5  riastrad 
    416  1.19      maya static const struct drm_i915_cmd_descriptor gen7_blt_cmds[] = {
    417   1.5  riastrad 	CMD(  MI_DISPLAY_FLIP,                  SMI,   !F,  0xFF,   R  ),
    418   1.5  riastrad 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  B,
    419   1.5  riastrad 	      .bits = {{
    420   1.5  riastrad 			.offset = 0,
    421   1.5  riastrad 			.mask = MI_GLOBAL_GTT,
    422   1.5  riastrad 			.expected = 0,
    423   1.5  riastrad 	      }},						       ),
    424   1.5  riastrad 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3F,   R  ),
    425   1.5  riastrad 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   B,
    426   1.5  riastrad 	      .bits = {{
    427   1.5  riastrad 			.offset = 0,
    428   1.5  riastrad 			.mask = MI_FLUSH_DW_NOTIFY,
    429   1.5  riastrad 			.expected = 0,
    430   1.5  riastrad 	      },
    431   1.5  riastrad 	      {
    432   1.5  riastrad 			.offset = 1,
    433   1.5  riastrad 			.mask = MI_FLUSH_DW_USE_GTT,
    434   1.5  riastrad 			.expected = 0,
    435   1.5  riastrad 			.condition_offset = 0,
    436   1.5  riastrad 			.condition_mask = MI_FLUSH_DW_OP_MASK,
    437   1.5  riastrad 	      },
    438   1.5  riastrad 	      {
    439   1.5  riastrad 			.offset = 0,
    440   1.5  riastrad 			.mask = MI_FLUSH_DW_STORE_INDEX,
    441   1.5  riastrad 			.expected = 0,
    442   1.5  riastrad 			.condition_offset = 0,
    443   1.5  riastrad 			.condition_mask = MI_FLUSH_DW_OP_MASK,
    444   1.5  riastrad 	      }},						       ),
    445   1.5  riastrad 	CMD(  COLOR_BLT,                        S2D,   !F,  0x3F,   S  ),
    446   1.5  riastrad 	CMD(  SRC_COPY_BLT,                     S2D,   !F,  0x3F,   S  ),
    447   1.5  riastrad };
    448   1.5  riastrad 
    449   1.5  riastrad static const struct drm_i915_cmd_descriptor hsw_blt_cmds[] = {
    450  1.19      maya 	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   R  ),
    451   1.5  riastrad 	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   R  ),
    452   1.5  riastrad };
    453   1.5  riastrad 
    454  1.19      maya /*
    455  1.19      maya  * For Gen9 we can still rely on the h/w to enforce cmd security, and only
    456  1.19      maya  * need to re-enforce the register access checks. We therefore only need to
    457  1.19      maya  * teach the cmdparser how to find the end of each command, and identify
    458  1.19      maya  * register accesses. The table doesn't need to reject any commands, and so
    459  1.19      maya  * the only commands listed here are:
    460  1.19      maya  *   1) Those that touch registers
    461  1.19      maya  *   2) Those that do not have the default 8-bit length
    462  1.19      maya  *
    463  1.19      maya  * Note that the default MI length mask chosen for this table is 0xFF, not
    464  1.19      maya  * the 0x3F used on older devices. This is because the vast majority of MI
    465  1.19      maya  * cmds on Gen9 use a standard 8-bit Length field.
    466  1.19      maya  * All the Gen9 blitter instructions are standard 0xFF length mask, and
    467  1.19      maya  * none allow access to non-general registers, so in fact no BLT cmds are
    468  1.19      maya  * included in the table at all.
    469  1.19      maya  *
    470  1.19      maya  */
    471  1.19      maya static const struct drm_i915_cmd_descriptor gen9_blt_cmds[] = {
    472  1.19      maya 	CMD(  MI_NOOP,                          SMI,    F,  1,      S  ),
    473  1.19      maya 	CMD(  MI_USER_INTERRUPT,                SMI,    F,  1,      S  ),
    474  1.19      maya 	CMD(  MI_WAIT_FOR_EVENT,                SMI,    F,  1,      S  ),
    475  1.19      maya 	CMD(  MI_FLUSH,                         SMI,    F,  1,      S  ),
    476  1.19      maya 	CMD(  MI_ARB_CHECK,                     SMI,    F,  1,      S  ),
    477  1.19      maya 	CMD(  MI_REPORT_HEAD,                   SMI,    F,  1,      S  ),
    478  1.19      maya 	CMD(  MI_ARB_ON_OFF,                    SMI,    F,  1,      S  ),
    479  1.19      maya 	CMD(  MI_SUSPEND_FLUSH,                 SMI,    F,  1,      S  ),
    480  1.19      maya 	CMD(  MI_LOAD_SCAN_LINES_INCL,          SMI,   !F,  0x3F,   S  ),
    481  1.19      maya 	CMD(  MI_LOAD_SCAN_LINES_EXCL,          SMI,   !F,  0x3F,   S  ),
    482  1.19      maya 	CMD(  MI_STORE_DWORD_IMM,               SMI,   !F,  0x3FF,  S  ),
    483  1.19      maya 	CMD(  MI_LOAD_REGISTER_IMM(1),          SMI,   !F,  0xFF,   W,
    484  1.19      maya 	      .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 }    ),
    485  1.19      maya 	CMD(  MI_UPDATE_GTT,                    SMI,   !F,  0x3FF,  S  ),
    486  1.19      maya 	CMD(  MI_STORE_REGISTER_MEM_GEN8,       SMI,    F,  4,      W,
    487  1.19      maya 	      .reg = { .offset = 1, .mask = 0x007FFFFC }               ),
    488  1.19      maya 	CMD(  MI_FLUSH_DW,                      SMI,   !F,  0x3F,   S  ),
    489  1.19      maya 	CMD(  MI_LOAD_REGISTER_MEM_GEN8,        SMI,    F,  4,      W,
    490  1.19      maya 	      .reg = { .offset = 1, .mask = 0x007FFFFC }               ),
    491  1.19      maya 	CMD(  MI_LOAD_REGISTER_REG,             SMI,    !F,  0xFF,  W,
    492  1.19      maya 	      .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 }    ),
    493  1.19      maya 
    494  1.19      maya 	/*
    495  1.19      maya 	 * We allow BB_START but apply further checks. We just sanitize the
    496  1.19      maya 	 * basic fields here.
    497  1.19      maya 	 */
    498  1.23  riastrad #define MI_BB_START_OPERAND_MASK   GENMASK(SMI-1, 0)
    499  1.23  riastrad #define MI_BB_START_OPERAND_EXPECT (MI_BATCH_PPGTT_HSW | 1)
    500  1.23  riastrad 	CMD(  MI_BATCH_BUFFER_START_GEN8,       SMI,    !F,  0xFF,  B,
    501  1.23  riastrad 	      .bits = {{
    502  1.19      maya 			.offset = 0,
    503  1.23  riastrad 			.mask = MI_BB_START_OPERAND_MASK,
    504  1.23  riastrad 			.expected = MI_BB_START_OPERAND_EXPECT,
    505  1.23  riastrad 	      }},						       ),
    506  1.19      maya };
    507  1.19      maya 
    508  1.23  riastrad static const struct drm_i915_cmd_descriptor noop_desc =
    509  1.23  riastrad 	CMD(MI_NOOP, SMI, F, 1, S);
    510  1.23  riastrad 
    511   1.5  riastrad #undef CMD
    512   1.5  riastrad #undef SMI
    513   1.5  riastrad #undef S3D
    514   1.5  riastrad #undef S2D
    515   1.5  riastrad #undef SMFX
    516   1.5  riastrad #undef F
    517   1.5  riastrad #undef S
    518   1.5  riastrad #undef R
    519   1.5  riastrad #undef W
    520   1.5  riastrad #undef B
    521   1.5  riastrad 
    522  1.19      maya static const struct drm_i915_cmd_table gen7_render_cmd_table[] = {
    523  1.19      maya 	{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
    524  1.19      maya 	{ gen7_render_cmds, ARRAY_SIZE(gen7_render_cmds) },
    525   1.5  riastrad };
    526   1.5  riastrad 
    527  1.19      maya static const struct drm_i915_cmd_table hsw_render_ring_cmd_table[] = {
    528  1.19      maya 	{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
    529  1.19      maya 	{ gen7_render_cmds, ARRAY_SIZE(gen7_render_cmds) },
    530   1.5  riastrad 	{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
    531   1.5  riastrad };
    532   1.5  riastrad 
    533  1.19      maya static const struct drm_i915_cmd_table gen7_video_cmd_table[] = {
    534  1.19      maya 	{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
    535  1.19      maya 	{ gen7_video_cmds, ARRAY_SIZE(gen7_video_cmds) },
    536   1.5  riastrad };
    537   1.5  riastrad 
    538  1.19      maya static const struct drm_i915_cmd_table hsw_vebox_cmd_table[] = {
    539  1.19      maya 	{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
    540  1.19      maya 	{ gen7_vecs_cmds, ARRAY_SIZE(gen7_vecs_cmds) },
    541   1.5  riastrad };
    542   1.5  riastrad 
    543  1.19      maya static const struct drm_i915_cmd_table gen7_blt_cmd_table[] = {
    544  1.19      maya 	{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
    545  1.19      maya 	{ gen7_blt_cmds, ARRAY_SIZE(gen7_blt_cmds) },
    546   1.5  riastrad };
    547   1.5  riastrad 
    548  1.19      maya static const struct drm_i915_cmd_table hsw_blt_ring_cmd_table[] = {
    549  1.19      maya 	{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
    550  1.19      maya 	{ gen7_blt_cmds, ARRAY_SIZE(gen7_blt_cmds) },
    551   1.5  riastrad 	{ hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) },
    552   1.5  riastrad };
    553   1.5  riastrad 
    554  1.19      maya static const struct drm_i915_cmd_table gen9_blt_cmd_table[] = {
    555  1.19      maya 	{ gen9_blt_cmds, ARRAY_SIZE(gen9_blt_cmds) },
    556  1.19      maya };
    557  1.19      maya 
    558  1.19      maya 
    559   1.5  riastrad /*
    560   1.5  riastrad  * Register whitelists, sorted by increasing register offset.
    561   1.5  riastrad  */
    562   1.5  riastrad 
    563   1.5  riastrad /*
    564   1.5  riastrad  * An individual whitelist entry granting access to register addr.  If
    565   1.5  riastrad  * mask is non-zero the argument of immediate register writes will be
    566   1.5  riastrad  * AND-ed with mask, and the command will be rejected if the result
    567   1.5  riastrad  * doesn't match value.
    568   1.5  riastrad  *
    569   1.5  riastrad  * Registers with non-zero mask are only allowed to be written using
    570   1.5  riastrad  * LRI.
    571   1.5  riastrad  */
    572   1.5  riastrad struct drm_i915_reg_descriptor {
    573  1.23  riastrad 	i915_reg_t addr;
    574   1.5  riastrad 	u32 mask;
    575   1.5  riastrad 	u32 value;
    576   1.5  riastrad };
    577   1.5  riastrad 
    578   1.5  riastrad /* Convenience macro for adding 32-bit registers. */
    579  1.23  riastrad #define REG32(_reg, ...) \
    580  1.23  riastrad 	{ .addr = (_reg), __VA_ARGS__ }
    581   1.5  riastrad 
    582   1.5  riastrad /*
    583   1.5  riastrad  * Convenience macro for adding 64-bit registers.
    584   1.5  riastrad  *
    585   1.5  riastrad  * Some registers that userspace accesses are 64 bits. The register
    586   1.5  riastrad  * access commands only allow 32-bit accesses. Hence, we have to include
    587   1.5  riastrad  * entries for both halves of the 64-bit registers.
    588   1.5  riastrad  */
    589  1.23  riastrad #define REG64(_reg) \
    590  1.23  riastrad 	{ .addr = _reg }, \
    591  1.23  riastrad 	{ .addr = _reg ## _UDW }
    592   1.5  riastrad 
    593  1.19      maya #define REG64_IDX(_reg, idx) \
    594  1.19      maya 	{ .addr = _reg(idx) }, \
    595  1.19      maya 	{ .addr = _reg ## _UDW(idx) }
    596  1.19      maya 
    597   1.5  riastrad static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
    598   1.5  riastrad 	REG64(GPGPU_THREADS_DISPATCHED),
    599   1.5  riastrad 	REG64(HS_INVOCATION_COUNT),
    600   1.5  riastrad 	REG64(DS_INVOCATION_COUNT),
    601   1.5  riastrad 	REG64(IA_VERTICES_COUNT),
    602   1.5  riastrad 	REG64(IA_PRIMITIVES_COUNT),
    603   1.5  riastrad 	REG64(VS_INVOCATION_COUNT),
    604   1.5  riastrad 	REG64(GS_INVOCATION_COUNT),
    605   1.5  riastrad 	REG64(GS_PRIMITIVES_COUNT),
    606   1.5  riastrad 	REG64(CL_INVOCATION_COUNT),
    607   1.5  riastrad 	REG64(CL_PRIMITIVES_COUNT),
    608   1.5  riastrad 	REG64(PS_INVOCATION_COUNT),
    609   1.5  riastrad 	REG64(PS_DEPTH_COUNT),
    610  1.23  riastrad 	REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE),
    611   1.5  riastrad 	REG64(MI_PREDICATE_SRC0),
    612   1.5  riastrad 	REG64(MI_PREDICATE_SRC1),
    613   1.5  riastrad 	REG32(GEN7_3DPRIM_END_OFFSET),
    614   1.5  riastrad 	REG32(GEN7_3DPRIM_START_VERTEX),
    615   1.5  riastrad 	REG32(GEN7_3DPRIM_VERTEX_COUNT),
    616   1.5  riastrad 	REG32(GEN7_3DPRIM_INSTANCE_COUNT),
    617   1.5  riastrad 	REG32(GEN7_3DPRIM_START_INSTANCE),
    618   1.5  riastrad 	REG32(GEN7_3DPRIM_BASE_VERTEX),
    619   1.5  riastrad 	REG32(GEN7_GPGPU_DISPATCHDIMX),
    620   1.5  riastrad 	REG32(GEN7_GPGPU_DISPATCHDIMY),
    621   1.5  riastrad 	REG32(GEN7_GPGPU_DISPATCHDIMZ),
    622  1.23  riastrad 	REG64_IDX(RING_TIMESTAMP, BSD_RING_BASE),
    623  1.23  riastrad 	REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 0),
    624  1.23  riastrad 	REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 1),
    625  1.23  riastrad 	REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 2),
    626  1.23  riastrad 	REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 3),
    627  1.23  riastrad 	REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 0),
    628  1.23  riastrad 	REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 1),
    629  1.23  riastrad 	REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 2),
    630  1.23  riastrad 	REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 3),
    631   1.5  riastrad 	REG32(GEN7_SO_WRITE_OFFSET(0)),
    632   1.5  riastrad 	REG32(GEN7_SO_WRITE_OFFSET(1)),
    633   1.5  riastrad 	REG32(GEN7_SO_WRITE_OFFSET(2)),
    634   1.5  riastrad 	REG32(GEN7_SO_WRITE_OFFSET(3)),
    635   1.5  riastrad 	REG32(GEN7_L3SQCREG1),
    636   1.5  riastrad 	REG32(GEN7_L3CNTLREG2),
    637   1.5  riastrad 	REG32(GEN7_L3CNTLREG3),
    638  1.23  riastrad 	REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
    639  1.23  riastrad };
    640  1.23  riastrad 
    641  1.23  riastrad static const struct drm_i915_reg_descriptor hsw_render_regs[] = {
    642  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 0),
    643  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 1),
    644  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 2),
    645  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 3),
    646  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 4),
    647  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 5),
    648  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 6),
    649  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 7),
    650  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 8),
    651  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 9),
    652  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 10),
    653  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 11),
    654  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 12),
    655  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 13),
    656  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 14),
    657  1.23  riastrad 	REG64_IDX(HSW_CS_GPR, 15),
    658   1.5  riastrad 	REG32(HSW_SCRATCH1,
    659   1.5  riastrad 	      .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE,
    660   1.5  riastrad 	      .value = 0),
    661   1.5  riastrad 	REG32(HSW_ROW_CHICKEN3,
    662   1.5  riastrad 	      .mask = ~(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE << 16 |
    663   1.5  riastrad                         HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE),
    664   1.5  riastrad 	      .value = 0),
    665   1.5  riastrad };
    666   1.5  riastrad 
    667   1.5  riastrad static const struct drm_i915_reg_descriptor gen7_blt_regs[] = {
    668  1.23  riastrad 	REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE),
    669  1.23  riastrad 	REG64_IDX(RING_TIMESTAMP, BSD_RING_BASE),
    670   1.5  riastrad 	REG32(BCS_SWCTRL),
    671  1.23  riastrad 	REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
    672   1.5  riastrad };
    673   1.5  riastrad 
    674  1.19      maya static const struct drm_i915_reg_descriptor gen9_blt_regs[] = {
    675  1.19      maya 	REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE),
    676  1.19      maya 	REG64_IDX(RING_TIMESTAMP, BSD_RING_BASE),
    677  1.19      maya 	REG32(BCS_SWCTRL),
    678  1.19      maya 	REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
    679  1.19      maya 	REG64_IDX(BCS_GPR, 0),
    680  1.19      maya 	REG64_IDX(BCS_GPR, 1),
    681  1.19      maya 	REG64_IDX(BCS_GPR, 2),
    682  1.19      maya 	REG64_IDX(BCS_GPR, 3),
    683  1.19      maya 	REG64_IDX(BCS_GPR, 4),
    684  1.19      maya 	REG64_IDX(BCS_GPR, 5),
    685  1.19      maya 	REG64_IDX(BCS_GPR, 6),
    686  1.19      maya 	REG64_IDX(BCS_GPR, 7),
    687  1.19      maya 	REG64_IDX(BCS_GPR, 8),
    688  1.19      maya 	REG64_IDX(BCS_GPR, 9),
    689  1.19      maya 	REG64_IDX(BCS_GPR, 10),
    690  1.19      maya 	REG64_IDX(BCS_GPR, 11),
    691  1.19      maya 	REG64_IDX(BCS_GPR, 12),
    692  1.19      maya 	REG64_IDX(BCS_GPR, 13),
    693  1.19      maya 	REG64_IDX(BCS_GPR, 14),
    694  1.19      maya 	REG64_IDX(BCS_GPR, 15),
    695   1.5  riastrad };
    696   1.5  riastrad 
    697   1.5  riastrad #undef REG64
    698   1.5  riastrad #undef REG32
    699   1.5  riastrad 
    700  1.23  riastrad struct drm_i915_reg_table {
    701  1.23  riastrad 	const struct drm_i915_reg_descriptor *regs;
    702  1.23  riastrad 	int num_regs;
    703  1.23  riastrad };
    704  1.23  riastrad 
    705  1.23  riastrad static const struct drm_i915_reg_table ivb_render_reg_tables[] = {
    706  1.23  riastrad 	{ gen7_render_regs, ARRAY_SIZE(gen7_render_regs) },
    707  1.23  riastrad };
    708  1.23  riastrad 
    709  1.23  riastrad static const struct drm_i915_reg_table ivb_blt_reg_tables[] = {
    710  1.23  riastrad 	{ gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) },
    711  1.23  riastrad };
    712  1.23  riastrad 
    713  1.23  riastrad static const struct drm_i915_reg_table hsw_render_reg_tables[] = {
    714  1.23  riastrad 	{ gen7_render_regs, ARRAY_SIZE(gen7_render_regs) },
    715  1.23  riastrad 	{ hsw_render_regs, ARRAY_SIZE(hsw_render_regs) },
    716  1.23  riastrad };
    717  1.23  riastrad 
    718  1.23  riastrad static const struct drm_i915_reg_table hsw_blt_reg_tables[] = {
    719  1.23  riastrad 	{ gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) },
    720  1.23  riastrad };
    721  1.23  riastrad 
    722  1.23  riastrad static const struct drm_i915_reg_table gen9_blt_reg_tables[] = {
    723  1.23  riastrad 	{ gen9_blt_regs, ARRAY_SIZE(gen9_blt_regs) },
    724  1.23  riastrad };
    725  1.23  riastrad 
    726   1.1  riastrad static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
    727   1.1  riastrad {
    728  1.23  riastrad 	u32 client = cmd_header >> INSTR_CLIENT_SHIFT;
    729   1.1  riastrad 	u32 subclient =
    730   1.1  riastrad 		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
    731   1.1  riastrad 
    732   1.1  riastrad 	if (client == INSTR_MI_CLIENT)
    733   1.1  riastrad 		return 0x3F;
    734   1.1  riastrad 	else if (client == INSTR_RC_CLIENT) {
    735   1.1  riastrad 		if (subclient == INSTR_MEDIA_SUBCLIENT)
    736   1.1  riastrad 			return 0xFFFF;
    737   1.1  riastrad 		else
    738   1.1  riastrad 			return 0xFF;
    739   1.1  riastrad 	}
    740   1.1  riastrad 
    741  1.23  riastrad 	DRM_DEBUG("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header);
    742   1.1  riastrad 	return 0;
    743   1.1  riastrad }
    744   1.1  riastrad 
    745   1.1  riastrad static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header)
    746   1.1  riastrad {
    747  1.23  riastrad 	u32 client = cmd_header >> INSTR_CLIENT_SHIFT;
    748   1.1  riastrad 	u32 subclient =
    749   1.1  riastrad 		(cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
    750   1.5  riastrad 	u32 op = (cmd_header & INSTR_26_TO_24_MASK) >> INSTR_26_TO_24_SHIFT;
    751   1.1  riastrad 
    752   1.1  riastrad 	if (client == INSTR_MI_CLIENT)
    753   1.1  riastrad 		return 0x3F;
    754   1.1  riastrad 	else if (client == INSTR_RC_CLIENT) {
    755   1.5  riastrad 		if (subclient == INSTR_MEDIA_SUBCLIENT) {
    756   1.5  riastrad 			if (op == 6)
    757   1.5  riastrad 				return 0xFFFF;
    758   1.5  riastrad 			else
    759   1.5  riastrad 				return 0xFFF;
    760   1.5  riastrad 		} else
    761   1.1  riastrad 			return 0xFF;
    762   1.1  riastrad 	}
    763   1.1  riastrad 
    764  1.23  riastrad 	DRM_DEBUG("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header);
    765   1.1  riastrad 	return 0;
    766   1.1  riastrad }
    767   1.1  riastrad 
    768   1.1  riastrad static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
    769   1.1  riastrad {
    770  1.23  riastrad 	u32 client = cmd_header >> INSTR_CLIENT_SHIFT;
    771   1.1  riastrad 
    772   1.1  riastrad 	if (client == INSTR_MI_CLIENT)
    773   1.1  riastrad 		return 0x3F;
    774   1.1  riastrad 	else if (client == INSTR_BC_CLIENT)
    775   1.1  riastrad 		return 0xFF;
    776   1.1  riastrad 
    777  1.23  riastrad 	DRM_DEBUG("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
    778   1.1  riastrad 	return 0;
    779   1.1  riastrad }
    780   1.1  riastrad 
    781  1.19      maya static u32 gen9_blt_get_cmd_length_mask(u32 cmd_header)
    782  1.19      maya {
    783  1.23  riastrad 	u32 client = cmd_header >> INSTR_CLIENT_SHIFT;
    784  1.19      maya 
    785  1.19      maya 	if (client == INSTR_MI_CLIENT || client == INSTR_BC_CLIENT)
    786  1.19      maya 		return 0xFF;
    787  1.19      maya 
    788  1.23  riastrad 	DRM_DEBUG("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
    789  1.19      maya 	return 0;
    790  1.19      maya }
    791  1.19      maya 
    792  1.23  riastrad static bool validate_cmds_sorted(const struct intel_engine_cs *engine,
    793   1.5  riastrad 				 const struct drm_i915_cmd_table *cmd_tables,
    794   1.5  riastrad 				 int cmd_table_count)
    795   1.1  riastrad {
    796   1.1  riastrad 	int i;
    797   1.5  riastrad 	bool ret = true;
    798   1.1  riastrad 
    799   1.5  riastrad 	if (!cmd_tables || cmd_table_count == 0)
    800   1.5  riastrad 		return true;
    801   1.1  riastrad 
    802   1.5  riastrad 	for (i = 0; i < cmd_table_count; i++) {
    803   1.5  riastrad 		const struct drm_i915_cmd_table *table = &cmd_tables[i];
    804   1.1  riastrad 		u32 previous = 0;
    805   1.1  riastrad 		int j;
    806   1.1  riastrad 
    807   1.1  riastrad 		for (j = 0; j < table->count; j++) {
    808   1.1  riastrad 			const struct drm_i915_cmd_descriptor *desc =
    809   1.5  riastrad 				&table->table[j];
    810   1.1  riastrad 			u32 curr = desc->cmd.value & desc->cmd.mask;
    811   1.1  riastrad 
    812   1.5  riastrad 			if (curr < previous) {
    813  1.23  riastrad 				DRM_ERROR("CMD: %s [%d] command table not sorted: "
    814  1.23  riastrad 					  "table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
    815  1.23  riastrad 					  engine->name, engine->id,
    816  1.23  riastrad 					  i, j, curr, previous);
    817   1.5  riastrad 				ret = false;
    818   1.5  riastrad 			}
    819   1.1  riastrad 
    820   1.1  riastrad 			previous = curr;
    821   1.1  riastrad 		}
    822   1.1  riastrad 	}
    823   1.5  riastrad 
    824   1.5  riastrad 	return ret;
    825   1.1  riastrad }
    826   1.1  riastrad 
    827  1.23  riastrad static bool check_sorted(const struct intel_engine_cs *engine,
    828   1.5  riastrad 			 const struct drm_i915_reg_descriptor *reg_table,
    829   1.5  riastrad 			 int reg_count)
    830   1.1  riastrad {
    831   1.1  riastrad 	int i;
    832   1.1  riastrad 	u32 previous = 0;
    833   1.5  riastrad 	bool ret = true;
    834   1.1  riastrad 
    835   1.1  riastrad 	for (i = 0; i < reg_count; i++) {
    836  1.23  riastrad 		u32 curr = i915_mmio_reg_offset(reg_table[i].addr);
    837   1.1  riastrad 
    838   1.5  riastrad 		if (curr < previous) {
    839  1.23  riastrad 			DRM_ERROR("CMD: %s [%d] register table not sorted: "
    840  1.23  riastrad 				  "entry=%d reg=0x%08X prev=0x%08X\n",
    841  1.23  riastrad 				  engine->name, engine->id,
    842  1.23  riastrad 				  i, curr, previous);
    843   1.5  riastrad 			ret = false;
    844   1.5  riastrad 		}
    845   1.1  riastrad 
    846   1.1  riastrad 		previous = curr;
    847   1.1  riastrad 	}
    848   1.5  riastrad 
    849   1.5  riastrad 	return ret;
    850   1.1  riastrad }
    851   1.1  riastrad 
    852  1.23  riastrad static bool validate_regs_sorted(struct intel_engine_cs *engine)
    853   1.1  riastrad {
    854  1.23  riastrad 	int i;
    855  1.23  riastrad 	const struct drm_i915_reg_table *table;
    856  1.23  riastrad 
    857  1.23  riastrad 	for (i = 0; i < engine->reg_table_count; i++) {
    858  1.23  riastrad 		table = &engine->reg_tables[i];
    859  1.23  riastrad 		if (!check_sorted(engine, table->regs, table->num_regs))
    860  1.23  riastrad 			return false;
    861  1.23  riastrad 	}
    862  1.23  riastrad 
    863  1.23  riastrad 	return true;
    864   1.5  riastrad }
    865   1.5  riastrad 
    866   1.5  riastrad struct cmd_node {
    867   1.5  riastrad 	const struct drm_i915_cmd_descriptor *desc;
    868   1.5  riastrad 	struct hlist_node node;
    869   1.5  riastrad };
    870   1.5  riastrad 
    871   1.5  riastrad /*
    872   1.5  riastrad  * Different command ranges have different numbers of bits for the opcode. For
    873   1.5  riastrad  * example, MI commands use bits 31:23 while 3D commands use bits 31:16. The
    874   1.5  riastrad  * problem is that, for example, MI commands use bits 22:16 for other fields
    875   1.5  riastrad  * such as GGTT vs PPGTT bits. If we include those bits in the mask then when
    876   1.5  riastrad  * we mask a command from a batch it could hash to the wrong bucket due to
    877   1.5  riastrad  * non-opcode bits being set. But if we don't include those bits, some 3D
    878   1.5  riastrad  * commands may hash to the same bucket due to not including opcode bits that
    879   1.5  riastrad  * make the command unique. For now, we will risk hashing to the same bucket.
    880   1.5  riastrad  */
    881  1.23  riastrad static inline u32 cmd_header_key(u32 x)
    882  1.23  riastrad {
    883  1.23  riastrad 	switch (x >> INSTR_CLIENT_SHIFT) {
    884  1.23  riastrad 	default:
    885  1.23  riastrad 	case INSTR_MI_CLIENT:
    886  1.23  riastrad 		return x >> STD_MI_OPCODE_SHIFT;
    887  1.23  riastrad 	case INSTR_RC_CLIENT:
    888  1.23  riastrad 		return x >> STD_3D_OPCODE_SHIFT;
    889  1.23  riastrad 	case INSTR_BC_CLIENT:
    890  1.23  riastrad 		return x >> STD_2D_OPCODE_SHIFT;
    891  1.23  riastrad 	}
    892  1.23  riastrad }
    893   1.5  riastrad 
    894  1.23  riastrad static int init_hash_table(struct intel_engine_cs *engine,
    895   1.5  riastrad 			   const struct drm_i915_cmd_table *cmd_tables,
    896   1.5  riastrad 			   int cmd_table_count)
    897   1.5  riastrad {
    898   1.5  riastrad 	int i, j;
    899   1.5  riastrad 
    900  1.23  riastrad 	hash_init(engine->cmd_hash);
    901   1.5  riastrad 
    902   1.5  riastrad 	for (i = 0; i < cmd_table_count; i++) {
    903   1.5  riastrad 		const struct drm_i915_cmd_table *table = &cmd_tables[i];
    904   1.5  riastrad 
    905   1.5  riastrad 		for (j = 0; j < table->count; j++) {
    906   1.5  riastrad 			const struct drm_i915_cmd_descriptor *desc =
    907   1.5  riastrad 				&table->table[j];
    908   1.5  riastrad 			struct cmd_node *desc_node =
    909   1.5  riastrad 				kmalloc(sizeof(*desc_node), GFP_KERNEL);
    910   1.5  riastrad 
    911   1.5  riastrad 			if (!desc_node)
    912   1.5  riastrad 				return -ENOMEM;
    913   1.5  riastrad 
    914   1.5  riastrad 			desc_node->desc = desc;
    915  1.23  riastrad 			hash_add(engine->cmd_hash, &desc_node->node,
    916  1.23  riastrad 				 cmd_header_key(desc->cmd.value));
    917   1.5  riastrad 		}
    918   1.5  riastrad 	}
    919   1.5  riastrad 
    920   1.5  riastrad 	return 0;
    921   1.5  riastrad }
    922   1.5  riastrad 
    923  1.23  riastrad static void fini_hash_table(struct intel_engine_cs *engine)
    924   1.5  riastrad {
    925   1.5  riastrad 	struct hlist_node *tmp;
    926   1.5  riastrad 	struct cmd_node *desc_node;
    927   1.5  riastrad 	int i;
    928   1.5  riastrad 
    929  1.23  riastrad 	hash_for_each_safe(engine->cmd_hash, i, tmp, desc_node, node) {
    930   1.5  riastrad 		hash_del(&desc_node->node);
    931   1.5  riastrad 		kfree(desc_node);
    932   1.5  riastrad 	}
    933   1.1  riastrad }
    934   1.1  riastrad 
    935   1.1  riastrad /**
    936  1.23  riastrad  * intel_engine_init_cmd_parser() - set cmd parser related fields for an engine
    937  1.23  riastrad  * @engine: the engine to initialize
    938   1.1  riastrad  *
    939   1.1  riastrad  * Optionally initializes fields related to batch buffer command parsing in the
    940   1.5  riastrad  * struct intel_engine_cs based on whether the platform requires software
    941   1.1  riastrad  * command parsing.
    942   1.1  riastrad  */
    943  1.23  riastrad void intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
    944   1.1  riastrad {
    945   1.5  riastrad 	const struct drm_i915_cmd_table *cmd_tables;
    946   1.5  riastrad 	int cmd_table_count;
    947   1.5  riastrad 	int ret;
    948   1.5  riastrad 
    949  1.23  riastrad 	if (!IS_GEN(engine->i915, 7) && !(IS_GEN(engine->i915, 9) &&
    950  1.23  riastrad 					  engine->class == COPY_ENGINE_CLASS))
    951  1.23  riastrad 		return;
    952   1.1  riastrad 
    953  1.23  riastrad 	switch (engine->class) {
    954  1.23  riastrad 	case RENDER_CLASS:
    955  1.23  riastrad 		if (IS_HASWELL(engine->i915)) {
    956  1.19      maya 			cmd_tables = hsw_render_ring_cmd_table;
    957   1.5  riastrad 			cmd_table_count =
    958  1.19      maya 				ARRAY_SIZE(hsw_render_ring_cmd_table);
    959   1.5  riastrad 		} else {
    960  1.19      maya 			cmd_tables = gen7_render_cmd_table;
    961  1.19      maya 			cmd_table_count = ARRAY_SIZE(gen7_render_cmd_table);
    962   1.5  riastrad 		}
    963   1.5  riastrad 
    964  1.23  riastrad 		if (IS_HASWELL(engine->i915)) {
    965  1.23  riastrad 			engine->reg_tables = hsw_render_reg_tables;
    966  1.23  riastrad 			engine->reg_table_count = ARRAY_SIZE(hsw_render_reg_tables);
    967  1.23  riastrad 		} else {
    968  1.23  riastrad 			engine->reg_tables = ivb_render_reg_tables;
    969  1.23  riastrad 			engine->reg_table_count = ARRAY_SIZE(ivb_render_reg_tables);
    970  1.23  riastrad 		}
    971  1.23  riastrad 		engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
    972   1.1  riastrad 		break;
    973  1.23  riastrad 	case VIDEO_DECODE_CLASS:
    974  1.19      maya 		cmd_tables = gen7_video_cmd_table;
    975  1.19      maya 		cmd_table_count = ARRAY_SIZE(gen7_video_cmd_table);
    976  1.23  riastrad 		engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
    977   1.1  riastrad 		break;
    978  1.23  riastrad 	case COPY_ENGINE_CLASS:
    979  1.23  riastrad 		engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
    980  1.23  riastrad 		if (IS_GEN(engine->i915, 9)) {
    981  1.19      maya 			cmd_tables = gen9_blt_cmd_table;
    982  1.19      maya 			cmd_table_count = ARRAY_SIZE(gen9_blt_cmd_table);
    983  1.23  riastrad 			engine->get_cmd_length_mask =
    984  1.19      maya 				gen9_blt_get_cmd_length_mask;
    985  1.19      maya 
    986  1.19      maya 			/* BCS Engine unsafe without parser */
    987  1.23  riastrad 			engine->flags |= I915_ENGINE_REQUIRES_CMD_PARSER;
    988  1.23  riastrad 		} else if (IS_HASWELL(engine->i915)) {
    989  1.19      maya 			cmd_tables = hsw_blt_ring_cmd_table;
    990  1.19      maya 			cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmd_table);
    991   1.5  riastrad 		} else {
    992  1.19      maya 			cmd_tables = gen7_blt_cmd_table;
    993  1.19      maya 			cmd_table_count = ARRAY_SIZE(gen7_blt_cmd_table);
    994   1.5  riastrad 		}
    995   1.5  riastrad 
    996  1.23  riastrad 		if (IS_GEN(engine->i915, 9)) {
    997  1.23  riastrad 			engine->reg_tables = gen9_blt_reg_tables;
    998  1.23  riastrad 			engine->reg_table_count =
    999  1.23  riastrad 				ARRAY_SIZE(gen9_blt_reg_tables);
   1000  1.23  riastrad 		} else if (IS_HASWELL(engine->i915)) {
   1001  1.23  riastrad 			engine->reg_tables = hsw_blt_reg_tables;
   1002  1.23  riastrad 			engine->reg_table_count = ARRAY_SIZE(hsw_blt_reg_tables);
   1003   1.5  riastrad 		} else {
   1004  1.23  riastrad 			engine->reg_tables = ivb_blt_reg_tables;
   1005  1.23  riastrad 			engine->reg_table_count = ARRAY_SIZE(ivb_blt_reg_tables);
   1006   1.5  riastrad 		}
   1007   1.1  riastrad 		break;
   1008  1.23  riastrad 	case VIDEO_ENHANCEMENT_CLASS:
   1009  1.19      maya 		cmd_tables = hsw_vebox_cmd_table;
   1010  1.19      maya 		cmd_table_count = ARRAY_SIZE(hsw_vebox_cmd_table);
   1011   1.1  riastrad 		/* VECS can use the same length_mask function as VCS */
   1012  1.23  riastrad 		engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
   1013   1.1  riastrad 		break;
   1014   1.1  riastrad 	default:
   1015  1.23  riastrad 		MISSING_CASE(engine->class);
   1016  1.23  riastrad 		return;
   1017   1.1  riastrad 	}
   1018   1.1  riastrad 
   1019  1.23  riastrad 	if (!validate_cmds_sorted(engine, cmd_tables, cmd_table_count)) {
   1020  1.23  riastrad 		DRM_ERROR("%s: command descriptions are not sorted\n",
   1021  1.23  riastrad 			  engine->name);
   1022  1.23  riastrad 		return;
   1023  1.23  riastrad 	}
   1024  1.23  riastrad 	if (!validate_regs_sorted(engine)) {
   1025  1.23  riastrad 		DRM_ERROR("%s: registers are not sorted\n", engine->name);
   1026  1.23  riastrad 		return;
   1027  1.23  riastrad 	}
   1028   1.5  riastrad 
   1029  1.23  riastrad 	ret = init_hash_table(engine, cmd_tables, cmd_table_count);
   1030   1.5  riastrad 	if (ret) {
   1031  1.23  riastrad 		DRM_ERROR("%s: initialised failed!\n", engine->name);
   1032  1.23  riastrad 		fini_hash_table(engine);
   1033  1.23  riastrad 		return;
   1034   1.5  riastrad 	}
   1035   1.5  riastrad 
   1036  1.23  riastrad 	engine->flags |= I915_ENGINE_USING_CMD_PARSER;
   1037   1.5  riastrad }
   1038   1.5  riastrad 
   1039   1.5  riastrad /**
   1040  1.23  riastrad  * intel_engine_cleanup_cmd_parser() - clean up cmd parser related fields
   1041  1.23  riastrad  * @engine: the engine to clean up
   1042   1.5  riastrad  *
   1043   1.5  riastrad  * Releases any resources related to command parsing that may have been
   1044  1.23  riastrad  * initialized for the specified engine.
   1045   1.5  riastrad  */
   1046  1.23  riastrad void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine)
   1047   1.5  riastrad {
   1048  1.23  riastrad 	if (!intel_engine_using_cmd_parser(engine))
   1049   1.5  riastrad 		return;
   1050   1.5  riastrad 
   1051  1.23  riastrad 	fini_hash_table(engine);
   1052   1.1  riastrad }
   1053   1.1  riastrad 
   1054   1.1  riastrad static const struct drm_i915_cmd_descriptor*
   1055  1.23  riastrad find_cmd_in_table(struct intel_engine_cs *engine,
   1056   1.1  riastrad 		  u32 cmd_header)
   1057   1.1  riastrad {
   1058   1.5  riastrad 	struct cmd_node *desc_node;
   1059   1.1  riastrad 
   1060  1.23  riastrad 	hash_for_each_possible(engine->cmd_hash, desc_node, node,
   1061  1.23  riastrad 			       cmd_header_key(cmd_header)) {
   1062   1.5  riastrad 		const struct drm_i915_cmd_descriptor *desc = desc_node->desc;
   1063  1.23  riastrad 		if (((cmd_header ^ desc->cmd.value) & desc->cmd.mask) == 0)
   1064   1.1  riastrad 			return desc;
   1065   1.1  riastrad 	}
   1066   1.1  riastrad 
   1067   1.1  riastrad 	return NULL;
   1068   1.1  riastrad }
   1069   1.1  riastrad 
   1070   1.1  riastrad /*
   1071   1.1  riastrad  * Returns a pointer to a descriptor for the command specified by cmd_header.
   1072   1.1  riastrad  *
   1073   1.1  riastrad  * The caller must supply space for a default descriptor via the default_desc
   1074  1.23  riastrad  * parameter. If no descriptor for the specified command exists in the engine's
   1075   1.1  riastrad  * command parser tables, this function fills in default_desc based on the
   1076  1.23  riastrad  * engine's default length encoding and returns default_desc.
   1077   1.1  riastrad  */
   1078   1.1  riastrad static const struct drm_i915_cmd_descriptor*
   1079  1.23  riastrad find_cmd(struct intel_engine_cs *engine,
   1080   1.1  riastrad 	 u32 cmd_header,
   1081  1.23  riastrad 	 const struct drm_i915_cmd_descriptor *desc,
   1082   1.1  riastrad 	 struct drm_i915_cmd_descriptor *default_desc)
   1083   1.1  riastrad {
   1084   1.1  riastrad 	u32 mask;
   1085   1.1  riastrad 
   1086  1.23  riastrad 	if (((cmd_header ^ desc->cmd.value) & desc->cmd.mask) == 0)
   1087  1.23  riastrad 		return desc;
   1088  1.23  riastrad 
   1089  1.23  riastrad 	desc = find_cmd_in_table(engine, cmd_header);
   1090   1.5  riastrad 	if (desc)
   1091   1.5  riastrad 		return desc;
   1092   1.1  riastrad 
   1093  1.23  riastrad 	mask = engine->get_cmd_length_mask(cmd_header);
   1094   1.1  riastrad 	if (!mask)
   1095   1.1  riastrad 		return NULL;
   1096   1.1  riastrad 
   1097  1.23  riastrad 	default_desc->cmd.value = cmd_header;
   1098  1.23  riastrad 	default_desc->cmd.mask = ~0u << MIN_OPCODE_SHIFT;
   1099  1.23  riastrad 	default_desc->length.mask = mask;
   1100   1.1  riastrad 	default_desc->flags = CMD_DESC_SKIP;
   1101   1.1  riastrad 	return default_desc;
   1102   1.1  riastrad }
   1103   1.1  riastrad 
   1104   1.5  riastrad static const struct drm_i915_reg_descriptor *
   1105  1.23  riastrad __find_reg(const struct drm_i915_reg_descriptor *table, int count, u32 addr)
   1106   1.1  riastrad {
   1107  1.23  riastrad 	int start = 0, end = count;
   1108  1.23  riastrad 	while (start < end) {
   1109  1.23  riastrad 		int mid = start + (end - start) / 2;
   1110  1.23  riastrad 		int ret = addr - i915_mmio_reg_offset(table[mid].addr);
   1111  1.23  riastrad 		if (ret < 0)
   1112  1.23  riastrad 			end = mid;
   1113  1.23  riastrad 		else if (ret > 0)
   1114  1.23  riastrad 			start = mid + 1;
   1115  1.23  riastrad 		else
   1116  1.23  riastrad 			return &table[mid];
   1117   1.1  riastrad 	}
   1118   1.5  riastrad 	return NULL;
   1119   1.1  riastrad }
   1120   1.1  riastrad 
   1121  1.23  riastrad static const struct drm_i915_reg_descriptor *
   1122  1.23  riastrad find_reg(const struct intel_engine_cs *engine, u32 addr)
   1123   1.1  riastrad {
   1124  1.23  riastrad 	const struct drm_i915_reg_table *table = engine->reg_tables;
   1125  1.23  riastrad 	const struct drm_i915_reg_descriptor *reg = NULL;
   1126  1.23  riastrad 	int count = engine->reg_table_count;
   1127   1.1  riastrad 
   1128  1.23  riastrad 	for (; !reg && (count > 0); ++table, --count)
   1129  1.23  riastrad 		reg = __find_reg(table->regs, table->num_regs, addr);
   1130   1.1  riastrad 
   1131  1.23  riastrad 	return reg;
   1132  1.12  riastrad }
   1133   1.1  riastrad 
   1134  1.23  riastrad /* Returns a vmap'd pointer to dst_obj, which the caller must unmap */
   1135  1.23  riastrad static u32 *copy_batch(struct drm_i915_gem_object *dst_obj,
   1136   1.5  riastrad 		       struct drm_i915_gem_object *src_obj,
   1137  1.23  riastrad 		       u32 offset, u32 length)
   1138   1.5  riastrad {
   1139  1.23  riastrad 	bool needs_clflush;
   1140  1.23  riastrad 	void *dst, *src;
   1141   1.5  riastrad 	int ret;
   1142   1.5  riastrad 
   1143  1.23  riastrad 	dst = i915_gem_object_pin_map(dst_obj, I915_MAP_FORCE_WB);
   1144  1.23  riastrad 	if (IS_ERR(dst))
   1145  1.23  riastrad 		return dst;
   1146   1.5  riastrad 
   1147  1.23  riastrad 	ret = i915_gem_object_pin_pages(src_obj);
   1148   1.5  riastrad 	if (ret) {
   1149  1.23  riastrad 		i915_gem_object_unpin_map(dst_obj);
   1150   1.5  riastrad 		return ERR_PTR(ret);
   1151   1.5  riastrad 	}
   1152   1.5  riastrad 
   1153  1.23  riastrad 	needs_clflush =
   1154  1.23  riastrad 		!(src_obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ);
   1155  1.23  riastrad 
   1156  1.23  riastrad 	src = ERR_PTR(-ENODEV);
   1157  1.23  riastrad 	if (needs_clflush && i915_has_memcpy_from_wc()) {
   1158  1.23  riastrad 		src = i915_gem_object_pin_map(src_obj, I915_MAP_WC);
   1159  1.23  riastrad 		if (!IS_ERR(src)) {
   1160  1.23  riastrad 			i915_unaligned_memcpy_from_wc(dst,
   1161  1.28  riastrad 						      src + offset,
   1162  1.23  riastrad 						      length);
   1163  1.23  riastrad 			i915_gem_object_unpin_map(src_obj);
   1164  1.23  riastrad 		}
   1165   1.5  riastrad 	}
   1166  1.23  riastrad 	if (IS_ERR(src)) {
   1167  1.23  riastrad 		void *ptr;
   1168  1.23  riastrad 		int x, n;
   1169   1.5  riastrad 
   1170  1.23  riastrad 		/*
   1171  1.23  riastrad 		 * We can avoid clflushing partial cachelines before the write
   1172  1.23  riastrad 		 * if we only every write full cache-lines. Since we know that
   1173  1.23  riastrad 		 * both the source and destination are in multiples of
   1174  1.23  riastrad 		 * PAGE_SIZE, we can simply round up to the next cacheline.
   1175  1.23  riastrad 		 * We don't care about copying too much here as we only
   1176  1.23  riastrad 		 * validate up to the end of the batch.
   1177  1.23  riastrad 		 */
   1178  1.25  riastrad 		if (!(dst_obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ)) {
   1179  1.25  riastrad #ifdef __NetBSD__
   1180  1.25  riastrad 			length = round_up(length,
   1181  1.25  riastrad 					  cpu_info_primary.ci_cflush_lsize);
   1182  1.25  riastrad #else
   1183  1.23  riastrad 			length = round_up(length,
   1184  1.23  riastrad 					  boot_cpu_data.x86_clflush_size);
   1185  1.25  riastrad #endif
   1186  1.25  riastrad 		}
   1187  1.23  riastrad 
   1188  1.23  riastrad 		ptr = dst;
   1189  1.23  riastrad 		x = offset_in_page(offset);
   1190  1.23  riastrad 		for (n = offset >> PAGE_SHIFT; length; n++) {
   1191  1.23  riastrad 			int len = min_t(int, length, PAGE_SIZE - x);
   1192  1.23  riastrad 
   1193  1.23  riastrad 			src = kmap_atomic(i915_gem_object_get_page(src_obj, n));
   1194  1.23  riastrad 			if (needs_clflush)
   1195  1.28  riastrad 				drm_clflush_virt_range(src + x, len);
   1196  1.28  riastrad 			memcpy(ptr, src + x, len);
   1197  1.23  riastrad 			kunmap_atomic(src);
   1198  1.23  riastrad 
   1199  1.28  riastrad 			ptr += len;
   1200  1.23  riastrad 			length -= len;
   1201  1.23  riastrad 			x = 0;
   1202  1.23  riastrad 		}
   1203   1.5  riastrad 	}
   1204   1.5  riastrad 
   1205   1.5  riastrad 	i915_gem_object_unpin_pages(src_obj);
   1206   1.5  riastrad 
   1207  1.23  riastrad 	/* dst_obj is returned with vmap pinned */
   1208  1.23  riastrad 	return dst;
   1209   1.5  riastrad }
   1210   1.5  riastrad 
   1211  1.23  riastrad static bool check_cmd(const struct intel_engine_cs *engine,
   1212   1.5  riastrad 		      const struct drm_i915_cmd_descriptor *desc,
   1213  1.23  riastrad 		      const u32 *cmd, u32 length)
   1214   1.5  riastrad {
   1215  1.23  riastrad 	if (desc->flags & CMD_DESC_SKIP)
   1216  1.23  riastrad 		return true;
   1217  1.23  riastrad 
   1218   1.5  riastrad 	if (desc->flags & CMD_DESC_REJECT) {
   1219  1.23  riastrad 		DRM_DEBUG("CMD: Rejected command: 0x%08X\n", *cmd);
   1220   1.5  riastrad 		return false;
   1221   1.5  riastrad 	}
   1222   1.5  riastrad 
   1223   1.5  riastrad 	if (desc->flags & CMD_DESC_REGISTER) {
   1224   1.5  riastrad 		/*
   1225   1.5  riastrad 		 * Get the distance between individual register offset
   1226   1.5  riastrad 		 * fields if the command can perform more than one
   1227   1.5  riastrad 		 * access at a time.
   1228   1.5  riastrad 		 */
   1229   1.5  riastrad 		const u32 step = desc->reg.step ? desc->reg.step : length;
   1230   1.5  riastrad 		u32 offset;
   1231   1.5  riastrad 
   1232   1.5  riastrad 		for (offset = desc->reg.offset; offset < length;
   1233   1.5  riastrad 		     offset += step) {
   1234   1.5  riastrad 			const u32 reg_addr = cmd[offset] & desc->reg.mask;
   1235   1.5  riastrad 			const struct drm_i915_reg_descriptor *reg =
   1236  1.23  riastrad 				find_reg(engine, reg_addr);
   1237   1.5  riastrad 
   1238   1.5  riastrad 			if (!reg) {
   1239  1.23  riastrad 				DRM_DEBUG("CMD: Rejected register 0x%08X in command: 0x%08X (%s)\n",
   1240  1.23  riastrad 					  reg_addr, *cmd, engine->name);
   1241   1.5  riastrad 				return false;
   1242   1.5  riastrad 			}
   1243   1.5  riastrad 
   1244   1.5  riastrad 			/*
   1245  1.23  riastrad 			 * Check the value written to the register against the
   1246  1.23  riastrad 			 * allowed mask/value pair given in the whitelist entry.
   1247   1.5  riastrad 			 */
   1248  1.23  riastrad 			if (reg->mask) {
   1249   1.5  riastrad 				if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
   1250  1.23  riastrad 					DRM_DEBUG("CMD: Rejected LRM to masked register 0x%08X\n",
   1251  1.23  riastrad 						  reg_addr);
   1252   1.5  riastrad 					return false;
   1253   1.5  riastrad 				}
   1254   1.5  riastrad 
   1255  1.23  riastrad 				if (desc->cmd.value == MI_LOAD_REGISTER_REG) {
   1256  1.23  riastrad 					DRM_DEBUG("CMD: Rejected LRR to masked register 0x%08X\n",
   1257  1.23  riastrad 						  reg_addr);
   1258   1.5  riastrad 					return false;
   1259   1.5  riastrad 				}
   1260   1.5  riastrad 
   1261   1.5  riastrad 				if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) &&
   1262   1.5  riastrad 				    (offset + 2 > length ||
   1263   1.5  riastrad 				     (cmd[offset + 1] & reg->mask) != reg->value)) {
   1264  1.23  riastrad 					DRM_DEBUG("CMD: Rejected LRI to masked register 0x%08X\n",
   1265  1.23  riastrad 						  reg_addr);
   1266   1.5  riastrad 					return false;
   1267   1.5  riastrad 				}
   1268   1.5  riastrad 			}
   1269   1.5  riastrad 		}
   1270   1.5  riastrad 	}
   1271   1.5  riastrad 
   1272   1.5  riastrad 	if (desc->flags & CMD_DESC_BITMASK) {
   1273   1.5  riastrad 		int i;
   1274   1.5  riastrad 
   1275   1.5  riastrad 		for (i = 0; i < MAX_CMD_DESC_BITMASKS; i++) {
   1276   1.5  riastrad 			u32 dword;
   1277   1.5  riastrad 
   1278   1.5  riastrad 			if (desc->bits[i].mask == 0)
   1279   1.5  riastrad 				break;
   1280   1.5  riastrad 
   1281   1.5  riastrad 			if (desc->bits[i].condition_mask != 0) {
   1282   1.5  riastrad 				u32 offset =
   1283   1.5  riastrad 					desc->bits[i].condition_offset;
   1284   1.5  riastrad 				u32 condition = cmd[offset] &
   1285   1.5  riastrad 					desc->bits[i].condition_mask;
   1286   1.5  riastrad 
   1287   1.5  riastrad 				if (condition == 0)
   1288   1.5  riastrad 					continue;
   1289   1.5  riastrad 			}
   1290   1.5  riastrad 
   1291  1.23  riastrad 			if (desc->bits[i].offset >= length) {
   1292  1.23  riastrad 				DRM_DEBUG("CMD: Rejected command 0x%08X, too short to check bitmask (%s)\n",
   1293  1.23  riastrad 					  *cmd, engine->name);
   1294  1.23  riastrad 				return false;
   1295  1.23  riastrad 			}
   1296  1.23  riastrad 
   1297   1.5  riastrad 			dword = cmd[desc->bits[i].offset] &
   1298   1.5  riastrad 				desc->bits[i].mask;
   1299   1.5  riastrad 
   1300   1.5  riastrad 			if (dword != desc->bits[i].expected) {
   1301  1.23  riastrad 				DRM_DEBUG("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (%s)\n",
   1302  1.23  riastrad 					  *cmd,
   1303  1.23  riastrad 					  desc->bits[i].mask,
   1304  1.23  riastrad 					  desc->bits[i].expected,
   1305  1.23  riastrad 					  dword, engine->name);
   1306   1.5  riastrad 				return false;
   1307   1.5  riastrad 			}
   1308   1.5  riastrad 		}
   1309   1.5  riastrad 	}
   1310   1.5  riastrad 
   1311   1.5  riastrad 	return true;
   1312   1.5  riastrad }
   1313   1.5  riastrad 
   1314  1.23  riastrad static int check_bbstart(u32 *cmd, u32 offset, u32 length,
   1315  1.23  riastrad 			 u32 batch_length,
   1316  1.23  riastrad 			 u64 batch_addr,
   1317  1.23  riastrad 			 u64 shadow_addr,
   1318  1.23  riastrad 			 const unsigned long *jump_whitelist)
   1319  1.19      maya {
   1320  1.19      maya 	u64 jump_offset, jump_target;
   1321  1.19      maya 	u32 target_cmd_offset, target_cmd_index;
   1322  1.19      maya 
   1323  1.19      maya 	/* For igt compatibility on older platforms */
   1324  1.23  riastrad 	if (!jump_whitelist) {
   1325  1.19      maya 		DRM_DEBUG("CMD: Rejecting BB_START for ggtt based submission\n");
   1326  1.19      maya 		return -EACCES;
   1327  1.19      maya 	}
   1328  1.19      maya 
   1329  1.19      maya 	if (length != 3) {
   1330  1.19      maya 		DRM_DEBUG("CMD: Recursive BB_START with bad length(%u)\n",
   1331  1.23  riastrad 			  length);
   1332  1.19      maya 		return -EINVAL;
   1333  1.19      maya 	}
   1334  1.19      maya 
   1335  1.23  riastrad 	jump_target = *(u64 *)(cmd + 1);
   1336  1.23  riastrad 	jump_offset = jump_target - batch_addr;
   1337  1.19      maya 
   1338  1.19      maya 	/*
   1339  1.19      maya 	 * Any underflow of jump_target is guaranteed to be outside the range
   1340  1.19      maya 	 * of a u32, so >= test catches both too large and too small
   1341  1.19      maya 	 */
   1342  1.23  riastrad 	if (jump_offset >= batch_length) {
   1343  1.26  riastrad 		DRM_DEBUG("CMD: BB_START to 0x%"PRIx64" jumps out of BB\n",
   1344  1.19      maya 			  jump_target);
   1345  1.19      maya 		return -EINVAL;
   1346  1.19      maya 	}
   1347  1.19      maya 
   1348  1.19      maya 	/*
   1349  1.19      maya 	 * This cannot overflow a u32 because we already checked jump_offset
   1350  1.23  riastrad 	 * is within the BB, and the batch_length is a u32
   1351  1.19      maya 	 */
   1352  1.19      maya 	target_cmd_offset = lower_32_bits(jump_offset);
   1353  1.19      maya 	target_cmd_index = target_cmd_offset / sizeof(u32);
   1354  1.19      maya 
   1355  1.23  riastrad 	*(u64 *)(cmd + 1) = shadow_addr + target_cmd_offset;
   1356  1.19      maya 
   1357  1.19      maya 	if (target_cmd_index == offset)
   1358  1.19      maya 		return 0;
   1359  1.19      maya 
   1360  1.23  riastrad 	if (IS_ERR(jump_whitelist))
   1361  1.23  riastrad 		return PTR_ERR(jump_whitelist);
   1362  1.23  riastrad 
   1363  1.23  riastrad 	if (!test_bit(target_cmd_index, jump_whitelist)) {
   1364  1.26  riastrad 		DRM_DEBUG("CMD: BB_START to 0x%"PRIx64" not a previously executed cmd\n",
   1365  1.19      maya 			  jump_target);
   1366  1.19      maya 		return -EINVAL;
   1367  1.19      maya 	}
   1368  1.19      maya 
   1369  1.19      maya 	return 0;
   1370  1.19      maya }
   1371  1.19      maya 
   1372  1.23  riastrad static unsigned long *alloc_whitelist(u32 batch_length)
   1373  1.19      maya {
   1374  1.23  riastrad 	unsigned long *jmp;
   1375  1.19      maya 
   1376  1.23  riastrad 	/*
   1377  1.23  riastrad 	 * We expect batch_length to be less than 256KiB for known users,
   1378  1.23  riastrad 	 * i.e. we need at most an 8KiB bitmap allocation which should be
   1379  1.23  riastrad 	 * reasonably cheap due to kmalloc caches.
   1380  1.23  riastrad 	 */
   1381  1.19      maya 
   1382  1.23  riastrad 	/* Prefer to report transient allocation failure rather than hit oom */
   1383  1.23  riastrad 	jmp = bitmap_zalloc(DIV_ROUND_UP(batch_length, sizeof(u32)),
   1384  1.23  riastrad 			    GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
   1385  1.23  riastrad 	if (!jmp)
   1386  1.23  riastrad 		return ERR_PTR(-ENOMEM);
   1387  1.19      maya 
   1388  1.23  riastrad 	return jmp;
   1389  1.23  riastrad }
   1390  1.19      maya 
   1391  1.23  riastrad #define LENGTH_BIAS 2
   1392  1.19      maya 
   1393  1.23  riastrad static bool shadow_needs_clflush(struct drm_i915_gem_object *obj)
   1394  1.23  riastrad {
   1395  1.23  riastrad 	return !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE);
   1396  1.19      maya }
   1397  1.19      maya 
   1398   1.1  riastrad /**
   1399  1.23  riastrad  * intel_engine_cmd_parser() - parse a batch buffer for privilege violations
   1400  1.23  riastrad  * @engine: the engine on which the batch is to execute
   1401  1.23  riastrad  * @batch: the batch buffer in question
   1402  1.23  riastrad  * @batch_offset: byte offset in the batch at which execution starts
   1403  1.23  riastrad  * @batch_length: length of the commands in batch_obj
   1404  1.23  riastrad  * @shadow: validated copy of the batch buffer in question
   1405  1.23  riastrad  * @trampoline: whether to emit a conditional trampoline at the end of the batch
   1406   1.1  riastrad  *
   1407   1.1  riastrad  * Parses the specified batch buffer looking for privilege violations as
   1408   1.1  riastrad  * described in the overview.
   1409   1.1  riastrad  *
   1410   1.5  riastrad  * Return: non-zero if the parser finds violations or otherwise fails; -EACCES
   1411   1.5  riastrad  * if the batch appears legal but should use hardware parsing
   1412   1.1  riastrad  */
   1413  1.23  riastrad int intel_engine_cmd_parser(struct intel_engine_cs *engine,
   1414  1.23  riastrad 			    struct i915_vma *batch,
   1415  1.23  riastrad 			    u32 batch_offset,
   1416  1.23  riastrad 			    u32 batch_length,
   1417  1.23  riastrad 			    struct i915_vma *shadow,
   1418  1.23  riastrad 			    bool trampoline)
   1419  1.23  riastrad {
   1420  1.23  riastrad 	u32 *cmd, *batch_end, offset = 0;
   1421  1.23  riastrad 	struct drm_i915_cmd_descriptor default_desc = noop_desc;
   1422  1.23  riastrad 	const struct drm_i915_cmd_descriptor *desc = &default_desc;
   1423  1.23  riastrad 	unsigned long *jump_whitelist;
   1424  1.23  riastrad 	u64 batch_addr, shadow_addr;
   1425   1.5  riastrad 	int ret = 0;
   1426   1.1  riastrad 
   1427  1.23  riastrad 	GEM_BUG_ON(!IS_ALIGNED(batch_offset, sizeof(*cmd)));
   1428  1.23  riastrad 	GEM_BUG_ON(!IS_ALIGNED(batch_length, sizeof(*cmd)));
   1429  1.23  riastrad 	GEM_BUG_ON(range_overflows_t(u64, batch_offset, batch_length,
   1430  1.23  riastrad 				     batch->size));
   1431  1.23  riastrad 	GEM_BUG_ON(!batch_length);
   1432  1.23  riastrad 
   1433  1.23  riastrad 	cmd = copy_batch(shadow->obj, batch->obj, batch_offset, batch_length);
   1434  1.23  riastrad 	if (IS_ERR(cmd)) {
   1435  1.23  riastrad 		DRM_DEBUG("CMD: Failed to copy batch\n");
   1436  1.23  riastrad 		return PTR_ERR(cmd);
   1437  1.23  riastrad 	}
   1438  1.23  riastrad 
   1439  1.23  riastrad 	jump_whitelist = NULL;
   1440  1.23  riastrad 	if (!trampoline)
   1441  1.23  riastrad 		/* Defer failure until attempted use */
   1442  1.23  riastrad 		jump_whitelist = alloc_whitelist(batch_length);
   1443   1.1  riastrad 
   1444  1.23  riastrad 	shadow_addr = gen8_canonical_addr(shadow->node.start);
   1445  1.23  riastrad 	batch_addr = gen8_canonical_addr(batch->node.start + batch_offset);
   1446  1.19      maya 
   1447   1.5  riastrad 	/*
   1448   1.5  riastrad 	 * We use the batch length as size because the shadow object is as
   1449   1.5  riastrad 	 * large or larger and copy_batch() will write MI_NOPs to the extra
   1450   1.5  riastrad 	 * space. Parsing should be faster in some cases this way.
   1451   1.5  riastrad 	 */
   1452  1.23  riastrad 	batch_end = cmd + batch_length / sizeof(*batch_end);
   1453  1.23  riastrad 	do {
   1454   1.1  riastrad 		u32 length;
   1455   1.1  riastrad 
   1456   1.1  riastrad 		if (*cmd == MI_BATCH_BUFFER_END)
   1457   1.1  riastrad 			break;
   1458   1.1  riastrad 
   1459  1.23  riastrad 		desc = find_cmd(engine, *cmd, desc, &default_desc);
   1460   1.1  riastrad 		if (!desc) {
   1461  1.23  riastrad 			DRM_DEBUG("CMD: Unrecognized command: 0x%08X\n", *cmd);
   1462   1.1  riastrad 			ret = -EINVAL;
   1463   1.1  riastrad 			break;
   1464   1.1  riastrad 		}
   1465   1.1  riastrad 
   1466   1.1  riastrad 		if (desc->flags & CMD_DESC_FIXED)
   1467   1.1  riastrad 			length = desc->length.fixed;
   1468   1.1  riastrad 		else
   1469  1.23  riastrad 			length = (*cmd & desc->length.mask) + LENGTH_BIAS;
   1470   1.1  riastrad 
   1471   1.1  riastrad 		if ((batch_end - cmd) < length) {
   1472  1.23  riastrad 			DRM_DEBUG("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n",
   1473  1.23  riastrad 				  *cmd,
   1474  1.23  riastrad 				  length,
   1475  1.23  riastrad 				  batch_end - cmd);
   1476   1.1  riastrad 			ret = -EINVAL;
   1477   1.1  riastrad 			break;
   1478   1.1  riastrad 		}
   1479   1.1  riastrad 
   1480  1.23  riastrad 		if (!check_cmd(engine, desc, cmd, length)) {
   1481  1.23  riastrad 			ret = -EACCES;
   1482  1.19      maya 			break;
   1483  1.19      maya 		}
   1484  1.19      maya 
   1485  1.19      maya 		if (desc->cmd.value == MI_BATCH_BUFFER_START) {
   1486  1.23  riastrad 			ret = check_bbstart(cmd, offset, length, batch_length,
   1487  1.23  riastrad 					    batch_addr, shadow_addr,
   1488  1.23  riastrad 					    jump_whitelist);
   1489   1.1  riastrad 			break;
   1490   1.1  riastrad 		}
   1491   1.1  riastrad 
   1492  1.23  riastrad 		if (!IS_ERR_OR_NULL(jump_whitelist))
   1493  1.23  riastrad 			__set_bit(offset, jump_whitelist);
   1494  1.19      maya 
   1495   1.5  riastrad 		cmd += length;
   1496  1.19      maya 		offset += length;
   1497  1.23  riastrad 		if  (cmd >= batch_end) {
   1498  1.23  riastrad 			DRM_DEBUG("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
   1499  1.23  riastrad 			ret = -EINVAL;
   1500  1.23  riastrad 			break;
   1501  1.23  riastrad 		}
   1502  1.23  riastrad 	} while (1);
   1503  1.23  riastrad 
   1504  1.23  riastrad 	if (trampoline) {
   1505  1.23  riastrad 		/*
   1506  1.23  riastrad 		 * With the trampoline, the shadow is executed twice.
   1507  1.23  riastrad 		 *
   1508  1.23  riastrad 		 *   1 - starting at offset 0, in privileged mode
   1509  1.23  riastrad 		 *   2 - starting at offset batch_len, as non-privileged
   1510  1.23  riastrad 		 *
   1511  1.23  riastrad 		 * Only if the batch is valid and safe to execute, do we
   1512  1.23  riastrad 		 * allow the first privileged execution to proceed. If not,
   1513  1.23  riastrad 		 * we terminate the first batch and use the second batchbuffer
   1514  1.23  riastrad 		 * entry to chain to the original unsafe non-privileged batch,
   1515  1.23  riastrad 		 * leaving it to the HW to validate.
   1516  1.23  riastrad 		 */
   1517  1.23  riastrad 		*batch_end = MI_BATCH_BUFFER_END;
   1518  1.23  riastrad 
   1519  1.23  riastrad 		if (ret) {
   1520  1.23  riastrad 			/* Batch unsafe to execute with privileges, cancel! */
   1521  1.23  riastrad 			cmd = page_mask_bits(shadow->obj->mm.mapping);
   1522  1.23  riastrad 			*cmd = MI_BATCH_BUFFER_END;
   1523  1.23  riastrad 
   1524  1.23  riastrad 			/* If batch is unsafe but valid, jump to the original */
   1525  1.23  riastrad 			if (ret == -EACCES) {
   1526  1.23  riastrad 				unsigned int flags;
   1527  1.23  riastrad 
   1528  1.23  riastrad 				flags = MI_BATCH_NON_SECURE_I965;
   1529  1.23  riastrad 				if (IS_HASWELL(engine->i915))
   1530  1.23  riastrad 					flags = MI_BATCH_NON_SECURE_HSW;
   1531  1.23  riastrad 
   1532  1.23  riastrad 				GEM_BUG_ON(!IS_GEN_RANGE(engine->i915, 6, 7));
   1533  1.23  riastrad 				__gen6_emit_bb_start(batch_end,
   1534  1.23  riastrad 						     batch_addr,
   1535  1.23  riastrad 						     flags);
   1536  1.23  riastrad 
   1537  1.23  riastrad 				ret = 0; /* allow execution */
   1538  1.23  riastrad 			}
   1539  1.23  riastrad 		}
   1540  1.23  riastrad 
   1541  1.23  riastrad 		if (shadow_needs_clflush(shadow->obj))
   1542  1.23  riastrad 			drm_clflush_virt_range(batch_end, 8);
   1543   1.5  riastrad 	}
   1544   1.1  riastrad 
   1545  1.23  riastrad 	if (shadow_needs_clflush(shadow->obj)) {
   1546  1.23  riastrad 		void *ptr = page_mask_bits(shadow->obj->mm.mapping);
   1547   1.1  riastrad 
   1548  1.23  riastrad 		drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr);
   1549  1.23  riastrad 	}
   1550  1.23  riastrad 
   1551  1.23  riastrad 	if (!IS_ERR_OR_NULL(jump_whitelist))
   1552  1.23  riastrad 		kfree(jump_whitelist);
   1553  1.23  riastrad 	i915_gem_object_unpin_map(shadow->obj);
   1554   1.5  riastrad 	return ret;
   1555   1.5  riastrad }
   1556   1.1  riastrad 
   1557   1.5  riastrad /**
   1558   1.5  riastrad  * i915_cmd_parser_get_version() - get the cmd parser version number
   1559  1.23  riastrad  * @dev_priv: i915 device private
   1560   1.5  riastrad  *
   1561   1.5  riastrad  * The cmd parser maintains a simple increasing integer version number suitable
   1562   1.5  riastrad  * for passing to userspace clients to determine what operations are permitted.
   1563   1.5  riastrad  *
   1564   1.5  riastrad  * Return: the current version number of the cmd parser
   1565   1.5  riastrad  */
   1566  1.19      maya int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv)
   1567   1.5  riastrad {
   1568  1.23  riastrad 	struct intel_engine_cs *engine;
   1569  1.23  riastrad 	bool active = false;
   1570  1.23  riastrad 
   1571  1.23  riastrad 	/* If the command parser is not enabled, report 0 - unsupported */
   1572  1.23  riastrad 	for_each_uabi_engine(engine, dev_priv) {
   1573  1.23  riastrad 		if (intel_engine_using_cmd_parser(engine)) {
   1574  1.23  riastrad 			active = true;
   1575  1.23  riastrad 			break;
   1576  1.23  riastrad 		}
   1577  1.23  riastrad 	}
   1578  1.23  riastrad 	if (!active)
   1579  1.23  riastrad 		return 0;
   1580  1.23  riastrad 
   1581   1.5  riastrad 	/*
   1582   1.5  riastrad 	 * Command parser version history
   1583   1.5  riastrad 	 *
   1584   1.5  riastrad 	 * 1. Initial version. Checks batches and reports violations, but leaves
   1585   1.5  riastrad 	 *    hardware parsing enabled (so does not allow new use cases).
   1586   1.5  riastrad 	 * 2. Allow access to the MI_PREDICATE_SRC0 and
   1587   1.5  riastrad 	 *    MI_PREDICATE_SRC1 registers.
   1588   1.5  riastrad 	 * 3. Allow access to the GPGPU_THREADS_DISPATCHED register.
   1589   1.5  riastrad 	 * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3.
   1590   1.5  riastrad 	 * 5. GPGPU dispatch compute indirect registers.
   1591  1.23  riastrad 	 * 6. TIMESTAMP register and Haswell CS GPR registers
   1592  1.23  riastrad 	 * 7. Allow MI_LOAD_REGISTER_REG between whitelisted registers.
   1593  1.23  riastrad 	 * 8. Don't report cmd_check() failures as EINVAL errors to userspace;
   1594  1.23  riastrad 	 *    rely on the HW to NOOP disallowed commands as it would without
   1595  1.23  riastrad 	 *    the parser enabled.
   1596  1.23  riastrad 	 * 9. Don't whitelist or handle oacontrol specially, as ownership
   1597  1.23  riastrad 	 *    for oacontrol state is moving to i915-perf.
   1598  1.23  riastrad 	 * 10. Support for Gen9 BCS Parsing
   1599   1.5  riastrad 	 */
   1600  1.23  riastrad 	return 10;
   1601   1.1  riastrad }
   1602