diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index d9d170238165..7f79d0704ba8 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -76,12 +76,19 @@ do { \
BUG_ON(atomic##bit##_read(&v) != expect); \
} while (0)
+#define TEST_ARGS_PLAIN(_, op, init, ret, expect, args...) \
+do { \
+ __WRITE_ONCE(n, init); \
+ BUG_ON(op(&n, ##args) != ret); \
+ BUG_ON(__READ_ONCE(n) != expect); \
+} while (0)
+
#define XCHG_FAMILY_TEST(bit, init, new) \
do { \
FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new); \
} while (0)
-#define CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \
+#define ATOMIC_CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \
do { \
FAMILY_TEST(TEST_ARGS, bit, cmpxchg, \
init, init, new, init, new); \@@ -89,6 +96,14 @@ do { \
init, init, init, wrong, new); \
} while (0)
+#define CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \
+do { \
+ FAMILY_TEST(TEST_ARGS_PLAIN, _, cmpxchg##bit, \
+ init, init, new, init, new); \
+ FAMILY_TEST(TEST_ARGS_PLAIN, _, cmpxchg##bit, \
+ init, init, init, wrong, new); \
+} while (0)
+
#define INC_RETURN_FAMILY_TEST(bit, i) \
do { \
FAMILY_TEST(TEST_ARGS, bit, inc_return, \@@ -109,6 +124,7 @@ static __init void test_atomic(void)
int one = 1;
atomic_t v;
+ int n;
int r;
TEST(, add, +=, onestwos);
@@ -139,6 +155,7 @@ static __init void test_atomic(void)
DEC_RETURN_FAMILY_TEST(, v0);
XCHG_FAMILY_TEST(, v0, v1);
+ ATOMIC_CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
}
@@ -155,6 +172,7 @@ static __init void test_atomic64(void)
int r_int;
atomic64_t v = ATOMIC64_INIT(v0);
+ long long n = 0;
long long r = v0;
BUG_ON(v.counter != r);
@@ -201,6 +219,7 @@ static __init void test_atomic64(void)
DEC_RETURN_FAMILY_TEST(64, v0);
XCHG_FAMILY_TEST(64, v0, v1);
+ ATOMIC_CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
INIT(v0);
@@ -245,10 +264,30 @@ static __init void test_atomic64(void)
BUG_ON(!r_int);
}
+#ifdef system_has_cmpxchg128
+static __init void test_atomic128(void)
+{
+ long long v0 = 0xaaa31337c001d00dLL;
+ long long v1 = 0xdeadbeefdeafcafeLL;
+ long long v2 = 0xfaceabadf00df001LL;
+ long long v3 = 0x8000000000000000LL;
+
+ s128 init = ((s128)v0 << 64) + v1;
+ s128 new = ((s128)v1 << 64) + v0;
+ s128 wrong = ((s128)v2 << 64) + v3;
+ s128 n = 1;
+
+ CMPXCHG_FAMILY_TEST(128, init, new, wrong);
+}
+#else
+static __init void test_atomic128(void) {}
+#endif
+
static __init int test_atomics_init(void)
{
test_atomic();
test_atomic64();
+ test_atomic128();
#ifdef CONFIG_X86
pr_info("passed for %s platform %s CX8 and %s SSE\n",--
2.38.1