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