[PATCH 35/36] drm/i915: Make command parser dma-fence signaling safe
Maarten Lankhorst
maarten.lankhorst at linux.intel.com
Thu Sep 17 13:08:37 UTC 2020
Allocate jump_whitelist in the execbuffer, and add annotations around
intel_engine_cmd_parser(), to ensure we only call the command parser
without allocating any memory, or taking any locks we're not supposed to.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
.../gpu/drm/i915/gem/i915_gem_execbuffer.c | 30 ++++++++++++++-----
drivers/gpu/drm/i915/i915_cmd_parser.c | 17 +++++------
drivers/gpu/drm/i915/i915_drv.h | 5 +++-
3 files changed, 33 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index fd1f0da9862b..6fc2efe82cdd 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -2362,6 +2362,7 @@ struct eb_parse_work {
struct i915_vma *trampoline;
unsigned int batch_offset;
unsigned int batch_length;
+ unsigned long *jump_whitelist;
const void *batch_map;
void *shadow_map;
};
@@ -2369,21 +2370,30 @@ struct eb_parse_work {
static int __eb_parse(struct dma_fence_work *work)
{
struct eb_parse_work *pw = container_of(work, typeof(*pw), base);
+ int ret;
+ bool cookie;
+
+ cookie = dma_fence_begin_signalling();
+ ret = intel_engine_cmd_parser(pw->engine,
+ pw->batch,
+ pw->batch_offset,
+ pw->batch_length,
+ pw->shadow,
+ pw->jump_whitelist,
+ pw->shadow_map,
+ pw->batch_map);
+ dma_fence_end_signalling(cookie);
- return intel_engine_cmd_parser(pw->engine,
- pw->batch,
- pw->batch_offset,
- pw->batch_length,
- pw->shadow,
- pw->trampoline,
- pw->shadow_map,
- pw->batch_map);
+ return ret;
}
static void __eb_parse_release(struct dma_fence_work *work)
{
struct eb_parse_work *pw = container_of(work, typeof(*pw), base);
+ if (!IS_ERR_OR_NULL(pw->jump_whitelist))
+ kfree(pw->jump_whitelist);
+
if (pw->batch_map)
i915_gem_object_unpin_map(pw->batch->obj);
else
@@ -2482,6 +2492,10 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb,
pw->batch_map = NULL;
}
+ pw->jump_whitelist =
+ intel_engine_cmd_parser_alloc_jump_whitelist(eb->batch_len,
+ trampoline);
+
dma_fence_work_init(&pw->base, &eb_parse_ops);
pw->engine = eb->engine;
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index e48c8b631abe..52b8188b269b 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -1348,10 +1348,14 @@ static int check_bbstart(u32 *cmd, u32 offset, u32 length,
return 0;
}
-static unsigned long *alloc_whitelist(u32 batch_length)
+unsigned long *intel_engine_cmd_parser_alloc_jump_whitelist(u32 batch_length,
+ bool trampoline)
{
unsigned long *jmp;
+ if (trampoline)
+ return NULL;
+
/*
* We expect batch_length to be less than 256KiB for known users,
* i.e. we need at most an 8KiB bitmap allocation which should be
@@ -1394,16 +1398,16 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
u32 batch_offset,
u32 batch_length,
struct i915_vma *shadow,
- bool trampoline,
+ unsigned long *jump_whitelist,
void *shadow_map,
const void *batch_map)
{
u32 *cmd, *batch_end, offset = 0;
struct drm_i915_cmd_descriptor default_desc = noop_desc;
const struct drm_i915_cmd_descriptor *desc = &default_desc;
- unsigned long *jump_whitelist;
u64 batch_addr, shadow_addr;
int ret = 0;
+ bool trampoline = !jump_whitelist;
GEM_BUG_ON(!IS_ALIGNED(batch_offset, sizeof(*cmd)));
GEM_BUG_ON(!IS_ALIGNED(batch_length, sizeof(*cmd)));
@@ -1418,11 +1422,6 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
return PTR_ERR(cmd);
}
- jump_whitelist = NULL;
- if (!trampoline)
- /* Defer failure until attempted use */
- jump_whitelist = alloc_whitelist(batch_length);
-
shadow_addr = gen8_canonical_addr(shadow->node.start);
batch_addr = gen8_canonical_addr(batch->node.start + batch_offset);
@@ -1530,8 +1529,6 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine,
drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr);
}
- if (!IS_ERR_OR_NULL(jump_whitelist))
- kfree(jump_whitelist);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 61b40dcfdf13..05a479be3652 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1946,12 +1946,15 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type);
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);
+unsigned long *intel_engine_cmd_parser_alloc_jump_whitelist(u32 batch_length,
+ bool trampoline);
+
int intel_engine_cmd_parser(struct intel_engine_cs *engine,
struct i915_vma *batch,
u32 batch_offset,
u32 batch_length,
struct i915_vma *shadow,
- bool trampoline,
+ unsigned long *jump_whitelist,
void *shadow_map,
const void *batch_map);
#define I915_CMD_PARSER_TRAMPOLINE_SIZE 8
--
2.28.0
More information about the Intel-gfx-trybot
mailing list