1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
292dd8dd4SShuah Khan /*
392dd8dd4SShuah Khan * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
492dd8dd4SShuah Khan *
592dd8dd4SShuah Khan * Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
692dd8dd4SShuah Khan */
792dd8dd4SShuah Khan
892dd8dd4SShuah Khan #include <stdio.h>
992dd8dd4SShuah Khan #include <stdlib.h>
1092dd8dd4SShuah Khan #include <unistd.h>
1192dd8dd4SShuah Khan #include <signal.h>
1292dd8dd4SShuah Khan #include <inttypes.h>
1392dd8dd4SShuah Khan
1492dd8dd4SShuah Khan
1592dd8dd4SShuah Khan #include <sys/prctl.h>
1692dd8dd4SShuah Khan #include <linux/prctl.h>
1792dd8dd4SShuah Khan
1892dd8dd4SShuah Khan /* Get/set the process' ability to use the timestamp counter instruction */
1992dd8dd4SShuah Khan #ifndef PR_GET_TSC
2092dd8dd4SShuah Khan #define PR_GET_TSC 25
2192dd8dd4SShuah Khan #define PR_SET_TSC 26
2292dd8dd4SShuah Khan # define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
2392dd8dd4SShuah Khan # define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
2492dd8dd4SShuah Khan #endif
2592dd8dd4SShuah Khan
2692dd8dd4SShuah Khan const char *tsc_names[] =
2792dd8dd4SShuah Khan {
2892dd8dd4SShuah Khan [0] = "[not set]",
2992dd8dd4SShuah Khan [PR_TSC_ENABLE] = "PR_TSC_ENABLE",
3092dd8dd4SShuah Khan [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
3192dd8dd4SShuah Khan };
3292dd8dd4SShuah Khan
rdtsc(void)3392dd8dd4SShuah Khan static uint64_t rdtsc(void)
3492dd8dd4SShuah Khan {
3592dd8dd4SShuah Khan uint32_t lo, hi;
3692dd8dd4SShuah Khan /* We cannot use "=A", since this would use %rax on x86_64 */
3792dd8dd4SShuah Khan __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
3892dd8dd4SShuah Khan return (uint64_t)hi << 32 | lo;
3992dd8dd4SShuah Khan }
4092dd8dd4SShuah Khan
sigsegv_cb(int sig)4192dd8dd4SShuah Khan static void sigsegv_cb(int sig)
4292dd8dd4SShuah Khan {
4392dd8dd4SShuah Khan int tsc_val = 0;
4492dd8dd4SShuah Khan
4592dd8dd4SShuah Khan printf("[ SIG_SEGV ]\n");
4692dd8dd4SShuah Khan printf("prctl(PR_GET_TSC, &tsc_val); ");
4792dd8dd4SShuah Khan fflush(stdout);
4892dd8dd4SShuah Khan
4992dd8dd4SShuah Khan if ( prctl(PR_GET_TSC, &tsc_val) == -1)
5092dd8dd4SShuah Khan perror("prctl");
5192dd8dd4SShuah Khan
5292dd8dd4SShuah Khan printf("tsc_val == %s\n", tsc_names[tsc_val]);
5392dd8dd4SShuah Khan printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
5492dd8dd4SShuah Khan fflush(stdout);
5592dd8dd4SShuah Khan if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
5692dd8dd4SShuah Khan perror("prctl");
5792dd8dd4SShuah Khan
5892dd8dd4SShuah Khan printf("rdtsc() == ");
5992dd8dd4SShuah Khan }
6092dd8dd4SShuah Khan
main(void)6192dd8dd4SShuah Khan int main(void)
6292dd8dd4SShuah Khan {
6392dd8dd4SShuah Khan int tsc_val = 0;
6492dd8dd4SShuah Khan
6592dd8dd4SShuah Khan signal(SIGSEGV, sigsegv_cb);
6692dd8dd4SShuah Khan
6792dd8dd4SShuah Khan printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
6892dd8dd4SShuah Khan printf("prctl(PR_GET_TSC, &tsc_val); ");
6992dd8dd4SShuah Khan fflush(stdout);
7092dd8dd4SShuah Khan
7192dd8dd4SShuah Khan if ( prctl(PR_GET_TSC, &tsc_val) == -1)
7292dd8dd4SShuah Khan perror("prctl");
7392dd8dd4SShuah Khan
7492dd8dd4SShuah Khan printf("tsc_val == %s\n", tsc_names[tsc_val]);
7592dd8dd4SShuah Khan printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
7692dd8dd4SShuah Khan printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
7792dd8dd4SShuah Khan fflush(stdout);
7892dd8dd4SShuah Khan
7992dd8dd4SShuah Khan if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
8092dd8dd4SShuah Khan perror("prctl");
8192dd8dd4SShuah Khan
8292dd8dd4SShuah Khan printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
8392dd8dd4SShuah Khan printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
8492dd8dd4SShuah Khan fflush(stdout);
8592dd8dd4SShuah Khan
8692dd8dd4SShuah Khan if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
8792dd8dd4SShuah Khan perror("prctl");
8892dd8dd4SShuah Khan
8992dd8dd4SShuah Khan printf("rdtsc() == ");
9092dd8dd4SShuah Khan fflush(stdout);
9192dd8dd4SShuah Khan printf("%llu\n", (unsigned long long)rdtsc());
9292dd8dd4SShuah Khan fflush(stdout);
9392dd8dd4SShuah Khan
9492dd8dd4SShuah Khan exit(EXIT_SUCCESS);
9592dd8dd4SShuah Khan }
9692dd8dd4SShuah Khan
97