162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2015, Michael Neuling, IBM Corp.
462306a36Sopenharmony_ci * Original: Michael Neuling 19/7/2013
562306a36Sopenharmony_ci * Edited: Rashmica Gupta 01/12/2015
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Do some transactions, see if the tar is corrupted.
862306a36Sopenharmony_ci * If the transaction is aborted, the TAR should be rolled back to the
962306a36Sopenharmony_ci * checkpointed value before the transaction began. The value written to
1062306a36Sopenharmony_ci * TAR in suspended mode should only remain in TAR if the transaction
1162306a36Sopenharmony_ci * completes.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <stdio.h>
1562306a36Sopenharmony_ci#include <stdlib.h>
1662306a36Sopenharmony_ci#include <unistd.h>
1762306a36Sopenharmony_ci#include <string.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "tm.h"
2062306a36Sopenharmony_ci#include "utils.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciint	num_loops	= 10000;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciint test_tar(void)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	int i;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	SKIP_IF(!have_htm());
2962306a36Sopenharmony_ci	SKIP_IF(htm_is_synthetic());
3062306a36Sopenharmony_ci	SKIP_IF(!is_ppc64le());
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	for (i = 0; i < num_loops; i++)
3362306a36Sopenharmony_ci	{
3462306a36Sopenharmony_ci		uint64_t result = 0;
3562306a36Sopenharmony_ci		asm __volatile__(
3662306a36Sopenharmony_ci			"li	7, 1;"
3762306a36Sopenharmony_ci			"mtspr	%[tar], 7;"	/* tar = 1 */
3862306a36Sopenharmony_ci			"tbegin.;"
3962306a36Sopenharmony_ci			"beq	3f;"
4062306a36Sopenharmony_ci			"li	4, 0x7000;"	/* Loop lots, to use time */
4162306a36Sopenharmony_ci			"2:;"			/* Start loop */
4262306a36Sopenharmony_ci			"li	7, 2;"
4362306a36Sopenharmony_ci			"mtspr	%[tar], 7;"	/* tar = 2 */
4462306a36Sopenharmony_ci			"tsuspend.;"
4562306a36Sopenharmony_ci			"li	7, 3;"
4662306a36Sopenharmony_ci			"mtspr	%[tar], 7;"	/* tar = 3 */
4762306a36Sopenharmony_ci			"tresume.;"
4862306a36Sopenharmony_ci			"subi	4, 4, 1;"
4962306a36Sopenharmony_ci			"cmpdi	4, 0;"
5062306a36Sopenharmony_ci			"bne	2b;"
5162306a36Sopenharmony_ci			"tend.;"
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci			/* Transaction sucess! TAR should be 3 */
5462306a36Sopenharmony_ci			"mfspr  7, %[tar];"
5562306a36Sopenharmony_ci			"ori	%[res], 7, 4;"  // res = 3|4 = 7
5662306a36Sopenharmony_ci			"b	4f;"
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci			/* Abort handler. TAR should be rolled back to 1 */
5962306a36Sopenharmony_ci			"3:;"
6062306a36Sopenharmony_ci			"mfspr  7, %[tar];"
6162306a36Sopenharmony_ci			"ori	%[res], 7, 8;"	// res = 1|8 = 9
6262306a36Sopenharmony_ci			"4:;"
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci			: [res]"=r"(result)
6562306a36Sopenharmony_ci			: [tar]"i"(SPRN_TAR)
6662306a36Sopenharmony_ci			   : "memory", "r0", "r4", "r7");
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		/* If result is anything else other than 7 or 9, the tar
6962306a36Sopenharmony_ci		 * value must have been corrupted. */
7062306a36Sopenharmony_ci		if ((result != 7) && (result != 9))
7162306a36Sopenharmony_ci			return 1;
7262306a36Sopenharmony_ci	}
7362306a36Sopenharmony_ci	return 0;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciint main(int argc, char *argv[])
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	/* A low number of iterations (eg 100) can cause a false pass */
7962306a36Sopenharmony_ci	if (argc > 1) {
8062306a36Sopenharmony_ci		if (strcmp(argv[1], "-h") == 0) {
8162306a36Sopenharmony_ci			printf("Syntax:\n\t%s [<num loops>]\n",
8262306a36Sopenharmony_ci			       argv[0]);
8362306a36Sopenharmony_ci			return 1;
8462306a36Sopenharmony_ci		} else {
8562306a36Sopenharmony_ci			num_loops = atoi(argv[1]);
8662306a36Sopenharmony_ci		}
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	printf("Starting, %d loops\n", num_loops);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	return test_harness(test_tar, "tm_tar");
9262306a36Sopenharmony_ci}
93