xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/powerpc/tm/tm-tar.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2015, Michael Neuling, IBM Corp.
4*4882a593Smuzhiyun  * Original: Michael Neuling 19/7/2013
5*4882a593Smuzhiyun  * Edited: Rashmica Gupta 01/12/2015
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Do some transactions, see if the tar is corrupted.
8*4882a593Smuzhiyun  * If the transaction is aborted, the TAR should be rolled back to the
9*4882a593Smuzhiyun  * checkpointed value before the transaction began. The value written to
10*4882a593Smuzhiyun  * TAR in suspended mode should only remain in TAR if the transaction
11*4882a593Smuzhiyun  * completes.
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <stdio.h>
15*4882a593Smuzhiyun #include <stdlib.h>
16*4882a593Smuzhiyun #include <unistd.h>
17*4882a593Smuzhiyun #include <string.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include "tm.h"
20*4882a593Smuzhiyun #include "utils.h"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun int	num_loops	= 10000;
23*4882a593Smuzhiyun 
test_tar(void)24*4882a593Smuzhiyun int test_tar(void)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	int i;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	SKIP_IF(!have_htm());
29*4882a593Smuzhiyun 	SKIP_IF(!is_ppc64le());
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	for (i = 0; i < num_loops; i++)
32*4882a593Smuzhiyun 	{
33*4882a593Smuzhiyun 		uint64_t result = 0;
34*4882a593Smuzhiyun 		asm __volatile__(
35*4882a593Smuzhiyun 			"li	7, 1;"
36*4882a593Smuzhiyun 			"mtspr	%[tar], 7;"	/* tar = 1 */
37*4882a593Smuzhiyun 			"tbegin.;"
38*4882a593Smuzhiyun 			"beq	3f;"
39*4882a593Smuzhiyun 			"li	4, 0x7000;"	/* Loop lots, to use time */
40*4882a593Smuzhiyun 			"2:;"			/* Start loop */
41*4882a593Smuzhiyun 			"li	7, 2;"
42*4882a593Smuzhiyun 			"mtspr	%[tar], 7;"	/* tar = 2 */
43*4882a593Smuzhiyun 			"tsuspend.;"
44*4882a593Smuzhiyun 			"li	7, 3;"
45*4882a593Smuzhiyun 			"mtspr	%[tar], 7;"	/* tar = 3 */
46*4882a593Smuzhiyun 			"tresume.;"
47*4882a593Smuzhiyun 			"subi	4, 4, 1;"
48*4882a593Smuzhiyun 			"cmpdi	4, 0;"
49*4882a593Smuzhiyun 			"bne	2b;"
50*4882a593Smuzhiyun 			"tend.;"
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 			/* Transaction sucess! TAR should be 3 */
53*4882a593Smuzhiyun 			"mfspr  7, %[tar];"
54*4882a593Smuzhiyun 			"ori	%[res], 7, 4;"  // res = 3|4 = 7
55*4882a593Smuzhiyun 			"b	4f;"
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 			/* Abort handler. TAR should be rolled back to 1 */
58*4882a593Smuzhiyun 			"3:;"
59*4882a593Smuzhiyun 			"mfspr  7, %[tar];"
60*4882a593Smuzhiyun 			"ori	%[res], 7, 8;"	// res = 1|8 = 9
61*4882a593Smuzhiyun 			"4:;"
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 			: [res]"=r"(result)
64*4882a593Smuzhiyun 			: [tar]"i"(SPRN_TAR)
65*4882a593Smuzhiyun 			   : "memory", "r0", "r4", "r7");
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 		/* If result is anything else other than 7 or 9, the tar
68*4882a593Smuzhiyun 		 * value must have been corrupted. */
69*4882a593Smuzhiyun 		if ((result != 7) && (result != 9))
70*4882a593Smuzhiyun 			return 1;
71*4882a593Smuzhiyun 	}
72*4882a593Smuzhiyun 	return 0;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
main(int argc,char * argv[])75*4882a593Smuzhiyun int main(int argc, char *argv[])
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	/* A low number of iterations (eg 100) can cause a false pass */
78*4882a593Smuzhiyun 	if (argc > 1) {
79*4882a593Smuzhiyun 		if (strcmp(argv[1], "-h") == 0) {
80*4882a593Smuzhiyun 			printf("Syntax:\n\t%s [<num loops>]\n",
81*4882a593Smuzhiyun 			       argv[0]);
82*4882a593Smuzhiyun 			return 1;
83*4882a593Smuzhiyun 		} else {
84*4882a593Smuzhiyun 			num_loops = atoi(argv[1]);
85*4882a593Smuzhiyun 		}
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	printf("Starting, %d loops\n", num_loops);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	return test_harness(test_tar, "tm_tar");
91*4882a593Smuzhiyun }
92