- Fixes for potential use-after-free and double-free (Rob)
- GuC locking and refcount fixes (John) - Display's reference clock value fix (Chaitanya) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAmPbuWwACgkQ+mJfZA7r E8pEnwf8CZK/1jD5XjlQ6DXpLXfQ0CvUP8WYFwkzw5K4rJ2Wsob7SQ+pfDT6Tmi9 7YmKzfpSvA+hGozXypqt0qOlC5IDEv9nuHL7EML8eVbcL5QRSYdWqEPSRz6EMzqS rrOdl0dSjl2JxXl4nTdxscfZ7TpeoHqjpBXa2S7fuh0B1PkqNEYq3srf19qXiQrh PZonZ91bSskUBmm0uuEVtxx/nEFGF8l5qKTe+PoAaQOAMXJtN9ZXTo9bczni7GZT 4/ggr09bb9Ioe2ThR999rvT4O+Qv+V5s5BD/GE0fZiBomJJcbciKgM/LC8JNaL8k rGHvKL6iTKvVeP9mKrku6j5Sg64gYA== =du8Z -----END PGP SIGNATURE----- Merge tag 'drm-intel-fixes-2023-02-02' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes - Fixes for potential use-after-free and double-free (Rob) - GuC locking and refcount fixes (John) - Display's reference clock value fix (Chaitanya) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/Y9u5pHjOYcxzS5Z7@intel.com
This commit is contained in:
commit
74d6c8ea18
11 changed files with 113 additions and 77 deletions
|
@ -1319,7 +1319,7 @@ static const struct intel_cdclk_vals adlp_cdclk_table[] = {
|
|||
{ .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
|
||||
{ .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
|
||||
{ .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
|
||||
{ .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 },
|
||||
{ .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
|
||||
|
||||
{ .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
|
||||
{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
|
||||
|
|
|
@ -1861,12 +1861,20 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv,
|
|||
vm = ctx->vm;
|
||||
GEM_BUG_ON(!vm);
|
||||
|
||||
err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Get a reference for the allocated handle. Once the handle is
|
||||
* visible in the vm_xa table, userspace could try to close it
|
||||
* from under our feet, so we need to hold the extra reference
|
||||
* first.
|
||||
*/
|
||||
i915_vm_get(vm);
|
||||
|
||||
err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL);
|
||||
if (err) {
|
||||
i915_vm_put(vm);
|
||||
return err;
|
||||
}
|
||||
|
||||
GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */
|
||||
args->value = id;
|
||||
args->size = 0;
|
||||
|
|
|
@ -305,10 +305,6 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
|
|||
spin_unlock(&obj->vma.lock);
|
||||
|
||||
obj->tiling_and_stride = tiling | stride;
|
||||
i915_gem_object_unlock(obj);
|
||||
|
||||
/* Force the fence to be reacquired for GTT access */
|
||||
i915_gem_object_release_mmap_gtt(obj);
|
||||
|
||||
/* Try to preallocate memory required to save swizzling on put-pages */
|
||||
if (i915_gem_object_needs_bit17_swizzle(obj)) {
|
||||
|
@ -321,6 +317,11 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
|
|||
obj->bit_17 = NULL;
|
||||
}
|
||||
|
||||
i915_gem_object_unlock(obj);
|
||||
|
||||
/* Force the fence to be reacquired for GTT access */
|
||||
i915_gem_object_release_mmap_gtt(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -528,7 +528,7 @@ struct i915_request *intel_context_create_request(struct intel_context *ce)
|
|||
return rq;
|
||||
}
|
||||
|
||||
struct i915_request *intel_context_find_active_request(struct intel_context *ce)
|
||||
struct i915_request *intel_context_get_active_request(struct intel_context *ce)
|
||||
{
|
||||
struct intel_context *parent = intel_context_to_parent(ce);
|
||||
struct i915_request *rq, *active = NULL;
|
||||
|
@ -552,6 +552,8 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce)
|
|||
|
||||
active = rq;
|
||||
}
|
||||
if (active)
|
||||
active = i915_request_get_rcu(active);
|
||||
spin_unlock_irqrestore(&parent->guc_state.lock, flags);
|
||||
|
||||
return active;
|
||||
|
|
|
@ -268,8 +268,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce,
|
|||
|
||||
struct i915_request *intel_context_create_request(struct intel_context *ce);
|
||||
|
||||
struct i915_request *
|
||||
intel_context_find_active_request(struct intel_context *ce);
|
||||
struct i915_request *intel_context_get_active_request(struct intel_context *ce);
|
||||
|
||||
static inline bool intel_context_is_barrier(const struct intel_context *ce)
|
||||
{
|
||||
|
|
|
@ -248,8 +248,8 @@ void intel_engine_dump_active_requests(struct list_head *requests,
|
|||
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine,
|
||||
ktime_t *now);
|
||||
|
||||
struct i915_request *
|
||||
intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine);
|
||||
void intel_engine_get_hung_entity(struct intel_engine_cs *engine,
|
||||
struct intel_context **ce, struct i915_request **rq);
|
||||
|
||||
u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
|
||||
struct intel_context *
|
||||
|
|
|
@ -2094,17 +2094,6 @@ static void print_request_ring(struct drm_printer *m, struct i915_request *rq)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned long list_count(struct list_head *list)
|
||||
{
|
||||
struct list_head *pos;
|
||||
unsigned long count = 0;
|
||||
|
||||
list_for_each(pos, list)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static unsigned long read_ul(void *p, size_t x)
|
||||
{
|
||||
return *(unsigned long *)(p + x);
|
||||
|
@ -2196,11 +2185,11 @@ void intel_engine_dump_active_requests(struct list_head *requests,
|
|||
}
|
||||
}
|
||||
|
||||
static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m)
|
||||
static void engine_dump_active_requests(struct intel_engine_cs *engine,
|
||||
struct drm_printer *m)
|
||||
{
|
||||
struct intel_context *hung_ce = NULL;
|
||||
struct i915_request *hung_rq = NULL;
|
||||
struct intel_context *ce;
|
||||
bool guc;
|
||||
|
||||
/*
|
||||
* No need for an engine->irq_seqno_barrier() before the seqno reads.
|
||||
|
@ -2209,27 +2198,22 @@ static void engine_dump_active_requests(struct intel_engine_cs *engine, struct d
|
|||
* But the intention here is just to report an instantaneous snapshot
|
||||
* so that's fine.
|
||||
*/
|
||||
lockdep_assert_held(&engine->sched_engine->lock);
|
||||
intel_engine_get_hung_entity(engine, &hung_ce, &hung_rq);
|
||||
|
||||
drm_printf(m, "\tRequests:\n");
|
||||
|
||||
guc = intel_uc_uses_guc_submission(&engine->gt->uc);
|
||||
if (guc) {
|
||||
ce = intel_engine_get_hung_context(engine);
|
||||
if (ce)
|
||||
hung_rq = intel_context_find_active_request(ce);
|
||||
} else {
|
||||
hung_rq = intel_engine_execlist_find_hung_request(engine);
|
||||
}
|
||||
|
||||
if (hung_rq)
|
||||
engine_dump_request(hung_rq, m, "\t\thung");
|
||||
else if (hung_ce)
|
||||
drm_printf(m, "\t\tGot hung ce but no hung rq!\n");
|
||||
|
||||
if (guc)
|
||||
if (intel_uc_uses_guc_submission(&engine->gt->uc))
|
||||
intel_guc_dump_active_requests(engine, hung_rq, m);
|
||||
else
|
||||
intel_engine_dump_active_requests(&engine->sched_engine->requests,
|
||||
hung_rq, m);
|
||||
intel_execlists_dump_active_requests(engine, hung_rq, m);
|
||||
|
||||
if (hung_rq)
|
||||
i915_request_put(hung_rq);
|
||||
}
|
||||
|
||||
void intel_engine_dump(struct intel_engine_cs *engine,
|
||||
|
@ -2239,7 +2223,6 @@ void intel_engine_dump(struct intel_engine_cs *engine,
|
|||
struct i915_gpu_error * const error = &engine->i915->gpu_error;
|
||||
struct i915_request *rq;
|
||||
intel_wakeref_t wakeref;
|
||||
unsigned long flags;
|
||||
ktime_t dummy;
|
||||
|
||||
if (header) {
|
||||
|
@ -2276,13 +2259,8 @@ void intel_engine_dump(struct intel_engine_cs *engine,
|
|||
i915_reset_count(error));
|
||||
print_properties(engine, m);
|
||||
|
||||
spin_lock_irqsave(&engine->sched_engine->lock, flags);
|
||||
engine_dump_active_requests(engine, m);
|
||||
|
||||
drm_printf(m, "\tOn hold?: %lu\n",
|
||||
list_count(&engine->sched_engine->hold));
|
||||
spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
|
||||
|
||||
drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base);
|
||||
wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm);
|
||||
if (wakeref) {
|
||||
|
@ -2328,8 +2306,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings,
|
|||
return siblings[0]->cops->create_virtual(siblings, count, flags);
|
||||
}
|
||||
|
||||
struct i915_request *
|
||||
intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)
|
||||
static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct i915_request *request, *active = NULL;
|
||||
|
||||
|
@ -2381,6 +2358,33 @@ intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)
|
|||
return active;
|
||||
}
|
||||
|
||||
void intel_engine_get_hung_entity(struct intel_engine_cs *engine,
|
||||
struct intel_context **ce, struct i915_request **rq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
*ce = intel_engine_get_hung_context(engine);
|
||||
if (*ce) {
|
||||
intel_engine_clear_hung_context(engine);
|
||||
|
||||
*rq = intel_context_get_active_request(*ce);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getting here with GuC enabled means it is a forced error capture
|
||||
* with no actual hang. So, no need to attempt the execlist search.
|
||||
*/
|
||||
if (intel_uc_uses_guc_submission(&engine->gt->uc))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&engine->sched_engine->lock, flags);
|
||||
*rq = engine_execlist_find_hung_request(engine);
|
||||
if (*rq)
|
||||
*rq = i915_request_get_rcu(*rq);
|
||||
spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
|
||||
}
|
||||
|
||||
void xehp_enable_ccs_engines(struct intel_engine_cs *engine)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -4148,6 +4148,33 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
|
|||
spin_unlock_irqrestore(&sched_engine->lock, flags);
|
||||
}
|
||||
|
||||
static unsigned long list_count(struct list_head *list)
|
||||
{
|
||||
struct list_head *pos;
|
||||
unsigned long count = 0;
|
||||
|
||||
list_for_each(pos, list)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void intel_execlists_dump_active_requests(struct intel_engine_cs *engine,
|
||||
struct i915_request *hung_rq,
|
||||
struct drm_printer *m)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&engine->sched_engine->lock, flags);
|
||||
|
||||
intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m);
|
||||
|
||||
drm_printf(m, "\tOn hold?: %lu\n",
|
||||
list_count(&engine->sched_engine->hold));
|
||||
|
||||
spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
#include "selftest_execlists.c"
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,10 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
|
|||
int indent),
|
||||
unsigned int max);
|
||||
|
||||
void intel_execlists_dump_active_requests(struct intel_engine_cs *engine,
|
||||
struct i915_request *hung_rq,
|
||||
struct drm_printer *m);
|
||||
|
||||
bool
|
||||
intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine);
|
||||
|
||||
|
|
|
@ -1702,7 +1702,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st
|
|||
goto next_context;
|
||||
|
||||
guilty = false;
|
||||
rq = intel_context_find_active_request(ce);
|
||||
rq = intel_context_get_active_request(ce);
|
||||
if (!rq) {
|
||||
head = ce->ring->tail;
|
||||
goto out_replay;
|
||||
|
@ -1715,6 +1715,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st
|
|||
head = intel_ring_wrap(ce->ring, rq->head);
|
||||
|
||||
__i915_request_reset(rq, guilty);
|
||||
i915_request_put(rq);
|
||||
out_replay:
|
||||
guc_reset_state(ce, head, guilty);
|
||||
next_context:
|
||||
|
@ -4817,6 +4818,8 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine)
|
|||
|
||||
xa_lock_irqsave(&guc->context_lookup, flags);
|
||||
xa_for_each(&guc->context_lookup, index, ce) {
|
||||
bool found;
|
||||
|
||||
if (!kref_get_unless_zero(&ce->ref))
|
||||
continue;
|
||||
|
||||
|
@ -4833,10 +4836,18 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine)
|
|||
goto next;
|
||||
}
|
||||
|
||||
found = false;
|
||||
spin_lock(&ce->guc_state.lock);
|
||||
list_for_each_entry(rq, &ce->guc_state.requests, sched.link) {
|
||||
if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
spin_unlock(&ce->guc_state.lock);
|
||||
|
||||
if (found) {
|
||||
intel_engine_set_hung_context(engine, ce);
|
||||
|
||||
/* Can only cope with one hang at a time... */
|
||||
|
@ -4844,6 +4855,7 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine)
|
|||
xa_lock(&guc->context_lookup);
|
||||
goto done;
|
||||
}
|
||||
|
||||
next:
|
||||
intel_context_put(ce);
|
||||
xa_lock(&guc->context_lookup);
|
||||
|
|
|
@ -1596,43 +1596,20 @@ capture_engine(struct intel_engine_cs *engine,
|
|||
{
|
||||
struct intel_engine_capture_vma *capture = NULL;
|
||||
struct intel_engine_coredump *ee;
|
||||
struct intel_context *ce;
|
||||
struct intel_context *ce = NULL;
|
||||
struct i915_request *rq = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags);
|
||||
if (!ee)
|
||||
return NULL;
|
||||
|
||||
ce = intel_engine_get_hung_context(engine);
|
||||
if (ce) {
|
||||
intel_engine_clear_hung_context(engine);
|
||||
rq = intel_context_find_active_request(ce);
|
||||
if (!rq || !i915_request_started(rq))
|
||||
goto no_request_capture;
|
||||
} else {
|
||||
/*
|
||||
* Getting here with GuC enabled means it is a forced error capture
|
||||
* with no actual hang. So, no need to attempt the execlist search.
|
||||
*/
|
||||
if (!intel_uc_uses_guc_submission(&engine->gt->uc)) {
|
||||
spin_lock_irqsave(&engine->sched_engine->lock, flags);
|
||||
rq = intel_engine_execlist_find_hung_request(engine);
|
||||
spin_unlock_irqrestore(&engine->sched_engine->lock,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
if (rq)
|
||||
rq = i915_request_get_rcu(rq);
|
||||
|
||||
if (!rq)
|
||||
intel_engine_get_hung_entity(engine, &ce, &rq);
|
||||
if (!rq || !i915_request_started(rq))
|
||||
goto no_request_capture;
|
||||
|
||||
capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL);
|
||||
if (!capture) {
|
||||
i915_request_put(rq);
|
||||
if (!capture)
|
||||
goto no_request_capture;
|
||||
}
|
||||
if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)
|
||||
intel_guc_capture_get_matching_node(engine->gt, ee, ce);
|
||||
|
||||
|
@ -1642,6 +1619,8 @@ capture_engine(struct intel_engine_cs *engine,
|
|||
return ee;
|
||||
|
||||
no_request_capture:
|
||||
if (rq)
|
||||
i915_request_put(rq);
|
||||
kfree(ee);
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue