linux/tools/testing/selftests/prctl/disable-tsc-test.c
<<
>>
Prefs
   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
  26const char *tsc_names[] =
  27{
  28        [0] = "[not set]",
  29        [PR_TSC_ENABLE] = "PR_TSC_ENABLE",
  30        [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
  31};
  32
  33static uint64_t rdtsc(void)
  34{
  35uint32_t lo, hi;
  36/* We cannot use "=A", since this would use %rax on x86_64 */
  37__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  38return (uint64_t)hi << 32 | lo;
  39}
  40
  41static 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
  61int 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