b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 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 | } |