From patchwork Tue Dec 18 22:10:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 154212 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4236430ljp; Tue, 18 Dec 2018 14:11:25 -0800 (PST) X-Google-Smtp-Source: AFSGD/VSdxLRHDALQ38FH90rEYebKwfXjS0g5bqYNWg8PK2TFMBt0gRfP+R4EVgqUxtti5uJhlFq X-Received: by 2002:a62:6408:: with SMTP id y8mr18072987pfb.202.1545171085715; Tue, 18 Dec 2018 14:11:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545171085; cv=none; d=google.com; s=arc-20160816; b=a9YzwrOL50KzR//AhlJSHNEt3luerlm4VX96LdLFFE3dW5v/nY95YcaHU7Vt615oJk v4K8/GN5Cr/enIq/CruarchJ6ADRX3dBfrn7hGjpOctFfmWOzg91ALlit28gbgv2EQOp +6c1zpyKbmL+cwFibc1iPOF71QRebcr4M4GS1uoKCX3+5tgrIrqMP2iSKIdEe2vBKB8h 4sTHH4CSzBxs8pEBJQyQbAUCAZiUJQ7hn+9rYerEe3JPgtwI0tLRkuhu5QU9VTP9Q2+i Ae7TsRWMrOXb9jVdQemuSX6FvkyL+x4qtP5tcwi2KrLvvJWq8PhMcPWW8DFJ5OZ0gIeD 5Bag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=hfkyEYgakDOkHOZUq5RdouOloM5PU/6JeqZ77LRt/8A=; b=J+GckLhN4I0NUD6rqoz/U6RbUNgiJOYoCZbmUFa9xOHt2wXVivrpdB4bsRo0wErgMK rMZBTMnYeNUqSqWGFtJweQ3QEpaByulaozwvt5E1yzG5LpT8pjOUF5Tm5nsO9sXXdgW+ iLDvuvDcROsRHM1/05C90a79PzBPzTuRqitj+4FyNZHCDQSep5GiPmwSdzyxoYkos08+ mT/lr37LJI63Clk3m6Witlym0fdxyW4M+k4htrAigf4XPnWhk7mlPkk+AQr82b3Yvk9E NvLkoi01Tw0bIMRd0CSjpI/roZKQvYxO/GjZLv4D+5fhgKuUOXRjMsFZt8/oeiqRVn1v pXHw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-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 c8si13817215pgl.507.2018.12.18.14.11.25; Tue, 18 Dec 2018 14:11:25 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-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 stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727576AbeLRWLY (ORCPT + 15 others); Tue, 18 Dec 2018 17:11:24 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:57202 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727133AbeLRWLY (ORCPT ); Tue, 18 Dec 2018 17:11:24 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gZNaA-000889-Gi; Tue, 18 Dec 2018 23:11:18 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , bigeasy@linutronix.de, Linus Torvalds , Ingo Molnar Subject: [PATCH STABLE v4.9 02/10] locking/qspinlock: Ensure node is initialised before updating prev->next Date: Tue, 18 Dec 2018 23:10:41 +0100 Message-Id: <20181218221049.6816-3-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20181218221049.6816-1-bigeasy@linutronix.de> References: <20181218221049.6816-1-bigeasy@linutronix.de> MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit 95bcade33a8af38755c9b0636e36a36ad3789fe6 upstream. When a locker ends up queuing on the qspinlock locking slowpath, we initialise the relevant mcs node and publish it indirectly by updating the tail portion of the lock word using xchg_tail. If we find that there was a pre-existing locker in the queue, we subsequently update their ->next field to point at our node so that we are notified when it's our turn to take the lock. This can be roughly illustrated as follows: /* Initialise the fields in node and encode a pointer to node in tail */ tail = initialise_node(node); /* * Exchange tail into the lockword using an atomic read-modify-write * operation with release semantics */ old = xchg_tail(lock, tail); /* If there was a pre-existing waiter ... */ if (old & _Q_TAIL_MASK) { prev = decode_tail(old); smp_read_barrier_depends(); /* ... then update their ->next field to point to node. WRITE_ONCE(prev->next, node); } The conditional update of prev->next therefore relies on the address dependency from the result of xchg_tail ensuring order against the prior initialisation of node. However, since the release semantics of the xchg_tail operation apply only to the write portion of the RmW, then this ordering is not guaranteed and it is possible for the CPU to return old before the writes to node have been published, consequently allowing us to point prev->next to an uninitialised node. This patch fixes the problem by making the update of prev->next a RELEASE operation, which also removes the reliance on dependency ordering. Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1518528177-19169-2-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- kernel/locking/qspinlock.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) -- 2.20.1 diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index 8710fbe8d26c0..6fce84401dba1 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -532,14 +532,15 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) */ if (old & _Q_TAIL_MASK) { prev = decode_tail(old); - /* - * The above xchg_tail() is also a load of @lock which - * generates, through decode_tail(), a pointer. The address - * dependency matches the RELEASE of xchg_tail() such that - * the subsequent access to @prev happens after. - */ - WRITE_ONCE(prev->next, node); + /* + * We must ensure that the stores to @node are observed before + * the write to prev->next. The address dependency from + * xchg_tail is not sufficient to ensure this because the read + * component of xchg_tail is unordered with respect to the + * initialisation of @node. + */ + smp_store_release(&prev->next, node); pv_wait_node(node, prev); arch_mcs_spin_lock_contended(&node->locked);