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

spinlock_test.c (2285B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/init.h>
      3#include <linux/kthread.h>
      4#include <linux/hrtimer.h>
      5#include <linux/fs.h>
      6#include <linux/debugfs.h>
      7#include <linux/export.h>
      8#include <linux/spinlock.h>
      9#include <asm/debug.h>
     10
     11static int ss_get(void *data, u64 *val)
     12{
     13	ktime_t start, finish;
     14	int loops;
     15	int cont;
     16	DEFINE_RAW_SPINLOCK(ss_spin);
     17
     18	loops = 1000000;
     19	cont = 1;
     20
     21	start = ktime_get();
     22
     23	while (cont) {
     24		raw_spin_lock(&ss_spin);
     25		loops--;
     26		if (loops == 0)
     27			cont = 0;
     28		raw_spin_unlock(&ss_spin);
     29	}
     30
     31	finish = ktime_get();
     32
     33	*val = ktime_us_delta(finish, start);
     34
     35	return 0;
     36}
     37
     38DEFINE_DEBUGFS_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n");
     39
     40
     41
     42struct spin_multi_state {
     43	raw_spinlock_t lock;
     44	atomic_t start_wait;
     45	atomic_t enter_wait;
     46	atomic_t exit_wait;
     47	int loops;
     48};
     49
     50struct spin_multi_per_thread {
     51	struct spin_multi_state *state;
     52	ktime_t start;
     53};
     54
     55static int multi_other(void *data)
     56{
     57	int loops;
     58	int cont;
     59	struct spin_multi_per_thread *pt = data;
     60	struct spin_multi_state *s = pt->state;
     61
     62	loops = s->loops;
     63	cont = 1;
     64
     65	atomic_dec(&s->enter_wait);
     66
     67	while (atomic_read(&s->enter_wait))
     68		; /* spin */
     69
     70	pt->start = ktime_get();
     71
     72	atomic_dec(&s->start_wait);
     73
     74	while (atomic_read(&s->start_wait))
     75		; /* spin */
     76
     77	while (cont) {
     78		raw_spin_lock(&s->lock);
     79		loops--;
     80		if (loops == 0)
     81			cont = 0;
     82		raw_spin_unlock(&s->lock);
     83	}
     84
     85	atomic_dec(&s->exit_wait);
     86	while (atomic_read(&s->exit_wait))
     87		; /* spin */
     88	return 0;
     89}
     90
     91static int multi_get(void *data, u64 *val)
     92{
     93	ktime_t finish;
     94	struct spin_multi_state ms;
     95	struct spin_multi_per_thread t1, t2;
     96
     97	ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get");
     98	ms.loops = 1000000;
     99
    100	atomic_set(&ms.start_wait, 2);
    101	atomic_set(&ms.enter_wait, 2);
    102	atomic_set(&ms.exit_wait, 2);
    103	t1.state = &ms;
    104	t2.state = &ms;
    105
    106	kthread_run(multi_other, &t2, "multi_get");
    107
    108	multi_other(&t1);
    109
    110	finish = ktime_get();
    111
    112	*val = ktime_us_delta(finish, t1.start);
    113
    114	return 0;
    115}
    116
    117DEFINE_DEBUGFS_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
    118
    119static int __init spinlock_test(void)
    120{
    121	debugfs_create_file_unsafe("spin_single", S_IRUGO, mips_debugfs_dir, NULL,
    122			    &fops_ss);
    123	debugfs_create_file_unsafe("spin_multi", S_IRUGO, mips_debugfs_dir, NULL,
    124			    &fops_multi);
    125	return 0;
    126}
    127device_initcall(spinlock_test);