From patchwork Mon Feb 5 15:51:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 126909 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp2083600ljc; Mon, 5 Feb 2018 07:51:37 -0800 (PST) X-Google-Smtp-Source: AH8x227w7Dc1iwOcPTbNx/5OzQNpHMGmVIPp8Cr+/ex36dcCZgqvl11DTnqOM5+t0hpxCPi91r4Y X-Received: by 10.98.60.5 with SMTP id j5mr13775715pfa.217.1517845896862; Mon, 05 Feb 2018 07:51:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517845896; cv=none; d=google.com; s=arc-20160816; b=OwX5bgSCWvlOHLOftTokPIACF9c69CM0Q2TVsRnemO8XsbMRSv1Msd7gM7NswpLzIr 31uyE1G5XFQK5zOO35FCzjelH0OPddWYyFCd2G+2U6jZDn61EwTSCVn6eGNUj4qcRW2L 2JgipS4VqqIlwi+j5Ad+DLoG/oZr+NZLh3QYEBWe/KpHXz56Y2qIxsXu8LnG0L1pzGcu PEKlWxDKJ/tcMV1sMUGW7Cd/g2ZpPUmRPwDdMAg5i3bCGOF0WBWivaOidvxEI27X5dcF LWj8LMlXrL1uhzAx+fzo2Aa3ttqMQCBbUT2CLBzVUvw49Cko2NEs6L8UVjIJAGF2Nu1H dv0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=F+uPz5fEBSPTBYY8b4+2b46rHZfXhudVGPuf1ylvqvA=; b=A38GRVyu4zxdprJwsX3e4PqkY+cQw+zIl3g5uh03rygytCwAYMKwSXoPkMg2eOjiS7 KcTjTZfIPpeJ1VLbCG9WLO14N7lafd2s9DvaWTUFaP7JFWlkGkyaCiPY93hbb+1c8HTZ sbGF75StSE3Cq2BbUxI3Z8+A8u15GmXuKAEzMOLzBe+BHNsThu3ILu+8z83eCHRzB2Lu X7kj8dvYj+toG0mDHPM7/1vTmY/kcW+En+gM2eJ4HQXGoHijO7w4wNV0WsccNa7Lp29W Ps1wUFvjQy9nvTSOesxM+xBqhVO3nIud5IG/kqu7vnhOaxnDn+oZXwgBJsixlLSnOo7O KENQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j3si5549106pgc.456.2018.02.05.07.51.36; Mon, 05 Feb 2018 07:51:36 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753352AbeBEPve (ORCPT + 28 others); Mon, 5 Feb 2018 10:51:34 -0500 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:52460 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752986AbeBEPvZ (ORCPT ); Mon, 5 Feb 2018 10:51:25 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9CF2A1435; Mon, 5 Feb 2018 07:51:24 -0800 (PST) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B0A283F25C; Mon, 5 Feb 2018 07:51:23 -0800 (PST) From: Mark Rutland To: linux-kernel@vger.kernel.org Cc: Mark Rutland , Peter Zijlstra , Ingo Molnar Subject: [PATCH] sched/core: avoid spurious spinlock recursion splats Date: Mon, 5 Feb 2018 15:51:18 +0000 Message-Id: <20180205155118.23657-1-mark.rutland@arm.com> X-Mailer: git-send-email 2.11.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The runqueue locks are special in that the owner changes over a context switch. To ensure that this is accounted for in CONFIG_DEBUG_SPINLOCK builds, finish_lock_switch updates rq->lock.owner while the lock is held. However, this happens *after* prev->on_cpu is cleared, which allows prev to be scheduled on another CPU. If prev then attempts to acquire the same rq lock, before the updated rq->lock.owner is made visible, it will see itself as the owner. This can happen in virtual environments, where a vCPU can be preempted for an arbitrarily long period between updating prev->on_cpu and rq->lock.owner, as has been observed on arm64 and x86 under KVM, e.g. BUG: spinlock recursion on CPU#1, syz-executor1/1521 lock: 0xffff80001a764080, .magic: dead4ead, .owner: syz-executor1/1521, .owner_cpu: 0 CPU: 1 PID: 1521 Comm: syz-executor1 Not tainted 4.15.0 #3 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x0/0x330 arch/arm64/kernel/time.c:52 show_stack+0x20/0x30 arch/arm64/kernel/traps.c:151 __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0xd0/0x120 lib/dump_stack.c:53 spin_dump+0x150/0x1f0 kernel/locking/spinlock_debug.c:67 spin_bug kernel/locking/spinlock_debug.c:75 [inline] debug_spin_lock_before kernel/locking/spinlock_debug.c:84 [inline] do_raw_spin_lock+0x1e4/0x250 kernel/locking/spinlock_debug.c:112 __raw_spin_lock include/linux/spinlock_api_smp.h:143 [inline] _raw_spin_lock+0x44/0x50 kernel/locking/spinlock.c:144 __task_rq_lock+0xc0/0x288 kernel/sched/core.c:103 wake_up_new_task+0x384/0x798 kernel/sched/core.c:2465 _do_fork+0x1b4/0xa78 kernel/fork.c:2069 SYSC_clone kernel/fork.c:2154 [inline] SyS_clone+0x48/0x60 kernel/fork.c:2132 el0_svc_naked+0x20/0x24 Let's avoid this updating rq->lock.owner before clearing prev->on_cpu. As the latter is a release, it ensures that the new owner is visible to prev if it is scheduled on another CPU. Signed-off-by: Mark Rutland Cc: Peter Zijlstra Cc: Ingo Molnar --- kernel/sched/sched.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) -- 2.11.0 diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index b19552a212de..4f0d2e3701c3 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1342,6 +1342,10 @@ static inline void prepare_lock_switch(struct rq *rq, struct task_struct *next) static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) { +#ifdef CONFIG_DEBUG_SPINLOCK + /* this is a valid case when another task releases the spinlock */ + rq->lock.owner = current; +#endif #ifdef CONFIG_SMP /* * After ->on_cpu is cleared, the task can be moved to a different CPU. @@ -1355,10 +1359,6 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) */ smp_store_release(&prev->on_cpu, 0); #endif -#ifdef CONFIG_DEBUG_SPINLOCK - /* this is a valid case when another task releases the spinlock */ - rq->lock.owner = current; -#endif /* * If we are tracking spinlock dependencies then we have to * fix up the runqueue lock - which gets 'carried over' from