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 21 #include "tm.h" 22 #include "utils.h" 23 24 int passed; 25 26 void *worker(void *unused) 27 { 28 __int128 vmx0; 29 uint64_t texasr; 30 31 asm goto ( 32 "li 3, 1;" /* Stick non-zero value in VMX0 */ 33 "std 3, 0(%[vmx0_ptr]);" 34 "lvx 0, 0, %[vmx0_ptr];" 35 36 /* Wait here a bit so we get scheduled out 255 times */ 37 "lis 3, 0x3fff;" 38 "1: ;" 39 "addi 3, 3, -1;" 40 "cmpdi 3, 0;" 41 "bne 1b;" 42 43 /* Kernel will hopefully turn VMX off now */ 44 45 "tbegin. ;" 46 "beq failure;" 47 48 /* Cause VMX unavail. Any VMX instruction */ 49 "vaddcuw 0,0,0;" 50 51 "tend. ;" 52 "b %l[success];" 53 54 /* Check VMX0 sanity after abort */ 55 "failure: ;" 56 "lvx 1, 0, %[vmx0_ptr];" 57 "vcmpequb. 2, 0, 1;" 58 "bc 4, 24, %l[value_mismatch];" 59 "b %l[value_match];" 60 : 61 : [vmx0_ptr] "r"(&vmx0) 62 : "r3" 63 : success, value_match, value_mismatch 64 ); 65 66 /* HTM aborted and VMX0 is corrupted */ 67 value_mismatch: 68 texasr = __builtin_get_texasr(); 69 70 printf("\n\n==============\n\n"); 71 printf("Failure with error: %lx\n", _TEXASR_FAILURE_CODE(texasr)); 72 printf("Summary error : %lx\n", _TEXASR_FAILURE_SUMMARY(texasr)); 73 printf("TFIAR exact : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr)); 74 75 passed = 0; 76 return NULL; 77 78 /* HTM aborted but VMX0 is correct */ 79 value_match: 80 // printf("!"); 81 return NULL; 82 83 success: 84 // printf("."); 85 return NULL; 86 } 87 88 int tm_vmx_unavail_test() 89 { 90 int threads; 91 pthread_t *thread; 92 93 SKIP_IF(!have_htm()); 94 95 passed = 1; 96 97 threads = sysconf(_SC_NPROCESSORS_ONLN) * 4; 98 thread = malloc(sizeof(pthread_t)*threads); 99 if (!thread) 100 return EXIT_FAILURE; 101 102 for (uint64_t i = 0; i < threads; i++) 103 pthread_create(&thread[i], NULL, &worker, NULL); 104 105 for (uint64_t i = 0; i < threads; i++) 106 pthread_join(thread[i], NULL); 107 108 free(thread); 109 110 return passed ? EXIT_SUCCESS : EXIT_FAILURE; 111 } 112 113 114 int main(int argc, char **argv) 115 { 116 return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test"); 117 } 118