From patchwork Sun Mar 10 02:05:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 13588001 Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2373E37708 for ; Sun, 10 Mar 2024 02:05:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710036357; cv=none; b=F6WteHlYrIEanFVP7awZUTm5MZio2HmB3x5WBPWMQYAln1xNp0K8IHiUSoCDk3MbHsbGk/V2Q+YnXCVeflDP9IoLT+EUlCPM/CLOe/nVf3MCZR/XaF/2bB4/UniYupnBKBtTwT2RKy/N+Ptw97XvrjP8WgAwZxh+MQBiCsYZFdo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710036357; c=relaxed/simple; bh=Fq4lcFad9HT9JmjkJEm98VVUDFCHd+jm9iRP80ik0Qk=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Content-Type; b=aa3NnH4BSyhXl02hSxtq7kBuiTk1hBAz+wWV30exSLDlb7H3Xm1gopirwyJ0oOOguti1tFcSXGJU82ZDanJkzP/qqFOlF0adu+Z9GLozIJhgNc/illTGr28wCtekfUScVUPxAO7Bq17LC8oex8XTVDXtRZVe937fRA53FnamVwU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Et8oLd0U; arc=none smtp.client-ip=209.85.219.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Et8oLd0U" Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-dcdc3db67f0so4933008276.1 for ; Sat, 09 Mar 2024 18:05:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1710036354; x=1710641154; darn=vger.kernel.org; h=to:from:subject:references:mime-version:message-id:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=EfWQCgRQvC61dW45rBVZGuz4IKfn5r36xpIYwQ99OM0=; b=Et8oLd0Uuwwe4+7kI3T6ViWYA6cGKXI7GR4TrQvRkiTDQYe/9R5M+ZfD2kWjDZvRbh X9CZYfs9El9ORL0q4RbfIWLW0QB4VriOmBvSW5cm9KsvKdimt3+rxA+ILZyat14alDI+ kdBPW1hPBca7cHrzJeFFsZ47zB3LuwqJjoGY+xMp1SFZIACbxh+P9x4u6vGiqqs2UKnn Tm2EscMTADk8ui3t0JiF0wxcs0P9EvfiH/VoRFLrT4dm6T4pbP+WZf+FPL0m/lZe0Utc JT6jgNebAvTjy9xU8z4MQmxi5+4xZ4dh461NZ30LZ76+3AXvAOpZcEsV6kOiWkuUhk4Z 1dvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710036354; x=1710641154; h=to:from:subject:references:mime-version:message-id:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=EfWQCgRQvC61dW45rBVZGuz4IKfn5r36xpIYwQ99OM0=; b=dHf3Fum9iBE0PSVIzd8FZIY/qw25M3NzE8iS511szoiH1+XWpuB6GHFYlLUEPFK5vK TvWmlRzT519WQH0FW3oSHSBl5o5++oDE3/1ISeJHxaVG1mNPlpnF88/kf5geIGbeSUDU YxJgoVJcXmV+WKZIbxVM7rEaWgjPjputRivIUu8iEuJTNS1fXmErQtBg9mXBUlBX6nYV pFg5dhy0tpeFV1U2L3eJ6UvMfo/ahJbaC79/LTnSMdCX4SEB5MvV/D894P3eKggLx+A1 aZHNQFsOn9ShJn0o3sc3XeqfLedY42FojvluiuOpkSFul4QLiTAd5WURxx5ZQ8sTXenX Ghng== X-Forwarded-Encrypted: i=1; AJvYcCWHxgifPt7zM+NePGLwfUUVPHKEIEnX5uC4VRSrVpgpk/WTB/yeAO4ech6FrHINuTj9Ue1c7/YPmK8eWD5U4ZO9UOIZjbRfpykzNEYbcsSj X-Gm-Message-State: AOJu0YzrB/k1hXTOAFC4tIKkdzR4sa4MzR7u1NWOHaGgR+7nw30GIIy8 ICw1pzA7yLBE1gVBCg+AE1r6yFdSDxDWx5fQFXg5xZKpTnL0XoODMrlyNRBwmlzVerm77ty1940 U4PDthg== X-Google-Smtp-Source: AGHT+IEbgF9/L10MqEQsfT/YgldjotiYAys6nVxOfaOObgpu5qrtCsaN68T0Sw/VHfW+vmC7K4OzTmNsXC8h X-Received: from irogers.svl.corp.google.com ([2620:15c:2a3:200:a63d:1b65:e810:3ad3]) (user=irogers job=sendgmr) by 2002:a05:6902:10c2:b0:dbd:b4e8:1565 with SMTP id w2-20020a05690210c200b00dbdb4e81565mr1091906ybu.4.1710036354130; Sat, 09 Mar 2024 18:05:54 -0800 (PST) Date: Sat, 9 Mar 2024 18:05:04 -0800 In-Reply-To: <20240310020509.647319-1-irogers@google.com> Message-Id: <20240310020509.647319-10-irogers@google.com> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240310020509.647319-1-irogers@google.com> X-Mailer: git-send-email 2.44.0.278.ge034bb2e1d-goog Subject: [PATCH v1 09/13] tools headers: Rewrite linux/atomic.h using C11's stdatomic.h From: Ian Rogers To: Arnd Bergmann , Andrii Nakryiko , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , Paolo Bonzini , Shuah Khan , Kees Cook , "Gustavo A. R. Silva" , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Andrew Morton , Liam Howlett , Miguel Ojeda , Will Deacon , Mark Brown , David Laight , "Michael S. Tsirkin" , Shunsuke Mie , Yafang Shao , Kui-Feng Lee , James Clark , Nick Forrington , Leo Yan , German Gomez , Rob Herring , John Garry , Sean Christopherson , Anup Patel , Fuad Tabba , Andrew Jones , Chao Peng , Haibo Xu , Peter Xu , Vishal Annapurve , linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-hardening@vger.kernel.org, llvm@lists.linux.dev Code in tools tries to follow the patterns of the kernel, so the atomic functions names match. However, having include/linux/atomic.h in tools complicates building code in tools as assembly and other functions are necessary - these are often configured in the kernel using CONFIG options. As tools C code is compiled with the -std=gnu11 flag, it is possible to use stdatomic.h and move the build and other complications to the compiler/libc. Signed-off-by: Ian Rogers --- tools/arch/x86/include/asm/atomic.h | 84 -------------- tools/include/asm-generic/atomic-gcc.h | 95 ---------------- tools/include/asm/atomic.h | 11 -- tools/include/linux/atomic.h | 107 ++++++++++++++++-- tools/include/linux/types.h | 15 ++- .../selftests/kvm/include/kvm_util_base.h | 3 +- 6 files changed, 110 insertions(+), 205 deletions(-) delete mode 100644 tools/arch/x86/include/asm/atomic.h delete mode 100644 tools/include/asm-generic/atomic-gcc.h delete mode 100644 tools/include/asm/atomic.h diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/asm/atomic.h deleted file mode 100644 index 365cf182df12..000000000000 --- a/tools/arch/x86/include/asm/atomic.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H -#define _TOOLS_LINUX_ASM_X86_ATOMIC_H - -#include -#include -#include "rmwcc.h" - -#define LOCK_PREFIX "\n\tlock; " - -#include -#include - -/* - * Atomic operations that C can't guarantee us. Useful for - * resource counting etc.. - */ - -#define ATOMIC_INIT(i) { (i) } - -/** - * atomic_read - read atomic variable - * @v: pointer of type atomic_t - * - * Atomically reads the value of @v. - */ -static inline int atomic_read(const atomic_t *v) -{ - return READ_ONCE((v)->counter); -} - -/** - * atomic_set - set atomic variable - * @v: pointer of type atomic_t - * @i: required value - * - * Atomically sets the value of @v to @i. - */ -static inline void atomic_set(atomic_t *v, int i) -{ - v->counter = i; -} - -/** - * atomic_inc - increment atomic variable - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1. - */ -static inline void atomic_inc(atomic_t *v) -{ - asm volatile(LOCK_PREFIX "incl %0" - : "+m" (v->counter)); -} - -/** - * atomic_dec_and_test - decrement and test - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ -static inline int atomic_dec_and_test(atomic_t *v) -{ - GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e"); -} - -static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new) -{ - return cmpxchg(&v->counter, old, new); -} - -static inline int test_and_set_bit(long nr, unsigned long *addr) -{ - GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, "Ir", nr, "%0", "c"); -} - -static inline int test_and_clear_bit(long nr, unsigned long *addr) -{ - GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, "Ir", nr, "%0", "c"); -} - -#endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */ diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-generic/atomic-gcc.h deleted file mode 100644 index 9b3c528bab92..000000000000 --- a/tools/include/asm-generic/atomic-gcc.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H -#define __TOOLS_ASM_GENERIC_ATOMIC_H - -#include -#include -#include - -/* - * Atomic operations that C can't guarantee us. Useful for - * resource counting etc.. - * - * Excerpts obtained from the Linux kernel sources. - */ - -#define ATOMIC_INIT(i) { (i) } - -/** - * atomic_read - read atomic variable - * @v: pointer of type atomic_t - * - * Atomically reads the value of @v. - */ -static inline int atomic_read(const atomic_t *v) -{ - return READ_ONCE((v)->counter); -} - -/** - * atomic_set - set atomic variable - * @v: pointer of type atomic_t - * @i: required value - * - * Atomically sets the value of @v to @i. - */ -static inline void atomic_set(atomic_t *v, int i) -{ - v->counter = i; -} - -/** - * atomic_inc - increment atomic variable - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1. - */ -static inline void atomic_inc(atomic_t *v) -{ - __sync_add_and_fetch(&v->counter, 1); -} - -/** - * atomic_dec_and_test - decrement and test - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ -static inline int atomic_dec_and_test(atomic_t *v) -{ - return __sync_sub_and_fetch(&v->counter, 1) == 0; -} - -#define cmpxchg(ptr, oldval, newval) \ - __sync_val_compare_and_swap(ptr, oldval, newval) - -static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval) -{ - return cmpxchg(&(v)->counter, oldval, newval); -} - -static inline int test_and_set_bit(long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - long old; - - addr += BIT_WORD(nr); - - old = __sync_fetch_and_or(addr, mask); - return !!(old & mask); -} - -static inline int test_and_clear_bit(long nr, unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - long old; - - addr += BIT_WORD(nr); - - old = __sync_fetch_and_and(addr, ~mask); - return !!(old & mask); -} - -#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */ diff --git a/tools/include/asm/atomic.h b/tools/include/asm/atomic.h deleted file mode 100644 index 8c9bfffd4191..000000000000 --- a/tools/include/asm/atomic.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __TOOLS_LINUX_ASM_ATOMIC_H -#define __TOOLS_LINUX_ASM_ATOMIC_H - -#if defined(__i386__) || defined(__x86_64__) -#include "../../arch/x86/include/asm/atomic.h" -#else -#include -#endif - -#endif /* __TOOLS_LINUX_ASM_ATOMIC_H */ diff --git a/tools/include/linux/atomic.h b/tools/include/linux/atomic.h index 01907b33537e..2cf4791ddd5d 100644 --- a/tools/include/linux/atomic.h +++ b/tools/include/linux/atomic.h @@ -2,14 +2,107 @@ #ifndef __TOOLS_LINUX_ATOMIC_H #define __TOOLS_LINUX_ATOMIC_H -#include +#include +#include // For atomic_t -void atomic_long_set(atomic_long_t *v, long i); +/* + * Reimplementation of the kernel's atomic.h using C11's stdatomic.h to avoid + * build logic around compilers, inline assembler, etc. + */ -/* atomic_cmpxchg_relaxed */ -#ifndef atomic_cmpxchg_relaxed -#define atomic_cmpxchg_relaxed atomic_cmpxchg -#define atomic_cmpxchg_release atomic_cmpxchg -#endif /* atomic_cmpxchg_relaxed */ +#define ATOMIC_OP(op, c_op) \ +static inline void generic_atomic_##op(int i, atomic_t *v) \ +{ \ + atomic_fetch_##op(v, i); \ +} + +#define ATOMIC_OP_RETURN(op, c_op) \ +static inline int generic_atomic_##op##_return(int i, atomic_t *v) \ +{ \ + int c = atomic_fetch_##op(v, i); \ + \ + return c c_op i; \ +} + +#define ATOMIC_FETCH_OP(op, c_op) \ +static inline int generic_atomic_fetch_##op(int i, atomic_t *v) \ +{ \ + return atomic_fetch_##op(v, i); \ +} + +static inline int generic_atomic_read(const atomic_t *v) +{ + return atomic_load(v); +} + +static inline void generic_atomic_set(atomic_t *v, int i) +{ + atomic_store(v, i); +} + +static inline int generic_atomic_cmpxchg_relaxed(atomic_t *v, int old, int new) +{ + int expected = old; + + atomic_compare_exchange_weak_explicit(v, &expected, new, + memory_order_relaxed, memory_order_relaxed); + return expected; +} + +static inline int generic_atomic_cmpxchg_release(atomic_t *v, int old, int new) +{ + int expected = old; + + /* + * Note, the stricter memory_order_seq_cst is used as + * memory_order_release fails with an invalid-memory-model error. + */ + atomic_compare_exchange_weak_explicit(v, &expected, new, + memory_order_seq_cst, memory_order_seq_cst); + return expected; +} + +ATOMIC_OP_RETURN(add, +) +ATOMIC_OP_RETURN(sub, -) + +ATOMIC_FETCH_OP(add, +) +ATOMIC_FETCH_OP(sub, -) +ATOMIC_FETCH_OP(and, &) +ATOMIC_FETCH_OP(or, |) +ATOMIC_FETCH_OP(xor, ^) + +ATOMIC_OP(add, +) +ATOMIC_OP(sub, -) +ATOMIC_OP(and, &) +ATOMIC_OP(or, |) +ATOMIC_OP(xor, ^) + +#undef ATOMIC_FETCH_OP +#undef ATOMIC_OP_RETURN +#undef ATOMIC_OP + +#define arch_atomic_add_return generic_atomic_add_return +#define arch_atomic_sub_return generic_atomic_sub_return + +#define arch_atomic_fetch_add generic_atomic_fetch_add +#define arch_atomic_fetch_sub generic_atomic_fetch_sub +#define arch_atomic_fetch_and generic_atomic_fetch_and +#define arch_atomic_fetch_or generic_atomic_fetch_or +#define arch_atomic_fetch_xor generic_atomic_fetch_xor + +#define arch_atomic_add generic_atomic_add +#define arch_atomic_sub generic_atomic_sub +#define arch_atomic_and generic_atomic_and +#define arch_atomic_or generic_atomic_or +#define arch_atomic_xor generic_atomic_xor + +#define arch_atomic_read(v) generic_atomic_read(v) +#define arch_atomic_set(v, i) generic_atomic_set(v, i) +#define atomic_set(v, i) generic_atomic_set(v, i) +#define atomic_read(v) generic_atomic_read(v) +#define atomic_cmpxchg_relaxed(v, o, n) generic_atomic_cmpxchg_relaxed(v, o, n) +#define atomic_cmpxchg_release(v, o, n) generic_atomic_cmpxchg_release(v, o, n) +#define atomic_inc(v) generic_atomic_add(1, v) +#define atomic_dec(v) generic_atomic_sub(1, v) #endif /* __TOOLS_LINUX_ATOMIC_H */ diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h index 8519386acd23..cb1f44f1ed5e 100644 --- a/tools/include/linux/types.h +++ b/tools/include/linux/types.h @@ -74,13 +74,16 @@ typedef u64 phys_addr_t; typedef u32 phys_addr_t; #endif -typedef struct { - int counter; -} atomic_t; +#ifndef __cplusplus +/* C++17 doesn't support stdatomic.h but C++23 does. */ +#include -typedef struct { - long counter; -} atomic_long_t; +typedef atomic_int atomic_t; + +#define ATOMIC_INIT(i) (i) + +typedef atomic_long atomic_long_t; +#endif #ifndef __aligned_u64 # define __aligned_u64 __u64 __attribute__((aligned(8))) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 9e5afc472c14..7c81da425abc 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -9,6 +9,7 @@ #include "test_util.h" +#include #include #include "linux/hashtable.h" #include "linux/list.h" @@ -17,8 +18,6 @@ #include "linux/rbtree.h" #include -#include - #include #include "sparsebit.h"