From patchwork Mon Mar 26 11:50:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10307695 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 41D5860386 for ; Mon, 26 Mar 2018 11:52:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 298762964D for ; Mon, 26 Mar 2018 11:52:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 28217296AC; Mon, 26 Mar 2018 11:52:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8608129743 for ; Mon, 26 Mar 2018 11:51:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 09CF86E492; Mon, 26 Mar 2018 11:51:18 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id ADD466E491 for ; Mon, 26 Mar 2018 11:51:16 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 11158600-1500050 for multiple; Mon, 26 Mar 2018 12:51:04 +0100 Received: by haswell.alporthouse.com (sSMTP sendmail emulation); Mon, 26 Mar 2018 12:51:03 +0100 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Mon, 26 Mar 2018 12:50:41 +0100 Message-Id: <20180326115044.2505-9-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.16.3 In-Reply-To: <20180326115044.2505-1-chris@chris-wilson.co.uk> References: <20180326115044.2505-1-chris@chris-wilson.co.uk> X-Originating-IP: 78.156.65.138 X-Country: code=GB country="United Kingdom" ip=78.156.65.138 Subject: [Intel-gfx] [PATCH 08/11] drm/i915/execlists: Force preemption via reset on timeout X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Install a timer when trying to preempt on behalf of an important context such that if the active context does not honour the preemption request within the desired timeout, then we reset the GPU to allow the important context to run. (Open: should not the timer be started from receiving the high priority request...) Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_lrc.c | 53 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 8 +++++ 2 files changed, 61 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 50688fc889d9..6da816d23cb3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -533,6 +533,47 @@ static void inject_preempt_context(struct intel_engine_cs *engine) execlists_clear_active(execlists, EXECLISTS_ACTIVE_HWACK); execlists_set_active(execlists, EXECLISTS_ACTIVE_PREEMPT); + + /* Set a timer to force preemption vs hostile userspace */ + if (execlists->queue_preempt_timeout) { + GEM_TRACE("%s timeout=%uns\n", + engine->name, execlists->queue_preempt_timeout); + hrtimer_start(&execlists->preempt_timer, + ktime_set(0, execlists->queue_preempt_timeout), + HRTIMER_MODE_REL); + } +} + +static enum hrtimer_restart preempt_timeout(struct hrtimer *hrtimer) +{ + struct intel_engine_execlists *execlists = + container_of(hrtimer, typeof(*execlists), preempt_timer); + + GEM_TRACE("%s\n", + container_of(execlists, + struct intel_engine_cs, + execlists)->name); + + queue_work(system_highpri_wq, &execlists->preempt_reset); + return HRTIMER_NORESTART; +} + +static void preempt_reset(struct work_struct *work) +{ + struct intel_engine_cs *engine = + container_of(work, typeof(*engine), execlists.preempt_reset); + + GEM_TRACE("%s\n", engine->name); + + tasklet_disable(&engine->execlists.tasklet); + + engine->execlists.tasklet.func(engine->execlists.tasklet.data); + + if (execlists_is_active(&engine->execlists, EXECLISTS_ACTIVE_PREEMPT)) + i915_handle_error(engine->i915, BIT(engine->id), 0, + "preemption timed out on %s", engine->name); + + tasklet_enable(&engine->execlists.tasklet); } static void complete_preempt_context(struct intel_engine_execlists *execlists) @@ -542,6 +583,10 @@ static void complete_preempt_context(struct intel_engine_execlists *execlists) execlists_cancel_port_requests(execlists); execlists_unwind_incomplete_requests(execlists); + /* If the timer already fired, complete the reset */ + if (hrtimer_try_to_cancel(&execlists->preempt_timer) < 0) + return; + execlists_clear_active(execlists, EXECLISTS_ACTIVE_PREEMPT); } @@ -708,6 +753,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) kmem_cache_free(engine->i915->priorities, p); } done: + execlists->queue_preempt_timeout = 0; /* preemption point passed */ execlists->queue_priority = rb ? to_priolist(rb)->priority : INT_MIN; execlists->first = rb; if (submit) @@ -864,6 +910,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) /* Remaining _unready_ requests will be nop'ed when submitted */ + execlists->queue_preempt_timeout = 0; execlists->queue_priority = INT_MIN; execlists->queue = RB_ROOT; execlists->first = NULL; @@ -1080,6 +1127,7 @@ static void queue_request(struct intel_engine_cs *engine, static void __submit_queue(struct intel_engine_cs *engine, int prio) { engine->execlists.queue_priority = prio; + engine->execlists.queue_preempt_timeout = 0; tasklet_hi_schedule(&engine->execlists.tasklet); } @@ -2270,6 +2318,11 @@ logical_ring_setup(struct intel_engine_cs *engine) tasklet_init(&engine->execlists.tasklet, execlists_submission_tasklet, (unsigned long)engine); + INIT_WORK(&engine->execlists.preempt_reset, preempt_reset); + hrtimer_init(&engine->execlists.preempt_timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + engine->execlists.preempt_timer.function = preempt_timeout; + logical_ring_default_vfuncs(engine); logical_ring_default_irqs(engine); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4c71dcdc722b..7166f47c8489 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -284,6 +284,11 @@ struct intel_engine_execlists { */ int queue_priority; + /** + * @queue_preempt_timeout: Timeout in ns before forcing preemption. + */ + unsigned int queue_preempt_timeout; + /** * @queue: queue of requests, in priority lists */ @@ -313,6 +318,9 @@ struct intel_engine_execlists { * @preempt_complete_status: expected CSB upon completing preemption */ u32 preempt_complete_status; + + struct hrtimer preempt_timer; + struct work_struct preempt_reset; }; #define INTEL_ENGINE_CS_MAX_NAME 8