1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...) 4 * 5 * Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <unistd.h> 11 #include <signal.h> 12 #include <inttypes.h> 13 14 15 #include <sys/prctl.h> 16 #include <linux/prctl.h> 17 18 /* Get/set the process' ability to use the timestamp counter instruction */ 19 #ifndef PR_GET_TSC 20 #define PR_GET_TSC 25 21 #define PR_SET_TSC 26 22 # define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ 23 # define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ 24 #endif 25 26 const char *tsc_names[] = 27 { 28 [0] = "[not set]", 29 [PR_TSC_ENABLE] = "PR_TSC_ENABLE", 30 [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV", 31 }; 32 33 static uint64_t rdtsc(void) 34 { 35 uint32_t lo, hi; 36 /* We cannot use "=A", since this would use %rax on x86_64 */ 37 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); 38 return (uint64_t)hi << 32 | lo; 39 } 40 41 static void sigsegv_cb(int sig) 42 { 43 int tsc_val = 0; 44 45 printf("[ SIG_SEGV ]\n"); 46 printf("prctl(PR_GET_TSC, &tsc_val); "); 47 fflush(stdout); 48 49 if ( prctl(PR_GET_TSC, &tsc_val) == -1) 50 perror("prctl"); 51 52 printf("tsc_val == %s\n", tsc_names[tsc_val]); 53 printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n"); 54 fflush(stdout); 55 if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1) 56 perror("prctl"); 57 58 printf("rdtsc() == "); 59 } 60 61 int main(void) 62 { 63 int tsc_val = 0; 64 65 signal(SIGSEGV, sigsegv_cb); 66 67 printf("rdtsc() == %llu\n", (unsigned long long)rdtsc()); 68 printf("prctl(PR_GET_TSC, &tsc_val); "); 69 fflush(stdout); 70 71 if ( prctl(PR_GET_TSC, &tsc_val) == -1) 72 perror("prctl"); 73 74 printf("tsc_val == %s\n", tsc_names[tsc_val]); 75 printf("rdtsc() == %llu\n", (unsigned long long)rdtsc()); 76 printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n"); 77 fflush(stdout); 78 79 if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1) 80 perror("prctl"); 81 82 printf("rdtsc() == %llu\n", (unsigned long long)rdtsc()); 83 printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n"); 84 fflush(stdout); 85 86 if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1) 87 perror("prctl"); 88 89 printf("rdtsc() == "); 90 fflush(stdout); 91 printf("%llu\n", (unsigned long long)rdtsc()); 92 fflush(stdout); 93 94 exit(EXIT_SUCCESS); 95 } 96 97