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

dscr_default_test.c (2623B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * POWER Data Stream Control Register (DSCR) default test
      4 *
      5 * This test modifies the system wide default DSCR through
      6 * it's sysfs interface and then verifies that all threads
      7 * see the correct changed DSCR value immediately.
      8 *
      9 * Copyright 2012, Anton Blanchard, IBM Corporation.
     10 * Copyright 2015, Anshuman Khandual, IBM Corporation.
     11 */
     12#include "dscr.h"
     13
     14static unsigned long dscr;		/* System DSCR default */
     15static unsigned long sequence;
     16static unsigned long result[THREADS];
     17
     18static void *do_test(void *in)
     19{
     20	unsigned long thread = (unsigned long)in;
     21	unsigned long i;
     22
     23	for (i = 0; i < COUNT; i++) {
     24		unsigned long d, cur_dscr, cur_dscr_usr;
     25		unsigned long s1, s2;
     26
     27		s1 = READ_ONCE(sequence);
     28		if (s1 & 1)
     29			continue;
     30		rmb();
     31
     32		d = dscr;
     33		cur_dscr = get_dscr();
     34		cur_dscr_usr = get_dscr_usr();
     35
     36		rmb();
     37		s2 = sequence;
     38
     39		if (s1 != s2)
     40			continue;
     41
     42		if (cur_dscr != d) {
     43			fprintf(stderr, "thread %ld kernel DSCR should be %ld "
     44				"but is %ld\n", thread, d, cur_dscr);
     45			result[thread] = 1;
     46			pthread_exit(&result[thread]);
     47		}
     48
     49		if (cur_dscr_usr != d) {
     50			fprintf(stderr, "thread %ld user DSCR should be %ld "
     51				"but is %ld\n", thread, d, cur_dscr_usr);
     52			result[thread] = 1;
     53			pthread_exit(&result[thread]);
     54		}
     55	}
     56	result[thread] = 0;
     57	pthread_exit(&result[thread]);
     58}
     59
     60int dscr_default(void)
     61{
     62	pthread_t threads[THREADS];
     63	unsigned long i, *status[THREADS];
     64	unsigned long orig_dscr_default;
     65
     66	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
     67
     68	orig_dscr_default = get_default_dscr();
     69
     70	/* Initial DSCR default */
     71	dscr = 1;
     72	set_default_dscr(dscr);
     73
     74	/* Spawn all testing threads */
     75	for (i = 0; i < THREADS; i++) {
     76		if (pthread_create(&threads[i], NULL, do_test, (void *)i)) {
     77			perror("pthread_create() failed");
     78			goto fail;
     79		}
     80	}
     81
     82	srand(getpid());
     83
     84	/* Keep changing the DSCR default */
     85	for (i = 0; i < COUNT; i++) {
     86		double ret = uniform_deviate(rand());
     87
     88		if (ret < 0.0001) {
     89			sequence++;
     90			wmb();
     91
     92			dscr++;
     93			if (dscr > DSCR_MAX)
     94				dscr = 0;
     95
     96			set_default_dscr(dscr);
     97
     98			wmb();
     99			sequence++;
    100		}
    101	}
    102
    103	/* Individual testing thread exit status */
    104	for (i = 0; i < THREADS; i++) {
    105		if (pthread_join(threads[i], (void **)&(status[i]))) {
    106			perror("pthread_join() failed");
    107			goto fail;
    108		}
    109
    110		if (*status[i]) {
    111			printf("%ldth thread failed to join with %ld status\n",
    112								i, *status[i]);
    113			goto fail;
    114		}
    115	}
    116	set_default_dscr(orig_dscr_default);
    117	return 0;
    118fail:
    119	set_default_dscr(orig_dscr_default);
    120	return 1;
    121}
    122
    123int main(int argc, char *argv[])
    124{
    125	return test_harness(dscr_default, "dscr_default_test");
    126}