1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2017, Michael Neuling, IBM Corp. 4 * Original: Breno Leitao <brenohl@br.ibm.com> & 5 * Gustavo Bueno Romero <gromero@br.ibm.com> 6 * Edited: Michael Neuling 7 * 8 * Force VMX unavailable during a transaction and see if it corrupts 9 * the checkpointed VMX register state after the abort. 10 */ 11 12 #include <inttypes.h> 13 #include <htmintrin.h> 14 #include <string.h> 15 #include <stdlib.h> 16 #include <stdio.h> 17 #include <pthread.h> 18 #include <sys/mman.h> 19 #include <unistd.h> 20 #include <pthread.h> 21 22 #include "tm.h" 23 #include "utils.h" 24 25 int passed; 26 27 void *worker(void *unused) 28 { 29 __int128 vmx0; 30 uint64_t texasr; 31 32 asm goto ( 33 "li 3, 1;" /* Stick non-zero value in VMX0 */ 34 "std 3, 0(%[vmx0_ptr]);" 35 "lvx 0, 0, %[vmx0_ptr];" 36 37 /* Wait here a bit so we get scheduled out 255 times */ 38 "lis 3, 0x3fff;" 39 "1: ;" 40 "addi 3, 3, -1;" 41 "cmpdi 3, 0;" 42 "bne 1b;" 43 44 /* Kernel will hopefully turn VMX off now */ 45 46 "tbegin. ;" 47 "beq failure;" 48 49 /* Cause VMX unavail. Any VMX instruction */ 50 "vaddcuw 0,0,0;" 51 52 "tend. ;" 53 "b %l[success];" 54 55 /* Check VMX0 sanity after abort */ 56 "failure: ;" 57 "lvx 1, 0, %[vmx0_ptr];" 58 "vcmpequb. 2, 0, 1;" 59 "bc 4, 24, %l[value_mismatch];" 60 "b %l[value_match];" 61 : 62 : [vmx0_ptr] "r"(&vmx0) 63 : "r3" 64 : success, value_match, value_mismatch 65 ); 66 67 /* HTM aborted and VMX0 is corrupted */ 68 value_mismatch: 69 texasr = __builtin_get_texasr(); 70 71 printf("\n\n==============\n\n"); 72 printf("Failure with error: %lx\n", _TEXASR_FAILURE_CODE(texasr)); 73 printf("Summary error : %lx\n", _TEXASR_FAILURE_SUMMARY(texasr)); 74 printf("TFIAR exact : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr)); 75 76 passed = 0; 77 return NULL; 78 79 /* HTM aborted but VMX0 is correct */ 80 value_match: 81 // printf("!"); 82 return NULL; 83 84 success: 85 // printf("."); 86 return NULL; 87 } 88 89 int tm_vmx_unavail_test() 90 { 91 int threads; 92 pthread_t *thread; 93 94 SKIP_IF(!have_htm()); 95 96 passed = 1; 97 98 threads = sysconf(_SC_NPROCESSORS_ONLN) * 4; 99 thread = malloc(sizeof(pthread_t)*threads); 100 if (!thread) 101 return EXIT_FAILURE; 102 103 for (uint64_t i = 0; i < threads; i++) 104 pthread_create(&thread[i], NULL, &worker, NULL); 105 106 for (uint64_t i = 0; i < threads; i++) 107 pthread_join(thread[i], NULL); 108 109 free(thread); 110 111 return passed ? EXIT_SUCCESS : EXIT_FAILURE; 112 } 113 114 115 int main(int argc, char **argv) 116 { 117 return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test"); 118 } 119