162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2015, Michael Neuling, IBM Corp. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Original: Michael Neuling 3/4/2014 662306a36Sopenharmony_ci * Modified: Rashmica Gupta 8/12/2015 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Check if any of the Transaction Memory SPRs get corrupted. 962306a36Sopenharmony_ci * - TFIAR - stores address of location of transaction failure 1062306a36Sopenharmony_ci * - TFHAR - stores address of software failure handler (if transaction 1162306a36Sopenharmony_ci * fails) 1262306a36Sopenharmony_ci * - TEXASR - lots of info about the transacion(s) 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * (1) create more threads than cpus 1562306a36Sopenharmony_ci * (2) in each thread: 1662306a36Sopenharmony_ci * (a) set TFIAR and TFHAR a unique value 1762306a36Sopenharmony_ci * (b) loop for awhile, continually checking to see if 1862306a36Sopenharmony_ci * either register has been corrupted. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * (3) Loop: 2162306a36Sopenharmony_ci * (a) begin transaction 2262306a36Sopenharmony_ci * (b) abort transaction 2362306a36Sopenharmony_ci * (c) check TEXASR to see if FS has been corrupted 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define _GNU_SOURCE 2762306a36Sopenharmony_ci#include <stdio.h> 2862306a36Sopenharmony_ci#include <stdlib.h> 2962306a36Sopenharmony_ci#include <unistd.h> 3062306a36Sopenharmony_ci#include <pthread.h> 3162306a36Sopenharmony_ci#include <string.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "utils.h" 3462306a36Sopenharmony_ci#include "tm.h" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciint num_loops = 1000000; 3762306a36Sopenharmony_ciint passed = 1; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_civoid tfiar_tfhar(void *in) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci unsigned long tfhar, tfhar_rd, tfiar, tfiar_rd; 4262306a36Sopenharmony_ci int i; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* TFIAR: Last bit has to be high so userspace can read register */ 4562306a36Sopenharmony_ci tfiar = ((unsigned long)in) + 1; 4662306a36Sopenharmony_ci tfiar += 2; 4762306a36Sopenharmony_ci mtspr(SPRN_TFIAR, tfiar); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci /* TFHAR: Last two bits are reserved */ 5062306a36Sopenharmony_ci tfhar = ((unsigned long)in); 5162306a36Sopenharmony_ci tfhar &= ~0x3UL; 5262306a36Sopenharmony_ci tfhar += 4; 5362306a36Sopenharmony_ci mtspr(SPRN_TFHAR, tfhar); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci for (i = 0; i < num_loops; i++) { 5662306a36Sopenharmony_ci tfhar_rd = mfspr(SPRN_TFHAR); 5762306a36Sopenharmony_ci tfiar_rd = mfspr(SPRN_TFIAR); 5862306a36Sopenharmony_ci if ( (tfhar != tfhar_rd) || (tfiar != tfiar_rd) ) { 5962306a36Sopenharmony_ci passed = 0; 6062306a36Sopenharmony_ci return; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci return; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_civoid texasr(void *in) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci unsigned long i; 6962306a36Sopenharmony_ci uint64_t result = 0; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci for (i = 0; i < num_loops; i++) { 7262306a36Sopenharmony_ci asm __volatile__( 7362306a36Sopenharmony_ci "tbegin.;" 7462306a36Sopenharmony_ci "beq 3f ;" 7562306a36Sopenharmony_ci "tabort. 0 ;" 7662306a36Sopenharmony_ci "tend.;" 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* Abort handler */ 7962306a36Sopenharmony_ci "3: ;" 8062306a36Sopenharmony_ci ::: "memory"); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* Check the TEXASR */ 8362306a36Sopenharmony_ci result = mfspr(SPRN_TEXASR); 8462306a36Sopenharmony_ci if ((result & TEXASR_FS) == 0) { 8562306a36Sopenharmony_ci passed = 0; 8662306a36Sopenharmony_ci return; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci return; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciint test_tmspr() 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci pthread_t *thread; 9562306a36Sopenharmony_ci int thread_num; 9662306a36Sopenharmony_ci unsigned long i; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci SKIP_IF(!have_htm()); 9962306a36Sopenharmony_ci SKIP_IF(htm_is_synthetic()); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* To cause some context switching */ 10262306a36Sopenharmony_ci thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci thread = malloc(thread_num * sizeof(pthread_t)); 10562306a36Sopenharmony_ci if (thread == NULL) 10662306a36Sopenharmony_ci return EXIT_FAILURE; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* Test TFIAR and TFHAR */ 10962306a36Sopenharmony_ci for (i = 0; i < thread_num; i += 2) { 11062306a36Sopenharmony_ci if (pthread_create(&thread[i], NULL, (void *)tfiar_tfhar, 11162306a36Sopenharmony_ci (void *)i)) 11262306a36Sopenharmony_ci return EXIT_FAILURE; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci /* Test TEXASR */ 11562306a36Sopenharmony_ci for (i = 1; i < thread_num; i += 2) { 11662306a36Sopenharmony_ci if (pthread_create(&thread[i], NULL, (void *)texasr, (void *)i)) 11762306a36Sopenharmony_ci return EXIT_FAILURE; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci for (i = 0; i < thread_num; i++) { 12162306a36Sopenharmony_ci if (pthread_join(thread[i], NULL) != 0) 12262306a36Sopenharmony_ci return EXIT_FAILURE; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci free(thread); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (passed) 12862306a36Sopenharmony_ci return 0; 12962306a36Sopenharmony_ci else 13062306a36Sopenharmony_ci return 1; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciint main(int argc, char *argv[]) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci if (argc > 1) { 13662306a36Sopenharmony_ci if (strcmp(argv[1], "-h") == 0) { 13762306a36Sopenharmony_ci printf("Syntax:\t [<num loops>]\n"); 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci } else { 14062306a36Sopenharmony_ci num_loops = atoi(argv[1]); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci return test_harness(test_tmspr, "tm_tmspr"); 14462306a36Sopenharmony_ci} 145