From: Greg Kroah-Hartman Date: Tue, 12 Nov 2019 18:10:06 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.4.201~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ed6d697a35f3bce0ffc209fa594250c17885539f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: drm-i915-add-gen9-bcs-cmdparsing.patch drm-i915-add-support-for-mandatory-cmdparsing.patch drm-i915-allow-parsing-of-unsized-batches.patch drm-i915-cleanup-use-of-instr_client_mask.patch drm-i915-cmdparser-add-support-for-backward-jumps.patch drm-i915-cmdparser-check-reg_table_count-before-derefencing.patch drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch drm-i915-cmdparser-fix-jump-whitelist-clearing.patch drm-i915-cmdparser-ignore-length-operands-during-command-matching.patch drm-i915-cmdparser-limit-clflush-to-active-cachelines.patch drm-i915-cmdparser-use-explicit-goto-for-error-paths.patch drm-i915-disable-secure-batches-for-gen6.patch drm-i915-don-t-whitelist-oacontrol-in-cmd-parser.patch drm-i915-gen8-add-rc6-ctx-corruption-wa.patch drm-i915-gtt-add-read-only-pages-to-gen8_pte_encode.patch drm-i915-gtt-disable-read-only-support-under-gvt.patch drm-i915-gtt-read-only-pages-for-insert_entries-on-bdw.patch drm-i915-kick-out-cmd_parser-specific-structs-from-i915_drv.h.patch drm-i915-lower-rm-timeout-to-avoid-dsi-hard-hangs.patch drm-i915-move-engine-needs_cmd_parser-to-engine-flags.patch drm-i915-prevent-writing-into-a-read-only-object-via-a-ggtt-mmap.patch drm-i915-remove-master-tables-from-cmdparser.patch drm-i915-rename-gen7-cmdparser-tables.patch drm-i915-return-eacces-for-check_cmd-failures.patch drm-i915-silence-smatch-for-cmdparser.patch drm-i915-support-ro-ppgtt-mapped-cmdparser-shadow-buffers.patch drm-i915-use-the-precomputed-value-for-whether-to-enable-command-parsing.patch --- diff --git a/queue-4.9/drm-i915-add-gen9-bcs-cmdparsing.patch b/queue-4.9/drm-i915-add-gen9-bcs-cmdparsing.patch new file mode 100644 index 00000000000..0e93aea7154 --- /dev/null +++ b/queue-4.9/drm-i915-add-gen9-bcs-cmdparsing.patch @@ -0,0 +1,264 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Mon, 23 Apr 2018 11:12:15 -0700 +Subject: drm/i915: Add gen9 BCS cmdparsing + +From: Jon Bloomfield + +commit 0f2f39758341df70202ae1c42d5a1e4ee392b6d3 upstream. + +For gen9 we enable cmdparsing on the BCS ring, specifically +to catch inadvertent accesses to sensitive registers + +Unlike gen7/hsw, we use the parser only to block certain +registers. We can rely on h/w to block restricted commands, +so the command tables only provide enough info to allow the +parser to delineate each command, and identify commands that +access registers. + +Note: This patch deliberately ignores checkpatch issues in +favour of matching the style of the surrounding code. We'll +correct the entire file in one go in a later patch. + +v3: rebase (Mika) +v4: Add RING_TIMESTAMP registers to whitelist (Jon) + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 116 ++++++++++++++++++++++++++++++--- + drivers/gpu/drm/i915/i915_gem_gtt.c | 3 + drivers/gpu/drm/i915/i915_reg.h | 4 + + 3 files changed, 112 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -442,6 +442,47 @@ static const struct drm_i915_cmd_descrip + CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ), + }; + ++/* ++ * For Gen9 we can still rely on the h/w to enforce cmd security, and only ++ * need to re-enforce the register access checks. We therefore only need to ++ * teach the cmdparser how to find the end of each command, and identify ++ * register accesses. The table doesn't need to reject any commands, and so ++ * the only commands listed here are: ++ * 1) Those that touch registers ++ * 2) Those that do not have the default 8-bit length ++ * ++ * Note that the default MI length mask chosen for this table is 0xFF, not ++ * the 0x3F used on older devices. This is because the vast majority of MI ++ * cmds on Gen9 use a standard 8-bit Length field. ++ * All the Gen9 blitter instructions are standard 0xFF length mask, and ++ * none allow access to non-general registers, so in fact no BLT cmds are ++ * included in the table at all. ++ * ++ */ ++static const struct drm_i915_cmd_descriptor gen9_blt_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_FLUSH, SMI, F, 1, S ), ++ CMD( MI_ARB_CHECK, SMI, F, 1, S ), ++ CMD( MI_REPORT_HEAD, SMI, F, 1, S ), ++ CMD( MI_ARB_ON_OFF, SMI, F, 1, S ), ++ CMD( MI_SUSPEND_FLUSH, SMI, F, 1, S ), ++ CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, S ), ++ CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, S ), ++ CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3FF, S ), ++ CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, ++ .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ), ++ CMD( MI_UPDATE_GTT, SMI, !F, 0x3FF, S ), ++ CMD( MI_STORE_REGISTER_MEM_GEN8, SMI, F, 4, W, ++ .reg = { .offset = 1, .mask = 0x007FFFFC } ), ++ CMD( MI_FLUSH_DW, SMI, !F, 0x3F, S ), ++ CMD( MI_LOAD_REGISTER_MEM_GEN8, SMI, F, 4, W, ++ .reg = { .offset = 1, .mask = 0x007FFFFC } ), ++ CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, W, ++ .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 } ), ++}; ++ + static const struct drm_i915_cmd_descriptor noop_desc = + CMD(MI_NOOP, SMI, F, 1, S); + +@@ -488,6 +529,11 @@ static const struct drm_i915_cmd_table h + { hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) }, + }; + ++static const struct drm_i915_cmd_table gen9_blt_cmd_table[] = { ++ { gen9_blt_cmds, ARRAY_SIZE(gen9_blt_cmds) }, ++}; ++ ++ + /* + * Register whitelists, sorted by increasing register offset. + */ +@@ -603,6 +649,29 @@ static const struct drm_i915_reg_descrip + REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE), + }; + ++static const struct drm_i915_reg_descriptor gen9_blt_regs[] = { ++ REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE), ++ REG64_IDX(RING_TIMESTAMP, BSD_RING_BASE), ++ REG32(BCS_SWCTRL), ++ REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE), ++ REG64_IDX(BCS_GPR, 0), ++ REG64_IDX(BCS_GPR, 1), ++ REG64_IDX(BCS_GPR, 2), ++ REG64_IDX(BCS_GPR, 3), ++ REG64_IDX(BCS_GPR, 4), ++ REG64_IDX(BCS_GPR, 5), ++ REG64_IDX(BCS_GPR, 6), ++ REG64_IDX(BCS_GPR, 7), ++ REG64_IDX(BCS_GPR, 8), ++ REG64_IDX(BCS_GPR, 9), ++ REG64_IDX(BCS_GPR, 10), ++ REG64_IDX(BCS_GPR, 11), ++ REG64_IDX(BCS_GPR, 12), ++ REG64_IDX(BCS_GPR, 13), ++ REG64_IDX(BCS_GPR, 14), ++ REG64_IDX(BCS_GPR, 15), ++}; ++ + #undef REG64 + #undef REG32 + +@@ -628,6 +697,10 @@ static const struct drm_i915_reg_table h + { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) }, + }; + ++static const struct drm_i915_reg_table gen9_blt_reg_tables[] = { ++ { gen9_blt_regs, ARRAY_SIZE(gen9_blt_regs) }, ++}; ++ + static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) + { + u32 client = cmd_header >> INSTR_CLIENT_SHIFT; +@@ -683,6 +756,17 @@ static u32 gen7_blt_get_cmd_length_mask( + return 0; + } + ++static u32 gen9_blt_get_cmd_length_mask(u32 cmd_header) ++{ ++ u32 client = cmd_header >> INSTR_CLIENT_SHIFT; ++ ++ if (client == INSTR_MI_CLIENT || client == INSTR_BC_CLIENT) ++ return 0xFF; ++ ++ DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header); ++ return 0; ++} ++ + static bool validate_cmds_sorted(const struct intel_engine_cs *engine, + const struct drm_i915_cmd_table *cmd_tables, + int cmd_table_count) +@@ -840,7 +924,8 @@ void intel_engine_init_cmd_parser(struct + int cmd_table_count; + int ret; + +- if (!IS_GEN7(engine->i915)) ++ if (!IS_GEN7(engine->i915) && !(IS_GEN9(engine->i915) && ++ engine->id == BCS)) + return; + + switch (engine->id) { +@@ -861,7 +946,6 @@ void intel_engine_init_cmd_parser(struct + engine->reg_tables = ivb_render_reg_tables; + engine->reg_table_count = ARRAY_SIZE(ivb_render_reg_tables); + } +- + engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask; + break; + case VCS: +@@ -870,7 +954,16 @@ void intel_engine_init_cmd_parser(struct + engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; + break; + case BCS: +- if (IS_HASWELL(engine->i915)) { ++ engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask; ++ if (IS_GEN9(engine->i915)) { ++ cmd_tables = gen9_blt_cmd_table; ++ cmd_table_count = ARRAY_SIZE(gen9_blt_cmd_table); ++ engine->get_cmd_length_mask = ++ gen9_blt_get_cmd_length_mask; ++ ++ /* BCS Engine unsafe without parser */ ++ engine->flags |= I915_ENGINE_REQUIRES_CMD_PARSER; ++ } else if (IS_HASWELL(engine->i915)) { + cmd_tables = hsw_blt_ring_cmd_table; + cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmd_table); + } else { +@@ -878,15 +971,17 @@ void intel_engine_init_cmd_parser(struct + cmd_table_count = ARRAY_SIZE(gen7_blt_cmd_table); + } + +- if (IS_HASWELL(engine->i915)) { ++ if (IS_GEN9(engine->i915)) { ++ engine->reg_tables = gen9_blt_reg_tables; ++ engine->reg_table_count = ++ ARRAY_SIZE(gen9_blt_reg_tables); ++ } else if (IS_HASWELL(engine->i915)) { + engine->reg_tables = hsw_blt_reg_tables; + engine->reg_table_count = ARRAY_SIZE(hsw_blt_reg_tables); + } else { + engine->reg_tables = ivb_blt_reg_tables; + engine->reg_table_count = ARRAY_SIZE(ivb_blt_reg_tables); + } +- +- engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask; + break; + case VECS: + cmd_tables = hsw_vebox_cmd_table; +@@ -1260,9 +1355,9 @@ int intel_engine_cmd_parser(struct intel + } + + /* +- * If the batch buffer contains a chained batch, return an +- * error that tells the caller to abort and dispatch the +- * workload as a non-secure batch. ++ * We don't try to handle BATCH_BUFFER_START because it adds ++ * non-trivial complexity. Instead we abort the scan and return ++ * and error to indicate that the batch is unsafe. + */ + if (desc->cmd.value == MI_BATCH_BUFFER_START) { + ret = -EACCES; +@@ -1341,6 +1436,7 @@ int i915_cmd_parser_get_version(struct d + * the parser enabled. + * 9. Don't whitelist or handle oacontrol specially, as ownership + * for oacontrol state is moving to i915-perf. ++ * 10. Support for Gen9 BCS Parsing + */ +- return 9; ++ return 10; + } +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -140,7 +140,8 @@ int intel_sanitize_enable_ppgtt(struct d + if (enable_ppgtt == 0 && INTEL_GEN(dev_priv) < 9) + return 0; + +- if (enable_ppgtt == 1) ++ /* Full PPGTT is required by the Gen9 cmdparser */ ++ if (enable_ppgtt == 1 && INTEL_GEN(dev_priv) != 9) + return 1; + + if (enable_ppgtt == 2 && has_full_ppgtt) +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -568,6 +568,10 @@ static inline bool i915_mmio_reg_valid(i + */ + #define BCS_SWCTRL _MMIO(0x22200) + ++/* There are 16 GPR registers */ ++#define BCS_GPR(n) _MMIO(0x22600 + (n) * 8) ++#define BCS_GPR_UDW(n) _MMIO(0x22600 + (n) * 8 + 4) ++ + #define GPGPU_THREADS_DISPATCHED _MMIO(0x2290) + #define GPGPU_THREADS_DISPATCHED_UDW _MMIO(0x2290 + 4) + #define HS_INVOCATION_COUNT _MMIO(0x2300) diff --git a/queue-4.9/drm-i915-add-support-for-mandatory-cmdparsing.patch b/queue-4.9/drm-i915-add-support-for-mandatory-cmdparsing.patch new file mode 100644 index 00000000000..eae942d0768 --- /dev/null +++ b/queue-4.9/drm-i915-add-support-for-mandatory-cmdparsing.patch @@ -0,0 +1,110 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Wed, 1 Aug 2018 09:33:59 -0700 +Subject: drm/i915: Add support for mandatory cmdparsing + +From: Jon Bloomfield + +commit 311a50e76a33d1e029563c24b2ff6db0c02b5afe upstream. + +The existing cmdparser for gen7 can be bypassed by specifying +batch_len=0 in the execbuf call. This is safe because bypassing +simply reduces the cmd-set available. + +In a later patch we will introduce cmdparsing for gen9, as a +security measure, which must be strictly enforced since without +it we are vulnerable to DoS attacks. + +Introduce the concept of 'required' cmd parsing that cannot be +bypassed by submitting zero-length bb's. + +v2: rebase (Mika) +v2: rebase (Mika) +v3: fix conflict on engine flags (Mika) + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 6 +++--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 ++- + drivers/gpu/drm/i915/intel_ringbuffer.h | 14 +++++++++++--- + 3 files changed, 16 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -916,7 +916,7 @@ void intel_engine_init_cmd_parser(struct + return; + } + +- engine->flags |= I915_ENGINE_NEEDS_CMD_PARSER; ++ engine->flags |= I915_ENGINE_USING_CMD_PARSER; + } + + /** +@@ -928,7 +928,7 @@ void intel_engine_init_cmd_parser(struct + */ + void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine) + { +- if (!intel_engine_needs_cmd_parser(engine)) ++ if (!intel_engine_using_cmd_parser(engine)) + return; + + fini_hash_table(engine); +@@ -1316,7 +1316,7 @@ int i915_cmd_parser_get_version(struct d + + /* If the command parser is not enabled, report 0 - unsupported */ + for_each_engine(engine, dev_priv) { +- if (intel_engine_needs_cmd_parser(engine)) { ++ if (intel_engine_using_cmd_parser(engine)) { + active = true; + break; + } +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1716,7 +1716,8 @@ i915_gem_do_execbuffer(struct drm_device + } + + params->args_batch_start_offset = args->batch_start_offset; +- if (intel_engine_needs_cmd_parser(engine) && args->batch_len) { ++ if (intel_engine_requires_cmd_parser(engine) || ++ (intel_engine_using_cmd_parser(engine) && args->batch_len)) { + struct i915_vma *vma; + + vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry, +--- a/drivers/gpu/drm/i915/intel_ringbuffer.h ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.h +@@ -341,7 +341,8 @@ struct intel_engine_cs { + + struct intel_engine_hangcheck hangcheck; + +-#define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) ++#define I915_ENGINE_USING_CMD_PARSER BIT(0) ++#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(3) + unsigned int flags; + + /* +@@ -375,9 +376,16 @@ intel_engine_initialized(const struct in + return engine->i915 != NULL; + } + +-static inline bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine) ++static inline bool ++intel_engine_using_cmd_parser(const struct intel_engine_cs *engine) ++{ ++ return engine->flags & I915_ENGINE_USING_CMD_PARSER; ++} ++ ++static inline bool ++intel_engine_requires_cmd_parser(const struct intel_engine_cs *engine) + { +- return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER; ++ return engine->flags & I915_ENGINE_REQUIRES_CMD_PARSER; + } + + static inline unsigned int diff --git a/queue-4.9/drm-i915-allow-parsing-of-unsized-batches.patch b/queue-4.9/drm-i915-allow-parsing-of-unsized-batches.patch new file mode 100644 index 00000000000..2cc3ea99eb3 --- /dev/null +++ b/queue-4.9/drm-i915-allow-parsing-of-unsized-batches.patch @@ -0,0 +1,75 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Wed, 1 Aug 2018 09:45:50 -0700 +Subject: drm/i915: Allow parsing of unsized batches + +From: Jon Bloomfield + +commit 435e8fc059dbe0eec823a75c22da2972390ba9e0 upstream. + +In "drm/i915: Add support for mandatory cmdparsing" we introduced the +concept of mandatory parsing. This allows the cmdparser to be invoked +even when user passes batch_len=0 to the execbuf ioctl's. + +However, the cmdparser needs to know the extents of the buffer being +scanned. Refactor the code to ensure the cmdparser uses the actual +object size, instead of the incoming length, if user passes 0. + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -55,6 +55,7 @@ struct i915_execbuffer_params { + struct i915_vma *batch; + u32 dispatch_flags; + u32 args_batch_start_offset; ++ u64 args_batch_len; + struct intel_engine_cs *engine; + struct i915_gem_context *ctx; + struct drm_i915_gem_request *request; +@@ -1506,13 +1507,10 @@ execbuf_submit(struct i915_execbuffer_pa + return ret; + } + +- exec_len = args->batch_len; ++ exec_len = params->args_batch_len; + exec_start = params->batch->node.start + + params->args_batch_start_offset; + +- if (exec_len == 0) +- exec_len = params->batch->size - params->args_batch_start_offset; +- + ret = params->engine->emit_bb_start(params->request, + exec_start, exec_len, + params->dispatch_flags); +@@ -1748,6 +1746,10 @@ i915_gem_do_execbuffer(struct drm_device + } + + params->args_batch_start_offset = args->batch_start_offset; ++ params->args_batch_len = args->batch_len; ++ if (args->batch_len == 0) ++ params->args_batch_len = params->batch->size - params->args_batch_start_offset; ++ + if (intel_engine_requires_cmd_parser(engine) || + (intel_engine_using_cmd_parser(engine) && args->batch_len)) { + struct i915_vma *vma; +@@ -1755,8 +1757,8 @@ i915_gem_do_execbuffer(struct drm_device + vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry, + params->batch->obj, + eb, vm, +- args->batch_start_offset, +- args->batch_len); ++ params->args_batch_start_offset, ++ params->args_batch_len); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; diff --git a/queue-4.9/drm-i915-cleanup-use-of-instr_client_mask.patch b/queue-4.9/drm-i915-cleanup-use-of-instr_client_mask.patch new file mode 100644 index 00000000000..ccad98110fb --- /dev/null +++ b/queue-4.9/drm-i915-cleanup-use-of-instr_client_mask.patch @@ -0,0 +1,65 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Matthew Auld +Date: Mon, 14 Nov 2016 22:39:34 +0000 +Subject: drm/i915: cleanup use of INSTR_CLIENT_MASK + +From: Matthew Auld + +commit e3f51ece02f877d2ce9619aa8d5919db56f39582 upstream. + +Doing cmd_header >> 29 to extract our 3-bit client value where we know +cmd_header is a u32 shouldn't then also require the use of a mask. So +remove the redundant operation and get rid of INSTR_CLIENT_MASK now that +there are no longer any users. + +Cc: Chris Wilson +Signed-off-by: Matthew Auld +Reviewed-by: Chris Wilson +Signed-off-by: Joonas Lahtinen +Signed-off-by: Jon Bloomfield +Link: http://patchwork.freedesktop.org/patch/msgid/1479163174-29686-1-git-send-email-matthew.auld@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 6 +++--- + drivers/gpu/drm/i915/i915_reg.h | 1 - + 2 files changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -655,7 +655,7 @@ static const struct drm_i915_reg_table h + + static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) + { +- u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; ++ u32 client = cmd_header >> INSTR_CLIENT_SHIFT; + u32 subclient = + (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT; + +@@ -674,7 +674,7 @@ static u32 gen7_render_get_cmd_length_ma + + static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header) + { +- u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; ++ u32 client = cmd_header >> INSTR_CLIENT_SHIFT; + u32 subclient = + (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT; + u32 op = (cmd_header & INSTR_26_TO_24_MASK) >> INSTR_26_TO_24_SHIFT; +@@ -697,7 +697,7 @@ static u32 gen7_bsd_get_cmd_length_mask( + + static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header) + { +- u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; ++ u32 client = cmd_header >> INSTR_CLIENT_SHIFT; + + if (client == INSTR_MI_CLIENT) + return 0x3F; +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -295,7 +295,6 @@ static inline bool i915_mmio_reg_valid(i + * 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 diff --git a/queue-4.9/drm-i915-cmdparser-add-support-for-backward-jumps.patch b/queue-4.9/drm-i915-cmdparser-add-support-for-backward-jumps.patch new file mode 100644 index 00000000000..a67e18796ca --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-add-support-for-backward-jumps.patch @@ -0,0 +1,424 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Thu, 20 Sep 2018 09:58:36 -0700 +Subject: drm/i915/cmdparser: Add support for backward jumps + +From: Jon Bloomfield + +commit f8c08d8faee5567803c8c533865296ca30286bbf upstream. + +To keep things manageable, the pre-gen9 cmdparser does not +attempt to track any form of nested BB_START's. This did not +prevent usermode from using nested starts, or even chained +batches because the cmdparser is not strictly enforced pre gen9. + +Instead, the existence of a nested BB_START would cause the batch +to be emitted in insecure mode, and any privileged capabilities +would not be available. + +For Gen9, the cmdparser becomes mandatory (for BCS at least), and +so not providing any form of nested BB_START support becomes +overly restrictive. Any such batch will simply not run. + +We make heavy use of backward jumps in igt, and it is much easier +to add support for this restricted subset of nested jumps, than to +rewrite the whole of our test suite to avoid them. + +Add the required logic to support limited backward jumps, to +instructions that have already been validated by the parser. + +Note that it's not sufficient to simply approve any BB_START +that jumps backwards in the buffer because this would allow an +attacker to embed a rogue instruction sequence within the +operand words of a harmless instruction (say LRI) and jump to +that. + +We introduce a bit array to track every instr offset successfully +validated, and test the target of BB_START against this. If the +target offset hits, it is re-written to the same offset in the +shadow buffer and the BB_START cmd is allowed. + +Note: This patch deliberately ignores checkpatch issues in the +cmdtables, in order to match the style of the surrounding code. +We'll correct the entire file in one go in a later patch. + +v2: set dispatch secure late (Mika) +v3: rebase (Mika) +v4: Clear whitelist on each parse +Minor review updates (Chris) +v5: Correct backward jump batching +v6: fix compilation error due to struct eb shuffle (Mika) + +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Jon Bloomfield +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 151 ++++++++++++++++++++++++++--- + drivers/gpu/drm/i915/i915_drv.h | 16 ++- + drivers/gpu/drm/i915/i915_gem_context.c | 5 + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 43 +++++--- + 4 files changed, 181 insertions(+), 34 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -481,6 +481,19 @@ static const struct drm_i915_cmd_descrip + .reg = { .offset = 1, .mask = 0x007FFFFC } ), + CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, W, + .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 } ), ++ ++ /* ++ * We allow BB_START but apply further checks. We just sanitize the ++ * basic fields here. ++ */ ++#define MI_BB_START_OPERAND_MASK GENMASK(SMI-1, 0) ++#define MI_BB_START_OPERAND_EXPECT (MI_BATCH_PPGTT_HSW | 1) ++ CMD( MI_BATCH_BUFFER_START_GEN8, SMI, !F, 0xFF, B, ++ .bits = {{ ++ .offset = 0, ++ .mask = MI_BB_START_OPERAND_MASK, ++ .expected = MI_BB_START_OPERAND_EXPECT, ++ }}, ), + }; + + static const struct drm_i915_cmd_descriptor noop_desc = +@@ -1292,15 +1305,113 @@ static bool check_cmd(const struct intel + return true; + } + ++static int check_bbstart(const struct i915_gem_context *ctx, ++ u32 *cmd, u32 offset, u32 length, ++ u32 batch_len, ++ u64 batch_start, ++ u64 shadow_batch_start) ++{ ++ u64 jump_offset, jump_target; ++ u32 target_cmd_offset, target_cmd_index; ++ ++ /* For igt compatibility on older platforms */ ++ if (CMDPARSER_USES_GGTT(ctx->i915)) { ++ DRM_DEBUG("CMD: Rejecting BB_START for ggtt based submission\n"); ++ return -EACCES; ++ } ++ ++ if (length != 3) { ++ DRM_DEBUG("CMD: Recursive BB_START with bad length(%u)\n", ++ length); ++ return -EINVAL; ++ } ++ ++ jump_target = *(u64*)(cmd+1); ++ jump_offset = jump_target - batch_start; ++ ++ /* ++ * Any underflow of jump_target is guaranteed to be outside the range ++ * of a u32, so >= test catches both too large and too small ++ */ ++ if (jump_offset >= batch_len) { ++ DRM_DEBUG("CMD: BB_START to 0x%llx jumps out of BB\n", ++ jump_target); ++ return -EINVAL; ++ } ++ ++ /* ++ * This cannot overflow a u32 because we already checked jump_offset ++ * is within the BB, and the batch_len is a u32 ++ */ ++ target_cmd_offset = lower_32_bits(jump_offset); ++ target_cmd_index = target_cmd_offset / sizeof(u32); ++ ++ *(u64*)(cmd + 1) = shadow_batch_start + target_cmd_offset; ++ ++ if (target_cmd_index == offset) ++ return 0; ++ ++ if (ctx->jump_whitelist_cmds <= target_cmd_index) { ++ DRM_DEBUG("CMD: Rejecting BB_START - truncated whitelist array\n"); ++ return -EINVAL; ++ } else if (!test_bit(target_cmd_index, ctx->jump_whitelist)) { ++ DRM_DEBUG("CMD: BB_START to 0x%llx not a previously executed cmd\n", ++ jump_target); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void init_whitelist(struct i915_gem_context *ctx, u32 batch_len) ++{ ++ const u32 batch_cmds = DIV_ROUND_UP(batch_len, sizeof(u32)); ++ const u32 exact_size = BITS_TO_LONGS(batch_cmds); ++ u32 next_size = BITS_TO_LONGS(roundup_pow_of_two(batch_cmds)); ++ unsigned long *next_whitelist; ++ ++ if (CMDPARSER_USES_GGTT(ctx->i915)) ++ return; ++ ++ if (batch_cmds <= ctx->jump_whitelist_cmds) { ++ memset(ctx->jump_whitelist, 0, exact_size * sizeof(u32)); ++ return; ++ } ++ ++again: ++ next_whitelist = kcalloc(next_size, sizeof(long), GFP_KERNEL); ++ if (next_whitelist) { ++ kfree(ctx->jump_whitelist); ++ ctx->jump_whitelist = next_whitelist; ++ ctx->jump_whitelist_cmds = ++ next_size * BITS_PER_BYTE * sizeof(long); ++ return; ++ } ++ ++ if (next_size > exact_size) { ++ next_size = exact_size; ++ goto again; ++ } ++ ++ DRM_DEBUG("CMD: Failed to extend whitelist. BB_START may be disallowed\n"); ++ memset(ctx->jump_whitelist, 0, ++ BITS_TO_LONGS(ctx->jump_whitelist_cmds) * sizeof(u32)); ++ ++ return; ++} ++ + #define LENGTH_BIAS 2 + + /** + * i915_parse_cmds() - parse a submitted batch buffer for privilege violations ++ * @ctx: the context in which the batch is to execute + * @engine: the engine on which the batch is to execute + * @batch_obj: the batch buffer in question +- * @shadow_batch_obj: copy of the batch buffer in question ++ * @batch_start: Canonical base address of batch + * @batch_start_offset: byte offset in the batch at which execution starts + * @batch_len: length of the commands in batch_obj ++ * @shadow_batch_obj: copy of the batch buffer in question ++ * @shadow_batch_start: Canonical base address of shadow_batch_obj + * + * Parses the specified batch buffer looking for privilege violations as + * described in the overview. +@@ -1308,13 +1419,17 @@ static bool check_cmd(const struct intel + * Return: non-zero if the parser finds violations or otherwise fails; -EACCES + * if the batch appears legal but should use hardware parsing + */ +-int intel_engine_cmd_parser(struct intel_engine_cs *engine, ++ ++int intel_engine_cmd_parser(struct i915_gem_context *ctx, ++ struct intel_engine_cs *engine, + struct drm_i915_gem_object *batch_obj, +- struct drm_i915_gem_object *shadow_batch_obj, ++ u64 batch_start, + u32 batch_start_offset, +- u32 batch_len) ++ u32 batch_len, ++ struct drm_i915_gem_object *shadow_batch_obj, ++ u64 shadow_batch_start) + { +- u32 *cmd, *batch_end; ++ u32 *cmd, *batch_end, offset = 0; + struct drm_i915_cmd_descriptor default_desc = noop_desc; + const struct drm_i915_cmd_descriptor *desc = &default_desc; + bool needs_clflush_after = false; +@@ -1328,6 +1443,8 @@ int intel_engine_cmd_parser(struct intel + return PTR_ERR(cmd); + } + ++ init_whitelist(ctx, batch_len); ++ + /* + * We use the batch length as size because the shadow object is as + * large or larger and copy_batch() will write MI_NOPs to the extra +@@ -1348,16 +1465,6 @@ int intel_engine_cmd_parser(struct intel + goto err; + } + +- /* +- * We don't try to handle BATCH_BUFFER_START because it adds +- * non-trivial complexity. Instead we abort the scan and return +- * and error to indicate that the batch is unsafe. +- */ +- if (desc->cmd.value == MI_BATCH_BUFFER_START) { +- ret = -EACCES; +- goto err; +- } +- + if (desc->flags & CMD_DESC_FIXED) + length = desc->length.fixed; + else +@@ -1377,7 +1484,21 @@ int intel_engine_cmd_parser(struct intel + goto err; + } + ++ if (desc->cmd.value == MI_BATCH_BUFFER_START) { ++ ret = check_bbstart(ctx, cmd, offset, length, ++ batch_len, batch_start, ++ shadow_batch_start); ++ ++ if (ret) ++ goto err; ++ break; ++ } ++ ++ if (ctx->jump_whitelist_cmds > offset) ++ set_bit(offset, ctx->jump_whitelist); ++ + cmd += length; ++ offset += length; + if (cmd >= batch_end) { + DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); + ret = -EINVAL; +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -943,6 +943,13 @@ struct i915_gem_context { + struct list_head link; + + u8 remap_slice; ++ ++ /** jump_whitelist: Bit array for tracking cmds during cmdparsing */ ++ unsigned long *jump_whitelist; ++ ++ /** jump_whitelist_cmds: No of cmd slots available */ ++ u32 jump_whitelist_cmds; ++ + bool closed:1; + }; + +@@ -3483,11 +3490,14 @@ const char *i915_cache_level_str(struct + int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv); + void intel_engine_init_cmd_parser(struct intel_engine_cs *engine); + void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine); +-int intel_engine_cmd_parser(struct intel_engine_cs *engine, ++int intel_engine_cmd_parser(struct i915_gem_context *cxt, ++ struct intel_engine_cs *engine, + struct drm_i915_gem_object *batch_obj, +- struct drm_i915_gem_object *shadow_batch_obj, ++ u64 user_batch_start, + u32 batch_start_offset, +- u32 batch_len); ++ u32 batch_len, ++ struct drm_i915_gem_object *shadow_batch_obj, ++ u64 shadow_batch_start); + + /* i915_suspend.c */ + extern int i915_save_state(struct drm_device *dev); +--- a/drivers/gpu/drm/i915/i915_gem_context.c ++++ b/drivers/gpu/drm/i915/i915_gem_context.c +@@ -158,6 +158,8 @@ void i915_gem_context_free(struct kref * + i915_vma_put(ce->state); + } + ++ kfree(ctx->jump_whitelist); ++ + put_pid(ctx->pid); + list_del(&ctx->link); + +@@ -327,6 +329,9 @@ __create_hw_context(struct drm_device *d + GEN8_CTX_ADDRESSING_MODE_SHIFT; + ATOMIC_INIT_NOTIFIER_HEAD(&ctx->status_notifier); + ++ ctx->jump_whitelist = NULL; ++ ctx->jump_whitelist_cmds = 0; ++ + return ctx; + + err_out: +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1429,27 +1429,44 @@ shadow_batch_pin(struct drm_i915_gem_obj + static struct i915_vma * + i915_gem_execbuffer_parse(struct intel_engine_cs *engine, + struct drm_i915_gem_exec_object2 *shadow_exec_entry, +- struct drm_i915_gem_object *batch_obj, ++ struct i915_execbuffer_params *params, + struct eb_vmas *eb, +- struct i915_address_space *vm, +- u32 batch_start_offset, +- u32 batch_len) ++ struct i915_address_space *vm) + { ++ struct drm_i915_gem_object *batch_obj = params->batch->obj; + struct drm_i915_gem_object *shadow_batch_obj; + struct i915_vma *vma; ++ u64 batch_start; ++ u32 batch_start_offset = params->args_batch_start_offset; ++ u32 batch_len = params->args_batch_len; ++ u64 shadow_batch_start; + int ret; + ++ + shadow_batch_obj = i915_gem_batch_pool_get(&engine->batch_pool, + PAGE_ALIGN(batch_len)); + if (IS_ERR(shadow_batch_obj)) + return ERR_CAST(shadow_batch_obj); + +- ret = intel_engine_cmd_parser(engine, ++ vma = shadow_batch_pin(shadow_batch_obj, vm); ++ if (IS_ERR(vma)) ++ goto out; ++ ++ batch_start = gen8_canonical_addr(params->batch->node.start) + ++ batch_start_offset; ++ shadow_batch_start = gen8_canonical_addr(vma->node.start); ++ ++ ret = intel_engine_cmd_parser(params->ctx, ++ engine, + batch_obj, +- shadow_batch_obj, ++ batch_start, + batch_start_offset, +- batch_len); ++ batch_len, ++ shadow_batch_obj, ++ shadow_batch_start); + if (ret) { ++ i915_vma_unpin(vma); ++ + /* + * Unsafe GGTT-backed buffers can still be submitted safely + * as non-secure. +@@ -1461,12 +1478,9 @@ i915_gem_execbuffer_parse(struct intel_e + vma = NULL; + else + vma = ERR_PTR(ret); +- goto out; +- } + +- vma = shadow_batch_pin(shadow_batch_obj, vm); +- if (IS_ERR(vma)) + goto out; ++ } + + memset(shadow_exec_entry, 0, sizeof(*shadow_exec_entry)); + +@@ -1745,6 +1759,7 @@ i915_gem_do_execbuffer(struct drm_device + goto err; + } + ++ params->ctx = ctx; + params->args_batch_start_offset = args->batch_start_offset; + params->args_batch_len = args->batch_len; + if (args->batch_len == 0) +@@ -1755,10 +1770,7 @@ i915_gem_do_execbuffer(struct drm_device + struct i915_vma *vma; + + vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry, +- params->batch->obj, +- eb, vm, +- params->args_batch_start_offset, +- params->args_batch_len); ++ params, eb, vm); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; +@@ -1829,7 +1841,6 @@ i915_gem_do_execbuffer(struct drm_device + params->file = file; + params->engine = engine; + params->dispatch_flags = dispatch_flags; +- params->ctx = ctx; + + ret = execbuf_submit(params, args, &eb->vmas); + err_request: diff --git a/queue-4.9/drm-i915-cmdparser-check-reg_table_count-before-derefencing.patch b/queue-4.9/drm-i915-cmdparser-check-reg_table_count-before-derefencing.patch new file mode 100644 index 00000000000..8310e46b76c --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-check-reg_table_count-before-derefencing.patch @@ -0,0 +1,55 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Michal Srb +Date: Mon, 5 Feb 2018 16:04:37 +0000 +Subject: drm/i915/cmdparser: Check reg_table_count before derefencing. + +From: Michal Srb + +commit 2f265fad9756a40c09e3f4dcc62d5d7fa73a9fb2 upstream. + +The find_reg function was assuming that there is always at least one table in +reg_tables. It is not always true. + +In case of VCS or VECS, the reg_tables is NULL and reg_table_count is 0, +implying that no register-accessing commands are allowed. However, the command +tables include commands such as MI_STORE_REGISTER_MEM. When trying to check +such command, the find_reg would dereference NULL pointer. + +Now it will just return NULL meaning that the register was not found and the +command will be rejected. + +Fixes: 76ff480ec963 ("drm/i915/cmdparser: Use binary search for faster register lookup") +Signed-off-by: Michal Srb +Link: https://patchwork.freedesktop.org/patch/msgid/20180205142916.27092-2-msrb@suse.com +Cc: Chris Wilson +Cc: Matthew Auld +Reviewed-by: Chris Wilson +Signed-off-by: Chris Wilson +Link: https://patchwork.freedesktop.org/patch/msgid/20180205160438.3267-1-chris@chris-wilson.co.uk +register lookup") +Reviewed-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1038,7 +1038,7 @@ find_reg(const struct intel_engine_cs *e + const struct drm_i915_reg_table *table = engine->reg_tables; + int count = engine->reg_table_count; + +- do { ++ for (; count > 0; ++table, --count) { + if (!table->master || is_master) { + const struct drm_i915_reg_descriptor *reg; + +@@ -1046,7 +1046,7 @@ find_reg(const struct intel_engine_cs *e + if (reg != NULL) + return reg; + } +- } while (table++, --count); ++ } + + return NULL; + } diff --git a/queue-4.9/drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch b/queue-4.9/drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch new file mode 100644 index 00000000000..536264c4300 --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch @@ -0,0 +1,43 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Michal Srb +Date: Mon, 5 Feb 2018 16:04:38 +0000 +Subject: drm/i915/cmdparser: Do not check past the cmd length. + +From: Michal Srb + +commit b3ad99ed45917f42884fee731fa3cf9b8229a26c upstream. + +The command MEDIA_VFE_STATE checks bits at offset +2 dwords. However, it is +possible to have MEDIA_VFE_STATE command with length = 0 + LENGTH_BIAS = 2. +In that case check_cmd will read bits from the following command, or even past +the end of the buffer. + +If the offset ends up outside of the command length, reject the command. + +Fixes: 351e3db2b363 ("drm/i915: Implement command buffer parsing logic") +Signed-off-by: Michal Srb +Link: https://patchwork.freedesktop.org/patch/msgid/20180205151745.29292-1-msrb@suse.com +Reviewed-by: Chris Wilson +Signed-off-by: Chris Wilson +Link: https://patchwork.freedesktop.org/patch/msgid/20180205160438.3267-2-chris@chris-wilson.co.uk +Signed-off-by: Rodrigo Vivi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1218,6 +1218,12 @@ static bool check_cmd(const struct intel + continue; + } + ++ if (desc->bits[i].offset >= length) { ++ DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X, too short to check bitmask (%s)\n", ++ *cmd, engine->name); ++ return false; ++ } ++ + dword = cmd[desc->bits[i].offset] & + desc->bits[i].mask; + diff --git a/queue-4.9/drm-i915-cmdparser-fix-jump-whitelist-clearing.patch b/queue-4.9/drm-i915-cmdparser-fix-jump-whitelist-clearing.patch new file mode 100644 index 00000000000..ce9cd87878d --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-fix-jump-whitelist-clearing.patch @@ -0,0 +1,49 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Ben Hutchings +Date: Mon, 11 Nov 2019 08:13:24 -0800 +Subject: drm/i915/cmdparser: Fix jump whitelist clearing + +From: Ben Hutchings + +commit ea0b163b13ffc52818c079adb00d55e227a6da6f upstream. + +When a jump_whitelist bitmap is reused, it needs to be cleared. +Currently this is done with memset() and the size calculation assumes +bitmaps are made of 32-bit words, not longs. So on 64-bit +architectures, only the first half of the bitmap is cleared. + +If some whitelist bits are carried over between successive batches +submitted on the same context, this will presumably allow embedding +the rogue instructions that we're trying to reject. + +Use bitmap_zero() instead, which gets the calculation right. + +Fixes: f8c08d8faee5 ("drm/i915/cmdparser: Add support for backward jumps") +Signed-off-by: Ben Hutchings +Signed-off-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1374,7 +1374,7 @@ static void init_whitelist(struct i915_g + return; + + if (batch_cmds <= ctx->jump_whitelist_cmds) { +- memset(ctx->jump_whitelist, 0, exact_size * sizeof(u32)); ++ bitmap_zero(ctx->jump_whitelist, batch_cmds); + return; + } + +@@ -1394,8 +1394,7 @@ again: + } + + DRM_DEBUG("CMD: Failed to extend whitelist. BB_START may be disallowed\n"); +- memset(ctx->jump_whitelist, 0, +- BITS_TO_LONGS(ctx->jump_whitelist_cmds) * sizeof(u32)); ++ bitmap_zero(ctx->jump_whitelist, ctx->jump_whitelist_cmds); + + return; + } diff --git a/queue-4.9/drm-i915-cmdparser-ignore-length-operands-during-command-matching.patch b/queue-4.9/drm-i915-cmdparser-ignore-length-operands-during-command-matching.patch new file mode 100644 index 00000000000..ecf199695a6 --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-ignore-length-operands-during-command-matching.patch @@ -0,0 +1,40 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Thu, 20 Sep 2018 09:45:10 -0700 +Subject: drm/i915/cmdparser: Ignore Length operands during command matching + +From: Jon Bloomfield + +commit 926abff21a8f29ef159a3ac893b05c6e50e043c3 upstream. + +Some of the gen instruction macros (e.g. MI_DISPLAY_FLIP) have the +length directly encoded in them. Since these are used directly in +the tables, the Length becomes part of the comparison used for +matching during parsing. Thus, if the cmd being parsed has a +different length to that in the table, it is not matched and the +cmd is accepted via the default variable length path. + +Fix by masking out everything except the Opcode in the cmd tables + +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Jon Bloomfield +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -187,7 +187,7 @@ struct drm_i915_cmd_table { + #define CMD(op, opm, f, lm, fl, ...) \ + { \ + .flags = (fl) | ((f) ? CMD_DESC_FIXED : 0), \ +- .cmd = { (op), ~0u << (opm) }, \ ++ .cmd = { (op & ~0u << (opm)), ~0u << (opm) }, \ + .length = { (lm) }, \ + __VA_ARGS__ \ + } diff --git a/queue-4.9/drm-i915-cmdparser-limit-clflush-to-active-cachelines.patch b/queue-4.9/drm-i915-cmdparser-limit-clflush-to-active-cachelines.patch new file mode 100644 index 00000000000..752d7c3391b --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-limit-clflush-to-active-cachelines.patch @@ -0,0 +1,72 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Chris Wilson +Date: Fri, 10 Mar 2017 11:55:18 +0000 +Subject: drm/i915/cmdparser: Limit clflush to active cachelines + +From: Chris Wilson + +commit 504ae4024131c5a01c3ce8382d49b801375e039c upstream. + +We only need to clflush those cachelines that we have validated to be +read by the GPU. Userspace typically fills the batch length in +correctly, the exceptions tend to be explicit tests within igt. + +v2: Use ptr_mask_bits() to make Mika happy +v3: cmd is not advanced on MI_BBE, so make sure to include an extra +dword in the clflush. + +Signed-off-by: Chris Wilson +Cc: Mika Kuoppala +Link: http://patchwork.freedesktop.org/patch/msgid/20170310115518.13832-1-chris@chris-wilson.co.uk +Signed-off-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1279,11 +1279,17 @@ int intel_engine_cmd_parser(struct intel + * space. Parsing should be faster in some cases this way. + */ + batch_end = cmd + (batch_len / sizeof(*batch_end)); +- while (cmd < batch_end) { ++ do { + u32 length; + +- if (*cmd == MI_BATCH_BUFFER_END) ++ if (*cmd == MI_BATCH_BUFFER_END) { ++ if (needs_clflush_after) { ++ void *ptr = ptr_mask_bits(shadow_batch_obj->mapping); ++ drm_clflush_virt_range(ptr, ++ (void *)(cmd + 1) - ptr); ++ } + break; ++ } + + desc = find_cmd(engine, *cmd, desc, &default_desc); + if (!desc) { +@@ -1323,17 +1329,14 @@ int intel_engine_cmd_parser(struct intel + } + + 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; +- } ++ if (cmd >= batch_end) { ++ DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); ++ ret = -EINVAL; ++ break; ++ } ++ } while (1); + +- if (ret == 0 && needs_clflush_after) +- drm_clflush_virt_range(shadow_batch_obj->mapping, batch_len); + i915_gem_object_unpin_map(shadow_batch_obj); +- + return ret; + } + diff --git a/queue-4.9/drm-i915-cmdparser-use-explicit-goto-for-error-paths.patch b/queue-4.9/drm-i915-cmdparser-use-explicit-goto-for-error-paths.patch new file mode 100644 index 00000000000..80f8d7fa03c --- /dev/null +++ b/queue-4.9/drm-i915-cmdparser-use-explicit-goto-for-error-paths.patch @@ -0,0 +1,98 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Thu, 27 Sep 2018 10:23:17 -0700 +Subject: drm/i915/cmdparser: Use explicit goto for error paths + +From: Jon Bloomfield + +commit 0546a29cd884fb8184731c79ab008927ca8859d0 upstream. + +In the next patch we will be adding a second valid +termination condition which will require a small +amount of refactoring to share logic with the BB_END +case. + +Refactor all error conditions to jump to a dedicated +exit path, with 'break' reserved only for a successful +parse. + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1337,21 +1337,15 @@ int intel_engine_cmd_parser(struct intel + do { + u32 length; + +- if (*cmd == MI_BATCH_BUFFER_END) { +- if (needs_clflush_after) { +- void *ptr = ptr_mask_bits(shadow_batch_obj->mapping); +- drm_clflush_virt_range(ptr, +- (void *)(cmd + 1) - ptr); +- } ++ if (*cmd == MI_BATCH_BUFFER_END) + break; +- } + + desc = find_cmd(engine, *cmd, desc, &default_desc); + if (!desc) { + DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n", + *cmd); + ret = -EINVAL; +- break; ++ goto err; + } + + /* +@@ -1361,7 +1355,7 @@ int intel_engine_cmd_parser(struct intel + */ + if (desc->cmd.value == MI_BATCH_BUFFER_START) { + ret = -EACCES; +- break; ++ goto err; + } + + if (desc->flags & CMD_DESC_FIXED) +@@ -1375,22 +1369,29 @@ int intel_engine_cmd_parser(struct intel + length, + batch_end - cmd); + ret = -EINVAL; +- break; ++ goto err; + } + + if (!check_cmd(engine, desc, cmd, length)) { + ret = -EACCES; +- break; ++ goto err; + } + + 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; +- break; ++ goto err; + } + } while (1); + ++ if (needs_clflush_after) { ++ void *ptr = ptr_mask_bits(shadow_batch_obj->mapping); ++ drm_clflush_virt_range(ptr, ++ (void *)(cmd + 1) - ptr); ++ } ++ ++err: + i915_gem_object_unpin_map(shadow_batch_obj); + return ret; + } diff --git a/queue-4.9/drm-i915-disable-secure-batches-for-gen6.patch b/queue-4.9/drm-i915-disable-secure-batches-for-gen6.patch new file mode 100644 index 00000000000..0c47dd097fe --- /dev/null +++ b/queue-4.9/drm-i915-disable-secure-batches-for-gen6.patch @@ -0,0 +1,79 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Fri, 8 Jun 2018 08:53:46 -0700 +Subject: drm/i915: Disable Secure Batches for gen6+ + +From: Jon Bloomfield + +commit 44157641d448cbc0c4b73c5231d2b911f0cb0427 upstream. + +Retroactively stop reporting support for secure batches +through the api for gen6+ so that older binaries trigger +the fallback path instead. + +Older binaries use secure batches pre gen6 to access resources +that are not available to normal usermode processes. However, +all known userspace explicitly checks for HAS_SECURE_BATCHES +before relying on the secure batch feature. + +Since there are no known binaries relying on this for newer gens +we can kill secure batches from gen6, via I915_PARAM_HAS_SECURE_BATCHES. + +v2: rebase (Mika) +v3: rebase (Mika) + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_drv.c | 2 +- + drivers/gpu/drm/i915/i915_drv.h | 2 ++ + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 ++++++++- + 3 files changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -280,7 +280,7 @@ static int i915_getparam(struct drm_devi + value = i915.semaphores; + break; + case I915_PARAM_HAS_SECURE_BATCHES: +- value = capable(CAP_SYS_ADMIN); ++ value = HAS_SECURE_BATCHES(dev_priv) && capable(CAP_SYS_ADMIN); + break; + case I915_PARAM_CMD_PARSER_VERSION: + value = i915_cmd_parser_get_version(dev_priv); +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -2661,6 +2661,8 @@ static inline struct scatterlist *__sg_n + #define HAS_BLT(dev_priv) HAS_ENGINE(dev_priv, BCS) + #define HAS_VEBOX(dev_priv) HAS_ENGINE(dev_priv, VECS) + ++#define HAS_SECURE_BATCHES(dev_priv) (INTEL_GEN(dev_priv) < 6) ++ + #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) + #define HAS_SNOOP(dev) (INTEL_INFO(dev)->has_snoop) + #define HAS_EDRAM(dev) (!!(__I915__(dev)->edram_cap & EDRAM_ENABLED)) +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1601,8 +1601,15 @@ i915_gem_do_execbuffer(struct drm_device + + dispatch_flags = 0; + if (args->flags & I915_EXEC_SECURE) { ++ if (INTEL_GEN(dev_priv) >= 11) ++ return -ENODEV; ++ ++ /* Return -EPERM to trigger fallback code on old binaries. */ ++ if (!HAS_SECURE_BATCHES(dev_priv)) ++ return -EPERM; ++ + if (!drm_is_current_master(file) || !capable(CAP_SYS_ADMIN)) +- return -EPERM; ++ return -EPERM; + + dispatch_flags |= I915_DISPATCH_SECURE; + } diff --git a/queue-4.9/drm-i915-don-t-whitelist-oacontrol-in-cmd-parser.patch b/queue-4.9/drm-i915-don-t-whitelist-oacontrol-in-cmd-parser.patch new file mode 100644 index 00000000000..19aa780d667 --- /dev/null +++ b/queue-4.9/drm-i915-don-t-whitelist-oacontrol-in-cmd-parser.patch @@ -0,0 +1,133 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Robert Bragg +Date: Tue, 8 Nov 2016 12:51:48 +0000 +Subject: drm/i915: don't whitelist oacontrol in cmd parser + +From: Robert Bragg + +commit 10ff401df041e57afc2b1619cd252b86d0ae5f30 upstream. + +Being able to program OACONTROL from a non-privileged batch buffer is +not sufficient to be able to configure the OA unit. This was originally +allowed to help enable Mesa to expose OA counters via the +INTEL_performance_query extension, but the current implementation based +on programming OACONTROL via a batch buffer isn't able to report useable +data without a more complete OA unit configuration. Mesa handles the +possibility that writes to OACONTROL may not be allowed and so only +advertises the extension after explicitly testing that a write to +OACONTROL succeeds. Based on this; removing OACONTROL from the whitelist +should be ok for userspace. + +Removing this simplifies adding a new kernel api for configuring the OA +unit without needing to consider the possibility that userspace might +trample on OACONTROL state which we'd like to start managing within +the kernel instead. In particular running any Mesa based GL application +currently results in clearing OACONTROL when initializing which would +disable the capturing of metrics. + +v2: + This bumps the command parser version from 8 to 9, as the change is + visible to userspace. + +Signed-off-by: Robert Bragg +Reviewed-by: Matthew Auld +Reviewed-by: Sourab Gupta Signed-off-by: Daniel Vetter +Signed-off-by: Jon Bloomfield +Link: http://patchwork.freedesktop.org/patch/msgid/20161108125148.25007-1-robert@sixbynine.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 42 +++------------------------------ + 1 file changed, 5 insertions(+), 37 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -546,7 +546,6 @@ static const struct drm_i915_reg_descrip + REG64(PS_INVOCATION_COUNT), + REG64(PS_DEPTH_COUNT), + REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE), +- REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */ + REG64(MI_PREDICATE_SRC0), + REG64(MI_PREDICATE_SRC1), + REG32(GEN7_3DPRIM_END_OFFSET), +@@ -1156,8 +1155,7 @@ bool intel_engine_needs_cmd_parser(struc + static bool check_cmd(const struct intel_engine_cs *engine, + const struct drm_i915_cmd_descriptor *desc, + const u32 *cmd, u32 length, +- const bool is_master, +- bool *oacontrol_set) ++ const bool is_master) + { + if (desc->flags & CMD_DESC_SKIP) + return true; +@@ -1195,31 +1193,6 @@ static bool check_cmd(const struct intel + } + + /* +- * OACONTROL requires some special handling for +- * writes. We want to make sure that any batch which +- * enables OA also disables it before the end of the +- * batch. The goal is to prevent one process from +- * snooping on the perf data from another process. To do +- * that, we need to check the value that will be written +- * to the register. Hence, limit OACONTROL writes to +- * only MI_LOAD_REGISTER_IMM commands. +- */ +- if (reg_addr == i915_mmio_reg_offset(OACONTROL)) { +- if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { +- DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); +- return false; +- } +- +- if (desc->cmd.value == MI_LOAD_REGISTER_REG) { +- DRM_DEBUG_DRIVER("CMD: Rejected LRR to OACONTROL\n"); +- return false; +- } +- +- if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) +- *oacontrol_set = (cmd[offset + 1] != 0); +- } +- +- /* + * Check the value written to the register against the + * allowed mask/value pair given in the whitelist entry. + */ +@@ -1310,7 +1283,6 @@ int intel_engine_cmd_parser(struct intel + u32 *cmd, *batch_end; + struct drm_i915_cmd_descriptor default_desc = noop_desc; + const struct drm_i915_cmd_descriptor *desc = &default_desc; +- bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */ + bool needs_clflush_after = false; + int ret = 0; + +@@ -1366,8 +1338,7 @@ int intel_engine_cmd_parser(struct intel + break; + } + +- if (!check_cmd(engine, desc, cmd, length, is_master, +- &oacontrol_set)) { ++ if (!check_cmd(engine, desc, cmd, length, is_master)) { + ret = -EACCES; + break; + } +@@ -1375,11 +1346,6 @@ int intel_engine_cmd_parser(struct intel + cmd += length; + } + +- if (oacontrol_set) { +- DRM_DEBUG_DRIVER("CMD: batch set OACONTROL but did not clear it\n"); +- ret = -EINVAL; +- } +- + if (cmd >= batch_end) { + DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); + ret = -EINVAL; +@@ -1431,6 +1397,8 @@ int i915_cmd_parser_get_version(struct d + * 8. Don't report cmd_check() failures as EINVAL errors to userspace; + * rely on the HW to NOOP disallowed commands as it would without + * the parser enabled. ++ * 9. Don't whitelist or handle oacontrol specially, as ownership ++ * for oacontrol state is moving to i915-perf. + */ +- return 8; ++ return 9; + } diff --git a/queue-4.9/drm-i915-gen8-add-rc6-ctx-corruption-wa.patch b/queue-4.9/drm-i915-gen8-add-rc6-ctx-corruption-wa.patch new file mode 100644 index 00000000000..273109018f5 --- /dev/null +++ b/queue-4.9/drm-i915-gen8-add-rc6-ctx-corruption-wa.patch @@ -0,0 +1,357 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Imre Deak +Date: Mon, 9 Jul 2018 18:24:27 +0300 +Subject: drm/i915/gen8+: Add RC6 CTX corruption WA + +From: Imre Deak + +commit 7e34f4e4aad3fd34c02b294a3cf2321adf5b4438 upstream. + +In some circumstances the RC6 context can get corrupted. We can detect +this and take the required action, that is disable RC6 and runtime PM. +The HW recovers from the corrupted state after a system suspend/resume +cycle, so detect the recovery and re-enable RC6 and runtime PM. + +v2: rebase (Mika) +v3: +- Move intel_suspend_gt_powersave() to the end of the GEM suspend + sequence. +- Add commit message. +v4: +- Rebased on intel_uncore_forcewake_put(i915->uncore, ...) API + change. +v5: +- Rebased on latest upstream gt_pm refactoring. + +Signed-off-by: Imre Deak +Signed-off-by: Mika Kuoppala +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_drv.c | 3 + drivers/gpu/drm/i915/i915_drv.h | 7 + + drivers/gpu/drm/i915/i915_gem.c | 6 + + drivers/gpu/drm/i915/i915_gem_request.c | 4 + drivers/gpu/drm/i915/i915_reg.h | 2 + drivers/gpu/drm/i915/intel_drv.h | 3 + drivers/gpu/drm/i915/intel_pm.c | 153 ++++++++++++++++++++++++++++---- + 7 files changed, 159 insertions(+), 19 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -1470,6 +1470,7 @@ static int i915_drm_suspend_late(struct + disable_rpm_wakeref_asserts(dev_priv); + + intel_display_set_init_power(dev_priv, false); ++ i915_rc6_ctx_wa_suspend(dev_priv); + + fw_csr = !IS_BROXTON(dev_priv) && + suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; +@@ -1706,6 +1707,8 @@ static int i915_drm_resume_early(struct + else + intel_display_set_init_power(dev_priv, true); + ++ i915_rc6_ctx_wa_resume(dev_priv); ++ + enable_rpm_wakeref_asserts(dev_priv); + + out: +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1228,6 +1228,7 @@ struct intel_gen6_power_mgmt { + bool client_boost; + + bool enabled; ++ bool ctx_corrupted; + struct delayed_work autoenable_work; + unsigned boosts; + +@@ -2695,11 +2696,13 @@ static inline struct scatterlist *__sg_n + /* Early gen2 have a totally busted CS tlb and require pinned batches. */ + #define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev)) + ++#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \ ++ (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) == 9) ++ + /* WaRsDisableCoarsePowerGating:skl,bxt */ + #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \ + (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) || \ +- IS_SKL_GT3(dev_priv) || \ +- IS_SKL_GT4(dev_priv)) ++ (INTEL_GEN(dev_priv) == 9)) + + /* + * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -2763,6 +2763,12 @@ i915_gem_idle_work_handler(struct work_s + + if (INTEL_GEN(dev_priv) >= 6) + gen6_rps_idle(dev_priv); ++ ++ if (NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv)) { ++ i915_rc6_ctx_wa_check(dev_priv); ++ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); ++ } ++ + intel_runtime_pm_put(dev_priv); + out_unlock: + mutex_unlock(&dev->struct_mutex); +--- a/drivers/gpu/drm/i915/i915_gem_request.c ++++ b/drivers/gpu/drm/i915/i915_gem_request.c +@@ -558,6 +558,10 @@ static void i915_gem_mark_busy(const str + return; + + intel_runtime_pm_get_noresume(dev_priv); ++ ++ if (NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv)) ++ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); ++ + dev_priv->gt.awake = true; + + intel_enable_gt_powersave(dev_priv); +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -223,6 +223,8 @@ static inline bool i915_mmio_reg_valid(i + #define GEN8_CONFIG0 _MMIO(0xD00) + #define GEN9_DEFAULT_FIXES (1 << 3 | 1 << 2 | 1 << 1) + ++#define GEN8_RC6_CTX_INFO _MMIO(0x8504) ++ + #define GAC_ECO_BITS _MMIO(0x14090) + #define ECOBITS_SNB_BIT (1<<13) + #define ECOBITS_PPGTT_CACHE64B (3<<8) +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -1730,6 +1730,9 @@ void intel_enable_gt_powersave(struct dr + void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv); + void intel_disable_gt_powersave(struct drm_i915_private *dev_priv); + void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv); ++bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915); ++void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915); ++void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915); + void gen6_rps_busy(struct drm_i915_private *dev_priv); + void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); + void gen6_rps_idle(struct drm_i915_private *dev_priv); +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -5156,19 +5156,23 @@ static void gen9_disable_rps(struct drm_ + I915_WRITE(GEN6_RP_CONTROL, 0); + } + +-static void gen6_disable_rps(struct drm_i915_private *dev_priv) ++static void gen6_disable_rc6(struct drm_i915_private *dev_priv) + { + I915_WRITE(GEN6_RC_CONTROL, 0); ++} ++ ++static void gen6_disable_rps(struct drm_i915_private *dev_priv) ++{ + I915_WRITE(GEN6_RPNSWREQ, 1 << 31); + I915_WRITE(GEN6_RP_CONTROL, 0); + } + +-static void cherryview_disable_rps(struct drm_i915_private *dev_priv) ++static void cherryview_disable_rc6(struct drm_i915_private *dev_priv) + { + I915_WRITE(GEN6_RC_CONTROL, 0); + } + +-static void valleyview_disable_rps(struct drm_i915_private *dev_priv) ++static void valleyview_disable_rc6(struct drm_i915_private *dev_priv) + { + /* we're doing forcewake before Disabling RC6, + * This what the BIOS expects when going into suspend */ +@@ -5433,7 +5437,8 @@ static void gen9_enable_rc6(struct drm_i + I915_WRITE(GEN9_RENDER_PG_IDLE_HYSTERESIS, 25); + + /* 3a: Enable RC6 */ +- if (intel_enable_rc6() & INTEL_RC6_ENABLE) ++ if (!dev_priv->rps.ctx_corrupted && ++ intel_enable_rc6() & INTEL_RC6_ENABLE) + rc6_mask = GEN6_RC_CTL_RC6_ENABLE; + DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); + /* WaRsUseTimeoutMode */ +@@ -5491,7 +5496,8 @@ static void gen8_enable_rps(struct drm_i + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + + /* 3: Enable RC6 */ +- if (intel_enable_rc6() & INTEL_RC6_ENABLE) ++ if (!dev_priv->rps.ctx_corrupted && ++ intel_enable_rc6() & INTEL_RC6_ENABLE) + rc6_mask = GEN6_RC_CTL_RC6_ENABLE; + intel_print_rc6_info(dev_priv, rc6_mask); + if (IS_BROADWELL(dev_priv)) +@@ -6662,6 +6668,95 @@ static void intel_init_emon(struct drm_i + dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK); + } + ++static bool i915_rc6_ctx_corrupted(struct drm_i915_private *dev_priv) ++{ ++ return !I915_READ(GEN8_RC6_CTX_INFO); ++} ++ ++static void i915_rc6_ctx_wa_init(struct drm_i915_private *i915) ++{ ++ if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915)) ++ return; ++ ++ if (i915_rc6_ctx_corrupted(i915)) { ++ DRM_INFO("RC6 context corrupted, disabling runtime power management\n"); ++ i915->rps.ctx_corrupted = true; ++ intel_runtime_pm_get(i915); ++ } ++} ++ ++static void i915_rc6_ctx_wa_cleanup(struct drm_i915_private *i915) ++{ ++ if (i915->rps.ctx_corrupted) { ++ intel_runtime_pm_put(i915); ++ i915->rps.ctx_corrupted = false; ++ } ++} ++ ++/** ++ * i915_rc6_ctx_wa_suspend - system suspend sequence for the RC6 CTX WA ++ * @i915: i915 device ++ * ++ * Perform any steps needed to clean up the RC6 CTX WA before system suspend. ++ */ ++void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915) ++{ ++ if (i915->rps.ctx_corrupted) ++ intel_runtime_pm_put(i915); ++} ++ ++/** ++ * i915_rc6_ctx_wa_resume - system resume sequence for the RC6 CTX WA ++ * @i915: i915 device ++ * ++ * Perform any steps needed to re-init the RC6 CTX WA after system resume. ++ */ ++void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915) ++{ ++ if (!i915->rps.ctx_corrupted) ++ return; ++ ++ if (i915_rc6_ctx_corrupted(i915)) { ++ intel_runtime_pm_get(i915); ++ return; ++ } ++ ++ DRM_INFO("RC6 context restored, re-enabling runtime power management\n"); ++ i915->rps.ctx_corrupted = false; ++} ++ ++static void intel_disable_rc6(struct drm_i915_private *dev_priv); ++ ++/** ++ * i915_rc6_ctx_wa_check - check for a new RC6 CTX corruption ++ * @i915: i915 device ++ * ++ * Check if an RC6 CTX corruption has happened since the last check and if so ++ * disable RC6 and runtime power management. ++ * ++ * Return false if no context corruption has happened since the last call of ++ * this function, true otherwise. ++*/ ++bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915) ++{ ++ if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915)) ++ return false; ++ ++ if (i915->rps.ctx_corrupted) ++ return false; ++ ++ if (!i915_rc6_ctx_corrupted(i915)) ++ return false; ++ ++ DRM_NOTE("RC6 context corruption, disabling runtime power management\n"); ++ ++ intel_disable_rc6(i915); ++ i915->rps.ctx_corrupted = true; ++ intel_runtime_pm_get_noresume(i915); ++ ++ return true; ++} ++ + void intel_init_gt_powersave(struct drm_i915_private *dev_priv) + { + /* +@@ -6676,6 +6771,8 @@ void intel_init_gt_powersave(struct drm_ + mutex_lock(&dev_priv->drm.struct_mutex); + mutex_lock(&dev_priv->rps.hw_lock); + ++ i915_rc6_ctx_wa_init(dev_priv); ++ + /* Initialize RPS limits (for userspace) */ + if (IS_CHERRYVIEW(dev_priv)) + cherryview_init_gt_powersave(dev_priv); +@@ -6725,6 +6822,8 @@ void intel_cleanup_gt_powersave(struct d + if (IS_VALLEYVIEW(dev_priv)) + valleyview_cleanup_gt_powersave(dev_priv); + ++ i915_rc6_ctx_wa_cleanup(dev_priv); ++ + if (!i915.enable_rc6) + intel_runtime_pm_put(dev_priv); + } +@@ -6756,27 +6855,47 @@ void intel_sanitize_gt_powersave(struct + gen6_reset_rps_interrupts(dev_priv); + } + +-void intel_disable_gt_powersave(struct drm_i915_private *dev_priv) ++static void __intel_disable_rc6(struct drm_i915_private *dev_priv) + { +- if (!READ_ONCE(dev_priv->rps.enabled)) +- return; ++ if (INTEL_GEN(dev_priv) >= 9) ++ gen9_disable_rc6(dev_priv); ++ else if (IS_CHERRYVIEW(dev_priv)) ++ cherryview_disable_rc6(dev_priv); ++ else if (IS_VALLEYVIEW(dev_priv)) ++ valleyview_disable_rc6(dev_priv); ++ else if (INTEL_GEN(dev_priv) >= 6) ++ gen6_disable_rc6(dev_priv); ++} + ++static void intel_disable_rc6(struct drm_i915_private *dev_priv) ++{ + mutex_lock(&dev_priv->rps.hw_lock); ++ __intel_disable_rc6(dev_priv); ++ mutex_unlock(&dev_priv->rps.hw_lock); ++} + +- if (INTEL_GEN(dev_priv) >= 9) { +- gen9_disable_rc6(dev_priv); ++static void intel_disable_rps(struct drm_i915_private *dev_priv) ++{ ++ if (INTEL_GEN(dev_priv) >= 9) + gen9_disable_rps(dev_priv); +- } else if (IS_CHERRYVIEW(dev_priv)) { +- cherryview_disable_rps(dev_priv); +- } else if (IS_VALLEYVIEW(dev_priv)) { +- valleyview_disable_rps(dev_priv); +- } else if (INTEL_GEN(dev_priv) >= 6) { ++ else if (INTEL_GEN(dev_priv) >= 6) + gen6_disable_rps(dev_priv); +- } else if (IS_IRONLAKE_M(dev_priv)) { ++ else if (IS_IRONLAKE_M(dev_priv)) + ironlake_disable_drps(dev_priv); +- } ++} ++ ++void intel_disable_gt_powersave(struct drm_i915_private *dev_priv) ++{ ++ if (!READ_ONCE(dev_priv->rps.enabled)) ++ return; ++ ++ mutex_lock(&dev_priv->rps.hw_lock); ++ ++ __intel_disable_rc6(dev_priv); ++ intel_disable_rps(dev_priv); + + dev_priv->rps.enabled = false; ++ + mutex_unlock(&dev_priv->rps.hw_lock); + } + diff --git a/queue-4.9/drm-i915-gtt-add-read-only-pages-to-gen8_pte_encode.patch b/queue-4.9/drm-i915-gtt-add-read-only-pages-to-gen8_pte_encode.patch new file mode 100644 index 00000000000..65032909a37 --- /dev/null +++ b/queue-4.9/drm-i915-gtt-add-read-only-pages-to-gen8_pte_encode.patch @@ -0,0 +1,108 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Thu, 12 Jul 2018 19:53:10 +0100 +Subject: drm/i915/gtt: Add read only pages to gen8_pte_encode + +From: Jon Bloomfield + +commit 25dda4dabeeb12af5209b0183c788ef2a88dabbe upstream. + +We can set a bit inside the ppGTT PTE to indicate a page is read-only; +writes from the GPU will be discarded. We can use this to protect pages +and in particular support read-only userptr mappings (necessary for +importing PROT_READ vma). + +Signed-off-by: Jon Bloomfield +Signed-off-by: Chris Wilson +Cc: Joonas Lahtinen +Cc: Matthew Auld +Reviewed-by: Joonas Lahtinen +Reviewed-by: Matthew Auld +Link: https://patchwork.freedesktop.org/patch/msgid/20180712185315.3288-1-chris@chris-wilson.co.uk +Reviewed-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_gem_gtt.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -197,11 +197,14 @@ static void ppgtt_unbind_vma(struct i915 + + static gen8_pte_t gen8_pte_encode(dma_addr_t addr, + enum i915_cache_level level, +- bool valid) ++ bool valid, u32 flags) + { + gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; + pte |= addr; + ++ if (unlikely(flags & PTE_READ_ONLY)) ++ pte &= ~_PAGE_RW; ++ + switch (level) { + case I915_CACHE_NONE: + pte |= PPAT_UNCACHED_INDEX; +@@ -472,7 +475,7 @@ static void gen8_initialize_pt(struct i9 + gen8_pte_t scratch_pte; + + scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, +- I915_CACHE_LLC, true); ++ I915_CACHE_LLC, true, 0); + + fill_px(vm->dev, pt, scratch_pte); + } +@@ -769,7 +772,7 @@ static void gen8_ppgtt_clear_range(struc + { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); + gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, +- I915_CACHE_LLC, use_scratch); ++ I915_CACHE_LLC, use_scratch, 0); + + if (!USES_FULL_48BIT_PPGTT(vm->dev)) { + gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, +@@ -809,7 +812,7 @@ gen8_ppgtt_insert_pte_entries(struct i91 + + pt_vaddr[pte] = + gen8_pte_encode(sg_page_iter_dma_address(sg_iter), +- cache_level, true); ++ cache_level, true, 0); + if (++pte == GEN8_PTES) { + kunmap_px(ppgtt, pt_vaddr); + pt_vaddr = NULL; +@@ -1452,7 +1455,7 @@ static void gen8_dump_ppgtt(struct i915_ + uint64_t start = ppgtt->base.start; + uint64_t length = ppgtt->base.total; + gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, +- I915_CACHE_LLC, true); ++ I915_CACHE_LLC, true, 0); + + if (!USES_FULL_48BIT_PPGTT(vm->dev)) { + gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); +@@ -2321,7 +2324,7 @@ static void gen8_ggtt_insert_page(struct + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); + +- gen8_set_pte(pte, gen8_pte_encode(addr, level, true)); ++ gen8_set_pte(pte, gen8_pte_encode(addr, level, true, 0)); + + I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); + POSTING_READ(GFX_FLSH_CNTL_GEN6); +@@ -2348,7 +2351,7 @@ static void gen8_ggtt_insert_entries(str + gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); + + for_each_sgt_dma(addr, sgt_iter, st) { +- gtt_entry = gen8_pte_encode(addr, level, true); ++ gtt_entry = gen8_pte_encode(addr, level, true, 0); + gen8_set_pte(>t_entries[i++], gtt_entry); + } + +@@ -2499,7 +2502,7 @@ static void gen8_ggtt_clear_range(struct + + scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, + I915_CACHE_LLC, +- use_scratch); ++ use_scratch, 0); + for (i = 0; i < num_entries; i++) + gen8_set_pte(>t_base[i], scratch_pte); + readl(gtt_base); diff --git a/queue-4.9/drm-i915-gtt-disable-read-only-support-under-gvt.patch b/queue-4.9/drm-i915-gtt-disable-read-only-support-under-gvt.patch new file mode 100644 index 00000000000..8d0a9cea965 --- /dev/null +++ b/queue-4.9/drm-i915-gtt-disable-read-only-support-under-gvt.patch @@ -0,0 +1,42 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Chris Wilson +Date: Thu, 12 Jul 2018 19:53:12 +0100 +Subject: drm/i915/gtt: Disable read-only support under GVT + +From: Chris Wilson + +commit c9e666880de5a1fed04dc412b046916d542b72dd upstream. + +GVT is not propagating the PTE bits, and is always setting the +read-write bit, thus breaking read-only support. + +Signed-off-by: Chris Wilson +Cc: Zhenyu Wang +Cc: Jon Bloomfield +Cc: Joonas Lahtinen +Cc: Matthew Auld +Reviewed-by: Jon Bloomfield +Link: https://patchwork.freedesktop.org/patch/msgid/20180712185315.3288-3-chris@chris-wilson.co.uk +Signed-off--by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_gem_gtt.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -1525,8 +1525,12 @@ static int gen8_ppgtt_init(struct i915_h + ppgtt->base.unbind_vma = ppgtt_unbind_vma; + ppgtt->base.bind_vma = ppgtt_bind_vma; + +- /* From bdw, there is support for read-only pages in the PPGTT */ +- ppgtt->base.has_read_only = true; ++ /* ++ * From bdw, there is support for read-only pages in the PPGTT. ++ * ++ * XXX GVT is not honouring the lack of RW in the PTE bits. ++ */ ++ ppgtt->base.has_read_only = !intel_vgpu_active(to_i915(ppgtt->base.dev)); + + ppgtt->debug_dump = gen8_dump_ppgtt; + diff --git a/queue-4.9/drm-i915-gtt-read-only-pages-for-insert_entries-on-bdw.patch b/queue-4.9/drm-i915-gtt-read-only-pages-for-insert_entries-on-bdw.patch new file mode 100644 index 00000000000..c94c29c6073 --- /dev/null +++ b/queue-4.9/drm-i915-gtt-read-only-pages-for-insert_entries-on-bdw.patch @@ -0,0 +1,179 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Mon, 6 Aug 2018 14:10:48 -0700 +Subject: drm/i915/gtt: Read-only pages for insert_entries on bdw+ + +From: Jon Bloomfield + +commit 250f8c8140ac0a5e5acb91891d6813f12778b224 upstream. + +Hook up the flags to allow read-only ppGTT mappings for gen8+ + +v2: Include a selftest to check that writes to a readonly PTE are +dropped +v3: Don't duplicate cpu_check() as we can just reuse it, and even worse +don't wholesale copy the theory-of-operation comment from igt_ctx_exec +without changing it to explain the intention behind the new test! +v4: Joonas really likes magic mystery values + +Signed-off-by: Jon Bloomfield +Cc: Joonas Lahtinen +Cc: Matthew Auld +Reviewed-by: Joonas Lahtinen +Reviewed-by: Matthew Auld +Link: https://patchwork.freedesktop.org/patch/msgid/20180712185315.3288-2-chris@chris-wilson.co.uk +Signed-off-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_gem_gtt.c | 28 ++++++++++++++++++++-------- + drivers/gpu/drm/i915/i915_gem_gtt.h | 3 +++ + drivers/gpu/drm/i915/intel_ringbuffer.c | 11 ++++++++--- + 3 files changed, 31 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -177,7 +177,7 @@ static int ppgtt_bind_vma(struct i915_vm + + vma->pages = vma->obj->pages; + +- /* Currently applicable only to VLV */ ++ /* Applicable to VLV, and gen8+ */ + if (vma->obj->gt_ro) + pte_flags |= PTE_READ_ONLY; + +@@ -793,7 +793,8 @@ gen8_ppgtt_insert_pte_entries(struct i91 + struct i915_page_directory_pointer *pdp, + struct sg_page_iter *sg_iter, + uint64_t start, +- enum i915_cache_level cache_level) ++ enum i915_cache_level cache_level, ++ u32 flags) + { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); + gen8_pte_t *pt_vaddr; +@@ -812,7 +813,7 @@ gen8_ppgtt_insert_pte_entries(struct i91 + + pt_vaddr[pte] = + gen8_pte_encode(sg_page_iter_dma_address(sg_iter), +- cache_level, true, 0); ++ cache_level, true, flags); + if (++pte == GEN8_PTES) { + kunmap_px(ppgtt, pt_vaddr); + pt_vaddr = NULL; +@@ -833,7 +834,7 @@ static void gen8_ppgtt_insert_entries(st + struct sg_table *pages, + uint64_t start, + enum i915_cache_level cache_level, +- u32 unused) ++ u32 flags) + { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); + struct sg_page_iter sg_iter; +@@ -842,7 +843,7 @@ static void gen8_ppgtt_insert_entries(st + + if (!USES_FULL_48BIT_PPGTT(vm->dev)) { + gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start, +- cache_level); ++ cache_level, flags); + } else { + struct i915_page_directory_pointer *pdp; + uint64_t pml4e; +@@ -850,7 +851,7 @@ static void gen8_ppgtt_insert_entries(st + + gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) { + gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter, +- start, cache_level); ++ start, cache_level, flags); + } + } + } +@@ -1523,6 +1524,10 @@ static int gen8_ppgtt_init(struct i915_h + ppgtt->base.clear_range = gen8_ppgtt_clear_range; + ppgtt->base.unbind_vma = ppgtt_unbind_vma; + ppgtt->base.bind_vma = ppgtt_bind_vma; ++ ++ /* From bdw, there is support for read-only pages in the PPGTT */ ++ ppgtt->base.has_read_only = true; ++ + ppgtt->debug_dump = gen8_dump_ppgtt; + + if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { +@@ -2335,7 +2340,7 @@ static void gen8_ggtt_insert_page(struct + static void gen8_ggtt_insert_entries(struct i915_address_space *vm, + struct sg_table *st, + uint64_t start, +- enum i915_cache_level level, u32 unused) ++ enum i915_cache_level level, u32 flags) + { + struct drm_i915_private *dev_priv = to_i915(vm->dev); + struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); +@@ -2346,6 +2351,9 @@ static void gen8_ggtt_insert_entries(str + int rpm_atomic_seq; + int i = 0; + ++ /* The GTT does not support read-only mappings */ ++ GEM_BUG_ON(flags & PTE_READ_ONLY); ++ + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); + + gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); +@@ -2607,7 +2615,7 @@ static int ggtt_bind_vma(struct i915_vma + if (ret) + return ret; + +- /* Currently applicable only to VLV */ ++ /* Applicable to VLV (gen8+ do not support RO in the GGTT) */ + if (obj->gt_ro) + pte_flags |= PTE_READ_ONLY; + +@@ -3196,6 +3204,10 @@ int i915_ggtt_init_hw(struct drm_i915_pr + ggtt->base.total -= PAGE_SIZE; + i915_address_space_init(&ggtt->base, dev_priv); + ggtt->base.total += PAGE_SIZE; ++ ++ /* Only VLV supports read-only GGTT mappings */ ++ ggtt->base.has_read_only = IS_VALLEYVIEW(dev_priv); ++ + if (!HAS_LLC(dev_priv)) + ggtt->base.mm.color_adjust = i915_gtt_color_adjust; + +--- a/drivers/gpu/drm/i915/i915_gem_gtt.h ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.h +@@ -392,6 +392,9 @@ struct i915_address_space { + */ + struct list_head unbound_list; + ++ /* Some systems support read-only mappings for GGTT and/or PPGTT */ ++ bool has_read_only:1; ++ + /* FIXME: Need a more generic return type */ + gen6_pte_t (*pte_encode)(dma_addr_t addr, + enum i915_cache_level level, +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -1951,6 +1951,7 @@ void intel_ring_unpin(struct intel_ring + static struct i915_vma * + intel_ring_create_vma(struct drm_i915_private *dev_priv, int size) + { ++ struct i915_address_space *vm = &dev_priv->ggtt.base; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + +@@ -1960,10 +1961,14 @@ intel_ring_create_vma(struct drm_i915_pr + if (IS_ERR(obj)) + return ERR_CAST(obj); + +- /* mark ring buffers as read-only from GPU side by default */ +- obj->gt_ro = 1; ++ /* ++ * Mark ring buffers as read-only from GPU side (so no stray overwrites) ++ * if supported by the platform's GGTT. ++ */ ++ if (vm->has_read_only) ++ obj->gt_ro = 1; + +- vma = i915_vma_create(obj, &dev_priv->ggtt.base, NULL); ++ vma = i915_vma_create(obj, vm, NULL); + if (IS_ERR(vma)) + goto err; + diff --git a/queue-4.9/drm-i915-kick-out-cmd_parser-specific-structs-from-i915_drv.h.patch b/queue-4.9/drm-i915-kick-out-cmd_parser-specific-structs-from-i915_drv.h.patch new file mode 100644 index 00000000000..2b62db6d81b --- /dev/null +++ b/queue-4.9/drm-i915-kick-out-cmd_parser-specific-structs-from-i915_drv.h.patch @@ -0,0 +1,234 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Matthew Auld +Date: Wed, 23 Nov 2016 23:02:27 +0000 +Subject: drm/i915: kick out cmd_parser specific structs from i915_drv.h + +From: Matthew Auld + +commit 007873b30b9001348c0dfc96deb9db220a3be116 upstream. + +No sense in keeping the cmd_descriptor and cmd_table structs in +i915_drv.h, now that they are no longer referenced externally. + +Cc: Chris Wilson +Signed-off-by: Matthew Auld +Reviewed-by: Joonas Lahtinen +Signed-off-by: Joonas Lahtinen +Signed-off-by: Jon Bloomfield +Link: http://patchwork.freedesktop.org/patch/msgid/1479942147-9837-1-git-send-email-matthew.auld@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 96 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/i915/i915_drv.h | 96 --------------------------------- + 2 files changed, 96 insertions(+), 96 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -86,6 +86,102 @@ + * general bitmasking mechanism. + */ + ++/* ++ * 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. ++ * ++ * A non-zero step value implies that the command may access multiple ++ * registers in sequence (e.g. LRI), in that case step gives the ++ * distance in dwords between individual offset fields. ++ */ ++ struct { ++ u32 offset; ++ u32 mask; ++ u32 step; ++ } 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. ++ * ++ * 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]; ++}; ++ ++/* ++ * A table of commands requiring special handling by the command parser. ++ * ++ * Each engine 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 STD_MI_OPCODE_SHIFT (32 - 9) + #define STD_3D_OPCODE_SHIFT (32 - 16) + #define STD_2D_OPCODE_SHIFT (32 - 10) +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -2476,102 +2476,6 @@ static inline struct scatterlist *__sg_n + (((__iter).curr += PAGE_SIZE) < (__iter).max) || \ + ((__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0)) + +-/* +- * 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. +- * +- * A non-zero step value implies that the command may access multiple +- * registers in sequence (e.g. LRI), in that case step gives the +- * distance in dwords between individual offset fields. +- */ +- struct { +- u32 offset; +- u32 mask; +- u32 step; +- } 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. +- * +- * 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]; +-}; +- +-/* +- * A table of commands requiring special handling by the command parser. +- * +- * Each engine 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; +-}; +- + /* Note that the (struct drm_i915_private *) cast is just to shut up gcc. */ + #define __I915__(p) ({ \ + struct drm_i915_private *__p; \ diff --git a/queue-4.9/drm-i915-lower-rm-timeout-to-avoid-dsi-hard-hangs.patch b/queue-4.9/drm-i915-lower-rm-timeout-to-avoid-dsi-hard-hangs.patch new file mode 100644 index 00000000000..851dbf8bd8c --- /dev/null +++ b/queue-4.9/drm-i915-lower-rm-timeout-to-avoid-dsi-hard-hangs.patch @@ -0,0 +1,74 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Uma Shankar +Date: Tue, 7 Aug 2018 21:15:35 +0530 +Subject: drm/i915: Lower RM timeout to avoid DSI hard hangs + +From: Uma Shankar + +commit 1d85a299c4db57c55e0229615132c964d17aa765 upstream. + +In BXT/APL, device 2 MMIO reads from MIPI controller requires its PLL +to be turned ON. When MIPI PLL is turned off (MIPI Display is not +active or connected), and someone (host or GT engine) tries to read +MIPI registers, it causes hard hang. This is a hardware restriction +or limitation. + +Driver by itself doesn't read MIPI registers when MIPI display is off. +But any userspace application can submit unprivileged batch buffer for +execution. In that batch buffer there can be mmio reads. And these +reads are allowed even for unprivileged applications. If these +register reads are for MIPI DSI controller and MIPI display is not +active during that time, then the MMIO read operation causes system +hard hang and only way to recover is hard reboot. A genuine +process/application won't submit batch buffer like this and doesn't +cause any issue. But on a compromised system, a malign userspace +process/app can generate such batch buffer and can trigger system +hard hang (denial of service attack). + +The fix is to lower the internal MMIO timeout value to an optimum +value of 950us as recommended by hardware team. If the timeout is +beyond 1ms (which will hit for any value we choose if MMIO READ on a +DSI specific register is performed without PLL ON), it causes the +system hang. But if the timeout value is lower than it will be below +the threshold (even if timeout happens) and system will not get into +a hung state. This will avoid a system hang without losing any +programming or GT interrupts, taking the worst case of lowest CDCLK +frequency and early DC5 abort into account. + +Signed-off-by: Uma Shankar +Reviewed-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_reg.h | 4 ++++ + drivers/gpu/drm/i915/intel_pm.c | 7 +++++++ + 2 files changed, 11 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -5939,6 +5939,10 @@ enum { + #define SKL_CSR_DC5_DC6_COUNT _MMIO(0x8002C) + #define BXT_CSR_DC3_DC5_COUNT _MMIO(0x80038) + ++/* Display Internal Timeout Register */ ++#define RM_TIMEOUT _MMIO(0x42060) ++#define MMIO_TIMEOUT_US(us) ((us) << 0) ++ + /* interrupts */ + #define DE_MASTER_IRQ_CONTROL (1 << 31) + #define DE_SPRITEB_FLIP_DONE (1 << 29) +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -105,6 +105,13 @@ static void bxt_init_clock_gating(struct + if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) + I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) | + PWM1_GATING_DIS | PWM2_GATING_DIS); ++ /* ++ * Lower the display internal timeout. ++ * This is needed to avoid any hard hangs when DSI port PLL ++ * is off and a MMIO access is attempted by any privilege ++ * application, using batch buffers or any other means. ++ */ ++ I915_WRITE(RM_TIMEOUT, MMIO_TIMEOUT_US(950)); + } + + static void i915_pineview_get_mem_freq(struct drm_device *dev) diff --git a/queue-4.9/drm-i915-move-engine-needs_cmd_parser-to-engine-flags.patch b/queue-4.9/drm-i915-move-engine-needs_cmd_parser-to-engine-flags.patch new file mode 100644 index 00000000000..42ad29b8930 --- /dev/null +++ b/queue-4.9/drm-i915-move-engine-needs_cmd_parser-to-engine-flags.patch @@ -0,0 +1,103 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Tvrtko Ursulin +Date: Wed, 29 Nov 2017 08:24:09 +0000 +Subject: drm/i915: Move engine->needs_cmd_parser to engine->flags + +From: Tvrtko Ursulin + +commit 439e2ee4ca520e72870e4fa44aa0076060ad6857 upstream. + +Will be adding a new per-engine flags shortly so it makes sense +to consolidate. + +v2: Keep the original code flow in intel_engine_cleanup_cmd_parser. + (Joonas Lahtinen) + +Signed-off-by: Tvrtko Ursulin +Suggested-by: Chris Wilson +Reviewed-by: Chris Wilson +Reviewed-by: Sagar Arun Kamble +Reviewed-by: Joonas Lahtinen +Link: https://patchwork.freedesktop.org/patch/msgid/20171129082409.18189-1-tvrtko.ursulin@linux.intel.com +Signed-off-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 7 ++++--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- + drivers/gpu/drm/i915/intel_ringbuffer.h | 10 ++++++++-- + 3 files changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -26,6 +26,7 @@ + */ + + #include "i915_drv.h" ++#include "intel_ringbuffer.h" + + /** + * DOC: batch buffer command parser +@@ -940,7 +941,7 @@ void intel_engine_init_cmd_parser(struct + return; + } + +- engine->needs_cmd_parser = true; ++ engine->flags |= I915_ENGINE_NEEDS_CMD_PARSER; + } + + /** +@@ -952,7 +953,7 @@ void intel_engine_init_cmd_parser(struct + */ + void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine) + { +- if (!engine->needs_cmd_parser) ++ if (!intel_engine_needs_cmd_parser(engine)) + return; + + fini_hash_table(engine); +@@ -1355,7 +1356,7 @@ int i915_cmd_parser_get_version(struct d + + /* If the command parser is not enabled, report 0 - unsupported */ + for_each_engine(engine, dev_priv) { +- if (engine->needs_cmd_parser) { ++ if (intel_engine_needs_cmd_parser(engine)) { + active = true; + break; + } +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1711,7 +1711,7 @@ i915_gem_do_execbuffer(struct drm_device + } + + params->args_batch_start_offset = args->batch_start_offset; +- if (engine->needs_cmd_parser && args->batch_len) { ++ if (intel_engine_needs_cmd_parser(engine) && args->batch_len) { + struct i915_vma *vma; + + vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry, +--- a/drivers/gpu/drm/i915/intel_ringbuffer.h ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.h +@@ -341,7 +341,8 @@ struct intel_engine_cs { + + struct intel_engine_hangcheck hangcheck; + +- bool needs_cmd_parser; ++#define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) ++ unsigned int flags; + + /* + * Table of commands the command parser needs to know about +@@ -374,7 +375,12 @@ intel_engine_initialized(const struct in + return engine->i915 != NULL; + } + +-static inline unsigned ++static inline bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine) ++{ ++ return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER; ++} ++ ++static inline unsigned int + intel_engine_flag(const struct intel_engine_cs *engine) + { + return 1 << engine->id; diff --git a/queue-4.9/drm-i915-prevent-writing-into-a-read-only-object-via-a-ggtt-mmap.patch b/queue-4.9/drm-i915-prevent-writing-into-a-read-only-object-via-a-ggtt-mmap.patch new file mode 100644 index 00000000000..72617de0f32 --- /dev/null +++ b/queue-4.9/drm-i915-prevent-writing-into-a-read-only-object-via-a-ggtt-mmap.patch @@ -0,0 +1,155 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Chris Wilson +Date: Thu, 12 Jul 2018 19:53:13 +0100 +Subject: drm/i915: Prevent writing into a read-only object via a GGTT mmap + +From: Chris Wilson + +commit 3e977ac6179b39faa3c0eda5fce4f00663ae298d upstream. + +If the user has created a read-only object, they should not be allowed +to circumvent the write protection by using a GGTT mmapping. Deny it. + +Also most machines do not support read-only GGTT PTEs, so again we have +to reject attempted writes. Fortunately, this is known a priori, so we +can at least reject in the call to create the mmap (with a sanity check +in the fault handler). + +v2: Check the vma->vm_flags during mmap() to allow readonly access. +v3: Remove VM_MAYWRITE to curtail mprotect() + +Testcase: igt/gem_userptr_blits/readonly_mmap* +Signed-off-by: Chris Wilson +Cc: Jon Bloomfield +Cc: Joonas Lahtinen +Cc: Matthew Auld +Cc: David Herrmann +Reviewed-by: Matthew Auld #v1 +Reviewed-by: Joonas Lahtinen +Link: https://patchwork.freedesktop.org/patch/msgid/20180712185315.3288-4-chris@chris-wilson.co.uk +Signed-off-by: Rodrigo Vivi +Reviewed-by: Jon Bloomfield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/drm_gem.c | 9 +++++++++ + drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++++ + drivers/gpu/drm/i915/i915_gem.c | 4 ++++ + drivers/gpu/drm/i915/i915_gem_gtt.c | 11 ++++++++--- + drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- + include/drm/drm_vma_manager.h | 1 + + 6 files changed, 35 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -996,6 +996,15 @@ int drm_gem_mmap(struct file *filp, stru + return -EACCES; + } + ++ if (node->readonly) { ++ if (vma->vm_flags & VM_WRITE) { ++ drm_gem_object_unreference_unlocked(obj); ++ return -EINVAL; ++ } ++ ++ vma->vm_flags &= ~VM_MAYWRITE; ++ } ++ + ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, + vma); + +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -2339,6 +2339,18 @@ i915_gem_object_put_unlocked(struct drm_ + __deprecated + extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *); + ++static inline void ++i915_gem_object_set_readonly(struct drm_i915_gem_object *obj) ++{ ++ obj->base.vma_node.readonly = true; ++} ++ ++static inline bool ++i915_gem_object_is_readonly(const struct drm_i915_gem_object *obj) ++{ ++ return obj->base.vma_node.readonly; ++} ++ + static inline bool + i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj) + { +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -1773,6 +1773,10 @@ int i915_gem_fault(struct vm_area_struct + unsigned int flags; + int ret; + ++ /* Sanity check that we allow writing into this object */ ++ if (i915_gem_object_is_readonly(obj) && write) ++ return VM_FAULT_SIGBUS; ++ + /* We don't use vmf->pgoff since that has the fake offset */ + page_offset = ((unsigned long)vmf->virtual_address - area->vm_start) >> + PAGE_SHIFT; +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -178,7 +178,7 @@ static int ppgtt_bind_vma(struct i915_vm + vma->pages = vma->obj->pages; + + /* Applicable to VLV, and gen8+ */ +- if (vma->obj->gt_ro) ++ if (i915_gem_object_is_readonly(vma->obj)) + pte_flags |= PTE_READ_ONLY; + + vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start, +@@ -2360,6 +2360,11 @@ static void gen8_ggtt_insert_entries(str + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); + ++ /* ++ * Note that we ignore PTE_READ_ONLY here. The caller must be careful ++ * not to allow the user to override access to a read only page. ++ */ ++ + gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); + + for_each_sgt_dma(addr, sgt_iter, st) { +@@ -2620,7 +2625,7 @@ static int ggtt_bind_vma(struct i915_vma + return ret; + + /* Applicable to VLV (gen8+ do not support RO in the GGTT) */ +- if (obj->gt_ro) ++ if (i915_gem_object_is_readonly(obj)) + pte_flags |= PTE_READ_ONLY; + + vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start, +@@ -2649,7 +2654,7 @@ static int aliasing_gtt_bind_vma(struct + + /* Currently applicable only to VLV */ + pte_flags = 0; +- if (vma->obj->gt_ro) ++ if (i915_gem_object_is_readonly(vma->obj)) + pte_flags |= PTE_READ_ONLY; + + +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -1966,7 +1966,7 @@ intel_ring_create_vma(struct drm_i915_pr + * if supported by the platform's GGTT. + */ + if (vm->has_read_only) +- obj->gt_ro = 1; ++ i915_gem_object_set_readonly(obj); + + vma = i915_vma_create(obj, vm, NULL); + if (IS_ERR(vma)) +--- a/include/drm/drm_vma_manager.h ++++ b/include/drm/drm_vma_manager.h +@@ -42,6 +42,7 @@ struct drm_vma_offset_node { + rwlock_t vm_lock; + struct drm_mm_node vm_node; + struct rb_root vm_files; ++ bool readonly:1; + }; + + struct drm_vma_offset_manager { diff --git a/queue-4.9/drm-i915-remove-master-tables-from-cmdparser.patch b/queue-4.9/drm-i915-remove-master-tables-from-cmdparser.patch new file mode 100644 index 00000000000..4af38ff689e --- /dev/null +++ b/queue-4.9/drm-i915-remove-master-tables-from-cmdparser.patch @@ -0,0 +1,301 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Fri, 8 Jun 2018 10:05:26 -0700 +Subject: drm/i915: Remove Master tables from cmdparser + +From: Jon Bloomfield + +commit 66d8aba1cd6db34af10de465c0d52af679288cb6 upstream. + +The previous patch has killed support for secure batches +on gen6+, and hence the cmdparsers master tables are +now dead code. Remove them. + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 84 +++++++---------------------- + drivers/gpu/drm/i915/i915_drv.h | 3 - + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 +-- + 3 files changed, 26 insertions(+), 70 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -51,13 +51,11 @@ + * 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. ++ * only be used by the kernel driver. The parser rejects such commands + * + * 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). ++ * provides a whitelist of registers which userspace may safely access + * + * Third, commands which access privileged memory (i.e. GGTT, HWS page, etc). + * The parser always rejects such commands. +@@ -82,9 +80,9 @@ + * in the per-engine 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. ++ * mentioned above: rejected, register whitelist. The parser implements a number ++ * of checks, including the privileged memory checks, via a general bitmasking ++ * mechanism. + */ + + /* +@@ -102,8 +100,6 @@ struct drm_i915_cmd_descriptor { + * 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) +@@ -111,7 +107,6 @@ struct drm_i915_cmd_descriptor { + #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. +@@ -207,14 +202,13 @@ struct drm_i915_cmd_table { + #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 gen7_common_cmds[] = { + CMD( MI_NOOP, SMI, F, 1, S ), + CMD( MI_USER_INTERRUPT, SMI, F, 1, R ), +- CMD( MI_WAIT_FOR_EVENT, SMI, F, 1, M ), ++ 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 ), +@@ -311,7 +305,7 @@ static const struct drm_i915_cmd_descrip + CMD( MI_URB_ATOMIC_ALLOC, SMI, F, 1, S ), + CMD( MI_SET_APPID, SMI, F, 1, S ), + CMD( MI_RS_CONTEXT, SMI, F, 1, S ), +- CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ), ++ 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, W, + .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 } ), +@@ -444,7 +438,7 @@ static const struct drm_i915_cmd_descrip + }; + + static const struct drm_i915_cmd_descriptor hsw_blt_cmds[] = { +- CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ), ++ CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, R ), + CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ), + }; + +@@ -461,7 +455,6 @@ static const struct drm_i915_cmd_descrip + #undef R + #undef W + #undef B +-#undef M + + static const struct drm_i915_cmd_table gen7_render_cmd_table[] = { + { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, +@@ -610,47 +603,29 @@ static const struct drm_i915_reg_descrip + REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE), + }; + +-static const struct drm_i915_reg_descriptor ivb_master_regs[] = { +- REG32(FORCEWAKE_MT), +- REG32(DERRMR), +- REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_A)), +- REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_B)), +- REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_C)), +-}; +- +-static const struct drm_i915_reg_descriptor hsw_master_regs[] = { +- REG32(FORCEWAKE_MT), +- REG32(DERRMR), +-}; +- + #undef REG64 + #undef REG32 + + struct drm_i915_reg_table { + const struct drm_i915_reg_descriptor *regs; + int num_regs; +- bool master; + }; + + static const struct drm_i915_reg_table ivb_render_reg_tables[] = { +- { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false }, +- { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true }, ++ { gen7_render_regs, ARRAY_SIZE(gen7_render_regs) }, + }; + + static const struct drm_i915_reg_table ivb_blt_reg_tables[] = { +- { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false }, +- { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true }, ++ { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) }, + }; + + static const struct drm_i915_reg_table hsw_render_reg_tables[] = { +- { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false }, +- { hsw_render_regs, ARRAY_SIZE(hsw_render_regs), false }, +- { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true }, ++ { gen7_render_regs, ARRAY_SIZE(gen7_render_regs) }, ++ { hsw_render_regs, ARRAY_SIZE(hsw_render_regs) }, + }; + + static const struct drm_i915_reg_table hsw_blt_reg_tables[] = { +- { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false }, +- { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true }, ++ { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) }, + }; + + static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) +@@ -1027,22 +1002,16 @@ __find_reg(const struct drm_i915_reg_des + } + + static const struct drm_i915_reg_descriptor * +-find_reg(const struct intel_engine_cs *engine, bool is_master, u32 addr) ++find_reg(const struct intel_engine_cs *engine, u32 addr) + { + const struct drm_i915_reg_table *table = engine->reg_tables; ++ const struct drm_i915_reg_descriptor *reg = NULL; + int count = engine->reg_table_count; + +- for (; count > 0; ++table, --count) { +- if (!table->master || is_master) { +- const struct drm_i915_reg_descriptor *reg; +- +- reg = __find_reg(table->regs, table->num_regs, addr); +- if (reg != NULL) +- return reg; +- } +- } ++ for (; !reg && (count > 0); ++table, --count) ++ reg = __find_reg(table->regs, table->num_regs, addr); + +- return NULL; ++ return reg; + } + + /* Returns a vmap'd pointer to dst_obj, which the caller must unmap */ +@@ -1127,8 +1096,7 @@ unpin_src: + + static bool check_cmd(const struct intel_engine_cs *engine, + const struct drm_i915_cmd_descriptor *desc, +- const u32 *cmd, u32 length, +- const bool is_master) ++ const u32 *cmd, u32 length) + { + if (desc->flags & CMD_DESC_SKIP) + return true; +@@ -1138,12 +1106,6 @@ static bool check_cmd(const struct intel + return false; + } + +- if ((desc->flags & CMD_DESC_MASTER) && !is_master) { +- DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n", +- *cmd); +- return false; +- } +- + if (desc->flags & CMD_DESC_REGISTER) { + /* + * Get the distance between individual register offset +@@ -1157,7 +1119,7 @@ static bool check_cmd(const struct intel + offset += step) { + const u32 reg_addr = cmd[offset] & desc->reg.mask; + const struct drm_i915_reg_descriptor *reg = +- find_reg(engine, is_master, reg_addr); ++ find_reg(engine, reg_addr); + + if (!reg) { + DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (exec_id=%d)\n", +@@ -1244,7 +1206,6 @@ static bool check_cmd(const struct intel + * @shadow_batch_obj: copy of the batch buffer in question + * @batch_start_offset: byte offset in the batch at which execution starts + * @batch_len: length of the commands in batch_obj +- * @is_master: is the submitting process the drm master? + * + * Parses the specified batch buffer looking for privilege violations as + * described in the overview. +@@ -1256,8 +1217,7 @@ int intel_engine_cmd_parser(struct intel + struct drm_i915_gem_object *batch_obj, + struct drm_i915_gem_object *shadow_batch_obj, + u32 batch_start_offset, +- u32 batch_len, +- bool is_master) ++ u32 batch_len) + { + u32 *cmd, *batch_end; + struct drm_i915_cmd_descriptor default_desc = noop_desc; +@@ -1323,7 +1283,7 @@ int intel_engine_cmd_parser(struct intel + break; + } + +- if (!check_cmd(engine, desc, cmd, length, is_master)) { ++ if (!check_cmd(engine, desc, cmd, length)) { + ret = -EACCES; + break; + } +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -3473,8 +3473,7 @@ int intel_engine_cmd_parser(struct intel + struct drm_i915_gem_object *batch_obj, + struct drm_i915_gem_object *shadow_batch_obj, + u32 batch_start_offset, +- u32 batch_len, +- bool is_master); ++ u32 batch_len); + + /* i915_suspend.c */ + extern int i915_save_state(struct drm_device *dev); +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1407,8 +1407,7 @@ i915_gem_execbuffer_parse(struct intel_e + struct drm_i915_gem_object *batch_obj, + struct eb_vmas *eb, + u32 batch_start_offset, +- u32 batch_len, +- bool is_master) ++ u32 batch_len) + { + struct drm_i915_gem_object *shadow_batch_obj; + struct i915_vma *vma; +@@ -1423,8 +1422,7 @@ i915_gem_execbuffer_parse(struct intel_e + batch_obj, + shadow_batch_obj, + batch_start_offset, +- batch_len, +- is_master); ++ batch_len); + if (ret) { + if (ret == -EACCES) /* unhandled chained batch */ + vma = NULL; +@@ -1725,8 +1723,7 @@ i915_gem_do_execbuffer(struct drm_device + params->batch->obj, + eb, + args->batch_start_offset, +- args->batch_len, +- drm_is_current_master(file)); ++ args->batch_len); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; diff --git a/queue-4.9/drm-i915-rename-gen7-cmdparser-tables.patch b/queue-4.9/drm-i915-rename-gen7-cmdparser-tables.patch new file mode 100644 index 00000000000..ad3cf098d25 --- /dev/null +++ b/queue-4.9/drm-i915-rename-gen7-cmdparser-tables.patch @@ -0,0 +1,179 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Fri, 20 Apr 2018 14:26:01 -0700 +Subject: drm/i915: Rename gen7 cmdparser tables + +From: Jon Bloomfield + +commit 0a2f661b6c21815a7fa60e30babe975fee8e73c6 upstream. + +We're about to introduce some new tables for later gens, and the +current naming for the gen7 tables will no longer make sense. + +v2: rebase + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 70 ++++++++++++++++----------------- + 1 file changed, 35 insertions(+), 35 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -211,7 +211,7 @@ struct drm_i915_cmd_table { + + /* Command Mask Fixed Len Action + ---------------------------------------------------------- */ +-static const struct drm_i915_cmd_descriptor common_cmds[] = { ++static const struct drm_i915_cmd_descriptor gen7_common_cmds[] = { + CMD( MI_NOOP, SMI, F, 1, S ), + CMD( MI_USER_INTERRUPT, SMI, F, 1, R ), + CMD( MI_WAIT_FOR_EVENT, SMI, F, 1, M ), +@@ -244,7 +244,7 @@ static const struct drm_i915_cmd_descrip + CMD( MI_BATCH_BUFFER_START, SMI, !F, 0xFF, S ), + }; + +-static const struct drm_i915_cmd_descriptor render_cmds[] = { ++static const struct drm_i915_cmd_descriptor gen7_render_cmds[] = { + CMD( MI_FLUSH, SMI, F, 1, S ), + CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), + CMD( MI_PREDICATE, SMI, F, 1, S ), +@@ -328,7 +328,7 @@ static const struct drm_i915_cmd_descrip + CMD( GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS, S3D, !F, 0x1FF, S ), + }; + +-static const struct drm_i915_cmd_descriptor video_cmds[] = { ++static const struct drm_i915_cmd_descriptor gen7_video_cmds[] = { + CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), + CMD( MI_SET_APPID, SMI, F, 1, S ), + CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, +@@ -372,7 +372,7 @@ static const struct drm_i915_cmd_descrip + CMD( MFX_WAIT, SMFX, F, 1, S ), + }; + +-static const struct drm_i915_cmd_descriptor vecs_cmds[] = { ++static const struct drm_i915_cmd_descriptor gen7_vecs_cmds[] = { + CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), + CMD( MI_SET_APPID, SMI, F, 1, S ), + CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, +@@ -410,7 +410,7 @@ static const struct drm_i915_cmd_descrip + }}, ), + }; + +-static const struct drm_i915_cmd_descriptor blt_cmds[] = { ++static const struct drm_i915_cmd_descriptor gen7_blt_cmds[] = { + CMD( MI_DISPLAY_FLIP, SMI, !F, 0xFF, R ), + CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3FF, B, + .bits = {{ +@@ -463,35 +463,35 @@ static const struct drm_i915_cmd_descrip + #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 gen7_render_cmd_table[] = { ++ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, ++ { gen7_render_cmds, ARRAY_SIZE(gen7_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) }, ++static const struct drm_i915_cmd_table hsw_render_ring_cmd_table[] = { ++ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, ++ { gen7_render_cmds, ARRAY_SIZE(gen7_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 gen7_video_cmd_table[] = { ++ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, ++ { gen7_video_cmds, ARRAY_SIZE(gen7_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 hsw_vebox_cmd_table[] = { ++ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, ++ { gen7_vecs_cmds, ARRAY_SIZE(gen7_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 const struct drm_i915_cmd_table gen7_blt_cmd_table[] = { ++ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, ++ { gen7_blt_cmds, ARRAY_SIZE(gen7_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) }, ++static const struct drm_i915_cmd_table hsw_blt_ring_cmd_table[] = { ++ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) }, ++ { gen7_blt_cmds, ARRAY_SIZE(gen7_blt_cmds) }, + { hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) }, + }; + +@@ -871,12 +871,12 @@ void intel_engine_init_cmd_parser(struct + switch (engine->id) { + case RCS: + if (IS_HASWELL(engine->i915)) { +- cmd_tables = hsw_render_ring_cmds; ++ cmd_tables = hsw_render_ring_cmd_table; + cmd_table_count = +- ARRAY_SIZE(hsw_render_ring_cmds); ++ ARRAY_SIZE(hsw_render_ring_cmd_table); + } else { +- cmd_tables = gen7_render_cmds; +- cmd_table_count = ARRAY_SIZE(gen7_render_cmds); ++ cmd_tables = gen7_render_cmd_table; ++ cmd_table_count = ARRAY_SIZE(gen7_render_cmd_table); + } + + if (IS_HASWELL(engine->i915)) { +@@ -890,17 +890,17 @@ void intel_engine_init_cmd_parser(struct + engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask; + break; + case VCS: +- cmd_tables = gen7_video_cmds; +- cmd_table_count = ARRAY_SIZE(gen7_video_cmds); ++ cmd_tables = gen7_video_cmd_table; ++ cmd_table_count = ARRAY_SIZE(gen7_video_cmd_table); + engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; + break; + case BCS: + if (IS_HASWELL(engine->i915)) { +- cmd_tables = hsw_blt_ring_cmds; +- cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds); ++ cmd_tables = hsw_blt_ring_cmd_table; ++ cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmd_table); + } else { +- cmd_tables = gen7_blt_cmds; +- cmd_table_count = ARRAY_SIZE(gen7_blt_cmds); ++ cmd_tables = gen7_blt_cmd_table; ++ cmd_table_count = ARRAY_SIZE(gen7_blt_cmd_table); + } + + if (IS_HASWELL(engine->i915)) { +@@ -914,8 +914,8 @@ void intel_engine_init_cmd_parser(struct + engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask; + break; + case VECS: +- cmd_tables = hsw_vebox_cmds; +- cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds); ++ cmd_tables = hsw_vebox_cmd_table; ++ cmd_table_count = ARRAY_SIZE(hsw_vebox_cmd_table); + /* VECS can use the same length_mask function as VCS */ + engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; + break; diff --git a/queue-4.9/drm-i915-return-eacces-for-check_cmd-failures.patch b/queue-4.9/drm-i915-return-eacces-for-check_cmd-failures.patch new file mode 100644 index 00000000000..7fcaa536317 --- /dev/null +++ b/queue-4.9/drm-i915-return-eacces-for-check_cmd-failures.patch @@ -0,0 +1,67 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Robert Bragg +Date: Mon, 7 Nov 2016 19:49:49 +0000 +Subject: drm/i915: return EACCES for check_cmd() failures + +From: Robert Bragg + +commit 9bbeaedb664a6d3e1cfbe6b0c2f07bf667512456 upstream. + +check_cmd() is checking whether a command adheres to certain +restrictions that ensure it's safe to execute within a privileged batch +buffer. Returning false implies a privilege problem, not that the +command is invalid. + +The distinction makes the difference between allowing the buffer to be +executed as an unprivileged batch buffer or returning an EINVAL error to +userspace without executing anything. + +In a case where userspace may want to test whether it can successfully +write to a register that needs privileges the distinction may be +important and an EINVAL error may be considered fatal. + +In particular this is currently true for Mesa, which includes a test for +whether OACONTROL can be written too, but Mesa treats any error when +flushing a batch buffer as fatal, calling exit(1). + +As it is currently Mesa can gracefully handle a failure to write to +OACONTROL if the command parser is disabled, but if we were to remove +OACONTROL from the parser's whitelist then the returned EINVAL would +break Mesa applications as they attempt an OACONTROL write. + +This bumps the command parser version from 7 to 8, as the change is +visible to userspace. + +Signed-off-by: Robert Bragg +Reviewed-by: Matthew Auld +Reviewed-by: Sourab Gupta +Signed-off-by: Daniel Vetter +Signed-off-by: Jon Bloomfield +Link: http://patchwork.freedesktop.org/patch/msgid/20161107194957.3385-4-robert@sixbynine.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1368,7 +1368,7 @@ int intel_engine_cmd_parser(struct intel + + if (!check_cmd(engine, desc, cmd, length, is_master, + &oacontrol_set)) { +- ret = -EINVAL; ++ ret = -EACCES; + break; + } + +@@ -1428,6 +1428,9 @@ int i915_cmd_parser_get_version(struct d + * 5. GPGPU dispatch compute indirect registers. + * 6. TIMESTAMP register and Haswell CS GPR registers + * 7. Allow MI_LOAD_REGISTER_REG between whitelisted registers. ++ * 8. Don't report cmd_check() failures as EINVAL errors to userspace; ++ * rely on the HW to NOOP disallowed commands as it would without ++ * the parser enabled. + */ +- return 7; ++ return 8; + } diff --git a/queue-4.9/drm-i915-silence-smatch-for-cmdparser.patch b/queue-4.9/drm-i915-silence-smatch-for-cmdparser.patch new file mode 100644 index 00000000000..9d64d0643ec --- /dev/null +++ b/queue-4.9/drm-i915-silence-smatch-for-cmdparser.patch @@ -0,0 +1,69 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Chris Wilson +Date: Tue, 7 Nov 2017 15:40:55 +0000 +Subject: drm/i915: Silence smatch for cmdparser + +From: Chris Wilson + +commit 0ffba1fc98e8ec35caae8d50b657296ebb9a9a51 upstream. + +drivers/gpu/drm/i915/i915_cmd_parser.c:808:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:811:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:814:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:808:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:811:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:814:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:808:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:811:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:814:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:808:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:811:23: error: not an lvalue +drivers/gpu/drm/i915/i915_cmd_parser.c:814:23: error: not an lvalue + +If we move the shift into each case not only do we kill the warning from +smatch, but we shrink the code slightly: + + text data bss dec hex filename +1267906 20587 3168 1291661 13b58d before +1267890 20587 3168 1291645 13b57d after + +Signed-off-by: Chris Wilson +Cc: Joonas Lahtinen +Cc: Mika Kuoppala +Cc: Matthew Auld +Link: https://patchwork.freedesktop.org/patch/msgid/20171107154055.19460-1-chris@chris-wilson.co.uk +Reviewed-by: Matthew Auld +Reviewed-by: Gabriel Krisman Bertazi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -798,22 +798,15 @@ struct cmd_node { + */ + static inline u32 cmd_header_key(u32 x) + { +- u32 shift; +- + switch (x >> INSTR_CLIENT_SHIFT) { + default: + case INSTR_MI_CLIENT: +- shift = STD_MI_OPCODE_SHIFT; +- break; ++ return x >> STD_MI_OPCODE_SHIFT; + case INSTR_RC_CLIENT: +- shift = STD_3D_OPCODE_SHIFT; +- break; ++ return x >> STD_3D_OPCODE_SHIFT; + case INSTR_BC_CLIENT: +- shift = STD_2D_OPCODE_SHIFT; +- break; ++ return x >> STD_2D_OPCODE_SHIFT; + } +- +- return x >> shift; + } + + static int init_hash_table(struct intel_engine_cs *engine, diff --git a/queue-4.9/drm-i915-support-ro-ppgtt-mapped-cmdparser-shadow-buffers.patch b/queue-4.9/drm-i915-support-ro-ppgtt-mapped-cmdparser-shadow-buffers.patch new file mode 100644 index 00000000000..fbc21901103 --- /dev/null +++ b/queue-4.9/drm-i915-support-ro-ppgtt-mapped-cmdparser-shadow-buffers.patch @@ -0,0 +1,198 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Jon Bloomfield +Date: Tue, 22 May 2018 13:59:06 -0700 +Subject: drm/i915: Support ro ppgtt mapped cmdparser shadow buffers + +From: Jon Bloomfield + +commit 4f7af1948abcb18b4772fe1bcd84d7d27d96258c upstream. + +For Gen7, the original cmdparser motive was to permit limited +use of register read/write instructions in unprivileged BB's. +This worked by copying the user supplied bb to a kmd owned +bb, and running it in secure mode, from the ggtt, only if +the scanner finds no unsafe commands or registers. + +For Gen8+ we can't use this same technique because running bb's +from the ggtt also disables access to ppgtt space. But we also +do not actually require 'secure' execution since we are only +trying to reduce the available command/register set. Instead we +will copy the user buffer to a kmd owned read-only bb in ppgtt, +and run in the usual non-secure mode. + +Note that ro pages are only supported by ppgtt (not ggtt), but +luckily that's exactly what we need. + +Add the required paths to map the shadow buffer to ppgtt ro for Gen8+ + +v2: IS_GEN7/IS_GEN (Mika) +v3: rebase +v4: rebase +v5: rebase + +Signed-off-by: Jon Bloomfield +Cc: Tony Luck +Cc: Dave Airlie +Cc: Takashi Iwai +Cc: Tyler Hicks +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_drv.h | 14 ++++++++ + drivers/gpu/drm/i915/i915_gem.c | 15 ++++++++ + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 50 +++++++++++++++++++++-------- + 3 files changed, 65 insertions(+), 14 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -2645,6 +2645,12 @@ static inline struct scatterlist *__sg_n + #define IS_GEN8(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(7))) + #define IS_GEN9(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(8))) + ++/* ++ * The Gen7 cmdparser copies the scanned buffer to the ggtt for execution ++ * All later gens can run the final buffer from the ppgtt ++ */ ++#define CMDPARSER_USES_GGTT(dev_priv) IS_GEN7(dev_priv) ++ + #define ENGINE_MASK(id) BIT(id) + #define RENDER_RING ENGINE_MASK(RCS) + #define BSD_RING ENGINE_MASK(VCS) +@@ -3016,6 +3022,14 @@ i915_gem_object_ggtt_pin(struct drm_i915 + u64 alignment, + u64 flags); + ++struct i915_vma * __must_check ++i915_gem_object_pin(struct drm_i915_gem_object *obj, ++ struct i915_address_space *vm, ++ const struct i915_ggtt_view *view, ++ u64 size, ++ u64 alignment, ++ u64 flags); ++ + int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, + u32 flags); + void __i915_vma_set_map_and_fenceable(struct i915_vma *vma); +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -3826,6 +3826,19 @@ i915_gem_object_ggtt_pin(struct drm_i915 + u64 flags) + { + struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base; ++ ++ return i915_gem_object_pin(obj, vm, view, size, alignment, ++ flags | PIN_GLOBAL); ++} ++ ++struct i915_vma * ++i915_gem_object_pin(struct drm_i915_gem_object *obj, ++ struct i915_address_space *vm, ++ const struct i915_ggtt_view *view, ++ u64 size, ++ u64 alignment, ++ u64 flags) ++{ + struct i915_vma *vma; + int ret; + +@@ -3850,7 +3863,7 @@ i915_gem_object_ggtt_pin(struct drm_i915 + return ERR_PTR(ret); + } + +- ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL); ++ ret = i915_vma_pin(vma, size, alignment, flags); + if (ret) + return ERR_PTR(ret); + +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1401,11 +1401,36 @@ i915_reset_gen7_sol_offsets(struct drm_i + return 0; + } + ++static struct i915_vma* ++shadow_batch_pin(struct drm_i915_gem_object *obj, struct i915_address_space *vm) ++{ ++ struct drm_i915_private *dev_priv = to_i915(obj->base.dev); ++ u64 flags; ++ ++ /* ++ * PPGTT backed shadow buffers must be mapped RO, to prevent ++ * post-scan tampering ++ */ ++ if (CMDPARSER_USES_GGTT(dev_priv)) { ++ flags = PIN_GLOBAL; ++ vm = &dev_priv->ggtt.base; ++ } else if (vm->has_read_only) { ++ flags = PIN_USER; ++ i915_gem_object_set_readonly(obj); ++ } else { ++ DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return i915_gem_object_pin(obj, vm, NULL, 0, 0, flags); ++} ++ + static struct i915_vma * + i915_gem_execbuffer_parse(struct intel_engine_cs *engine, + struct drm_i915_gem_exec_object2 *shadow_exec_entry, + struct drm_i915_gem_object *batch_obj, + struct eb_vmas *eb, ++ struct i915_address_space *vm, + u32 batch_start_offset, + u32 batch_len) + { +@@ -1424,14 +1449,21 @@ i915_gem_execbuffer_parse(struct intel_e + batch_start_offset, + batch_len); + if (ret) { +- if (ret == -EACCES) /* unhandled chained batch */ ++ /* ++ * Unsafe GGTT-backed buffers can still be submitted safely ++ * as non-secure. ++ * For PPGTT backing however, we have no choice but to forcibly ++ * reject unsafe buffers ++ */ ++ if (CMDPARSER_USES_GGTT(eb->i915) && (ret == -EACCES)) ++ /* Execute original buffer non-secure */ + vma = NULL; + else + vma = ERR_PTR(ret); + goto out; + } + +- vma = i915_gem_object_ggtt_pin(shadow_batch_obj, NULL, 0, 0, 0); ++ vma = shadow_batch_pin(shadow_batch_obj, vm); + if (IS_ERR(vma)) + goto out; + +@@ -1722,7 +1754,7 @@ i915_gem_do_execbuffer(struct drm_device + + vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry, + params->batch->obj, +- eb, ++ eb, vm, + args->batch_start_offset, + args->batch_len); + if (IS_ERR(vma)) { +@@ -1731,16 +1763,8 @@ i915_gem_do_execbuffer(struct drm_device + } + + if (vma) { +- /* +- * Batch parsed and accepted: +- * +- * 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 on batches the +- * command parser has accepted. +- */ +- dispatch_flags |= I915_DISPATCH_SECURE; ++ if (CMDPARSER_USES_GGTT(dev_priv)) ++ dispatch_flags |= I915_DISPATCH_SECURE; + params->args_batch_start_offset = 0; + params->batch = vma; + } diff --git a/queue-4.9/drm-i915-use-the-precomputed-value-for-whether-to-enable-command-parsing.patch b/queue-4.9/drm-i915-use-the-precomputed-value-for-whether-to-enable-command-parsing.patch new file mode 100644 index 00000000000..f8b53d32b09 --- /dev/null +++ b/queue-4.9/drm-i915-use-the-precomputed-value-for-whether-to-enable-command-parsing.patch @@ -0,0 +1,130 @@ +From foo@baz Tue 12 Nov 2019 04:09:52 PM CET +From: Chris Wilson +Date: Thu, 24 Nov 2016 12:58:51 +0000 +Subject: drm/i915: Use the precomputed value for whether to enable command parsing + +From: Chris Wilson + +commit 41736a8e3331a67445b271e73be39536c498659e upstream. + +As i915.enable_cmd_parser is an unsafe option, make it read-only at +runtime. Now that it is constant, we can use the value determined during +initialisation as to whether we need the cmdparser at execbuffer time. + +v2: Remove the inline for its single user, it is clear enough (and +shorter) without! + +Signed-off-by: Chris Wilson +Reviewed-by: Joonas Lahtinen +Signed-off-by: Jon Bloomfield +Link: http://patchwork.freedesktop.org/patch/msgid/20161124125851.6615-1-chris@chris-wilson.co.uk +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 23 +---------------------- + drivers/gpu/drm/i915/i915_drv.h | 1 - + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- + drivers/gpu/drm/i915/i915_params.c | 6 +++--- + drivers/gpu/drm/i915/i915_params.h | 2 +- + 5 files changed, 6 insertions(+), 28 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -1131,27 +1131,6 @@ unpin_src: + return dst; + } + +-/** +- * intel_engine_needs_cmd_parser() - should a given engine use software +- * command parsing? +- * @engine: the engine in question +- * +- * Only certain platforms require software batch buffer command parsing, and +- * only when enabled via module parameter. +- * +- * Return: true if the engine requires software command parsing +- */ +-bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine) +-{ +- if (!engine->needs_cmd_parser) +- return false; +- +- if (!USES_PPGTT(engine->i915)) +- return false; +- +- return (i915.enable_cmd_parser == 1); +-} +- + static bool check_cmd(const struct intel_engine_cs *engine, + const struct drm_i915_cmd_descriptor *desc, + const u32 *cmd, u32 length, +@@ -1374,7 +1353,7 @@ int i915_cmd_parser_get_version(struct d + + /* If the command parser is not enabled, report 0 - unsupported */ + for_each_engine(engine, dev_priv) { +- if (intel_engine_needs_cmd_parser(engine)) { ++ if (engine->needs_cmd_parser) { + active = true; + break; + } +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -3455,7 +3455,6 @@ const char *i915_cache_level_str(struct + int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv); + void intel_engine_init_cmd_parser(struct intel_engine_cs *engine); + void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine); +-bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine); + int intel_engine_cmd_parser(struct intel_engine_cs *engine, + struct drm_i915_gem_object *batch_obj, + struct drm_i915_gem_object *shadow_batch_obj, +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1711,7 +1711,7 @@ i915_gem_do_execbuffer(struct drm_device + } + + params->args_batch_start_offset = args->batch_start_offset; +- if (intel_engine_needs_cmd_parser(engine) && args->batch_len) { ++ if (engine->needs_cmd_parser && args->batch_len) { + struct i915_vma *vma; + + vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry, +--- a/drivers/gpu/drm/i915/i915_params.c ++++ b/drivers/gpu/drm/i915/i915_params.c +@@ -49,7 +49,7 @@ struct i915_params i915 __read_mostly = + .reset = true, + .invert_brightness = 0, + .disable_display = 0, +- .enable_cmd_parser = 1, ++ .enable_cmd_parser = true, + .use_mmio_flip = 0, + .mmio_debug = 0, + .verbose_state_checks = 1, +@@ -178,9 +178,9 @@ MODULE_PARM_DESC(invert_brightness, + module_param_named(disable_display, i915.disable_display, bool, 0400); + MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); + +-module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, int, 0600); ++module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, bool, 0400); + MODULE_PARM_DESC(enable_cmd_parser, +- "Enable command parsing (1=enabled [default], 0=disabled)"); ++ "Enable command parsing (true=enabled [default], false=disabled)"); + + module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600); + MODULE_PARM_DESC(use_mmio_flip, +--- a/drivers/gpu/drm/i915/i915_params.h ++++ b/drivers/gpu/drm/i915/i915_params.h +@@ -44,7 +44,6 @@ struct i915_params { + int disable_power_well; + int enable_ips; + int invert_brightness; +- int enable_cmd_parser; + int enable_guc_loading; + int enable_guc_submission; + int guc_log_level; +@@ -53,6 +52,7 @@ struct i915_params { + int edp_vswing; + unsigned int inject_load_failure; + /* leave bools at the end to not create holes */ ++ bool enable_cmd_parser; + bool enable_hangcheck; + bool fastboot; + bool prefault_disable; diff --git a/queue-4.9/series b/queue-4.9/series index 52ae35ea6d4..a521da5cb00 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -63,3 +63,30 @@ can-flexcan-disable-completely-the-ecc-mechanism.patch mm-filemap.c-don-t-initiate-writeback-if-mapping-has-no-dirty-pages.patch cgroup-writeback-don-t-switch-wbs-immediately-on-dead-wbs-if-the-memcg-is-dead.patch net-prevent-load-store-tearing-on-sk-sk_stamp.patch +drm-i915-kick-out-cmd_parser-specific-structs-from-i915_drv.h.patch +drm-i915-cleanup-use-of-instr_client_mask.patch +drm-i915-return-eacces-for-check_cmd-failures.patch +drm-i915-don-t-whitelist-oacontrol-in-cmd-parser.patch +drm-i915-use-the-precomputed-value-for-whether-to-enable-command-parsing.patch +drm-i915-cmdparser-limit-clflush-to-active-cachelines.patch +drm-i915-gtt-add-read-only-pages-to-gen8_pte_encode.patch +drm-i915-gtt-read-only-pages-for-insert_entries-on-bdw.patch +drm-i915-gtt-disable-read-only-support-under-gvt.patch +drm-i915-prevent-writing-into-a-read-only-object-via-a-ggtt-mmap.patch +drm-i915-cmdparser-check-reg_table_count-before-derefencing.patch +drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch +drm-i915-silence-smatch-for-cmdparser.patch +drm-i915-move-engine-needs_cmd_parser-to-engine-flags.patch +drm-i915-rename-gen7-cmdparser-tables.patch +drm-i915-disable-secure-batches-for-gen6.patch +drm-i915-remove-master-tables-from-cmdparser.patch +drm-i915-add-support-for-mandatory-cmdparsing.patch +drm-i915-support-ro-ppgtt-mapped-cmdparser-shadow-buffers.patch +drm-i915-allow-parsing-of-unsized-batches.patch +drm-i915-add-gen9-bcs-cmdparsing.patch +drm-i915-cmdparser-use-explicit-goto-for-error-paths.patch +drm-i915-cmdparser-add-support-for-backward-jumps.patch +drm-i915-cmdparser-ignore-length-operands-during-command-matching.patch +drm-i915-lower-rm-timeout-to-avoid-dsi-hard-hangs.patch +drm-i915-gen8-add-rc6-ctx-corruption-wa.patch +drm-i915-cmdparser-fix-jump-whitelist-clearing.patch