162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2017, Michael Neuling, IBM Corp. 462306a36Sopenharmony_ci * Original: Breno Leitao <brenohl@br.ibm.com> & 562306a36Sopenharmony_ci * Gustavo Bueno Romero <gromero@br.ibm.com> 662306a36Sopenharmony_ci * Edited: Michael Neuling 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Force VMX unavailable during a transaction and see if it corrupts 962306a36Sopenharmony_ci * the checkpointed VMX register state after the abort. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <inttypes.h> 1362306a36Sopenharmony_ci#include <htmintrin.h> 1462306a36Sopenharmony_ci#include <string.h> 1562306a36Sopenharmony_ci#include <stdlib.h> 1662306a36Sopenharmony_ci#include <stdio.h> 1762306a36Sopenharmony_ci#include <pthread.h> 1862306a36Sopenharmony_ci#include <sys/mman.h> 1962306a36Sopenharmony_ci#include <unistd.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "tm.h" 2262306a36Sopenharmony_ci#include "utils.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciint passed; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_civoid *worker(void *unused) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci __int128 vmx0; 2962306a36Sopenharmony_ci uint64_t texasr; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci asm goto ( 3262306a36Sopenharmony_ci "li 3, 1;" /* Stick non-zero value in VMX0 */ 3362306a36Sopenharmony_ci "std 3, 0(%[vmx0_ptr]);" 3462306a36Sopenharmony_ci "lvx 0, 0, %[vmx0_ptr];" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci /* Wait here a bit so we get scheduled out 255 times */ 3762306a36Sopenharmony_ci "lis 3, 0x3fff;" 3862306a36Sopenharmony_ci "1: ;" 3962306a36Sopenharmony_ci "addi 3, 3, -1;" 4062306a36Sopenharmony_ci "cmpdi 3, 0;" 4162306a36Sopenharmony_ci "bne 1b;" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci /* Kernel will hopefully turn VMX off now */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci "tbegin. ;" 4662306a36Sopenharmony_ci "beq failure;" 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* Cause VMX unavail. Any VMX instruction */ 4962306a36Sopenharmony_ci "vaddcuw 0,0,0;" 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci "tend. ;" 5262306a36Sopenharmony_ci "b %l[success];" 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci /* Check VMX0 sanity after abort */ 5562306a36Sopenharmony_ci "failure: ;" 5662306a36Sopenharmony_ci "lvx 1, 0, %[vmx0_ptr];" 5762306a36Sopenharmony_ci "vcmpequb. 2, 0, 1;" 5862306a36Sopenharmony_ci "bc 4, 24, %l[value_mismatch];" 5962306a36Sopenharmony_ci "b %l[value_match];" 6062306a36Sopenharmony_ci : 6162306a36Sopenharmony_ci : [vmx0_ptr] "r"(&vmx0) 6262306a36Sopenharmony_ci : "r3" 6362306a36Sopenharmony_ci : success, value_match, value_mismatch 6462306a36Sopenharmony_ci ); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* HTM aborted and VMX0 is corrupted */ 6762306a36Sopenharmony_civalue_mismatch: 6862306a36Sopenharmony_ci texasr = __builtin_get_texasr(); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci printf("\n\n==============\n\n"); 7162306a36Sopenharmony_ci printf("Failure with error: %lx\n", _TEXASR_FAILURE_CODE(texasr)); 7262306a36Sopenharmony_ci printf("Summary error : %lx\n", _TEXASR_FAILURE_SUMMARY(texasr)); 7362306a36Sopenharmony_ci printf("TFIAR exact : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr)); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci passed = 0; 7662306a36Sopenharmony_ci return NULL; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* HTM aborted but VMX0 is correct */ 7962306a36Sopenharmony_civalue_match: 8062306a36Sopenharmony_ci// printf("!"); 8162306a36Sopenharmony_ci return NULL; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cisuccess: 8462306a36Sopenharmony_ci// printf("."); 8562306a36Sopenharmony_ci return NULL; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciint tm_vmx_unavail_test() 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci int threads; 9162306a36Sopenharmony_ci pthread_t *thread; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci SKIP_IF(!have_htm()); 9462306a36Sopenharmony_ci SKIP_IF(htm_is_synthetic()); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci passed = 1; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci threads = sysconf(_SC_NPROCESSORS_ONLN) * 4; 9962306a36Sopenharmony_ci thread = malloc(sizeof(pthread_t)*threads); 10062306a36Sopenharmony_ci if (!thread) 10162306a36Sopenharmony_ci return EXIT_FAILURE; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci for (uint64_t i = 0; i < threads; i++) 10462306a36Sopenharmony_ci pthread_create(&thread[i], NULL, &worker, NULL); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci for (uint64_t i = 0; i < threads; i++) 10762306a36Sopenharmony_ci pthread_join(thread[i], NULL); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci free(thread); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return passed ? EXIT_SUCCESS : EXIT_FAILURE; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint main(int argc, char **argv) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test"); 11862306a36Sopenharmony_ci} 119