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

tm-tmspr.c (2968B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2015, Michael Neuling, IBM Corp.
      4 *
      5 * Original: Michael Neuling 3/4/2014
      6 * Modified: Rashmica Gupta 8/12/2015
      7 *
      8 * Check if any of the Transaction Memory SPRs get corrupted.
      9 * - TFIAR  - stores address of location of transaction failure
     10 * - TFHAR  - stores address of software failure handler (if transaction
     11 *   fails)
     12 * - TEXASR - lots of info about the transacion(s)
     13 *
     14 * (1) create more threads than cpus
     15 * (2) in each thread:
     16 * 	(a) set TFIAR and TFHAR a unique value
     17 * 	(b) loop for awhile, continually checking to see if
     18 * 	either register has been corrupted.
     19 *
     20 * (3) Loop:
     21 * 	(a) begin transaction
     22 *    	(b) abort transaction
     23 *	(c) check TEXASR to see if FS has been corrupted
     24 */
     25
     26#define _GNU_SOURCE
     27#include <stdio.h>
     28#include <stdlib.h>
     29#include <unistd.h>
     30#include <pthread.h>
     31#include <string.h>
     32
     33#include "utils.h"
     34#include "tm.h"
     35
     36int	num_loops	= 1000000;
     37int	passed = 1;
     38
     39void tfiar_tfhar(void *in)
     40{
     41	unsigned long tfhar, tfhar_rd, tfiar, tfiar_rd;
     42	int i;
     43
     44	/* TFIAR: Last bit has to be high so userspace can read register */
     45	tfiar = ((unsigned long)in) + 1;
     46	tfiar += 2;
     47	mtspr(SPRN_TFIAR, tfiar);
     48
     49	/* TFHAR: Last two bits are reserved */
     50	tfhar = ((unsigned long)in);
     51	tfhar &= ~0x3UL;
     52	tfhar += 4;
     53	mtspr(SPRN_TFHAR, tfhar);
     54
     55	for (i = 0; i < num_loops; i++)	{
     56		tfhar_rd = mfspr(SPRN_TFHAR);
     57		tfiar_rd = mfspr(SPRN_TFIAR);
     58		if ( (tfhar != tfhar_rd) || (tfiar != tfiar_rd) ) {
     59			passed = 0;
     60			return;
     61		}
     62	}
     63	return;
     64}
     65
     66void texasr(void *in)
     67{
     68	unsigned long i;
     69	uint64_t result = 0;
     70
     71	for (i = 0; i < num_loops; i++) {
     72		asm __volatile__(
     73			"tbegin.;"
     74			"beq    3f ;"
     75			"tabort. 0 ;"
     76			"tend.;"
     77
     78			/* Abort handler */
     79			"3: ;"
     80			::: "memory");
     81
     82                /* Check the TEXASR */
     83                result = mfspr(SPRN_TEXASR);
     84		if ((result & TEXASR_FS) == 0) {
     85			passed = 0;
     86			return;
     87		}
     88	}
     89	return;
     90}
     91
     92int test_tmspr()
     93{
     94	pthread_t	*thread;
     95	int	   	thread_num;
     96	unsigned long	i;
     97
     98	SKIP_IF(!have_htm());
     99	SKIP_IF(htm_is_synthetic());
    100
    101	/* To cause some context switching */
    102	thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
    103
    104	thread = malloc(thread_num * sizeof(pthread_t));
    105	if (thread == NULL)
    106		return EXIT_FAILURE;
    107
    108	/* Test TFIAR and TFHAR */
    109	for (i = 0; i < thread_num; i += 2) {
    110		if (pthread_create(&thread[i], NULL, (void *)tfiar_tfhar,
    111				   (void *)i))
    112			return EXIT_FAILURE;
    113	}
    114	/* Test TEXASR */
    115	for (i = 1; i < thread_num; i += 2) {
    116		if (pthread_create(&thread[i], NULL, (void *)texasr, (void *)i))
    117			return EXIT_FAILURE;
    118	}
    119
    120	for (i = 0; i < thread_num; i++) {
    121		if (pthread_join(thread[i], NULL) != 0)
    122			return EXIT_FAILURE;
    123	}
    124
    125	free(thread);
    126
    127	if (passed)
    128		return 0;
    129	else
    130		return 1;
    131}
    132
    133int main(int argc, char *argv[])
    134{
    135	if (argc > 1) {
    136		if (strcmp(argv[1], "-h") == 0) {
    137			printf("Syntax:\t [<num loops>]\n");
    138			return 0;
    139		} else {
    140			num_loops = atoi(argv[1]);
    141		}
    142	}
    143	return test_harness(test_tmspr, "tm_tmspr");
    144}