Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp6195583ybv; Wed, 12 Feb 2020 07:43:38 -0800 (PST) X-Google-Smtp-Source: APXvYqwKZs7IHqhcHgt4hogUT7KKhEh82bneZUR8bktyzgqjoiiclKBrrJ4nSnEipNOZbSLCnhJY X-Received: by 2002:a9d:4110:: with SMTP id o16mr9802881ote.101.1581522217711; Wed, 12 Feb 2020 07:43:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1581522217; cv=none; d=google.com; s=arc-20160816; b=Qh+i3haiyiBFeltzefOK5biLsVVHD0B7gUsnMEqwclIvOtZra1sLntYIIGLVdCC6Ol X3qqrL0zk+lWsxdNt85Xv/GIF10dBlcPm2o0pkxoupotXsDzmGp6mXsB2jOTbwm/iSQN 3YzTVd/UBNrLDrTLz0xTsIBvVD0kJECF4aH7oddWqcc+C7/coo36yom2ZbANRqE92sjY r5/jWGEqi2s+exUBl/BnDJVOQ1v9r+8f22nVQnRzLpcMJI03eV/nkIyVI+CGkHZyQi7E Qiv70/pe7LeSThw+IYahIqfKST3oVhUgO3KappolHvbLrtYY8Wbbaduzw/onN6/shSAE B87g== 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 :dkim-signature; bh=N7xT5k/FYGx7N/5C+nsY2hbvNfivZ8aBxdpBg8mpNHU=; b=ajPOZdT1RRgpA+BBz9LqCKW7DFAPK+0cAJsfzFLO+SxRZM+FO2fdsh5IGkDz91uwPY Myo0v2dv0rCHY2hyXYs7CWRs6J03j9IrD+g3GIzkDttVnTAoYP9lFwKpTTZ03P/MIHmk 7A18gx8i18kjdIJb4R1Dgdr4uR4z8b8Dz0nEZU3gZwvG3lNmDOxgAItBHIz2CEBO5Of0 g/4AFmBDXQB2AK97Y/hfdk32ZjIAIrDHalQ6L0pPLtjhtItWZx2V8cXkNXE5f3EgZ+gw 9pUleHaG/BKcvauJfxxv8M3fnz2+KPx6XTuUUHJLAzu46Db4idr4k7w49LqekgfAEvpR qaSA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@monstr-eu.20150623.gappssmtp.com header.s=20150623 header.b=FLotEYA6; 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 l26si394209oti.152.2020.02.12.07.43.25; Wed, 12 Feb 2020 07:43:37 -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=fail header.i=@monstr-eu.20150623.gappssmtp.com header.s=20150623 header.b=FLotEYA6; 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 S1728692AbgBLPmt (ORCPT + 99 others); Wed, 12 Feb 2020 10:42:49 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:53885 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728245AbgBLPms (ORCPT ); Wed, 12 Feb 2020 10:42:48 -0500 Received: by mail-wm1-f66.google.com with SMTP id s10so2833399wmh.3 for ; Wed, 12 Feb 2020 07:42:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monstr-eu.20150623.gappssmtp.com; s=20150623; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=N7xT5k/FYGx7N/5C+nsY2hbvNfivZ8aBxdpBg8mpNHU=; b=FLotEYA67VaNKBky+3tBGMm3yUYok7qLcWQwIJwSICHy8PCokdwggaaSIe2ZNAtX0r VeHxpRajI6cgGCqOzqkcknQ+Fr9voAbUl4fd7AJQPCEY15t6fFjovDQ6l+E1Bb+1AZ0V LHLM4z6m/9fftAA61KLf+zsl+22Es7vQ3fCGu2B+ynfoJfMJizcxPbfQNaBdmV8eECtf VxZ5ApYq5x8sBuoL05dfuva/Cs/EvjTc6lLqgDgNWhMjUhLyIxDiYETFSmstRgB04XWV AAyo0u9pEPy7JFXQePsRCCaKWa4DJdClmazlcXopscHdZrC/iJ59cT/pQI/XzuguIj5j Hlyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=N7xT5k/FYGx7N/5C+nsY2hbvNfivZ8aBxdpBg8mpNHU=; b=ElAhFlm4K0wjq2+lAmtsblHc0cYuO4o/t2O+tA+sDE+Ds11sJrlDYRfhAvtNQ5VzrH wiqJmPCM2XeXk5Z8yaLzqMVNIqarmkTGBFBwDq1N7jNNOPFEgjImW6Ea8jf0bwJVmM5C QSOoSTMw0wnsUQPXuIOc43BTgjXuYICjyAIexhsdkDL8oc9f6nhsuj+wIiU/fJmybMXv C07gpb/z/ML/osGQYN+F4k6yjK6KiJbRiLR9Y0qam9m2RyJAexqrHEgjg4oU1x0SX1TD EuMB+13tkdvNHQihD2NdtpQBj2erPC8keJrRziWShlcde/JWH/lWC9siVj5XaITeitJr a+TQ== X-Gm-Message-State: APjAAAX0MPb6l29rqIQwvCLklCJeNAKk43v7sko+F3iQ5cs5kQOJx3Ya Qo/YKfvaOd53mAwIwEHRPiAkKYR2ltQLCJK/ X-Received: by 2002:a1c:65d6:: with SMTP id z205mr12969094wmb.38.1581522164413; Wed, 12 Feb 2020 07:42:44 -0800 (PST) Received: from localhost (nat-35.starnet.cz. [178.255.168.35]) by smtp.gmail.com with ESMTPSA id u14sm1045583wrm.51.2020.02.12.07.42.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 12 Feb 2020 07:42:43 -0800 (PST) From: Michal Simek To: linux-kernel@vger.kernel.org, monstr@monstr.eu, michal.simek@xilinx.com, git@xilinx.com, arnd@arndb.de Cc: Stefan Asserhall load and store , Boqun Feng , Peter Zijlstra , Will Deacon Subject: [PATCH 7/7] microblaze: Do atomic operations by using exclusive ops Date: Wed, 12 Feb 2020 16:42:29 +0100 Message-Id: X-Mailer: git-send-email 2.25.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Stefan Asserhall load and store Implement SMP aware atomic operations. Signed-off-by: Stefan Asserhall Signed-off-by: Michal Simek --- arch/microblaze/include/asm/atomic.h | 265 +++++++++++++++++++++++++-- 1 file changed, 253 insertions(+), 12 deletions(-) diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h index 41e9aff23a62..522d704fad63 100644 --- a/arch/microblaze/include/asm/atomic.h +++ b/arch/microblaze/include/asm/atomic.h @@ -1,28 +1,269 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2013-2020 Xilinx, Inc. + */ + #ifndef _ASM_MICROBLAZE_ATOMIC_H #define _ASM_MICROBLAZE_ATOMIC_H +#include #include -#include -#include + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) READ_ONCE((v)->counter) + +static inline void atomic_set(atomic_t *v, int i) +{ + int result, tmp; + + __asm__ __volatile__ ( + /* load conditional address in %2 to %0 */ + "1: lwx %0, %2, r0;\n" + /* attempt store */ + " swx %3, %2, r0;\n" + /* checking msr carry flag */ + " addic %1, r0, 0;\n" + /* store failed (MSR[C] set)? try again */ + " bnei %1, 1b;\n" + /* Outputs: result value */ + : "=&r" (result), "=&r" (tmp) + /* Inputs: counter address */ + : "r" (&v->counter), "r" (i) + : "cc", "memory" + ); +} +#define atomic_set atomic_set + +/* Atomically perform op with v->counter and i, return result */ +#define ATOMIC_OP_RETURN(op, asm) \ +static inline int atomic_##op##_return_relaxed(int i, atomic_t *v) \ +{ \ + int result, tmp; \ + \ + __asm__ __volatile__ ( \ + /* load conditional address in %2 to %0 */ \ + "1: lwx %0, %2, r0;\n" \ + /* perform operation and save it to result */ \ + #asm " %0, %3, %0;\n" \ + /* attempt store */ \ + " swx %0, %2, r0;\n" \ + /* checking msr carry flag */ \ + " addic %1, r0, 0;\n" \ + /* store failed (MSR[C] set)? try again */ \ + " bnei %1, 1b;\n" \ + /* Outputs: result value */ \ + : "=&r" (result), "=&r" (tmp) \ + /* Inputs: counter address */ \ + : "r" (&v->counter), "r" (i) \ + : "cc", "memory" \ + ); \ + \ + return result; \ +} \ + \ +static inline void atomic_##op(int i, atomic_t *v) \ +{ \ + atomic_##op##_return_relaxed(i, v); \ +} + +/* Atomically perform op with v->counter and i, return orig v->counter */ +#define ATOMIC_FETCH_OP_RELAXED(op, asm) \ +static inline int atomic_fetch_##op##_relaxed(int i, atomic_t *v) \ +{ \ + int old, tmp; \ + \ + __asm__ __volatile__ ( \ + /* load conditional address in %2 to %0 */ \ + "1: lwx %0, %2, r0;\n" \ + /* perform operation and save it to tmp */ \ + #asm " %1, %3, %0;\n" \ + /* attempt store */ \ + " swx %1, %2, r0;\n" \ + /* checking msr carry flag */ \ + " addic %1, r0, 0;\n" \ + /* store failed (MSR[C] set)? try again */ \ + " bnei %1, 1b;\n" \ + /* Outputs: old value */ \ + : "=&r" (old), "=&r" (tmp) \ + /* Inputs: counter address */ \ + : "r" (&v->counter), "r" (i) \ + : "cc", "memory" \ + ); \ + \ + return old; \ +} + +#define ATOMIC_OPS(op, asm) \ + ATOMIC_FETCH_OP_RELAXED(op, asm) \ + ATOMIC_OP_RETURN(op, asm) + +ATOMIC_OPS(and, and) +#define atomic_and atomic_and +#define atomic_and_return_relaxed atomic_and_return_relaxed +#define atomic_fetch_and_relaxed atomic_fetch_and_relaxed + +ATOMIC_OPS(add, add) +#define atomic_add atomic_add +#define atomic_add_return_relaxed atomic_add_return_relaxed +#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed + +ATOMIC_OPS(xor, xor) +#define atomic_xor atomic_xor +#define atomic_xor_return_relaxed atomic_xor_return_relaxed +#define atomic_fetch_xor_relaxed atomic_fetch_xor_relaxed + +ATOMIC_OPS(or, or) +#define atomic_or atomic_or +#define atomic_or_return_relaxed atomic_or_return_relaxed +#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed + +ATOMIC_OPS(sub, rsub) +#define atomic_sub atomic_sub +#define atomic_sub_return_relaxed atomic_sub_return_relaxed +#define atomic_fetch_sub_relaxed atomic_fetch_sub_relaxed + +static inline int atomic_inc_return_relaxed(atomic_t *v) +{ + int result, tmp; + + __asm__ __volatile__ ( + /* load conditional address in %2 to %0 */ + "1: lwx %0, %2, r0;\n" + /* increment counter by 1 */ + " addi %0, %0, 1;\n" + /* attempt store */ + " swx %0, %2, r0;\n" + /* checking msr carry flag */ + " addic %1, r0, 0;\n" + /* store failed (MSR[C] set)? try again */ + " bnei %1, 1b;\n" + /* Outputs: result value */ + : "=&r" (result), "=&r" (tmp) + /* Inputs: counter address */ + : "r" (&v->counter) + : "cc", "memory" + ); + + return result; +} +#define atomic_inc_return_relaxed atomic_inc_return_relaxed + +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) + +static inline int atomic_dec_return(atomic_t *v) +{ + int result, tmp; + + __asm__ __volatile__ ( + /* load conditional address in %2 to %0 */ + "1: lwx %0, %2, r0;\n" + /* increment counter by -1 */ + " addi %0, %0, -1;\n" + /* attempt store */ + " swx %0, %2, r0;\n" + /* checking msr carry flag */ + " addic %1, r0, 0;\n" + /* store failed (MSR[C] set)? try again */ + " bnei %1, 1b;\n" + /* Outputs: result value */ + : "=&r" (result), "=&r" (tmp) + /* Inputs: counter address */ + : "r" (&v->counter) + : "cc", "memory" + ); + + return result; +} +#define atomic_dec_return atomic_dec_return + +static inline void atomic_dec(atomic_t *v) +{ + atomic_dec_return(v); +} +#define atomic_dec atomic_dec + +#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) + +#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + +/** + * atomic_add_unless - add unless the number is a given value + * @v: pointer of type atomic_t + * @a: the amount to add to v... + * @u: ...unless v is equal to u. + * + * Atomically adds @a to @v, so long as it was not @u. + * Returns the old value of @v. + */ +static inline int __atomic_add_unless(atomic_t *v, int a, int u) +{ + int result, tmp; + + __asm__ __volatile__ ( + /* load conditional address in %2 to %0 */ + "1: lwx %0, %2, r0;\n" + /* compare loaded value with old value*/ + " cmp %1, %0, %3;\n" + /* equal to u, don't increment */ + " beqid %1, 2f;\n" + /* increment counter by i */ + " add %1, %0, %4;\n" + /* attempt store of new value*/ + " swx %1, %2, r0;\n" + /* checking msr carry flag */ + " addic %1, r0, 0;\n" + /* store failed (MSR[C] set)? try again */ + " bnei %1, 1b;\n" + "2:" + /* Outputs: result value */ + : "=&r" (result), "=&r" (tmp) + /* Inputs: counter address, old, new */ + : "r" (&v->counter), "r" (u), "r" (a) + : "cc", "memory" + ); + + return result; +} /* * Atomically test *v and decrement if it is greater than 0. - * The function returns the old value of *v minus 1. + * The function returns the old value of *v minus 1, even if + * the atomic variable, v, was not decremented. */ static inline int atomic_dec_if_positive(atomic_t *v) { - unsigned long flags; - int res; + int result, tmp; - local_irq_save(flags); - res = v->counter - 1; - if (res >= 0) - v->counter = res; - local_irq_restore(flags); + __asm__ __volatile__ ( + /* load conditional address in %2 to %0 */ + "1: lwx %0, %2, r0;\n" + /* decrement counter by 1*/ + " addi %0, %0, -1;\n" + /* if < 0 abort (*v was <= 0)*/ + " blti %0, 2f;\n" + /* attempt store of new value*/ + " swx %0, %2, r0;\n" + /* checking msr carry flag */ + " addic %1, r0, 0;\n" + /* store failed (MSR[C] set)? try again */ + " bnei %1, 1b;\n" + "2: " + /* Outputs: result value */ + : "=&r" (result), "=&r" (tmp) + /* Inputs: counter address */ + : "r" (&v->counter) + : "cc", "memory" + ); - return res; + return result; } -#define atomic_dec_if_positive atomic_dec_if_positive +#define atomic_dec_if_positive atomic_dec_if_positive + +#define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0) + +#include #endif /* _ASM_MICROBLAZE_ATOMIC_H */ -- 2.25.0