Received: by 10.223.185.111 with SMTP id b44csp236093wrg; Fri, 9 Mar 2018 04:15:13 -0800 (PST) X-Google-Smtp-Source: AG47ELvAaweAL8MIyujcsItul1RDUOqFUTyFbnQFVUlv8kH6a/s3dO7K7qCs1olerMCJ/kRuFJLP X-Received: by 10.98.33.76 with SMTP id h73mr12197547pfh.144.1520597713350; Fri, 09 Mar 2018 04:15:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520597713; cv=none; d=google.com; s=arc-20160816; b=iF5fDU+EaiOEw6cs5gcm0XLOSCVtzM1/113xWLT5Yd3NpP+wBBVl/iJvik5zKW1lvM eKvliQSh9qbpUeIkWx5dI1zMmRwjq9JbV4aiQpqHmwEun9HkgLqeWsn44qozqZfBjLF3 EQJiBsPXV8FoQcB4xv44SoakrynUb/xdPFIgNCRcDVZI1sW3/UAX/BhbK95XId0E4RBe j6xqYE3PNsKE+RsUBMYDkVsdxvXIfdmbxZzyUWdEXD+VgLgAGcdlpGHxJJuL+zvMiILN F1TjG9vHpbk9fW1Ldb4bgGe0sULYdDYlbA5lPXvuPcqHdnzVuE809dMlscTVZjn1AVUv 5J+w== 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 :dkim-signature:arc-authentication-results; bh=GCZFQ0H6gtwNCNnnDoEFhmbr9XFqWH+BHJtu/g9jFDA=; b=UXn1y6Jk0KHiCWjvIhD8xW3tjNYowNNr7jQh+9B6kNAMyrx+IdpUR+sefJGI+P1s8p 0beAXAfVWu709zdNc0lta+VVwIrMEM54cUGTjMvUrB/sLqHJW8WZP+dA/25UPBGraXHg vT6WEEThSAKuB9l0juCke/D/8G1nrY2CbfTUB9bJiGOu1EnXn02cG6v14Zf2q70IDu+U A7gRkVOUGJeNwrif6Tkvjd7g67ywi5R2q/I/zai3y8mtNKukeEYfznqeGW68saxE1ZGj 6Hf0bR5ErI9cHeGV7khZ55RN+8oxag8KqzqO59iMtTSarlhzpGPH4RACkswNB9U5jh6d sfbQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=psSmqqFv; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m63-v6si777854pld.602.2018.03.09.04.14.58; Fri, 09 Mar 2018 04:15:13 -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; dkim=pass header.i=@gmail.com header.s=20161025 header.b=psSmqqFv; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751206AbeCIMNf (ORCPT + 99 others); Fri, 9 Mar 2018 07:13:35 -0500 Received: from mail-wr0-f196.google.com ([209.85.128.196]:38174 "EHLO mail-wr0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751075AbeCIMNe (ORCPT ); Fri, 9 Mar 2018 07:13:34 -0500 Received: by mail-wr0-f196.google.com with SMTP id n7so8812584wrn.5 for ; Fri, 09 Mar 2018 04:13:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=GCZFQ0H6gtwNCNnnDoEFhmbr9XFqWH+BHJtu/g9jFDA=; b=psSmqqFvYMPQsBMqp3Evbp8fjXDcCOGgDntLCKlRb0vcuQG2IRayScay8KqYqRA1/I cl41rqhg+SEYlhm5B2t9mnwvKAyOzEUGu56hka+WWxNLvtXgcJvpQCRjDIg6qh25Oirc rqrntvI9qHOr72K7IVeZnuaeMSnpjl1HZow4aMpgfVogNutcobk1ZQqSyWPR1CVWtf84 Vg9ZRK8ZewUXa1hreMYzgZXLY58aFV1bCinSvflTD+8I28KoD3sz93+QmVG77vrtufGL JeM/OiduA5tVMKymlaA06//LyUMxnU2Zn/rXOp71eELlA6UFk/0hS59XDKl6R+/lhFXG 7QRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=GCZFQ0H6gtwNCNnnDoEFhmbr9XFqWH+BHJtu/g9jFDA=; b=fnrdtMQUnSCS8hfxGFjhoeRGj/KlRLyux1YOxILvZsURdG4IWFND3Km2MmRnO4LSq6 2wTV5/pO0qh+JRVIBybVQiCEBmaAOQy6Ccs12YUy8QM63Q6kDTRrr98KaXVAb4UsL14l t6fPgILL97eyCYjntixjVC9qhc8JzGXXizcTki+BWmHGdOWynvwUZzdz95wufr08+Tgi 39F//QyQOB4yYi9RKMhtsqL87NJ39jWQ+ovPfUQ/pFErgUNkbR8jVse7mPafIAiUFX4q dftDr9BFO4opoCLPggjPQj2qpzkPZBelDHuIr+Vu+01VMK6cXcZokPanUalE9Eh03+SA 3J5A== X-Gm-Message-State: AElRT7G8t9wy4q3rM4j7hSAAV/z47a2oeHPPQPz5OjHkyzOTrMurbmur H+0H8oH4n8LVdxSZhaXiH48= X-Received: by 10.223.188.1 with SMTP id s1mr538115wrg.97.1520597612606; Fri, 09 Mar 2018 04:13:32 -0800 (PST) Received: from andrea.amarulasolutions.com (85.100.broadband17.iol.cz. [109.80.100.85]) by smtp.gmail.com with ESMTPSA id e50sm1068625wre.49.2018.03.09.04.13.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 09 Mar 2018 04:13:32 -0800 (PST) From: Andrea Parri To: Palmer Dabbelt , Albert Ou Cc: Daniel Lustig , Alan Stern , Will Deacon , Peter Zijlstra , Boqun Feng , Nicholas Piggin , David Howells , Jade Alglave , Luc Maranget , Paul McKenney , Akira Yokosawa , Ingo Molnar , Linus Torvalds , linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Andrea Parri Subject: [PATCH v2 1/2] riscv/spinlock: Strengthen implementations with fences Date: Fri, 9 Mar 2018 13:13:20 +0100 Message-Id: <1520597600-16603-1-git-send-email-parri.andrea@gmail.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Current implementations map locking operations using .rl and .aq annotations. However, this mapping is unsound w.r.t. the kernel memory consistency model (LKMM) [1]: Referring to the "unlock-lock-read-ordering" test reported below, Daniel wrote: "I think an RCpc interpretation of .aq and .rl would in fact allow the two normal loads in P1 to be reordered [...] The intuition would be that the amoswap.w.aq can forward from the amoswap.w.rl while that's still in the store buffer, and then the lw x3,0(x4) can also perform while the amoswap.w.rl is still in the store buffer, all before the l1 x1,0(x2) executes. That's not forbidden unless the amoswaps are RCsc, unless I'm missing something. Likewise even if the unlock()/lock() is between two stores. A control dependency might originate from the load part of the amoswap.w.aq, but there still would have to be something to ensure that this load part in fact performs after the store part of the amoswap.w.rl performs globally, and that's not automatic under RCpc." Simulation of the RISC-V memory consistency model confirmed this expectation. In order to "synchronize" LKMM and RISC-V's implementation, this commit strengthens the implementations of the locking operations by replacing .rl and .aq with the use of ("lightweigth") fences, resp., "fence rw, w" and "fence r , rw". C unlock-lock-read-ordering {} /* s initially owned by P1 */ P0(int *x, int *y) { WRITE_ONCE(*x, 1); smp_wmb(); WRITE_ONCE(*y, 1); } P1(int *x, int *y, spinlock_t *s) { int r0; int r1; r0 = READ_ONCE(*y); spin_unlock(s); spin_lock(s); r1 = READ_ONCE(*x); } exists (1:r0=1 /\ 1:r1=0) [1] https://marc.info/?l=linux-kernel&m=151930201102853&w=2 https://groups.google.com/a/groups.riscv.org/forum/#!topic/isa-dev/hKywNHBkAXM https://marc.info/?l=linux-kernel&m=151633436614259&w=2 Signed-off-by: Andrea Parri Cc: Palmer Dabbelt Cc: Albert Ou Cc: Daniel Lustig Cc: Alan Stern Cc: Will Deacon Cc: Peter Zijlstra Cc: Boqun Feng Cc: Nicholas Piggin Cc: David Howells Cc: Jade Alglave Cc: Luc Maranget Cc: "Paul E. McKenney" Cc: Akira Yokosawa Cc: Ingo Molnar Cc: Linus Torvalds Cc: linux-riscv@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- arch/riscv/include/asm/fence.h | 12 ++++++++++++ arch/riscv/include/asm/spinlock.h | 29 +++++++++++++++-------------- 2 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 arch/riscv/include/asm/fence.h diff --git a/arch/riscv/include/asm/fence.h b/arch/riscv/include/asm/fence.h new file mode 100644 index 0000000000000..2b443a3a487f3 --- /dev/null +++ b/arch/riscv/include/asm/fence.h @@ -0,0 +1,12 @@ +#ifndef _ASM_RISCV_FENCE_H +#define _ASM_RISCV_FENCE_H + +#ifdef CONFIG_SMP +#define RISCV_ACQUIRE_BARRIER "\tfence r , rw\n" +#define RISCV_RELEASE_BARRIER "\tfence rw, w\n" +#else +#define RISCV_ACQUIRE_BARRIER +#define RISCV_RELEASE_BARRIER +#endif + +#endif /* _ASM_RISCV_FENCE_H */ diff --git a/arch/riscv/include/asm/spinlock.h b/arch/riscv/include/asm/spinlock.h index 2fd27e8ef1fd6..8eb26d1ede819 100644 --- a/arch/riscv/include/asm/spinlock.h +++ b/arch/riscv/include/asm/spinlock.h @@ -17,6 +17,7 @@ #include #include +#include /* * Simple spin lock operations. These provide no fairness guarantees. @@ -28,10 +29,7 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock) { - __asm__ __volatile__ ( - "amoswap.w.rl x0, x0, %0" - : "=A" (lock->lock) - :: "memory"); + smp_store_release(&lock->lock, 0); } static inline int arch_spin_trylock(arch_spinlock_t *lock) @@ -39,7 +37,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) int tmp = 1, busy; __asm__ __volatile__ ( - "amoswap.w.aq %0, %2, %1" + " amoswap.w %0, %2, %1\n" + RISCV_ACQUIRE_BARRIER : "=r" (busy), "+A" (lock->lock) : "r" (tmp) : "memory"); @@ -68,8 +67,9 @@ static inline void arch_read_lock(arch_rwlock_t *lock) "1: lr.w %1, %0\n" " bltz %1, 1b\n" " addi %1, %1, 1\n" - " sc.w.aq %1, %1, %0\n" + " sc.w %1, %1, %0\n" " bnez %1, 1b\n" + RISCV_ACQUIRE_BARRIER : "+A" (lock->lock), "=&r" (tmp) :: "memory"); } @@ -82,8 +82,9 @@ static inline void arch_write_lock(arch_rwlock_t *lock) "1: lr.w %1, %0\n" " bnez %1, 1b\n" " li %1, -1\n" - " sc.w.aq %1, %1, %0\n" + " sc.w %1, %1, %0\n" " bnez %1, 1b\n" + RISCV_ACQUIRE_BARRIER : "+A" (lock->lock), "=&r" (tmp) :: "memory"); } @@ -96,8 +97,9 @@ static inline int arch_read_trylock(arch_rwlock_t *lock) "1: lr.w %1, %0\n" " bltz %1, 1f\n" " addi %1, %1, 1\n" - " sc.w.aq %1, %1, %0\n" + " sc.w %1, %1, %0\n" " bnez %1, 1b\n" + RISCV_ACQUIRE_BARRIER "1:\n" : "+A" (lock->lock), "=&r" (busy) :: "memory"); @@ -113,8 +115,9 @@ static inline int arch_write_trylock(arch_rwlock_t *lock) "1: lr.w %1, %0\n" " bnez %1, 1f\n" " li %1, -1\n" - " sc.w.aq %1, %1, %0\n" + " sc.w %1, %1, %0\n" " bnez %1, 1b\n" + RISCV_ACQUIRE_BARRIER "1:\n" : "+A" (lock->lock), "=&r" (busy) :: "memory"); @@ -125,7 +128,8 @@ static inline int arch_write_trylock(arch_rwlock_t *lock) static inline void arch_read_unlock(arch_rwlock_t *lock) { __asm__ __volatile__( - "amoadd.w.rl x0, %1, %0" + RISCV_RELEASE_BARRIER + " amoadd.w x0, %1, %0\n" : "+A" (lock->lock) : "r" (-1) : "memory"); @@ -133,10 +137,7 @@ static inline void arch_read_unlock(arch_rwlock_t *lock) static inline void arch_write_unlock(arch_rwlock_t *lock) { - __asm__ __volatile__ ( - "amoswap.w.rl x0, x0, %0" - : "=A" (lock->lock) - :: "memory"); + smp_store_release(&lock->lock, 0); } #endif /* _ASM_RISCV_SPINLOCK_H */ -- 2.7.4