]> xenbits.xensource.com Git - xen.git/commitdiff
xen/bitops: Cleanup and new infrastructure ahead of rearrangements
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 8 Mar 2024 23:45:08 +0000 (23:45 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Sat, 1 Jun 2024 01:28:14 +0000 (02:28 +0100)
 * Rename __attribute_pure__ to just __pure before it gains users.
 * Introduce __constructor which is going to be used in lib/, and is
   unconditionally cf_check.
 * Identify the areas of xen/bitops.h which are a mess.
 * Introduce xen/self-tests.h as helpers for compile and boot time testing.
   This provides a statement of the ABI, and a confirmation that arch-specific
   implementations behave as expected.
 * Introduce HIDE() in macros.h.  While it's only used in self-tests.h for
   now, we're going to consolidate similar constructs in due course.

Sadly Clang 7 and older isn't happy with the compile time checks.  Skip them,
and just rely on the runtime checks.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Release-acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
xen/include/xen/bitops.h
xen/include/xen/compiler.h
xen/include/xen/macros.h
xen/include/xen/self-tests.h [new file with mode: 0644]

index e3c5a4ccf3216a713274aad1f3c84ef34e5c16b5..9b40f20381a265d1c9cf44cf8818ff0c2b4ac6dc 100644 (file)
@@ -1,5 +1,7 @@
-#ifndef _LINUX_BITOPS_H
-#define _LINUX_BITOPS_H
+#ifndef XEN_BITOPS_H
+#define XEN_BITOPS_H
+
+#include <xen/compiler.h>
 #include <xen/types.h>
 
 /*
@@ -103,8 +105,13 @@ static inline int generic_flsl(unsigned long x)
  * Include this here because some architectures need generic_ffs/fls in
  * scope
  */
+
+/* --------------------- Please tidy above here --------------------- */
+
 #include <asm/bitops.h>
 
+/* --------------------- Please tidy below here --------------------- */
+
 #ifndef find_next_bit
 /**
  * find_next_bit - find the next set bit in a memory region
@@ -294,4 +301,4 @@ static inline __u32 ror32(__u32 word, unsigned int shift)
 
 #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
 
-#endif
+#endif /* XEN_BITOPS_H */
index 179ff23e62c57318b189dd7972d4bd096670b946..444bf80142c78ac01f3428672b355d645e377a30 100644 (file)
@@ -86,7 +86,8 @@
 #define inline inline __init
 #endif
 
-#define __attribute_pure__  __attribute__((__pure__))
+#define __constructor       __attribute__((__constructor__)) cf_check
+#define __pure              __attribute__((__pure__))
 #define __attribute_const__ __attribute__((__const__))
 #define __transparent__     __attribute__((__transparent_union__))
 
index e64373f0187d7bc4881904fc98d3e17459d3affb..ec89f4654fcf6a890022eb5f8c90eb37b6289345 100644 (file)
 #define BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond))
 #endif
 
+/* Hide a value from the optimiser. */
+#define HIDE(x)                                 \
+    ({                                          \
+        typeof(x) _x = (x);                     \
+        asm volatile ( "" : "+r" (_x) );        \
+        _x;                                     \
+    })
+
 #define ABS(x) ({                              \
     typeof(x) x_ = (x);                        \
     (x_ < 0) ? -x_ : x_;                       \
diff --git a/xen/include/xen/self-tests.h b/xen/include/xen/self-tests.h
new file mode 100644 (file)
index 0000000..8410db7
--- /dev/null
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Helpers for Xen self-tests of basic logic, including confirming that
+ * examples which should be calculated by the compiler are.
+ */
+#ifndef XEN_SELF_TESTS_H
+#define XEN_SELF_TESTS_H
+
+#include <xen/lib.h>
+
+/*
+ * Check that fn(val) can be calcuated by the compiler, and that it gives the
+ * expected answer.
+ *
+ * Clang < 8 can't fold constants through static inlines, causing this to
+ * fail.  Simply skip it for incredibly old compilers.
+ */
+#if !CONFIG_CC_IS_CLANG || CONFIG_CLANG_VERSION >= 80000
+#define COMPILE_CHECK(fn, val, res)                                     \
+    do {                                                                \
+        typeof(fn(val)) real = fn(val);                                 \
+                                                                        \
+        if ( !__builtin_constant_p(real) )                              \
+            asm ( ".error \"'" STR(fn(val)) "' not compile-time constant\"" ); \
+        else if ( real != res )                                         \
+            asm ( ".error \"Compile time check '" STR(fn(val) == res) "' failed\"" ); \
+    } while ( 0 )
+#else
+#define COMPILE_CHECK(fn, val, res)
+#endif
+
+/*
+ * Check that Xen's runtime logic for fn(val) gives the expected answer.  This
+ * requires using HIDE() to prevent the optimiser from collapsing the logic
+ * into a constant.
+ */
+#define RUNTIME_CHECK(fn, val, res)                     \
+    do {                                                \
+        typeof(fn(val)) real = fn(HIDE(val));           \
+                                                        \
+        if ( real != res )                              \
+            panic("%s: %s(%s) expected %u, got %u\n",   \
+                  __func__, #fn, #val, real, res);      \
+    } while ( 0 )
+
+/*
+ * Perform compile-time and runtime checks for fn(val) == res.
+ */
+#define CHECK(fn, val, res)                     \
+    do {                                        \
+        COMPILE_CHECK(fn, val, res);            \
+        RUNTIME_CHECK(fn, val, res);            \
+    } while ( 0 )
+
+#endif /* XEN_SELF_TESTS_H */