xref: /linux/tools/testing/selftests/powerpc/tm/tm-tmspr.c (revision 16aab321872400a4ce35b90ba40484fcb5d636ba)
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