Received: by 10.223.185.116 with SMTP id b49csp2901118wrg; Mon, 5 Mar 2018 10:26:02 -0800 (PST) X-Google-Smtp-Source: AG47ELsTK8Eg/+9tvr5/lnUD5RuL0Emso1KlcuM3wgHI+mwWTNYkQE/0oPdHGAKHIau6rLezHh7e X-Received: by 10.98.27.10 with SMTP id b10mr16267613pfb.121.1520274362727; Mon, 05 Mar 2018 10:26:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520274362; cv=none; d=google.com; s=arc-20160816; b=ESl5fcB0W/cwn7TOgOM1Ubx+5AOm6qefAY+wK5BwxbvwuUNScsxdA+H5kjhThzfnGc KL1Lm62SYpw++5Ik/1bxAVVlnuJvE80QN9h+R5M52xU8Kct20/yA4SO0dLYNS1rtGepO SOhG/zLTdOc8Q71DmtSnDQaiNcnLGoOTuE8aq2im3VbYuyKkocKFjZZVd8IQie/4SUq4 DWJHPyOjvBmp2Czb5VUlAfI+nf+fJHUbd085HqUBxEZ2truVIX3woKhu09bCgttQXFDY YPe4VQ4y4FZTihH7iXE4PMf5qiTvgDDeYVygtpnYW4ygWmZSWhAUtZ2sK8giUy+xaZj0 9GZQ== 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=ZPBZFcVWxh5ZV/3Ioii/e81b5pX8t31vaZsyNC2BQGmWhHlnADQSaUs6rDitAu0ZFF ER5sj556dCAV8OM4CZIU73GsyHz7ck+pEohn+tNaS611yTXAKtf9KQH1Rfkss2HV8Gg0 UJ74nLzDU679UhdCU3ZjYeOuhjCEfWfIVZBOzuLLVgTd+vNihd9bzBsWPFeoX+JXVJvQ u0E3A8v4AMLp3xd5WYimv+VNt3qcQDLtKnXOeggZVOm2ogjT+8eAdS+Rj3ZDJMkVLKAB VSdWBtQSGWXq19VJCxEkAe/L49myVqe+gKsYjlDVrLpiw9sbJ5OK8glWT+wEdFB0YXkw zelg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=IbZTTDDi; 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 32-v6si9798789pls.319.2018.03.05.10.25.49; Mon, 05 Mar 2018 10:26:02 -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=IbZTTDDi; 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 S1752576AbeCESYd (ORCPT + 99 others); Mon, 5 Mar 2018 13:24:33 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36421 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751838AbeCESYc (ORCPT ); Mon, 5 Mar 2018 13:24:32 -0500 Received: by mail-wm0-f68.google.com with SMTP id 188so17409343wme.1 for ; Mon, 05 Mar 2018 10:24:31 -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=IbZTTDDi1jHt9LfZ84HJ7uvlEPhpmxlZqlbr2KCSXFhfnUAP5SujpYMMZZsssyAj6/ KV9EYOcwyKlgO2HC6fkuIDrFI9hX6Mn4PT+VTiJXDxWW2tC0+UjMsk18WF8MgeQlVNfB OedKcWAyhMU27uiNH5TzB05M2eqU3SjKGF5racjaq+C+jWqQIv2ssfkQDPOvHURwdKkD qsjhH2lWctDUJx0pFXFCHc8y6/HgwPxhYZ2nitJlF72TdoiMEvRG0TZ33+/XoxsPeb+B AgGVYm8z7j/hbz3nAmhNpD6QPtZK1DWCuIruDXbJdoIzqlYaEFq0CEZ5f6rW0jK/KkSV IHXw== 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=INWanYt5LsnB12/cOHBUXe5PhQNhfQC9jpjgPJBMoOLErBmPIvLA29Ztoy60OTZImu je5X1qfbZ/6c/IgULXiKHUTCDp15ber3uRLsSCkfuE9GGF+DrvTZeqYqN3KLPF0Mt6Ak 0MyiBPrjOXr6Z66OBmT0XNeUtwJ4H72CKjN31ONkS3y95AQq2C8Gh9JpyvvkgFwPccwL /zQ28Szn7Z6IY6xtyprANxVIMwcIbO560PaH4y7S2UjW3LrWbGRZDJ0u3MJrgAimUBqI miDgnXJqF+RbSCsPtJV7zMRJudu8XhWKieKRXJIW/mKUqU9xeiFN8b+b2VdDujYov+HA KcIg== X-Gm-Message-State: AElRT7Hs+01bnDiNl/kMiAu3Qgv58p9W2xYToFhyguKLWcvgSMUy02MY 4U5i4cKbWNEwqLbf50hyoaw= X-Received: by 10.28.6.205 with SMTP id 196mr9992401wmg.136.1520274270873; Mon, 05 Mar 2018 10:24:30 -0800 (PST) Received: from localhost.localdomain (94-74-211-130.client.rionet.cz. [94.74.211.130]) by smtp.gmail.com with ESMTPSA id m187sm11468843wmg.0.2018.03.05.10.24.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 05 Mar 2018 10:24:30 -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: [RFC PATCH 1/2] riscv/spinlock: Strengthen implementations with fences Date: Mon, 5 Mar 2018 19:24:09 +0100 Message-Id: <1520274249-21815-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