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

vmx_preempt.c (2812B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 2015, Cyril Bur, IBM Corp.
      4 *
      5 * This test attempts to see if the VMX registers change across preemption.
      6 * Two things should be noted here a) The check_vmx function in asm only checks
      7 * the non volatile registers as it is reused from the syscall test b) There is
      8 * no way to be sure preemption happened so this test just uses many threads
      9 * and a long wait. As such, a successful test doesn't mean much but a failure
     10 * is bad.
     11 */
     12
     13#include <stdio.h>
     14#include <unistd.h>
     15#include <sys/syscall.h>
     16#include <sys/time.h>
     17#include <sys/types.h>
     18#include <sys/wait.h>
     19#include <stdlib.h>
     20#include <pthread.h>
     21
     22#include "utils.h"
     23
     24/* Time to wait for workers to get preempted (seconds) */
     25#define PREEMPT_TIME 20
     26/*
     27 * Factor by which to multiply number of online CPUs for total number of
     28 * worker threads
     29 */
     30#define THREAD_FACTOR 8
     31
     32__thread vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
     33	{13,14,15,16},{17,18,19,20},{21,22,23,24},
     34	{25,26,27,28},{29,30,31,32},{33,34,35,36},
     35	{37,38,39,40},{41,42,43,44},{45,46,47,48}};
     36
     37int threads_starting;
     38int running;
     39
     40extern void preempt_vmx(vector int *varray, int *threads_starting, int *running);
     41
     42void *preempt_vmx_c(void *p)
     43{
     44	int i, j;
     45	srand(pthread_self());
     46	for (i = 0; i < 12; i++)
     47		for (j = 0; j < 4; j++)
     48			varray[i][j] = rand();
     49
     50	/* Test fails if it ever returns */
     51	preempt_vmx(varray, &threads_starting, &running);
     52	return p;
     53}
     54
     55int test_preempt_vmx(void)
     56{
     57	int i, rc, threads;
     58	pthread_t *tids;
     59
     60	// vcmpequd used in vmx_asm.S is v2.07
     61	SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07));
     62
     63	threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
     64	tids = malloc(threads * sizeof(pthread_t));
     65	FAIL_IF(!tids);
     66
     67	running = true;
     68	threads_starting = threads;
     69	for (i = 0; i < threads; i++) {
     70		rc = pthread_create(&tids[i], NULL, preempt_vmx_c, NULL);
     71		FAIL_IF(rc);
     72	}
     73
     74	setbuf(stdout, NULL);
     75	/* Not really nessesary but nice to wait for every thread to start */
     76	printf("\tWaiting for all workers to start...");
     77	while(threads_starting)
     78		asm volatile("": : :"memory");
     79	printf("done\n");
     80
     81	printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
     82	sleep(PREEMPT_TIME);
     83	printf("done\n");
     84
     85	printf("\tStopping workers...");
     86	/*
     87	 * Working are checking this value every loop. In preempt_vmx 'cmpwi r5,0; bne 2b'.
     88	 * r5 will have loaded the value of running.
     89	 */
     90	running = 0;
     91	for (i = 0; i < threads; i++) {
     92		void *rc_p;
     93		pthread_join(tids[i], &rc_p);
     94
     95		/*
     96		 * Harness will say the fail was here, look at why preempt_vmx
     97		 * returned
     98		 */
     99		if ((long) rc_p)
    100			printf("oops\n");
    101		FAIL_IF((long) rc_p);
    102	}
    103	printf("done\n");
    104
    105	return 0;
    106}
    107
    108int main(int argc, char *argv[])
    109{
    110	return test_harness(test_preempt_vmx, "vmx_preempt");
    111}