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