cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

atomic64_test.c (6587B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Testsuite for atomic64_t functions
      4 *
      5 * Copyright © 2010  Luca Barbieri
      6 */
      7
      8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      9
     10#include <linux/init.h>
     11#include <linux/bug.h>
     12#include <linux/kernel.h>
     13#include <linux/atomic.h>
     14#include <linux/module.h>
     15
     16#ifdef CONFIG_X86
     17#include <asm/cpufeature.h>	/* for boot_cpu_has below */
     18#endif
     19
     20#define TEST(bit, op, c_op, val)				\
     21do {								\
     22	atomic##bit##_set(&v, v0);				\
     23	r = v0;							\
     24	atomic##bit##_##op(val, &v);				\
     25	r c_op val;						\
     26	WARN(atomic##bit##_read(&v) != r, "%Lx != %Lx\n",	\
     27		(unsigned long long)atomic##bit##_read(&v),	\
     28		(unsigned long long)r);				\
     29} while (0)
     30
     31/*
     32 * Test for a atomic operation family,
     33 * @test should be a macro accepting parameters (bit, op, ...)
     34 */
     35
     36#define FAMILY_TEST(test, bit, op, args...)	\
     37do {						\
     38	test(bit, op, ##args);		\
     39	test(bit, op##_acquire, ##args);	\
     40	test(bit, op##_release, ##args);	\
     41	test(bit, op##_relaxed, ##args);	\
     42} while (0)
     43
     44#define TEST_RETURN(bit, op, c_op, val)				\
     45do {								\
     46	atomic##bit##_set(&v, v0);				\
     47	r = v0;							\
     48	r c_op val;						\
     49	BUG_ON(atomic##bit##_##op(val, &v) != r);		\
     50	BUG_ON(atomic##bit##_read(&v) != r);			\
     51} while (0)
     52
     53#define TEST_FETCH(bit, op, c_op, val)				\
     54do {								\
     55	atomic##bit##_set(&v, v0);				\
     56	r = v0;							\
     57	r c_op val;						\
     58	BUG_ON(atomic##bit##_##op(val, &v) != v0);		\
     59	BUG_ON(atomic##bit##_read(&v) != r);			\
     60} while (0)
     61
     62#define RETURN_FAMILY_TEST(bit, op, c_op, val)			\
     63do {								\
     64	FAMILY_TEST(TEST_RETURN, bit, op, c_op, val);		\
     65} while (0)
     66
     67#define FETCH_FAMILY_TEST(bit, op, c_op, val)			\
     68do {								\
     69	FAMILY_TEST(TEST_FETCH, bit, op, c_op, val);		\
     70} while (0)
     71
     72#define TEST_ARGS(bit, op, init, ret, expect, args...)		\
     73do {								\
     74	atomic##bit##_set(&v, init);				\
     75	BUG_ON(atomic##bit##_##op(&v, ##args) != ret);		\
     76	BUG_ON(atomic##bit##_read(&v) != expect);		\
     77} while (0)
     78
     79#define XCHG_FAMILY_TEST(bit, init, new)				\
     80do {									\
     81	FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new);	\
     82} while (0)
     83
     84#define CMPXCHG_FAMILY_TEST(bit, init, new, wrong)			\
     85do {									\
     86	FAMILY_TEST(TEST_ARGS, bit, cmpxchg, 				\
     87			init, init, new, init, new);			\
     88	FAMILY_TEST(TEST_ARGS, bit, cmpxchg,				\
     89			init, init, init, wrong, new);			\
     90} while (0)
     91
     92#define INC_RETURN_FAMILY_TEST(bit, i)			\
     93do {							\
     94	FAMILY_TEST(TEST_ARGS, bit, inc_return,		\
     95			i, (i) + one, (i) + one);	\
     96} while (0)
     97
     98#define DEC_RETURN_FAMILY_TEST(bit, i)			\
     99do {							\
    100	FAMILY_TEST(TEST_ARGS, bit, dec_return,		\
    101			i, (i) - one, (i) - one);	\
    102} while (0)
    103
    104static __init void test_atomic(void)
    105{
    106	int v0 = 0xaaa31337;
    107	int v1 = 0xdeadbeef;
    108	int onestwos = 0x11112222;
    109	int one = 1;
    110
    111	atomic_t v;
    112	int r;
    113
    114	TEST(, add, +=, onestwos);
    115	TEST(, add, +=, -one);
    116	TEST(, sub, -=, onestwos);
    117	TEST(, sub, -=, -one);
    118	TEST(, or, |=, v1);
    119	TEST(, and, &=, v1);
    120	TEST(, xor, ^=, v1);
    121	TEST(, andnot, &= ~, v1);
    122
    123	RETURN_FAMILY_TEST(, add_return, +=, onestwos);
    124	RETURN_FAMILY_TEST(, add_return, +=, -one);
    125	RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
    126	RETURN_FAMILY_TEST(, sub_return, -=, -one);
    127
    128	FETCH_FAMILY_TEST(, fetch_add, +=, onestwos);
    129	FETCH_FAMILY_TEST(, fetch_add, +=, -one);
    130	FETCH_FAMILY_TEST(, fetch_sub, -=, onestwos);
    131	FETCH_FAMILY_TEST(, fetch_sub, -=, -one);
    132
    133	FETCH_FAMILY_TEST(, fetch_or,  |=, v1);
    134	FETCH_FAMILY_TEST(, fetch_and, &=, v1);
    135	FETCH_FAMILY_TEST(, fetch_andnot, &= ~, v1);
    136	FETCH_FAMILY_TEST(, fetch_xor, ^=, v1);
    137
    138	INC_RETURN_FAMILY_TEST(, v0);
    139	DEC_RETURN_FAMILY_TEST(, v0);
    140
    141	XCHG_FAMILY_TEST(, v0, v1);
    142	CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
    143
    144}
    145
    146#define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
    147static __init void test_atomic64(void)
    148{
    149	long long v0 = 0xaaa31337c001d00dLL;
    150	long long v1 = 0xdeadbeefdeafcafeLL;
    151	long long v2 = 0xfaceabadf00df001LL;
    152	long long v3 = 0x8000000000000000LL;
    153	long long onestwos = 0x1111111122222222LL;
    154	long long one = 1LL;
    155	int r_int;
    156
    157	atomic64_t v = ATOMIC64_INIT(v0);
    158	long long r = v0;
    159	BUG_ON(v.counter != r);
    160
    161	atomic64_set(&v, v1);
    162	r = v1;
    163	BUG_ON(v.counter != r);
    164	BUG_ON(atomic64_read(&v) != r);
    165
    166	TEST(64, add, +=, onestwos);
    167	TEST(64, add, +=, -one);
    168	TEST(64, sub, -=, onestwos);
    169	TEST(64, sub, -=, -one);
    170	TEST(64, or, |=, v1);
    171	TEST(64, and, &=, v1);
    172	TEST(64, xor, ^=, v1);
    173	TEST(64, andnot, &= ~, v1);
    174
    175	RETURN_FAMILY_TEST(64, add_return, +=, onestwos);
    176	RETURN_FAMILY_TEST(64, add_return, +=, -one);
    177	RETURN_FAMILY_TEST(64, sub_return, -=, onestwos);
    178	RETURN_FAMILY_TEST(64, sub_return, -=, -one);
    179
    180	FETCH_FAMILY_TEST(64, fetch_add, +=, onestwos);
    181	FETCH_FAMILY_TEST(64, fetch_add, +=, -one);
    182	FETCH_FAMILY_TEST(64, fetch_sub, -=, onestwos);
    183	FETCH_FAMILY_TEST(64, fetch_sub, -=, -one);
    184
    185	FETCH_FAMILY_TEST(64, fetch_or,  |=, v1);
    186	FETCH_FAMILY_TEST(64, fetch_and, &=, v1);
    187	FETCH_FAMILY_TEST(64, fetch_andnot, &= ~, v1);
    188	FETCH_FAMILY_TEST(64, fetch_xor, ^=, v1);
    189
    190	INIT(v0);
    191	atomic64_inc(&v);
    192	r += one;
    193	BUG_ON(v.counter != r);
    194
    195	INIT(v0);
    196	atomic64_dec(&v);
    197	r -= one;
    198	BUG_ON(v.counter != r);
    199
    200	INC_RETURN_FAMILY_TEST(64, v0);
    201	DEC_RETURN_FAMILY_TEST(64, v0);
    202
    203	XCHG_FAMILY_TEST(64, v0, v1);
    204	CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
    205
    206	INIT(v0);
    207	BUG_ON(atomic64_add_unless(&v, one, v0));
    208	BUG_ON(v.counter != r);
    209
    210	INIT(v0);
    211	BUG_ON(!atomic64_add_unless(&v, one, v1));
    212	r += one;
    213	BUG_ON(v.counter != r);
    214
    215	INIT(onestwos);
    216	BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
    217	r -= one;
    218	BUG_ON(v.counter != r);
    219
    220	INIT(0);
    221	BUG_ON(atomic64_dec_if_positive(&v) != -one);
    222	BUG_ON(v.counter != r);
    223
    224	INIT(-one);
    225	BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
    226	BUG_ON(v.counter != r);
    227
    228	INIT(onestwos);
    229	BUG_ON(!atomic64_inc_not_zero(&v));
    230	r += one;
    231	BUG_ON(v.counter != r);
    232
    233	INIT(0);
    234	BUG_ON(atomic64_inc_not_zero(&v));
    235	BUG_ON(v.counter != r);
    236
    237	INIT(-one);
    238	BUG_ON(!atomic64_inc_not_zero(&v));
    239	r += one;
    240	BUG_ON(v.counter != r);
    241
    242	/* Confirm the return value fits in an int, even if the value doesn't */
    243	INIT(v3);
    244	r_int = atomic64_inc_not_zero(&v);
    245	BUG_ON(!r_int);
    246}
    247
    248static __init int test_atomics_init(void)
    249{
    250	test_atomic();
    251	test_atomic64();
    252
    253#ifdef CONFIG_X86
    254	pr_info("passed for %s platform %s CX8 and %s SSE\n",
    255#ifdef CONFIG_X86_64
    256		"x86-64",
    257#elif defined(CONFIG_X86_CMPXCHG64)
    258		"i586+",
    259#else
    260		"i386+",
    261#endif
    262	       boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
    263	       boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
    264#else
    265	pr_info("passed\n");
    266#endif
    267
    268	return 0;
    269}
    270
    271static __exit void test_atomics_exit(void) {}
    272
    273module_init(test_atomics_init);
    274module_exit(test_atomics_exit);
    275
    276MODULE_LICENSE("GPL");