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

percpu_test.c (3300B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#include <linux/module.h>
      3
      4/* validate @native and @pcp counter values match @expected */
      5#define CHECK(native, pcp, expected)                                    \
      6	do {                                                            \
      7		WARN((native) != (expected),                            \
      8		     "raw %ld (0x%lx) != expected %lld (0x%llx)",	\
      9		     (native), (native),				\
     10		     (long long)(expected), (long long)(expected));	\
     11		WARN(__this_cpu_read(pcp) != (expected),                \
     12		     "pcp %ld (0x%lx) != expected %lld (0x%llx)",	\
     13		     __this_cpu_read(pcp), __this_cpu_read(pcp),	\
     14		     (long long)(expected), (long long)(expected));	\
     15	} while (0)
     16
     17static DEFINE_PER_CPU(long, long_counter);
     18static DEFINE_PER_CPU(unsigned long, ulong_counter);
     19
     20static int __init percpu_test_init(void)
     21{
     22	/*
     23	 * volatile prevents compiler from optimizing it uses, otherwise the
     24	 * +ul_one/-ul_one below would replace with inc/dec instructions.
     25	 */
     26	volatile unsigned int ui_one = 1;
     27	long l = 0;
     28	unsigned long ul = 0;
     29
     30	pr_info("percpu test start\n");
     31
     32	preempt_disable();
     33
     34	l += -1;
     35	__this_cpu_add(long_counter, -1);
     36	CHECK(l, long_counter, -1);
     37
     38	l += 1;
     39	__this_cpu_add(long_counter, 1);
     40	CHECK(l, long_counter, 0);
     41
     42	ul = 0;
     43	__this_cpu_write(ulong_counter, 0);
     44
     45	ul += 1UL;
     46	__this_cpu_add(ulong_counter, 1UL);
     47	CHECK(ul, ulong_counter, 1);
     48
     49	ul += -1UL;
     50	__this_cpu_add(ulong_counter, -1UL);
     51	CHECK(ul, ulong_counter, 0);
     52
     53	ul += -(unsigned long)1;
     54	__this_cpu_add(ulong_counter, -(unsigned long)1);
     55	CHECK(ul, ulong_counter, -1);
     56
     57	ul = 0;
     58	__this_cpu_write(ulong_counter, 0);
     59
     60	ul -= 1;
     61	__this_cpu_dec(ulong_counter);
     62	CHECK(ul, ulong_counter, -1);
     63	CHECK(ul, ulong_counter, ULONG_MAX);
     64
     65	l += -ui_one;
     66	__this_cpu_add(long_counter, -ui_one);
     67	CHECK(l, long_counter, 0xffffffff);
     68
     69	l += ui_one;
     70	__this_cpu_add(long_counter, ui_one);
     71	CHECK(l, long_counter, (long)0x100000000LL);
     72
     73
     74	l = 0;
     75	__this_cpu_write(long_counter, 0);
     76
     77	l -= ui_one;
     78	__this_cpu_sub(long_counter, ui_one);
     79	CHECK(l, long_counter, -1);
     80
     81	l = 0;
     82	__this_cpu_write(long_counter, 0);
     83
     84	l += ui_one;
     85	__this_cpu_add(long_counter, ui_one);
     86	CHECK(l, long_counter, 1);
     87
     88	l += -ui_one;
     89	__this_cpu_add(long_counter, -ui_one);
     90	CHECK(l, long_counter, (long)0x100000000LL);
     91
     92	l = 0;
     93	__this_cpu_write(long_counter, 0);
     94
     95	l -= ui_one;
     96	this_cpu_sub(long_counter, ui_one);
     97	CHECK(l, long_counter, -1);
     98	CHECK(l, long_counter, ULONG_MAX);
     99
    100	ul = 0;
    101	__this_cpu_write(ulong_counter, 0);
    102
    103	ul += ui_one;
    104	__this_cpu_add(ulong_counter, ui_one);
    105	CHECK(ul, ulong_counter, 1);
    106
    107	ul = 0;
    108	__this_cpu_write(ulong_counter, 0);
    109
    110	ul -= ui_one;
    111	__this_cpu_sub(ulong_counter, ui_one);
    112	CHECK(ul, ulong_counter, -1);
    113	CHECK(ul, ulong_counter, ULONG_MAX);
    114
    115	ul = 3;
    116	__this_cpu_write(ulong_counter, 3);
    117
    118	ul = this_cpu_sub_return(ulong_counter, ui_one);
    119	CHECK(ul, ulong_counter, 2);
    120
    121	ul = __this_cpu_sub_return(ulong_counter, ui_one);
    122	CHECK(ul, ulong_counter, 1);
    123
    124	preempt_enable();
    125
    126	pr_info("percpu test done\n");
    127	return -EAGAIN;  /* Fail will directly unload the module */
    128}
    129
    130static void __exit percpu_test_exit(void)
    131{
    132}
    133
    134module_init(percpu_test_init)
    135module_exit(percpu_test_exit)
    136
    137MODULE_LICENSE("GPL");
    138MODULE_AUTHOR("Greg Thelen");
    139MODULE_DESCRIPTION("percpu operations test");