root/tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rdtsc
  2. sigsegv_expect
  3. segvtask
  4. sigsegv_fail
  5. rdtsctask
  6. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
   4  *
   5  * Tests if the control register is updated correctly
   6  * at context switches
   7  *
   8  * Warning: this test will cause a very high load for a few seconds
   9  *
  10  */
  11 
  12 #include <stdio.h>
  13 #include <stdlib.h>
  14 #include <unistd.h>
  15 #include <signal.h>
  16 #include <inttypes.h>
  17 #include <wait.h>
  18 
  19 
  20 #include <sys/prctl.h>
  21 #include <linux/prctl.h>
  22 
  23 /* Get/set the process' ability to use the timestamp counter instruction */
  24 #ifndef PR_GET_TSC
  25 #define PR_GET_TSC 25
  26 #define PR_SET_TSC 26
  27 # define PR_TSC_ENABLE          1   /* allow the use of the timestamp counter */
  28 # define PR_TSC_SIGSEGV         2   /* throw a SIGSEGV instead of reading the TSC */
  29 #endif
  30 
  31 static uint64_t rdtsc(void)
  32 {
  33 uint32_t lo, hi;
  34 /* We cannot use "=A", since this would use %rax on x86_64 */
  35 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  36 return (uint64_t)hi << 32 | lo;
  37 }
  38 
  39 static void sigsegv_expect(int sig)
  40 {
  41         /* */
  42 }
  43 
  44 static void segvtask(void)
  45 {
  46         if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
  47         {
  48                 perror("prctl");
  49                 exit(0);
  50         }
  51         signal(SIGSEGV, sigsegv_expect);
  52         alarm(10);
  53         rdtsc();
  54         fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
  55         exit(0);
  56 }
  57 
  58 
  59 static void sigsegv_fail(int sig)
  60 {
  61         fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
  62         exit(0);
  63 }
  64 
  65 static void rdtsctask(void)
  66 {
  67         if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
  68         {
  69                 perror("prctl");
  70                 exit(0);
  71         }
  72         signal(SIGSEGV, sigsegv_fail);
  73         alarm(10);
  74         for(;;) rdtsc();
  75 }
  76 
  77 
  78 int main(void)
  79 {
  80         int n_tasks = 100, i;
  81 
  82         fprintf(stderr, "[No further output means we're allright]\n");
  83 
  84         for (i=0; i<n_tasks; i++)
  85                 if (fork() == 0)
  86                 {
  87                         if (i & 1)
  88                                 segvtask();
  89                         else
  90                                 rdtsctask();
  91                 }
  92 
  93         for (i=0; i<n_tasks; i++)
  94                 wait(NULL);
  95 
  96         exit(0);
  97 }
  98 

/* [<][>][^][v][top][bottom][index][help] */