Re: [PATCH v2] drm/i915: Reacquire priolist cache after dropping the engine lock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/02/2019 16:09, Chris Wilson wrote:
> If we drop the engine lock, we may run execlists_dequeue which may free
> the priolist. Therefore if we ever drop the execution lock on the
> engine, we have to discard our cache and refetch the priolist to ensure
> we do not use a stale pointer.

On first look one would observe current code is trying to re-acquire the prio list on changing the engine, so I guess the problem is this check is hidden under an additional conditional.

So a simpler approach of:

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index d01683167c77..74896e7dbfa7 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -341,16 +341,17 @@ static void __i915_schedule(struct i915_request *rq,
                engine = sched_lock_engine(node, engine);
                lockdep_assert_held(&engine->timeline.lock);
 
+               if (last != engine) {
+                       pl = i915_sched_lookup_priolist(engine, prio);
+                       last = engine;
+               }
+
                /* Recheck after acquiring the engine->timeline.lock */
                if (prio <= node->attr.priority || node_signaled(node))
                        continue;
 
                node->attr.priority = prio;
                if (!list_empty(&node->link)) {
-                       if (last != engine) {
-                               pl = i915_sched_lookup_priolist(engine, prio);
-                               last = engine;
-                       }
                        list_move_tail(&node->link, pl);
                } else {
                        /*
Would not be acceptable?

> 
> [  506.418935] [IGT] gem_exec_whisper: starting subtest contexts-priority
> [  593.240825] general protection fault: 0000 [#1] SMP
> [  593.240863] CPU: 1 PID: 494 Comm: gem_exec_whispe Tainted: G     U            5.0.0-rc6+ #100
> [  593.240879] Hardware name:  /NUC6CAYB, BIOS AYAPLCEL.86A.0029.2016.1124.1625 11/24/2016
> [  593.240965] RIP: 0010:__i915_schedule+0x1fe/0x320 [i915]
> [  593.240981] Code: 48 8b 0c 24 48 89 c3 49 8b 45 28 49 8b 75 20 4c 89 3c 24 48 89 46 08 48 89 30 48 8b 43 08 48 89 4b 08 49 89 5d 20 49 89 45 28 <48> 89 08 45 39 a7 b8 03 00 00 7d 44 45 89 a7 b8 03 00 00 49 8b 85
> [  593.240999] RSP: 0018:ffffc90000057a60 EFLAGS: 00010046
> [  593.241013] RAX: 6b6b6b6b6b6b6b6b RBX: ffff8882582d7870 RCX: ffff88826baba6f0
> [  593.241026] RDX: 0000000000000000 RSI: ffff8882582d6e70 RDI: ffff888273482194
> [  593.241049] RBP: ffffc90000057a68 R08: ffff8882582d7680 R09: ffff8882582d7840
> [  593.241068] R10: 0000000000000000 R11: ffffea00095ebe08 R12: 0000000000000728
> [  593.241105] R13: ffff88826baba6d0 R14: ffffc90000057a40 R15: ffff888273482158
> [  593.241120] FS:  00007f4613fb3900(0000) GS:ffff888277a80000(0000) knlGS:0000000000000000
> [  593.241133] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [  593.241146] CR2: 00007f57d3c66a84 CR3: 000000026e2b6000 CR4: 00000000001406e0
> [  593.241158] Call Trace:
> [  593.241233]  i915_schedule+0x1f/0x30 [i915]
> [  593.241326]  i915_request_add+0x1a9/0x290 [i915]
> [  593.241393]  i915_gem_do_execbuffer+0x45f/0x1150 [i915]
> [  593.241411]  ? init_object+0x49/0x80
> [  593.241425]  ? ___slab_alloc.constprop.91+0x4b8/0x4e0
> [  593.241491]  ? i915_gem_execbuffer2_ioctl+0x99/0x380 [i915]
> [  593.241563]  ? i915_gem_execbuffer_ioctl+0x270/0x270 [i915]
> [  593.241629]  i915_gem_execbuffer2_ioctl+0x1bb/0x380 [i915]
> [  593.241705]  ? i915_gem_execbuffer_ioctl+0x270/0x270 [i915]
> [  593.241724]  drm_ioctl_kernel+0x81/0xd0
> [  593.241738]  drm_ioctl+0x1a7/0x310
> [  593.241803]  ? i915_gem_execbuffer_ioctl+0x270/0x270 [i915]
> [  593.241819]  ? __update_load_avg_se+0x1c9/0x240
> [  593.241834]  ? pick_next_entity+0x7e/0x120
> [  593.241851]  do_vfs_ioctl+0x88/0x5d0
> [  593.241880]  ksys_ioctl+0x35/0x70
> [  593.241894]  __x64_sys_ioctl+0x11/0x20
> [  593.241907]  do_syscall_64+0x44/0xf0
> [  593.241924]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> [  593.241940] RIP: 0033:0x7f4615ffe757
> [  593.241952] Code: 00 00 90 48 8b 05 39 a7 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 09 a7 0c 00 f7 d8 64 89 01 48
> [  593.241970] RSP: 002b:00007ffc1030ddf8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
> [  593.241984] RAX: ffffffffffffffda RBX: 00007ffc10324420 RCX: 00007f4615ffe757
> [  593.241997] RDX: 00007ffc1030e220 RSI: 0000000040406469 RDI: 0000000000000003
> [  593.242010] RBP: 00007ffc1030e220 R08: 00007f46160c9208 R09: 00007f46160c9240
> [  593.242022] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000040406469
> [  593.242038] R13: 0000000000000003 R14: 0000000000000000 R15: 0000000000000000
> [  593.242058] Modules linked in: i915 intel_gtt drm_kms_helper prime_numbers
> 
> v2: Track the local engine cache and explicitly clear it when switching
> engine locks.
> 
> Fixes: a02eb975be78 ("drm/i915/execlists: Cache the priolist when rescheduling")
> Testcase: igt/gem_exec_whisper/contexts-priority # rare!
> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx>
> Cc: Michał Winiarski <michal.winiarski@xxxxxxxxx>
> ---
>   drivers/gpu/drm/i915/i915_scheduler.c | 27 +++++++++++++++++----------
>   1 file changed, 17 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
> index d01683167c77..8bc042551692 100644
> --- a/drivers/gpu/drm/i915/i915_scheduler.c
> +++ b/drivers/gpu/drm/i915/i915_scheduler.c
> @@ -223,8 +223,14 @@ i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio)
>   	return &p->requests[idx];
>   }
>   
> +struct sched_cache {
> +	struct list_head *priolist;
> +};

Do you plan to add more stuff since you decided to wrap into a struct
and use memset?

Regards,

Tvrtko

> +
>   static struct intel_engine_cs *
> -sched_lock_engine(struct i915_sched_node *node, struct intel_engine_cs *locked)
> +sched_lock_engine(const struct i915_sched_node *node,
> +		  struct intel_engine_cs *locked,
> +		  struct sched_cache *cache)
>   {
>   	struct intel_engine_cs *engine = node_to_request(node)->engine;
>   
> @@ -232,6 +238,7 @@ sched_lock_engine(struct i915_sched_node *node, struct intel_engine_cs *locked)
>   
>   	if (engine != locked) {
>   		spin_unlock(&locked->timeline.lock);
> +		memset(cache, 0, sizeof(*cache));
>   		spin_lock(&engine->timeline.lock);
>   	}
>   
> @@ -253,11 +260,11 @@ static bool inflight(const struct i915_request *rq,
>   static void __i915_schedule(struct i915_request *rq,
>   			    const struct i915_sched_attr *attr)
>   {
> -	struct list_head *uninitialized_var(pl);
> -	struct intel_engine_cs *engine, *last;
> +	struct intel_engine_cs *engine;
>   	struct i915_dependency *dep, *p;
>   	struct i915_dependency stack;
>   	const int prio = attr->priority;
> +	struct sched_cache cache;
>   	LIST_HEAD(dfs);
>   
>   	/* Needed in order to use the temporary link inside i915_dependency */
> @@ -328,7 +335,7 @@ static void __i915_schedule(struct i915_request *rq,
>   		__list_del_entry(&stack.dfs_link);
>   	}
>   
> -	last = NULL;
> +	memset(&cache, 0, sizeof(cache));
>   	engine = rq->engine;
>   	spin_lock_irq(&engine->timeline.lock);
>   
> @@ -338,7 +345,7 @@ static void __i915_schedule(struct i915_request *rq,
>   
>   		INIT_LIST_HEAD(&dep->dfs_link);
>   
> -		engine = sched_lock_engine(node, engine);
> +		engine = sched_lock_engine(node, engine, &cache);
>   		lockdep_assert_held(&engine->timeline.lock);
>   
>   		/* Recheck after acquiring the engine->timeline.lock */
> @@ -347,11 +354,11 @@ static void __i915_schedule(struct i915_request *rq,
>   
>   		node->attr.priority = prio;
>   		if (!list_empty(&node->link)) {
> -			if (last != engine) {
> -				pl = i915_sched_lookup_priolist(engine, prio);
> -				last = engine;
> -			}
> -			list_move_tail(&node->link, pl);
> +			if (!cache.priolist)
> +				cache.priolist =
> +					i915_sched_lookup_priolist(engine,
> +								   prio);
> +			list_move_tail(&node->link, cache.priolist);
>   		} else {
>   			/*
>   			 * If the request is not in the priolist queue because
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux