Add bpf_atomic.h including atomic read/write macros like READ_ONCE() and
try_cmpxchg(). This version is a stripped down copy of the one currently
present in selftests/bpf/libarena.

Signed-off-by: Gabriele Monaco <[email protected]>
---
 .../verification/rv/bpf_monitors/bpf_atomic.h | 105 ++++++++++++++++++
 1 file changed, 105 insertions(+)
 create mode 100644 tools/verification/rv/bpf_monitors/bpf_atomic.h

diff --git a/tools/verification/rv/bpf_monitors/bpf_atomic.h 
b/tools/verification/rv/bpf_monitors/bpf_atomic.h
new file mode 100644
index 000000000000..f834ea91c9d3
--- /dev/null
+++ b/tools/verification/rv/bpf_monitors/bpf_atomic.h
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
+#ifndef BPF_ATOMIC_H
+#define BPF_ATOMIC_H
+
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+
+extern bool CONFIG_X86_64 __kconfig __weak;
+
+/*
+ * __unqual_typeof(x) - Declare an unqualified scalar type, leaving
+ *                     non-scalar types unchanged,
+ *
+ * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
+ * is not type-compatible with 'signed char', and we define a separate case.
+ *
+ * This is copied verbatim from kernel's include/linux/compiler_types.h, but
+ * with default expression (for pointers) changed from (x) to (typeof(x)0).
+ *
+ * This is because LLVM has a bug where for lvalue (x), it does not get rid of
+ * an extra address_space qualifier, but does in case of rvalue (typeof(x)0).
+ * Hence, for pointers, we need to create an rvalue expression to get the
+ * desired type. See https://github.com/llvm/llvm-project/issues/53400.
+ */
+#define __scalar_type_to_expr_cases(type) \
+       unsigned type : (unsigned type)0, signed type : (signed type)0
+
+#define __unqual_typeof(x)                              \
+       typeof(_Generic((x),                            \
+               char: (char)0,                          \
+               __scalar_type_to_expr_cases(char),      \
+               __scalar_type_to_expr_cases(short),     \
+               __scalar_type_to_expr_cases(int),       \
+               __scalar_type_to_expr_cases(long),      \
+               __scalar_type_to_expr_cases(long long), \
+               default: (typeof(x))0))
+
+/* No-op for BPF */
+#define cpu_relax() ({})
+
+#define READ_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+#ifndef WRITE_ONCE
+#define WRITE_ONCE(x, val) ((*(volatile typeof(x) *)&(x)) = (val))
+#endif
+
+#define cmpxchg(p, old, new) __sync_val_compare_and_swap((p), old, new)
+
+#define try_cmpxchg(p, pold, new)                                 \
+       ({                                                        \
+               __unqual_typeof(*(pold)) __o = *(pold);           \
+               __unqual_typeof(*(p)) __r = cmpxchg(p, __o, new); \
+               if (__r != __o)                                   \
+                       *(pold) = __r;                            \
+               __r == __o;                                       \
+       })
+
+#define try_cmpxchg_relaxed(p, pold, new) try_cmpxchg(p, pold, new)
+
+#define try_cmpxchg_acquire(p, pold, new) try_cmpxchg(p, pold, new)
+
+#define smp_mb()                                 \
+       ({                                       \
+               volatile unsigned long __val;    \
+               __sync_fetch_and_add(&__val, 0); \
+       })
+
+#define smp_rmb()                   \
+       ({                          \
+               if (!CONFIG_X86_64) \
+                       smp_mb();   \
+               else                \
+                       barrier();  \
+       })
+
+#define smp_wmb()                   \
+       ({                          \
+               if (!CONFIG_X86_64) \
+                       smp_mb();   \
+               else                \
+                       barrier();  \
+       })
+
+/* Control dependency provides LOAD->STORE, provide LOAD->LOAD */
+#define smp_acquire__after_ctrl_dep() ({ smp_rmb(); })
+
+#define smp_load_acquire(p)                                  \
+       ({                                                   \
+               __unqual_typeof(*(p)) __v = READ_ONCE(*(p)); \
+               if (!CONFIG_X86_64)                          \
+                       smp_mb();                            \
+               barrier();                                   \
+               __v;                                         \
+       })
+
+#define smp_store_release(p, val)      \
+       ({                             \
+               if (!CONFIG_X86_64)    \
+                       smp_mb();      \
+               barrier();             \
+               WRITE_ONCE(*(p), val); \
+       })
+
+#endif /* BPF_ATOMIC_H */
-- 
2.55.0


Reply via email to